Bluetooth Audio Transceiver
Bluetooth Audio Transceiver is an application developed based on Common SDK. It has the capability of Bluetooth, Bluetooth Low Energy, and Audio. The host (external MCU) can communicate with Bluetooth Audio Transceiver through the UART interface. Before introducing the functions of the application, a few terms will first be defined:
ACI: Application Controller Interface, the communication interface between the ACI Host and Device.
ACI Device: Application Controller Interface Device, the chip that runs the Bluetooth Audio Transceiver application.
ACI Host: Application Controller Interface Host, the host can be an external MCU chip or PC, which must support the UART interface.
The objective of this ACI UART Transport Layer is to enable the use of the RTK Vendor Command set over a serial interface between two UARTs. The ACI Device provides common functions, such as power on, power off, factory reset, recording from the local MIC, local playback audio from ACI Host, HFP AG/HF, A2DP Source/Sink, etc.
These features are demonstrated in four different types of demo applications: Bluetooth Audio Transmitter, Bluetooth Audio Receiver, Bluetooth Audio Transceiver, Bluetooth Audio Transmitter MP3, and Bluetooth Audio Intergrated Transceiver. Later sections will detail the features supported by each scenario type and the flowcharts for implementing these features.
Bluetooth Audio Transmitter
The system block diagram shown below consists of 4 parts: Phone, ACI Host, ACI Device, Headset. Different modules use various interfaces to communicate with each other:
Phone <-> ACI Device: Communication with Bluetooth/Bluetooth Low Energy.
ACI Host <-> ACI Device: Communication with UART.
ACI Device <-> Headset: Communication with Bluetooth/Bluetooth Low Energy.
MIC is connected to the internal codec.
The ACI Host connects with the ACI Device via the UART interface. Through the RTK Command set, the ACI Host controls the ACI Device into pairing mode, as well as active scanning and pairing with the Headset. In this application, the ACI Device acts as a Bluetooth Low Energy Peripheral. It will advertise and accept Bluetooth Low Energy connect requests from the mobile phone, and the phone can control the ACI Device through the Bluetooth Low Energy connection. The audio data flow is identified by the blue line with arrows.
For the Bluetooth link with the Headset, ACI Device acts as the Source of A2DP or AG of HFP and can play the audio data from MIC, line-in, or I2S to the Headset through the A2DP or SCO link.
Bluetooth Audio Receiver
The system block diagram is shown as follows, consisting of 3 parts: Phone, ACI Host, ACI Device, different modules use various interfaces to communicate with each other:
Phone <-> ACI Device: Communication with Bluetooth/Bluetooth Low Energy.
ACI Host <-> ACI Device: Communication with UART.
ACI Device <-> Headset: Communication with Bluetooth.
MIC and SPK are connected to the internal codec.
In this application, ACI Device acts as Bluetooth Low Energy Peripheral, it will advertise and accept Bluetooth Low Energy connect requests from the mobile phone, and the phone can control ACI Device through Bluetooth Low Energy connection. The audio data flow is identified by the blue line with arrows.
For the Bluetooth link with the cell phone, ACI Device acts as the HF role of HFP and A2DP Sink role of A2DP, which can play music and handle phone calls.
Bluetooth Audio Transceiver
The system block diagram is shown as follows, which consists of 5 parts: Phone, ACI Host, ACI Device 1, ACI Device 2, Headset, different modules use various interfaces to communicate with each other:
Phone <-> ACI Device 1: Communication with Bluetooth/Bluetooth Low Energy.
ACI Host <-> ACI Device 1: Communication with UART.
ACI Host <-> ACI Device 2: Communication with UART.
ACI Device 1 <-> ACI Device 2: Communication with SPI and GPIO.
ACI Device 2 <-> Headset: Communication with Bluetooth/Bluetooth Low Energy.
ACI Device 1 supports A2DP Sink and HFP HF; ACI Device 2 supports A2DP Source and HFP AG. The audio data flow is identified by the blue line with arrows.
In A2DP scenario:
Audio data are routed as follows: Phone -> ACI Device 1 -> ACI Device 2 -> Headset.
In SCO scenario:
Downstream voice data are routed as follows: Phone -> ACI Device 1 -> ACI Device 2 -> Headset SPK.
Upstream voice data are routed as follows: Headset MIC -> ACI Device 2 -> ACI Device 1 -> Phone.
Bluetooth Audio Transmitter MP3
The system block diagram is shown as follows in the figure below:
The system block diagram is the same as bt_audio_transmitter
. The only difference is that the audio data is from ACI Host. The audio data flow is identified by the blue line with arrows.
For the ACI Device itself, the audio data received from the ACI Host can not only be played out through the A2DP Source to the Headset but also through the local SPK, similarly, audio data sampled through the ACI Device’s MIC can also be sent to the ACI Host through the ACI.
For the Bluetooth link with the Headset, the ACI Device acts as the Source of A2DP and can play the audio data from ACI Host to the Headset through the A2DP link.
Bluetooth Audio Intergrated Transceiver
The system block diagram is shown as follows, which consists of 4 parts: Phone, ACI Host, ACI Device, Headset. different modules use various interfaces to communicate with each other:
Phone <-> ACI Device: Communication with Bluetooth;
ACI Host <-> ACI Device: Communication with UART;
ACI Device <-> Headset: Communication with Bluetooth.
ACI Device supports both A2DP Sink/Source role and HFP HF/AG role. As a feature of this application, ACI Device needs to be connected to Phone and Headset at the same time. The audio data flow is identified by the blue line with arrows.
Requirements
The sample supports the following development kits:
Hardware Platforms |
Board Name |
Build Target |
---|---|---|
RTL87x3E HDK |
RTL87x3E EVB |
bt_audio_trx_4M_lea_dual_bank0 |
RTL87x3D HDK |
RTL87x3D EVB |
bt_audio_trx_16M_lea_dual_bank0 |
RTL87x3EP HDK |
RTL87x3EP EVB |
bt_audio_trx_16M_lea_dual_bank0 |
When built for an xxx_4M_xxx
or xxx_16M_xxx
build target, the sample is configured to build and run with a 4M or 16M flash map.
To quickly set up the development environment, please refer to the detailed instructions provided in Quick Start.
DSP
There are 3 types of images for Common SDK, which are shown below. We just take RTL8763EAU as an example:
cs: Common SDK.
pipe: Audio Pipe.
lea: LE Audio.
ull: Ultra Low Latency.
DSP Image Type |
Directory |
---|---|
cs_pipe_stereo |
|
cs_lea_pipe_stereo |
|
cs_leaaudio_pipe_stereo_ull |
|
The supported function list of each image is listed in the table below:
Function |
cs_pipe_stereo |
cs_lea_pipe_stereo |
cs_leaaudio_pipe_stereo_ull |
---|---|---|---|
DSP Share 80K to MCU |
Y |
N |
Y |
DSP Voice SPK Algorithm |
N |
Y |
N |
LE Audio |
N |
Y |
Y |
BIS TX ULL |
N |
N |
Y |
CIS TX ULL |
N |
N |
Y |
Notification (VP & Ringtone) |
Y |
Y |
N |
Playback |
Y |
Y |
N |
Record Gain Control |
Y |
Y |
N |
Record |
Y |
Y |
Y |
Audio (A2DP) |
Y |
Y |
N |
Voice (HFP, 1 MIC) |
Y |
Y |
N |
Line-in |
Y |
Y |
Y |
Audio Pipe |
Y |
Y |
Y |
Local Playback |
Y |
Y |
N |
MP3 Decode |
Y |
Y |
Y |
Configurations
To understand the main function of Bluetooth Audio Transceiver, the application can be categorized into 5 scenarios, which are bt_audio_transmitter
, bt_audio_receiver
, bt_audio_transceiver
, bt_audio_transmitter_mp3
, and bt_audio_intergrated_transceiver
.
As in the table below, the SDK has demo bins for providing these application scenarios and how to compile to generate these demo bins in the directory: release\board\evb\bt_audio_trx\mdk\rtl87x3e_bt_audio_trx.uvprojx
.
Application Scenarios |
Demo Bins |
Macro Define in app_flags.h |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The directory paths of the above source codes are as follows:
bt_audio_transmitter
:sample\bt_audio_trx\source_play
.bt_audio_receiver
:sample\bt_audio_trx\bredr
.bt_audio_transceiver
:sample\bt_audio_trx\transfer_path
.bt_audio_transmitter_mp3
:sample\bt_audio_trx\music_playback
.bt_audio_intergrated_transceiver
:sample\bt_audio_trx\source_play
.
DSP Configuration
The supported function list of each image in DSPConfig Tool are listed in the table below:
DSPConfig Tool |
Tab |
Function Block |
cs_pipe_stereo |
cs_lea_pipe_stereo |
cs_leaaudio_pipe_stereo_ull |
---|---|---|---|---|---|
Voice |
Decode |
NR |
N |
Y |
N |
HPF |
N |
Y |
N |
||
MB-DRC |
N |
Y |
N |
||
32KHz Process |
N |
Y |
N |
||
N |
Y |
N |
|||
Fade In/Out |
N |
Y |
N |
||
Comfort Noise |
N |
Y |
N |
||
Digital Gain |
Y |
Y |
N |
||
N |
N |
N |
|||
Encode |
N |
N |
N |
||
DC Remover |
Y |
Y |
N |
||
DSP Gain |
Y |
Y |
N |
||
AEC |
Y |
Y |
N |
||
Multi MIC |
Y |
Y |
N |
||
NR/AES |
Y |
Y |
N |
||
HPF |
Y |
Y |
N |
||
MB-DRC |
Y |
Y |
N |
||
EQ |
Y |
Y |
N |
||
32KHz Process |
Y |
Y |
N |
||
Fade In/Out |
Y |
Y |
N |
||
PostGain |
Y |
Y |
N |
||
HW Sidetone |
Y |
Y |
N |
||
Side Tone |
Y |
Y |
N |
||
Record |
ADC |
N |
N |
N |
|
DC Remover |
N |
N |
N |
||
DSP Gain |
N |
N |
N |
||
AEC |
N |
N |
N |
||
Multi MIC |
N |
N |
N |
||
NR/AES |
N |
N |
N |
||
HPF |
N |
N |
N |
||
MB-DRC |
N |
N |
N |
||
EQ |
N |
N |
N |
||
32KHz Process |
N |
N |
N |
||
Fade In/Out |
N |
N |
N |
||
PostGain |
Y |
Y |
N |
||
Audio |
MB-AGC |
Y |
Y |
N |
|
Parameter EQ |
Y |
Y |
N |
||
Audio Widening |
Y |
Y |
N |
||
Digital Gain |
Y |
Y |
N |
||
Transducer EQ |
N |
N |
N |
||
DAC |
N |
N |
N |
||
Line-in |
ADC |
N |
N |
N |
|
MB-AGC |
N |
N |
N |
||
Parameter EQ |
N |
N |
N |
||
Audio Widening |
N |
N |
N |
||
Transducer EQ |
N |
N |
N |
||
DAC |
N |
N |
N |
||
Notification |
Default SPK Gain for Ringtone |
Y |
Y |
N |
|
Default SPK Gain for VP |
Y |
Y |
N |
Building and Downloading
This sample can be found under sdk\board\evb\bt_audio_trx
in SDK folder structure.
Take the project rtl87x3e_bt_audio_trx.uvprojx
and demo bin bt_audio_transmitter
as an example. To build and run the sample with Keil development environment, follow the steps listed below:
Open the project
rtl87x3e_bt_audio_trx.uvprojx
.Set
F_APP_BT_AUDIO_TRANSMITTER_DEMO_SUPPORT
inapp_flasg.h
to 1, and other macros below shall be set to 0./** * NOTE: Only one demo support flag shall be set to 1. */ #define F_APP_BT_AUDIO_TRANSMITTER_DEMO_SUPPORT 1 #define F_APP_BT_AUDIO_RECEIVER_DEMO_SUPPORT 0 #define F_APP_BT_AUDIO_TRANSCEIVER_DEMO_SUPPORT 0 #define F_APP_BT_AUDIO_TRANSMITTER_MP3_DEMO_SUPPORT 0 #define F_APP_CHARGE_CASE_DEMO_SUPPORT 0 #define F_APP_DASHBOARD_DEMO_SUPPORT 0
Choose the build target
bt_audio_trx_4M_lea_dual_bank0
.Build the target.
After a successful build, the APP bin file
bt_audio_trx_bank0_MP-v0.0.0.0-xxx.bin
will be generated in the directorybin\rtl87x3e\flash_4M_dualbank\bank0
.Download the generated APP bin
bt_audio_trx_bank0_MP-v0.0.0.0-xxx.bin
into EVB board.Press reset button on the EVB board.
Experimental Verification
After programming the application bin to the EVB board, testing can be done with a Bluetooth headset or a mobile phone, depending on the specific application type of the bin. The following sections introduce the message sequence charts and implementation steps of each application demo bin, which are divided into:
Message Sequence Charts
This chapter shows typical interactions between Application Controller Interface (ACI) commands and events. It focuses on the message sequence charts (MSCs) for the procedures specified in Code Flow. This chapter illustrates only the most useful scenarios; it does not cover all possible alternatives. In all message sequence charts, it is assumed that all events are not masked, so the Controller will not filter out any events. The sequence of messages in these message sequence charts is for illustrative purposes. The messages may be sent in a different order where allowed by the ACI. If any of these charts differ from the text in the ACI Parts, the text in those Parts overrides these charts.
Notation
The notation used in the message sequence charts consists of ovals, elongated hexagons, boxes, lines, and arrows. The vertical lines terminated on the top by a shadow box and at the bottom by a solid oval indicate a protocol entity that resides in a device. MSCs describe interactions between these entities and the states those entities may be in.
The following notations represent interactions and states:
Notation |
Description |
---|---|
Oval |
Defines the context for the message sequence chart. |
Hexagon |
Indicates a condition needed to start the transaction below this hexagon. The location and width of the Hexagon indicate which entity or entities make this decision. |
Box |
Replaces a group of transactions. May indicate a user action, or a procedure in the link layer. |
Note |
Gives an explanation of an element. |
Alt/else |
Performs the appropriate action based on the alternative condition. |
Loop |
Repeats the loop to perform some behavior. |
Control Flow
Some message sequences are split into several charts. In these charts, numbers indicate normal or required ordering, and letters represent alternative paths. For example, Step 4 is after Step 3, and Step 5a could be executed instead of Step 5b.
Example MSC
The protocol entities represented in the example illustrate the interactions of two devices named A and B; each device includes a Host and a link layer entity in this example. Other MSCs in this chapter may show the interactions of more than two devices.
Forward Compatibility
Many of the message sequences in this part use ACI Commands or events that have enhanced or extended variants that were added to the specification later than the relevant sequence. Such variants can be related commands or events with different names or commands or events with multiple versions. In some instances, a Host is required to use the new variant rather than the one shown in the MSC. Even when this is not a requirement, Host implementers may prefer to use the newer variants.
In these circumstances, the MSCs have not been rewritten to use newer features but have been left unchanged. In general, the new commands and events will directly replace the old ones, but this is not always the case and readers should not assume it.
Basic Functions
This chapter introduces some basic features, which are supported in various application scenarios. This chapter describes how to use these functions and the flow for testing them, including the MSCs of the ACI Device and ACI Host interaction, and the commands used.
Power On/Off and Factory Reset
Power on, power off, and factory reset functions are introduced in this chapter.
Power on state: The execution of any function must ensure that the system is in the power on state.
Power off state: The APP layer will do the corresponding processing to make DSP enter a power off state. Since the power on state will enter DLPS mode automatically, the power off state cannot be set.
Factory reset: This function can clear Bluetooth pairing information and reset FTL information. This command needs to be executed once after downloading.
Power On
The chip needs to execute the power on command after downloading.
Note
Using ACI Host CLI test may require sending the mmi pwron
command multiple times to wake up the chip. This problem will not exist when the ACI Host wakes up the chip through GPIO.
When there is no task, the chip in power on state will enter DLPS mode automatically.
The ACI Host CLI CMD for power on is mmi pwron
, the corresponding UART CMD packet and tool log are as follows:
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_MMI = 0x0004 |
action = MMI_DEV_POWER_ON(0x54) |
mmi pwron |
2023-01-05 17:40:36,041 INFO: input command: mmi pwron
2023-01-05 17:40:36,041 INFO: Parser cmdParser: cmd opcode: 0004 param: [00 54] name: CMD_MMI
2023-01-05 17:40:36,042 INFO: Packet sendPacket: <<<send packet: AA 0F 04 00 04 00 00 54 95
2023-01-05 17:40:36,046 INFO: AciHostCLI continuously_read: >>>receive packet: AA 02 05 00 00 00 04 00 00 F5
2023-01-05 17:40:36,046 INFO: Parser eventParser: syncWord: AA,seqn: 02,len: 5,opcode: 0000,params: [04 00 00], check_sum: F5
2023-01-05 17:40:36,046 INFO: Parser eventParser: event name: APP_APP_EVENT_ACK
2023-01-05 17:40:36,047 INFO: Parser eventParser: event_id: [04 00]
2023-01-05 17:40:36,047 INFO: Parser eventParser: status: [00]
The chip that has executed the power on command will actively report APP_EVENT_DEVICE_STATE
is powered on after reset.
The corresponding event packet and tool log are as follows:
Event |
Parameters |
---|---|
APP_EVENT_DEVICE_STATE = 0x0007 |
state = APP_DEVICE_STATE_ON(1) |
2023-01-05 17:40:36,078 INFO: AciHostCLI continuously_read: >>>receive packet: AA 03 03 00 07 00 01 F2
2023-01-05 17:40:36,078 INFO: Parser eventParser: syncWord: AA,seqn: 03,len: 3,opcode: 0007,params: [01], check_sum: F2
2023-01-05 17:40:36,079 INFO: Parser eventParser: event name: APP_EVENT_DEVICE_STATE
2023-01-05 17:40:36,079 INFO: Parser eventParser: device_state: [01]
2023-01-05 17:40:36,080 INFO: Packet sendPacket: <<<send packet: AA 10 05 00 00 00 07 00 00 E4
The corresponding flow chart is as follows:
Power Off
After executing the power off command, the APP layer will do the corresponding processing to make the enter the power down state.
The ACI Host CLI CMD for power off is mmi pwroff
, the corresponding UART CMD packet and tool log are as follows:
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_MMI = 0x0004 |
action = MMI_DEV_POWER_OFF(0x56) |
mmi pwroff |
2023-01-05 17:42:08,000 INFO: input command: mmi pwroff
2023-01-05 17:42:08,000 INFO: Parser cmdParser: cmd opcode: 0004 param: [00 56] name: CMD_MMI
2023-01-05 17:42:08,001 INFO: Packet sendPacket: <<<send packet: AA 11 04 00 04 00 00 56 91
2023-01-05 17:42:08,013 INFO: AciHostCLI continuously_read: >>>receive packet: AA 04 05 00 00 00 04 00 00 F3
2023-01-05 17:42:08,014 INFO: Parser eventParser: syncWord: AA,seqn: 04,len: 5,opcode: 0000,params: [04 00 00], check_sum: F3
2023-01-05 17:42:08,014 INFO: Parser eventParser: event name: APP_EVENT_ACK
2023-01-05 17:42:08,014 INFO: Parser eventParser: event_id: [04 00]
2023-01-05 17:42:08,014 INFO: Parser eventParser: status: [00]
The chip will return APP_EVENT_DEVICE_STATE
with APP_DEVICE_STATE_OFF_ING
to indicate the start of the power off preparation procedure.
When the power off preparation procedure is completed, it will report the event of APP_EVENT_DEVICE_STATE
with APP_DEVICE_STATE_OFF
.
The corresponding UART event packet and tool log are as follows:
Event |
Parameters |
---|---|
APP_EVENT_DEVICE_STATE = 0x0007 |
state = APP_DEVICE_STATE_OFF_ING(2) |
APP_EVENT_DEVICE_STATE = 0x0007 |
state = APP_DEVICE_STATE_OFF(0) |
2023-01-05 17:42:08,014 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 03 00 07 00 02 EF
2023-01-05 17:42:08,015 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 3,opcode: 0007,params: [02], check_sum: EF
2023-01-05 17:42:08,015 INFO: Parser eventParser: event name: APP_EVENT_DEVICE_STATE
2023-01-05 17:42:08,015 INFO: Parser eventParser: device_state: [02]
2023-01-05 17:42:08,016 INFO: Packet sendPacket: <<<send packet: AA 12 05 00 00 00 07 00 00 E2
2023-01-05 17:42:09,500 INFO: AciHostCLI continuously_read: >>>receive packet: AA 06 03 00 07 00 00 F0
2023-01-05 17:42:09,500 INFO: Parser eventParser: syncWord: AA,seqn: 06,len: 3,opcode: 0007,params: [00], check_sum: F0
2023-01-05 17:42:09,501 INFO: Parser eventParser: event name: APP_EVENT_DEVICE_STATE
2023-01-05 17:42:09,501 INFO: Parser eventParser: device_state: [00]
2023-01-05 17:42:09,501 INFO: Packet sendPacket: <<<send packet: AA 13 05 00 00 00 07 00 00 E1
2023-01-05 17:42:10,395 ERROR: gap in packets, between 6 and 1 packet before: [170, 6, 3, 0, 7, 0, 0, 240] packet after: [170, 1, 2, 0, 32, 9, 212]
2023-01-05 17:42:10,396 INFO: AciHostCLI continuously_read: >>>receive packet: AA 01 02 00 20 09 D4
2023-01-05 17:42:10,396 INFO: Parser eventParser: syncWord: AA,seqn: 01,len: 2,opcode: 0920,params: [], check_sum: D4
2023-01-05 17:42:10,396 INFO: Parser eventParser: event name: EVENT_BT_READY
2023-01-05 17:42:10,397 INFO: Packet sendPacket: <<<send packet: AA 14 05 00 00 00 20 09 00 BE
The corresponding flow chart is as follows:
Factory Reset
Note
Before executing the factory reset command, it is necessary to ensure that the device is in a power on state. Only after the factory reset is executed, the device can enter DLPS mode. As a result, it needs to be executed once after downloading.
After executing the factory reset command, the device will enter the power off state first, and then enter the power on state automatically.
The ACI Host CLI CMD for factory reset is mmi freset
, the corresponding UART CMD packet and tool log are as follows:
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_MMI = 0x0004 |
action = MMI_DEV_FACTORY_RESET(0x58) |
mmi freset |
After the factory reset, the chip will restore from the device state before the factory reset executes.
2023-01-05 17:50:34,629 INFO: input command: mmi freset
2023-01-05 17:50:34,630 INFO: Parser cmdParser: cmd opcode: 0004 param: [00 58] name: CMD_MMI
2023-01-05 17:50:34,631 INFO: Packet sendPacket: <<<send packet: AA 1E 04 00 04 00 00 58 82
2023-01-05 17:50:34,641 INFO: AciHostCLI continuously_read: >>>receive packet: AA 04 05 00 00 00 04 00 00 F3
2023-01-05 17:50:34,642 INFO: Parser eventParser: syncWord: AA,seqn: 04,len: 5,opcode: 0000,params: [04 00 00], check_sum: F3
2023-01-05 17:50:34,642 INFO: Parser eventParser: event name: APP_EVENT_ACK
2023-01-05 17:50:34,642 INFO: Parser eventParser: event_id: [04 00]
2023-01-05 17:50:34,643 INFO: Parser eventParser: status: [00]
2023-01-05 17:50:34,643 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 03 00 07 00 02 EF
2023-01-05 17:50:34,643 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 3,opcode: 0007,params: [02], check_sum: EF
2023-01-05 17:50:34,644 INFO: Parser eventParser: event name: APP_EVENT_DEVICE_STATE
2023-01-05 17:50:34,644 INFO: Parser eventParser: device_state: [02]
2023-01-05 17:50:34,645 INFO: Packet sendPacket: <<<send packet: AA 1F 05 00 00 00 07 00 00 D5
2023-01-05 17:50:35,153 INFO: AciHostCLI continuously_read: >>>receive packet: AA 06 03 00 07 00 00 F0
2023-01-05 17:50:35,154 INFO: Parser eventParser: syncWord: AA,seqn: 06,len: 3,opcode: 0007,params: [00], check_sum: F0
2023-01-05 17:50:35,154 INFO: Parser eventParser: event name: APP_EVENT_DEVICE_STATE
2023-01-05 17:50:35,155 INFO: Parser eventParser: device_state: [00]
2023-01-05 17:50:35,155 INFO: Packet sendPacket: <<<send packet: AA 20 05 00 00 00 07 00 00 D4
2023-01-05 17:50:35,675 INFO: AciHostCLI continuously_read: >>>receive packet: AA 01 02 00 20 09 D4
2023-01-05 17:50:35,675 INFO: Parser eventParser: syncWord: AA,seqn: 01,len: 2,opcode: 0920,params: [], check_sum: D4
2023-01-05 17:50:35,675 INFO: Parser eventParser: event name: EVENT_BT_READY
2023-01-05 17:50:35,676 INFO: Packet sendPacket: <<<send packet: AA 07 05 00 00 00 20 09 00 CB
The corresponding flow chart is as follows:
Connection and Linkback Function
This chapter introduces the functions of connecting to phone and connecting to BUD.
Connect to Phone
The function of connecting to the phone is implemented by sending ACI Host CLI CMD.
ACI Host CLI Test: Connect to Phone
Command |
Parameters |
ACI Host CLI CMD |
Description |
---|---|---|---|
CMD_XM_SET_MODE = 0x0030 |
device_mode = BT_DEVICE_MODE_IDLE(0) |
mode idle |
BR/EDR radio in undiscoverable and unconnectable mode. |
CMD_XM_SET_MODE = 0x0030 |
device_mode = |
mode inq_scan |
BR/EDR radio in discoverable mode. |
CMD_XM_SET_MODE = 0x0030 |
device_mode = |
mode page_scan |
BR/EDR radio in connectable mode. |
CMD_XM_SET_MODE = 0x0030 |
device_mode = |
mode all_enable |
BR/EDR radio in discoverable and connectable mode. |
CMD_BT_CREATE_CONNECTION = 0x0002 |
profile_mask, bd_addr |
connect phone_sample |
It chooses device to connect by inquiry scan result by index, no UART packet. |
CMD_XM_USER_CFM_REQ = 0x8013 |
true = 0x01 |
btcfm t |
Confirm connect request. |
When using the connect phone_sample
, the bd_addr
parameter needs to be changed to the address of the phone.
ACI Host CLI test: Device enters discoverable and connectable mode.
2023-04-21 17:17:51,030 INFO: input command: mode all_enable 2023-04-21 17:17:51,031 INFO: Parser cmdParser: cmd opcode: 0030 param: [03] name: CMD_XM_SET_MODE 2023-04-21 17:17:51,031 INFO: Packet sendPacket: <<<send packet: AA 09 03 00 30 00 03 C1 2023-04-21 17:17:51,037 INFO: AciHostCLI continuously_read: >>>receive packet: AA 04 05 00 00 00 30 00 00 C7 2023-04-21 17:17:51,039 INFO: Parser eventParser: syncWord: AA,seqn: 04,len: 5,opcode: 0000,params: [30 00 00], check_sum: C7 2023-04-21 17:17:51,044 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-21 17:17:51,045 INFO: Parser eventParser: event_id: [30 00] 2023-04-21 17:17:51,047 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Pair/connect with
phone_sample
.2023-04-21 17:20:32,106 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 08 00 25 09 41 AF 7B 6C 32 20 9C 2023-04-21 17:20:32,108 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 8,opcode: 0925,params: [41 AF 7B 6C 32 20], check_sum: 9C 2023-04-21 17:20:32,108 INFO: Parser eventParser: event name: APP_EVENT_BR_PAIRING_REQ 2023-04-21 17:20:32,109 INFO: Parser eventParser: bd_addr: [41 AF 7B 6C 32 20] 2023-04-21 17:20:32,111 INFO: Packet sendPacket: <<<send packet: AA 08 05 00 00 00 25 09 00 C5 2023-04-21 17:20:32,155 INFO: AciHostCLI continuously_read: >>>receive packet: AA 06 0C 00 14 00 01 00 AF 7B 6C 32 20 00 00 00 F1 2023-04-21 17:20:32,156 INFO: Parser eventParser: syncWord: AA,seqn: 06,len: 12,opcode: 0014,params: [01 00 AF 7B 6C 32 20 00 00 00], check_sum: F1 2023-04-21 17:20:32,158 INFO: Parser eventParser: event name: APP_EVENT_BR_LINK_STATUS 2023-04-21 17:20:32,165 INFO: Parser eventParser: link_status: [01] 2023-04-21 17:20:32,166 INFO: Parser eventParser: bd_addr: [00 AF 7B 6C 32 20] 2023-04-21 17:20:32,167 INFO: Packet sendPacket: <<<send packet: AA 09 05 00 00 00 14 00 00 DE 2023-04-21 17:20:32,170 INFO: AciHostCLI continuously_read: >>>receive packet: AA 07 31 00 09 00 00 41 AF 7B 6C 32 20 47 61 6C 61 78 79 20 41 34 30 73 00 00 00 00 00 00 00 00 2023-04-21 17:20:32,171 INFO: Parser eventParser: syncWord: AA,seqn: 07,len: 49,opcode: 0009,params: [00 41 AF 7B 6C 32 20 47 61 6C 61 78 79 20 41 34 30 73 00 00 00 00 00 00 00 00 00 00 00 00 00 00], check_sum: F8 2023-04-21 17:20:32,172 INFO: Parser eventParser: event name: APP_EVENT_BR_REMOTE_NAME 2023-04-21 17:20:32,172 INFO: Parser eventParser: cause: [00] 2023-04-21 17:20:32,173 INFO: Parser eventParser: bd_addr: [41 AF 7B 6C 32 20] 2023-04-21 17:20:32,174 INFO: Parser eventParser: name: [47 61 6C 61 78 79 20 41 34 30 73 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00] 2023-04-21 17:20:32,177 INFO: Parser eventParser: remote_name: Galaxy A40s 2023-04-21 17:20:32,181 INFO: Packet sendPacket: <<<send packet: AA 0A 05 00 00 00 09 00 00 E8 2023-04-21 17:20:32,378 INFO: AciHostCLI continuously_read: >>>receive packet: AA 08 0C 00 26 09 AC C9 07 00 41 AF 7B 6C 32 20 18 2023-04-21 17:20:32,379 INFO: Parser eventParser: syncWord: AA,seqn: 08,len: 12,opcode: 0926,params: [AC C9 07 00 41 AF 7B 6C 32 20], check_sum: 18 2023-04-21 17:20:32,381 INFO: Parser eventParser: event name: APP_EVENT_BR_SSP_NUMERIC_VALUE 2023-04-21 17:20:32,382 INFO: Parser eventParser: display_val: [AC C9 07 00] 2023-04-21 17:20:32,383 INFO: Parser eventParser: bd_addr: [41 AF 7B 6C 32 20] 2023-04-21 17:20:32,384 INFO: Packet sendPacket: <<<send packet: AA 0B 05 00 00 00 26 09 00 C1 2023-04-21 17:20:32,394 INFO: AciHostCLI continuously_read: >>>receive packet: AA 09 0D 00 00 88 41 AF 7B 6C 32 20 AC C9 07 00 00 BD 2023-04-21 17:20:32,395 INFO: Parser eventParser: syncWord: AA,seqn: 09,len: 13,opcode: 8800,params: [41 AF 7B 6C 32 20 AC C9 07 00 00], check_sum: BD 2023-04-21 17:20:32,397 INFO: Parser eventParser: event name: EVENT_XM_USER_CONFIRMATION_REQ 2023-04-21 17:20:32,401 INFO: Parser eventParser: bd_addr: [41 AF 7B 6C 32 20] 2023-04-21 17:20:32,402 INFO: Parser eventParser: display_val: [AC C9 07 00] 2023-04-21 17:20:32,403 INFO: Packet sendPacket: <<<send packet: AA 0C 05 00 00 00 00 88 00 67
ACI Host CLI test: Confirm connection request.
2023-04-21 17:20:38,347 INFO: input command: btcfm t 2023-04-21 17:20:38,348 INFO: Parser cmdParser: cmd opcode: 8013 param: [00 01] name: CMD_XM_USER_CFM_REQ 2023-04-21 17:20:38,348 INFO: Packet sendPacket: <<<send packet: AA 0D 04 00 13 80 00 01 5B 2023-04-21 17:20:38,366 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0A 05 00 00 00 13 80 00 5E 2023-04-21 17:20:38,369 INFO: Parser eventParser: syncWord: AA,seqn: 0A,len: 5,opcode: 0000,params: [13 80 00], check_sum: 5E 2023-04-21 17:20:38,371 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-21 17:20:38,374 INFO: Parser eventParser: event_id: [13 80] 2023-04-21 17:20:38,378 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Connection successful.
2023-04-21 17:20:39,741 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0B 0A 00 03 00 04 41 AF 7B 6C 32 20 01 BA 2023-04-21 17:20:39,742 INFO: Parser eventParser: syncWord: AA,seqn: 0B,len: 10,opcode: 0003,params: [04 41 AF 7B 6C 32 20 01], check_sum: BA 2023-04-21 17:20:39,743 INFO: Parser eventParser: event name: APP_EVENT_PROFILE_CONN_STATUS 2023-04-21 17:20:39,743 INFO: Parser eventParser: profile: [04] 2023-04-21 17:20:39,743 INFO: Parser eventParser: bd_addr: [41 AF 7B 6C 32 20] 2023-04-21 17:20:39,744 INFO: Parser eventParser: others: [01] 2023-04-21 17:20:39,744 INFO: Packet sendPacket: <<<send packet: AA 0E 05 00 00 00 03 00 00 EA 2023-04-21 17:20:39,949 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0C 09 00 03 00 01 41 AF 7B 6C 32 20 BE 2023-04-21 17:20:39,950 INFO: Parser eventParser: syncWord: AA,seqn: 0C,len: 9,opcode: 0003,params: [01 41 AF 7B 6C 32 20], check_sum: BE 2023-04-21 17:20:39,953 INFO: Parser eventParser: event name: APP_EVENT_PROFILE_CONN_STATUS 2023-04-21 17:20:39,954 INFO: Parser eventParser: profile: [01] 2023-04-21 17:20:39,966 INFO: Parser eventParser: bd_addr: [41 AF 7B 6C 32 20] 2023-04-21 17:20:39,968 INFO: Parser eventParser: others: [] 2023-04-21 17:20:39,970 INFO: Packet sendPacket: <<<send packet: AA 0F 05 00 00 00 03 00 00 E9 2023-04-21 17:20:44,039 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0D 09 00 03 00 02 41 AF 7B 6C 32 20 BC 2023-04-21 17:20:44,040 INFO: Parser eventParser: syncWord: AA,seqn: 0D,len: 9,opcode: 0003,params: [02 41 AF 7B 6C 32 20], check_sum: BC 2023-04-21 17:20:44,041 INFO: Parser eventParser: event name: APP_EVENT_PROFILE_CONN_STATUS 2023-04-21 17:20:44,042 INFO: Parser eventParser: profile: [02] 2023-04-21 17:20:44,043 INFO: Parser eventParser: bd_addr: [41 AF 7B 6C 32 20] 2023-04-21 17:20:44,044 INFO: Parser eventParser: others: [] 2023-04-21 17:20:44,045 INFO: Packet sendPacket: <<<send packet: AA 10 05 00 00 00 03 00 00 E8
Connect to BUD
The function of connecting to BUD is implemented by sending ACI Host CLI CMD.
ACI Host CLI Test: Connect to BUD
Command |
Parameters |
ACI Host CLI CMD |
Description |
---|---|---|---|
CMD_XM_SET_MODE = 0x0030 |
device_mode = BT_DEVICE_MODE_IDLE(0) |
mode idle |
BR/EDR radio in undiscoverable and unconnectable mode. |
CMD_XM_SET_MODE = 0x0030 |
device_mode = BT_DEVICE_MODE_DISCOVERABLE(1) |
mode inq_scan |
BR/EDR radio in discoverable mode. |
CMD_XM_SET_MODE = 0x0030 |
device_mode = BT_DEVICE_MODE_CONNECTABLE(2) |
mode page_scan |
BR/EDR radio in connectable mode. |
CMD_XM_SET_MODE = 0x0030 |
device_mode = BT_DEVICE_MODE_DISCOVERABLE_CONNECTABLE(3) |
mode all_enable |
BR/EDR radio in discoverable and connectable mode. |
CMD_BT_CREATE_CONNECTION = 0x0002 |
profile_mask, bd_addr |
connect device |
It chooses a device to connect by the inquiry scan result by an index, no UART packet. |
CMD_INQUIRY = 0x0321 |
0x00 |
inquiry start |
Start inquiry. |
CMD_BT_CREATE_CONNECTION = 0x0002 |
None |
connect idx |
Show devices that can be connected. |
CMD_XM_USER_CFM_REQ = 0x8013 |
true = 0x01 |
btcfm t |
Confirm connect request. |
When using the connect headset_sample
, the parameter of bd_addr
needs to be changed to the address of the BUD.
ACI Host CLI test: Connect to BUD with specific address directly.
2023-04-23 19:07:07,166 INFO: input command: connect headset_sample 2023-04-23 19:07:07,170 INFO: Parser cmdParser: cmd opcode: 0002 param: [07 01 00 00 DD CC BB AA 22 12] name: CMD_BT_CREATE_CONNECTION 2023-04-23 19:07:07,171 INFO: Packet sendPacket: <<<send packet: AA 09 0C 00 02 00 07 01 00 00 DD CC BB AA 22 12 9F 2023-04-23 19:07:07,183 INFO: AciHostCLI continuously_read: >>>receive packet: AA 07 05 00 00 00 02 00 00 F2 2023-04-23 19:07:07,186 INFO: Parser eventParser: syncWord: AA,seqn: 07,len: 5,opcode: 0000,params: [02 00 00], check_sum: F2 2023-04-23 19:07:07,192 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-23 19:07:07,197 INFO: Parser eventParser: event_id: [02 00] 2023-04-23 19:07:07,206 INFO: Parser eventParser: status: [00]
In addition to direct connection, BUD can also be connected through the inquiry process.
ACI Host CLI test: BUDs inquiry start.
2023-04-21 17:26:01,020 INFO: input command: inquiry start 2023-04-21 17:26:01,021 INFO: Parser cmdParser: cmd opcode: 0321 param: [00 08] name: CMD_INQUIRY 2023-04-21 17:26:01,021 INFO: Packet sendPacket: <<<send packet: AA 2C 04 00 21 03 00 08 A4 2023-04-21 17:26:01,027 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 05 00 00 00 21 03 00 D2 2023-04-21 17:26:01,028 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 5,opcode: 0000,params: [21 03 00], check_sum: D2 2023-04-21 17:26:01,031 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-21 17:26:01,032 INFO: Parser eventParser: event_id: [21 03] 2023-04-21 17:26:01,036 INFO: Parser eventParser: status: [00] 2023-04-21 17:26:01,037 INFO: AciHostCLI continuously_read: >>>receive packet: AA 06 03 00 23 09 01 CA 2023-04-21 17:26:01,037 INFO: Parser eventParser: syncWord: AA,seqn: 06,len: 3,opcode: 0923,params: [01], check_sum: CA 2023-04-21 17:26:01,037 INFO: Parser eventParser: event name: APP_EVENT_BR_INQUIRY_STATE 2023-04-21 17:26:01,038 INFO: Parser eventParser: inquiry_state: [01] 2023-04-21 17:26:01,038 INFO: Packet sendPacket: <<<send packet: AA 2D 05 00 00 00 23 09 00 A2
ACI Host CLI test: BUDs inquired.
2023-04-21 17:26:25,514 INFO: AciHostCLI continuously_read: >>>receive packet: AA 09 35 00 29 09 B0 EC 33 E7 50 70 04 84 24 00 0D 4A 42 4C 20 57 41 56 45 20 46 4C 45 58 00 00 2023-04-21 17:26:25,515 INFO: Parser eventParser: syncWord: AA,seqn: 09,len: 53,opcode: 0929,params: [B0 EC 33 E7 50 70 04 84 24 00 0D 4A 42 4C 20 57 41 56 45 20 46 4C 45 58 00 00 00 00 00 00 00 00], check_sum: E7 2023-04-21 17:26:25,518 INFO: Parser eventParser: event name: APP_EVENT_BR_INQUIRY_RESULT 2023-04-21 17:26:25,519 INFO: Parser eventParser: bd_addr: [B0 EC 33 E7 50 70] 2023-04-21 17:26:25,520 INFO: Parser eventParser: cod: [04 84 24 00] 2023-04-21 17:26:25,520 INFO: Parser eventParser: name_len: [0D] 2023-04-21 17:26:25,521 INFO: Parser eventParser: name: [4A 42 4C 20 57 41 56 45 20 46 4C 45 58 00 00 00 00 00 00 00] 2023-04-21 17:26:25,521 INFO: Parser eventParser: name: JBL WAVE FLEX 2023-04-21 17:26:25,521 INFO: Packet sendPacket: <<<send packet: AA 30 05 00 00 00 29 09 00 99
ACI Host CLI test: Show the device index of BUDs, and enter the index of the device to be connected.
For example, in the following log, input
1
then enter.connect idx 2023-04-21 17:33:24,158 INFO: Parser cmdParser: device index: 1 bd_addr: B0 EC 33 E7 50 70 cod: 04 84 24 00, name: JBL WAVE FLEX 1
ACI Host CLI test: Confirm connection request.
Input
btcfm t
after the eventEVENT_XM_USER_CONFIRMATION_REQ
.2023-04-21 17:33:39,021 INFO: Parser eventParser: event name: EVENT_XM_USER_CONFIRMATION_REQ 2023-04-21 17:33:39,021 INFO: Parser eventParser: bd_addr: [B0 EC 33 E7 50 70] 2023-04-21 17:33:39,021 INFO: Parser eventParser: display_val: [31 E2 01 00] 2023-04-21 17:33:39,021 INFO: Packet sendPacket: <<<send packet: AA 35 05 00 00 00 00 88 00 3E btcfm t 2023-04-21 17:33:41,984 INFO: input command: btcfm t 2023-04-21 17:33:41,985 INFO: Parser cmdParser: cmd opcode: 8013 param: [00 01] name: CMD_XM_USER_CFM_REQ 2023-04-21 17:33:41,985 INFO: Packet sendPacket: <<<send packet: AA 36 04 00 13 80 00 01 32 2023-04-21 17:33:41,991 INFO: AciHostCLI continuously_read: >>>receive packet: AA 33 05 00 00 00 13 80 00 35 2023-04-21 17:33:41,993 INFO: Parser eventParser: syncWord: AA,seqn: 33,len: 5,opcode: 0000,params: [13 80 00], check_sum: 35 2023-04-21 17:33:41,996 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-21 17:33:42,000 INFO: Parser eventParser: event_id: [13 80] 2023-04-21 17:33:42,001 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Connect success and linkback.
The following protocols are established by default: A2DP (0x01), AVRCP (0x02), and HFP (0x04).
2023-04-21 17:55:49,697 INFO: AciHostCLI continuously_read: >>>receive packet: AA 11 09 00 03 00 01 B0 EC 33 E7 50 70 6C 2023-04-21 17:55:49,699 INFO: Parser eventParser: syncWord: AA,seqn: 11,len: 9,opcode: 0003,params: [01 B0 EC 33 E7 50 70], check_sum: 6C 2023-04-21 17:55:49,699 INFO: Parser eventParser: event name: APP_EVENT_PROFILE_CONN_STATUS 2023-04-21 17:55:49,700 INFO: Parser eventParser: profile: [01] 2023-04-21 17:55:49,701 INFO: Parser eventParser: bd_addr: [B0 EC 33 E7 50 70] 2023-04-21 17:55:49,702 INFO: Parser eventParser: others: [] 2023-04-21 17:55:49,703 INFO: Packet sendPacket: <<<send packet: AA 29 05 00 00 00 03 00 00 CF 2023-04-21 17:55:49,921 INFO: AciHostCLI continuously_read: >>>receive packet: AA 12 09 00 24 09 00 B0 EC 33 E7 50 70 42 2023-04-21 17:55:49,921 INFO: Parser eventParser: syncWord: AA,seqn: 12,len: 9,opcode: 0924,params: [00 B0 EC 33 E7 50 70], check_sum: 42 2023-04-21 17:55:49,923 INFO: Parser eventParser: event name: EVENT_SERVICES_SEARCH_STATE 2023-04-21 17:55:49,924 INFO: Packet sendPacket: <<<send packet: AA 2A 05 00 00 00 24 09 00 A4 2023-04-21 17:55:50,033 INFO: AciHostCLI continuously_read: >>>receive packet: AA 13 09 00 03 00 02 B0 EC 33 E7 50 70 69 2023-04-21 17:55:50,035 INFO: Parser eventParser: syncWord: AA,seqn: 13,len: 9,opcode: 0003,params: [02 B0 EC 33 E7 50 70], check_sum: 69 2023-04-21 17:55:50,040 INFO: Parser eventParser: event name: APP_EVENT_PROFILE_CONN_STATUS 2023-04-21 17:55:50,042 INFO: Parser eventParser: profile: [02] 2023-04-21 17:55:50,042 INFO: Parser eventParser: bd_addr: [B0 EC 33 E7 50 70] 2023-04-21 17:55:50,043 INFO: Parser eventParser: others: [] 2023-04-21 17:55:50,043 INFO: Packet sendPacket: <<<send packet: AA 2B 05 00 00 00 03 00 00 CD 2023-04-21 17:55:50,256 INFO: AciHostCLI continuously_read: >>>receive packet: AA 14 09 00 24 09 00 B0 EC 33 E7 50 70 40 2023-04-21 17:55:50,260 INFO: Parser eventParser: syncWord: AA,seqn: 14,len: 9,opcode: 0924,params: [00 B0 EC 33 E7 50 70], check_sum: 40 2023-04-21 17:55:50,262 INFO: Parser eventParser: event name: EVENT_SERVICES_SEARCH_STATE 2023-04-21 17:55:50,268 INFO: Packet sendPacket: <<<send packet: AA 2C 05 00 00 00 24 09 00 A2 2023-04-21 17:55:50,527 INFO: AciHostCLI continuously_read: >>>receive packet: AA 15 03 00 36 03 00 AF 2023-04-21 17:55:50,528 INFO: Parser eventParser: syncWord: AA,seqn: 15,len: 3,opcode: 0336,params: [00], check_sum: AF 2023-04-21 17:55:50,530 INFO: Packet sendPacket: <<<send packet: AA 2D 05 00 00 00 36 03 00 95 2023-04-21 17:55:50,560 INFO: AciHostCLI continuously_read: >>>receive packet: AA 16 0A 00 03 00 04 B0 EC 33 E7 50 70 01 62 2023-04-21 17:55:50,561 INFO: Parser eventParser: syncWord: AA,seqn: 16,len: 10,opcode: 0003,params: [04 B0 EC 33 E7 50 70 01], check_sum: 62 2023-04-21 17:55:50,565 INFO: Parser eventParser: event name: APP_EVENT_PROFILE_CONN_STATUS 2023-04-21 17:55:50,572 INFO: Parser eventParser: profile: [04] 2023-04-21 17:55:50,574 INFO: Parser eventParser: bd_addr: [B0 EC 33 E7 50 70] 2023-04-21 17:55:50,574 INFO: Parser eventParser: others: [01] 2023-04-21 17:55:50,574 INFO: Packet sendPacket: <<<send packet: AA 2E 05 00 00 00 03 00 00 CA
ACI Host CLI test: Linkback to ACI Device.
Input
mode page_scan
to enter connectable mode. In the scenario that needs BUD linkback, please make BUD enters pairing mode, ACI Device will be connected with BUD automatically.2023-04-23 19:24:06,535 INFO: input command: mode page_scan 2023-04-23 19:24:06,538 INFO: Parser cmdParser: cmd opcode: 0030 param: [02] name: CMD_XM_SET_MODE 2023-04-23 19:24:06,544 INFO: Packet sendPacket: <<<send packet: AA 0C 03 00 30 00 02 BF 2023-04-23 19:24:06,553 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0A 05 00 00 00 30 00 00 C1 2023-04-23 19:24:06,565 INFO: Parser eventParser: syncWord: AA,seqn: 0A,len: 5,opcode: 0000,params: [30 00 00], check_sum: C1 2023-04-23 19:24:06,576 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-23 19:24:06,585 INFO: Parser eventParser: event_id: [30 00] 2023-04-23 19:24:06,589 INFO: Parser eventParser: status: [00]
Bluetooth Low Energy Function
The ACI Device can act as a Central, scanning surrounding advertisements and initiating connections, and can also operate as a Peripheral, broadcasting and accepting connections.
For the Central role, it typically uses the following commands.
Command |
Parameters |
ACI Host CLI |
Description |
---|---|---|---|
CMD_LE_START_SCAN = 0x0103 |
local_addr_type, phys, filter_policy, filter_duplicates, scan_type_1M, scan_interval_1M, scan_window_1M, scan_type_Coded, scan_interval_Coded, scan_window_Coded, |
le start_scan |
Start scanning. |
CMD_LE_STOP_SCAN = 0x0104 |
None |
le stop_scan |
Stop scanning. |
CMD_LE_CREATE_CONN = 0x010E |
None |
le conn_idx |
Show scan list and enter device index to initiate a connection. |
CMD_LE_CREATE_CONN = 0x010E |
init_phys, remote_bd_type, remote_bd[6], local_bd_type, scan_timeout |
connect_sample |
Initiate a connection to the specific device. |
CMD_LE_START_PAIR = 0x0109 |
link_id |
le start_pair_dev1 |
Pair with the specific device. |
For the Peripheral role, these commands are commonly required.
Command |
Parameters |
ACI Host CLI |
Description |
---|---|---|---|
CMD_XM_LE_ADV_CREATE = 0x804B |
adv_data(arbitrary value), adv_prop, interval_min, interval_max, owner_addr_type, owner_addr, peer_addr_type, peer_addr, adv_data_len, adv_data, scan_rsp_len, scan_rsp |
le adv_create |
Create LE ADV with params. |
CMD_XM_LE_START_ADVERTISING = 0x8040 |
adv_interval |
le advstart |
Start LE ADV with a handle. |
CMD_XM_LE_STOP_ADVERTISING = 0x8041 |
adv_interval |
le advstop |
Stop LE ADV with a handle. |
CMD_XM_LE_ADV_DATA_UPDATE = 0x8044 |
adv_handle, adv_len, adv_data |
le adv_data |
Update ADV data for preset LE ADV. |
CMD_XM_LE_SCAN_RSP_DATA_UPDATE = 0x8045 |
adv_handle, scan_rsp_len = 0x001F, scan_rsp |
le scan_rsp_data |
Update scan rsp for preset LE ADV. |
CMD_XM_LE_ADV_INTVAL_UPDATE = 0x8046 |
adv_handle, adv_interval = 0x0320 |
le adv500ms |
It chooses the device to connect with inquiry scan result by an index, no UART packet. |
CMD_XM_LE_USER_CFM_REQ = 0x8049 |
link_id, action = true |
lecfm t |
Accept pairing request. |
CMD_XM_LE_USER_CFM_REQ = 0x8049 |
link_id, action = false |
lecfm f |
Reject pairing request. |
Once a connection is established, connection parameters can be updated, data can be transferred, and the connection can be disconnected among other operations.
Command |
Parameters |
ACI Host CLI |
Description |
---|---|---|---|
CMD_XM_LE_DISC = 0x8042 |
app_link_id |
le disconn |
Disconnect phone with profile and address. |
CMD_XM_LE_CONN_PARAM_UPDATE = 0x8043 |
app_link_id, conn_interval = 0x0050, latency = 0x0000, supervision_tout = 0x01F4 |
le conn_param |
ConnInterval is 0x50 * 1.25 = 100ms, |
CMD_XM_LE_ATT_GET_MTU = 0x8047 |
app_link_id |
le mtu |
Get the MTU for the le link with app_link_id. |
CMD_LE_DATA_TRANSFER = 0x0102 |
app_link_id, pkt_type=PKT_TYPE_SINGLE(0x00), total_len, pkt_len, payload |
le send1 |
An example for GATT service data transfer. |
Additionally, the ACI Device supports features such as the use of a white list, a resolving list, and resolution capabilities.
Command |
Parameters |
ACI Host CLI |
Description |
---|---|---|---|
CMD_LE_MODIFY_WHITELIST = 0x0161 |
opcode = GAP_WHITE_LIST_OP_CLEAR |
whitelist clr_sample |
Clear the white list. |
CMD_LE_MODIFY_WHITELIST = 0x0161 |
opcode = GAP_WHITE_LIST_OP_ADD, |
whitelist add_sample |
Add a device to white list. |
CMD_LE_MODIFY_WHITELIST = 0x0161 |
opcode = GAP_WHITE_LIST_OP_REMOVE, |
whitelist rmv_sample |
Remove a device from white list. |
CMD_LE_MODIFY_WHITELIST_BY_IDX= 0x0162 |
opcode, device_idx |
whitelist_id add_idx0 |
Add the first device stored in the bond list to the white list. |
CMD_LE_MODIFY_WHITELIST_BY_IDX= 0x0162 |
opcode, device_idx |
whitelist_id rmv_idx0 |
Remove the first device stored in the bond list from the white list. |
CMD_LE_MODIFY_RESOLVELIST_BY_IDX= 0x0163 |
opcode, device_idx |
resolvlist_id add_idx0 |
Add the first device stored in the bond list to the resolving list. |
CMD_LE_MODIFY_RESOLVELIST_BY_IDX= 0x0163 |
opcode, device_idx |
resolvlist_id rmv_idx0 |
Remove the first device stored in the bond list from the resolving list. |
CMD_LE_SET_RESOLUTION = 0x0164 |
operation |
le_resolution enable/le_resolution disable |
Enable/disable resolution. |
ACI Host CLI Test: Advertising
Start advertising with le adv_create
and le advstart
. Meanwhile, be sure that EVB is in power on mode.
le adv_create
2023-04-25 15:13:40,814 INFO: input command: le adv_create
2023-04-25 15:13:40,816 INFO: Parser cmdParser: cmd opcode: 804B param: [00 13 20 00 20 00 01 59 27 EF 53 9D FC 01 11 33 11 66 55 66 0A 00 03 16 95 FE 05 09 41 41 41 41] name: CMD_XM_LE_ADV_CREATE
2023-04-25 15:13:40,818 INFO: Packet sendPacket: <<<send packet: AA 01 2A 00 4B 80 00 13 20 00 20 00 01 59 27 EF 53 9D FC 01 11 33 11 66 55 66 0A 00 03 16 95 FE
2023-04-25 15:13:40,831 INFO: AciHostCLI continuously_read: >>>receive packet: AA 03 05 00 00 00 4B 80 00 6C
2023-04-25 15:13:40,838 INFO: Parser eventParser: syncWord: AA,seqn: 03,len: 5,opcode: 0000,params: [4B 80 00], check_sum: 6C
2023-04-25 15:13:40,840 INFO: Parser eventParser: event name: APP_EVENT_ACK
2023-04-25 15:13:40,841 INFO: Parser eventParser: event_id: [4B 80]
2023-04-25 15:13:40,843 INFO: Parser eventParser: status: [00]
2023-04-25 15:13:40,844 INFO: AciHostCLI continuously_read: >>>receive packet: AA 04 03 00 08 81 00 70
2023-04-25 15:13:40,845 INFO: Parser eventParser: syncWord: AA,seqn: 04,len: 3,opcode: 8108,params: [00], check_sum: 70
2023-04-25 15:13:40,846 INFO: Parser eventParser: event name: EVENT_XM_LE_ADV_CREATED
2023-04-25 15:13:40,847 INFO: Parser eventParser: handle: [00]
2023-04-25 15:13:40,853 INFO: Packet sendPacket: <<<send packet: AA 02 05 00 00 00 08 81 00 70
le advstart
2023-04-25 16:57:57,670 INFO: input command: le advstart
2023-04-25 16:57:57,671 INFO: Parser cmdParser: cmd opcode: 8040 param: [00 78 00] name: CMD_XM_LE_START_ADVERTISING
2023-04-25 16:57:57,672 INFO: Packet sendPacket: <<<send packet: AA 1B 05 00 40 80 00 78 00 E7
2023-04-25 16:57:57,684 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0E 05 00 40 80 00 01 00 6B
2023-04-25 16:57:57,685 INFO: Parser eventParser: syncWord: AA,seqn: 0E,len: 5,opcode: 8040,params: [00 01 00], check_sum: 6B
2023-04-25 16:57:57,686 INFO: Parser eventParser: event name: EVENT_XM_LE_ADV_STATE
2023-04-25 16:57:57,686 INFO: Parser eventParser: adv_state: [00]
2023-04-25 16:57:57,687 INFO: Parser eventParser: stop_cause: [01]
2023-04-25 16:57:57,687 INFO: Packet sendPacket: <<<send packet: AA 1C 05 00 00 00 40 80 00 5E
2023-04-25 16:57:57,700 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0F 05 00 00 00 40 80 00 6B
2023-04-25 16:57:57,701 INFO: Parser eventParser: syncWord: AA,seqn: 0F,len: 5,opcode: 0000,params: [40 80 00], check_sum: 6B
2023-04-25 16:57:57,702 INFO: Parser eventParser: event name: APP_EVENT_ACK
2023-04-25 16:57:57,703 INFO: Parser eventParser: event_id: [40 80]
2023-04-25 16:57:57,703 INFO: Parser eventParser: status: [00]
ACI Host CLI Test: Connection Establishment
If a Central device (such as a mobile phone) establishes a connection with the ACI Device (operating as a Peripheral), or if the ACI Device (operating as a Central) establishes a connection with a Peripheral device (such as a headphone), the ACI Device will report the APP_EVENT_LE_CONNECTED
.
2023-04-25 16:58:35,969 INFO: AciHostCLI continuously_read: >>>receive packet: AA 10 05 00 40 80 00 00 02 68
2023-04-25 16:58:35,969 INFO: Parser eventParser: syncWord: AA,seqn: 10,len: 5,opcode: 8100,params: [00 00 02], check_sum: 68
2023-04-25 16:58:35,970 INFO: Parser eventParser: event name: EVENT_XM_LE_ADV_STATE
2023-04-25 16:58:35,970 INFO: Parser eventParser: adv_state: [00]
2023-04-25 16:58:35,971 INFO: Parser eventParser: stop_cause: [00]
2023-04-25 16:58:35,971 INFO: Packet sendPacket: <<<send packet: AA 1D 05 00 00 00 00 81 00 5D
2023-04-25 16:58:35,985 INFO: AciHostCLI continuously_read: >>>receive packet: AA 11 03 00 00 01 00 EB
2023-04-25 16:58:35,985 INFO: Parser eventParser: syncWord: AA,seqn: 11,len: 3,opcode: 0100,params: [00], check_sum: EB
2023-04-25 16:58:35,986 INFO: Parser eventParser: event name: APP_EVENT_LE_CONNECTED
2023-04-25 16:58:35,986 INFO: Parser eventParser: link_id: [00]
2023-04-25 16:58:35,987 INFO: Packet sendPacket: <<<send packet: AA 1E 05 00 00 00 00 01 00 DC
2023-04-25 16:58:36,001 INFO: AciHostCLI continuously_read: >>>receive packet: AA 12 14 00 03 81 02 00 0D 00 02 01 D3 27 0A 2B 27 53 24 00 00 00 F4 01 82
2023-04-25 16:58:36,002 INFO: Parser eventParser: syncWord: AA,seqn: 12,len: 20,opcode: 8103,params: [02 00 0D 00 02 01 D3 27 0A 2B 27 53 24 00 00 00 F4 01], check_sum: 82
2023-04-25 16:58:36,002 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_STATE
2023-04-25 16:58:36,002 INFO: Parser eventParser: link_state: [02]
2023-04-25 16:58:36,003 INFO: Parser eventParser: app_link_id: [00]
2023-04-25 16:58:36,003 INFO: Parser eventParser: conn_handle: [0D 00]
2023-04-25 16:58:36,004 INFO: Parser eventParser: role: [02]
2023-04-25 16:58:36,577 INFO: AciHostCLI continuously_read: >>>receive packet: AA 14 0A 00 04 81 00 00 06 00 00 00 F4 01 62
2023-04-25 16:58:36,578 INFO: Parser eventParser: syncWord: AA,seqn: 14,len: 10,opcode: 8104,params: [00 00 06 00 00 00 F4 01], check_sum: 62
2023-04-25 16:58:36,579 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM
2023-04-25 16:58:36,579 INFO: Parser eventParser: app_link_id: [00]
2023-04-25 16:58:36,580 INFO: Parser eventParser: res: [00]
2023-04-25 16:58:36,580 INFO: Parser eventParser: connInterval: [06 00]
2023-04-25 16:58:36,581 INFO: Parser eventParser: connLatency: [00 00]
2023-04-25 16:58:36,581 INFO: Parser eventParser: supTimeout: [F4 01]
2023-04-25 16:58:36,581 INFO: Packet sendPacket: <<<send packet: AA 21 05 00 00 00 04 81 00 55
2023-04-25 16:58:36,880 INFO: AciHostCLI continuously_read: >>>receive packet: AA 15 0A 00 04 81 00 00 24 00 00 00 F4 01 43
2023-04-25 16:58:36,881 INFO: Parser eventParser: syncWord: AA,seqn: 15,len: 10,opcode: 8104,params: [00 00 24 00 00 00 F4 01], check_sum: 43
2023-04-25 16:58:36,882 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM
2023-04-25 16:58:36,882 INFO: Parser eventParser: app_link_id: [00]
2023-04-25 16:58:36,883 INFO: Parser eventParser: res: [00]
2023-04-25 16:58:36,883 INFO: Parser eventParser: connInterval: [24 00]
2023-04-25 16:58:36,883 INFO: Parser eventParser: connLatency: [00 00]
2023-04-25 16:58:36,884 INFO: Parser eventParser: supTimeout: [F4 01]
2023-04-25 16:58:36,885 INFO: Packet sendPacket: <<<send packet: AA 22 05 00 00 00 04 81 00 54
ACI Host CLI Test: Data Transfer
Phone should subscript notification with UUID 0xFD04. If pairing needed (EVENT_XM_LE_USER_CONFIRMATION_REQ
), input lecfm t
to confirm the pairing authorization.
lecfm t
2023-04-25 17:15:25,084 INFO: input command: lecfm t
2023-04-25 17:15:25,085 INFO: Parser cmdParser: cmd opcode: 8049 param: [00 01] name: CMD_XM_LE_USER_CFM_REQ
2023-04-25 17:15:25,086 INFO: Packet sendPacket: <<<send packet: AA 13 04 00 49 80 00 01 5E
2023-04-25 17:15:25,091 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0F 05 00 00 00 49 80 00 62
2023-04-25 17:15:25,093 INFO: Parser eventParser: syncWord: AA,seqn: 0F,len: 5,opcode: 0000,params: [49 80 00], check_sum: 62
2023-04-25 17:15:25,096 INFO: Parser eventParser: event name: APP_EVENT_ACK
2023-04-25 17:15:25,097 INFO: Parser eventParser: event_id: [49 80]
2023-04-25 17:15:25,097 INFO: Parser eventParser: status: [00]
2023-04-25 17:15:28,494 INFO: AciHostCLI continuously_read: >>>receive packet: AA 10 0B 00 02 01 00 00 00 22 75 9A C6 3D 50 5E
2023-04-25 17:15:28,495 INFO: Parser eventParser: syncWord: AA,seqn: 10,len: 11,opcode: 0102,params: [00 00 00 22 75 9A C6 3D 50], check_sum: 5E
2023-04-25 17:15:28,496 INFO: Parser eventParser: event name: APP_EVENT_LE_PAIR_STATUS
2023-04-25 17:15:28,496 INFO: Parser eventParser: link_id: [00]
2023-04-25 17:15:28,497 INFO: Parser eventParser: cause: [00 00]
2023-04-25 17:15:28,497 INFO: Parser eventParser: resolved_addr: [22 75 9A C6 3D 50]
2023-04-25 17:15:28,498 INFO: Packet sendPacket: <<<send packet: AA 14 05 00 00 00 02 01 00 E4
2023-04-25 17:15:29,070 INFO: AciHostCLI continuously_read: >>>receive packet: AA 11 0B 00 06 30 0D 00 04 00 00 02 00 02 00 99
2023-04-25 17:15:29,071 INFO: Parser eventParser: syncWord: AA,seqn: 11,len: 11,opcode: 3006,params: [0D 00 04 00 00 02 00 02 00], check_sum: 99
2023-04-25 17:15:29,072 INFO: Packet sendPacket: <<<send packet: AA 15 05 00 00 00 06 30 00 B0
Then le send1
can send data 0x01 0x34 0x56
.
le send1
2023-04-25 17:05:50,644 INFO: input command: le send1
2023-04-25 17:05:50,645 INFO: Parser cmdParser: cmd opcode: 0102 param: [00 00 03 00 03 00 01 34 56] name: CMD_LE_DATA_TRANSFER
2023-04-25 17:05:50,646 INFO: Packet sendPacket: <<<send packet: AA 31 0B 00 02 01 00 00 03 00 03 00 01 34 56 30
2023-04-25 17:05:50,659 INFO: AciHostCLI continuously_read: >>>receive packet: AA 24 05 00 00 00 02 01 00 D4
2023-04-25 17:05:50,660 INFO: Parser eventParser: syncWord: AA,seqn: 24,len: 5,opcode: 0000,params: [02 01 00], check_sum: D4
2023-04-25 17:05:50,660 INFO: Parser eventParser: event name: APP_EVENT_ACK
2023-04-25 17:05:50,661 INFO: Parser eventParser: event_id: [02 01]
2023-04-25 17:05:50,661 INFO: Parser eventParser: status: [00]
ACI Host CLI Test: Scan Devices
The ACI Device currently supports two scan commands: CMD_LE_START_SCAN
and CMD_LEA_SCAN
. These are used to scan all LE devices and devices that support LE Audio respectively. This chapter introduces the CMD_LE_START_SCAN
command. For information on the CMD_LEA_SCAN
command, please refer to chapter Initiator General ACI Host CLI Test. Please note, after scanning the devices, both commands report information through the EVENT_LE_AUDIO_SCAN_INFO
event.
2024-05-20 10:34:10,712 INFO: input command: le start_scan
2024-05-20 10:34:10,713 INFO: Parser cmdParser: cmd opcode: 0103 param: [00 01 00 01 01 90 01 C8 00 01 90 01 C8 00] name: CMD_LE_START_SCAN
2024-05-20 10:34:10,713 INFO: Packet sendPacket: <<<send packet: AA 0A 10 00 03 01 00 01 00 01 01 90 01 C8 00 01 90 01 C8 00 2C
2024-05-20 10:34:10,793 INFO: AciHostCLI continuously_read: >>>receive packet: AA 03 05 00 00 00 03 01 00 F4
2024-05-20 10:34:10,793 INFO: Parser eventParser: syncWord: AA,seqn: 03,len: 5,opcode: 0000,params: [03 01 00], check_sum: F4
2024-05-20 10:34:10,794 INFO: Parser eventParser: event name: APP_EVENT_ACK
2024-05-20 10:34:10,794 INFO: Parser eventParser: event_id: [03 01]
2024-05-20 10:34:10,796 INFO: Parser eventParser: status: [00]
2024-05-20 10:34:10,825 INFO: AciHostCLI continuously_read: >>>receive packet: AA 04 34 00 40 01 13 00 01 0A B2 8E 26 D5 68 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2024-05-20 10:34:10,826 INFO: Parser eventParser: syncWord: AA,seqn: 04,len: 52,opcode: 0140,params: [13 00 01 0A B2 8E 26 D5 68 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00], check_sum: C6
2024-05-20 10:34:10,827 INFO: Parser eventParser: event name: APP_EVENT_LE_AUDIO_SCAN_INFO
2024-05-20 10:34:10,828 INFO: Parser eventParser: event_type: [13 00]
2024-05-20 10:34:10,828 INFO: Parser eventParser: addr_type: [01]
2024-05-20 10:34:10,829 INFO: Parser eventParser: addr: [0A B2 8E 26 D5 68]
2024-05-20 10:34:10,830 INFO: Parser eventParser: name_len: [00]
2024-05-20 10:34:10,830 INFO: Parser eventParser: name: [00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]
2024-05-20 10:34:10,831 INFO: Parser eventParser: name:
2024-05-20 10:34:10,831 INFO: Packet sendPacket: <<<send packet: AA 0B 05 00 00 00 40 01 00 AF
2024-05-20 10:34:10,841 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 34 00 40 01 10 00 01 10 EF E9 32 1D C9 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2024-05-20 10:34:10,842 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 52,opcode: 0140,params: [10 00 01 10 EF E9 32 1D C9 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00], check_sum: 75
2024-05-20 10:34:10,843 INFO: Parser eventParser: event name: APP_EVENT_LE_AUDIO_SCAN_INFO
2024-05-20 10:34:10,843 INFO: Parser eventParser: event_type: [10 00]
2024-05-20 10:34:10,844 INFO: Parser eventParser: addr_type: [01]
2024-05-20 10:34:10,847 INFO: Parser eventParser: addr: [10 EF E9 32 1D C9]
2024-05-20 10:34:10,848 INFO: Parser eventParser: name_len: [00]
2024-05-20 10:34:10,849 INFO: Parser eventParser: name: [00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]
2024-05-20 10:34:10,849 INFO: Parser eventParser: name:
2024-05-20 10:34:10,851 INFO: Packet sendPacket: <<<send packet: AA 0C 05 00 00 00 40 01 00 AE
2024-05-20 10:34:10,857 INFO: AciHostCLI continuously_read: >>>receive packet: AA 06 34 00 40 01 10 00 01 01 53 93 7A F1 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2024-05-20 10:34:10,857 INFO: Parser eventParser: syncWord: AA,seqn: 06,len: 52,opcode: 0140,params: [10 00 01 01 53 93 7A F1 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00], check_sum: 1E
2024-05-20 10:34:10,858 INFO: Parser eventParser: event name: APP_EVENT_LE_AUDIO_SCAN_INFO
2024-05-20 10:34:10,859 INFO: Parser eventParser: event_type: [10 00]
2024-05-20 10:34:10,860 INFO: Parser eventParser: addr_type: [01]
2024-05-20 10:34:10,860 INFO: Parser eventParser: addr: [01 53 93 7A F1 04]
2024-05-20 10:34:10,861 INFO: Parser eventParser: name_len: [00]
2024-05-20 10:34:10,861 INFO: Parser eventParser: name: [00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]
2024-05-20 10:34:10,862 INFO: Parser eventParser: name:
2024-05-20 10:34:10,862 INFO: Packet sendPacket: <<<send packet: AA 0D 05 00 00 00 40 01 00 AD
2024-05-20 10:34:10,873 INFO: AciHostCLI continuously_read: >>>receive packet: AA 07 34 00 40 01 10 00 01 1F 86 5A 27 51 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2024-05-20 10:34:10,874 INFO: Parser eventParser: syncWord: AA,seqn: 07,len: 52,opcode: 0140,params: [10 00 01 1F 86 5A 27 51 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00], check_sum: C8
2024-05-20 10:34:10,874 INFO: Parser eventParser: event name: APP_EVENT_LE_AUDIO_SCAN_INFO
2024-05-20 10:34:10,875 INFO: Parser eventParser: event_type: [10 00]
2024-05-20 10:34:10,876 INFO: Parser eventParser: addr_type: [01]
2024-05-20 10:34:10,876 INFO: Parser eventParser: addr: [1F 86 5A 27 51 34]
2024-05-20 10:34:10,877 INFO: Parser eventParser: name_len: [00]
2024-05-20 10:34:10,877 INFO: Parser eventParser: name: [00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]
2024-05-20 10:34:10,878 INFO: Parser eventParser: name:
2024-05-20 10:34:10,879 INFO: Packet sendPacket: <<<send packet: AA 0E 05 00 00 00 40 01 00 AC
2024-05-20 10:34:10,889 INFO: AciHostCLI continuously_read: >>>receive packet: AA 08 34 00 40 01 01 00 00 01 23 15 DD AA DD 0F 38 37 37 33 45 53 4C 5F 64 61 6E 6E 69 5F 52 00
2024-05-20 10:34:10,890 INFO: Parser eventParser: syncWord: AA,seqn: 08,len: 52,opcode: 0140,params: [01 00 00 01 23 15 DD AA DD 0F 38 37 37 33 45 53 4C 5F 64 61 6E 6E 69 5F 52 00 00 00 00 00 00 00], check_sum: FF
2024-05-20 10:34:10,890 INFO: Parser eventParser: event name: APP_EVENT_LE_AUDIO_SCAN_INFO
2024-05-20 10:34:10,891 INFO: Parser eventParser: event_type: [01 00]
2024-05-20 10:34:10,892 INFO: Parser eventParser: addr_type: [00]
2024-05-20 10:34:10,893 INFO: Parser eventParser: addr: [01 23 15 DD AA DD]
2024-05-20 10:34:10,894 INFO: Parser eventParser: name_len: [0F]
2024-05-20 10:34:10,895 INFO: Parser eventParser: name: [38 37 37 33 45 53 4C 5F 64 61 6E 6E 69 5F 52 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]
2024-05-20 10:34:10,895 INFO: Parser eventParser: name: 8773ESL_danni_R
ACI Host CLI Test: Initiate Connection
By entering the le conn_idx
command, it is possible to list all scanned devices on the ACI Host CLI Tool. After entering the index of the device to connect with, the ACI Device will initiate a connection with that device, as well as automatically pair and discover services. The initiation of a connection is actually triggered through the CMD_LE_CREATE_CONN
command.
2024-05-20 10:34:22,119 INFO: input command: le conn_idx
2024-05-20 10:34:22,119 INFO: Parser cmdParser: device index: 0 addr_type 1 bd_addr: 0A B2 8E 26 D5 68 , name:
2024-05-20 10:34:22,120 INFO: Parser cmdParser: device index: 1 addr_type 1 bd_addr: 10 EF E9 32 1D C9 , name:
2024-05-20 10:34:22,120 INFO: Parser cmdParser: device index: 2 addr_type 1 bd_addr: 01 53 93 7A F1 04 , name:
2024-05-20 10:34:22,121 INFO: Parser cmdParser: device index: 3 addr_type 1 bd_addr: 1F 86 5A 27 51 34 , name:
2024-05-20 10:34:22,122 INFO: Parser cmdParser: device index: 4 addr_type 0 bd_addr: 01 23 15 DD AA DD , name: 8773ESL_danni_R
2024-05-20 10:34:43,692 INFO: Parser cmdParser: input dev_index: 4
2024-05-20 10:34:43,693 INFO: Parser cmdParser: cmd opcode: 010E param: [03 00 01 23 15 DD AA DD 00 E8 03] name: CMD_LE_CREATE_CONN
2024-05-20 10:34:43,694 INFO: Packet sendPacket: <<<send packet: AA AB 0D 00 0E 01 03 00 01 23 15 DD AA DD 00 E8 03 AE
2024-05-20 10:34:44,109 INFO: AciHostCLI continuously_read: >>>receive packet: AA D4 05 00 00 00 0E 01 00 18
2024-05-20 10:34:44,110 INFO: Parser eventParser: syncWord: AA,seqn: D4,len: 5,opcode: 0000,params: [0E 01 00], check_sum: 18
2024-05-20 10:34:44,110 INFO: Parser eventParser: event name: APP_EVENT_ACK
2024-05-20 10:34:44,111 INFO: Parser eventParser: event_id: [0E 01]
2024-05-20 10:34:44,111 INFO: Parser eventParser: status: [00]
2024-05-20 10:34:44,125 INFO: AciHostCLI continuously_read: >>>receive packet: AA D5 05 00 07 01 00 02 02 1A
2024-05-20 10:34:44,128 INFO: Parser eventParser: syncWord: AA,seqn: D5,len: 5,opcode: 0107,params: [00 02 02], check_sum: 1A
2024-05-20 10:34:44,131 INFO: Parser eventParser: event name: EVENT_LE_PHY_UPD
2024-05-20 10:34:44,134 INFO: Parser eventParser: app_link_id: [00]
2024-05-20 10:34:44,135 INFO: Parser eventParser: tx_phy: [02]
2024-05-20 10:34:44,135 INFO: Parser eventParser: rx_phy: [02]
2024-05-20 10:34:44,136 INFO: Packet sendPacket: <<<send packet: AA AC 05 00 00 00 07 01 00 47
2024-05-20 10:34:44,141 INFO: AciHostCLI continuously_read: >>>receive packet: AA D6 03 00 00 01 00 26
2024-05-20 10:34:44,144 INFO: Parser eventParser: syncWord: AA,seqn: D6,len: 3,opcode: 0100,params: [00], check_sum: 26
2024-05-20 10:34:44,145 INFO: Parser eventParser: event name: APP_EVENT_LE_CONNECTED
2024-05-20 10:34:44,146 INFO: Parser eventParser: link_id: [00]
2024-05-20 10:34:44,146 INFO: Packet sendPacket: <<<send packet: AA AD 05 00 00 00 00 01 00 4D
2024-05-20 10:34:44,157 INFO: AciHostCLI continuously_read: >>>receive packet: AA D7 14 00 43 80 02 00 05 00 01 00 01 23 15 DD AA DD 18 00 00 00 F4 01 A0
2024-05-20 10:34:44,159 INFO: Parser eventParser: syncWord: AA,seqn: D7,len: 20,opcode: 8043,params: [02 00 05 00 01 00 01 23 15 DD AA DD 18 00 00 00 F4 01], check_sum: A0
2024-05-20 10:34:44,161 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_STATE
2024-05-20 10:34:44,162 INFO: Parser eventParser: link_state: [02]
2024-05-20 10:34:44,163 INFO: Parser eventParser: app_link_id: [00]
2024-05-20 10:34:44,166 INFO: Parser eventParser: conn_handle: [05 00]
2024-05-20 10:34:44,167 INFO: Parser eventParser: role: [01]
2024-05-20 10:34:44,167 INFO: Parser eventParser: remote addr type: [00]
2024-05-20 10:34:44,168 INFO: Parser eventParser: remote addr: [01 23 15 DD AA DD]
2024-05-20 10:34:44,168 INFO: Parser eventParser: connInterval: [18 00]
2024-05-20 10:34:44,170 INFO: Parser eventParser: connLatency: [00 00]
2024-05-20 10:34:44,171 INFO: Parser eventParser: supTimeout: [F4 01]
2024-05-20 10:34:44,174 INFO: Packet sendPacket: <<<send packet: AA AE 05 00 00 00 43 80 00 8A
2024-05-20 10:34:44,189 INFO: AciHostCLI continuously_read: >>>receive packet: AA D8 05 00 41 80 00 F4 00 6E
2024-05-20 10:34:44,191 INFO: Parser eventParser: syncWord: AA,seqn: D8,len: 5,opcode: 8041,params: [00 F4 00], check_sum: 6E
2024-05-20 10:34:44,194 INFO: Parser eventParser: event name: EVENT_XM_LE_MTU
2024-05-20 10:34:44,196 INFO: Parser eventParser: mtu_size: [00 F4]
2024-05-20 10:34:44,200 INFO: Packet sendPacket: <<<send packet: AA AF 05 00 00 00 41 80 00 8B
2024-05-20 10:34:44,237 INFO: AciHostCLI continuously_read: >>>receive packet: AA D9 0B 00 06 01 00 FB 00 28 04 FB 00 28 04 C7
2024-05-20 10:34:44,238 INFO: Parser eventParser: syncWord: AA,seqn: D9,len: 11,opcode: 0106,params: [00 FB 00 28 04 FB 00 28 04], check_sum: C7
2024-05-20 10:34:44,244 INFO: Parser eventParser: event name: EVENT_LE_SET_DATA_LEN
2024-05-20 10:34:44,245 INFO: Parser eventParser: app_link_id: [00]
2024-05-20 10:34:44,246 INFO: Parser eventParser: max_tx_octets: [FB 00]
2024-05-20 10:34:44,246 INFO: Parser eventParser: max_tx_time: [28 04]
2024-05-20 10:34:44,247 INFO: Parser eventParser: max_rx_octets: [FB 00]
2024-05-20 10:34:44,248 INFO: Parser eventParser: max_rx_time: [28 04]
2024-05-20 10:34:44,249 INFO: Packet sendPacket: <<<send packet: AA B0 05 00 00 00 06 01 00 44
2024-05-20 10:34:44,540 INFO: AciHostCLI continuously_read: >>>receive packet: AA DA 0A 00 44 80 00 00 18 00 0F 00 F4 01 3C
2024-05-20 10:34:44,541 INFO: Parser eventParser: syncWord: AA,seqn: DA,len: 10,opcode: 8044,params: [00 00 18 00 0F 00 F4 01], check_sum: 3C
2024-05-20 10:34:44,543 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM
2024-05-20 10:34:44,548 INFO: Parser eventParser: app_link_id: [00]
2024-05-20 10:34:44,549 INFO: Parser eventParser: res: [00]
2024-05-20 10:34:44,550 INFO: Parser eventParser: connInterval: [18 00]
2024-05-20 10:34:44,550 INFO: Parser eventParser: connLatency: [0F 00]
2024-05-20 10:34:44,551 INFO: Parser eventParser: supTimeout: [F4 01]
2024-05-20 10:34:44,552 INFO: Packet sendPacket: <<<send packet: AA B1 05 00 00 00 44 80 00 86
2024-05-20 10:34:45,690 INFO: AciHostCLI continuously_read: >>>receive packet: AA DB 0B 00 02 01 00 00 00 01 23 15 DD AA DD 7A
2024-05-20 10:34:45,691 INFO: Parser eventParser: syncWord: AA,seqn: DB,len: 11,opcode: 0102,params: [00 00 00 01 23 15 DD AA DD], check_sum: 7A
2024-05-20 10:34:45,693 INFO: Parser eventParser: event name: APP_EVENT_LE_PAIR_STATUS
2024-05-20 10:34:45,696 INFO: Parser eventParser: link_id: [00]
2024-05-20 10:34:45,697 INFO: Parser eventParser: cause: [00 00]
2024-05-20 10:34:45,698 INFO: Parser eventParser: resolved_addr: [01 23 15 DD AA DD]
2024-05-20 10:34:45,698 INFO: Packet sendPacket: <<<send packet: AA B2 05 00 00 00 02 01 00 46
2024-05-20 10:34:46,473 INFO: AciHostCLI continuously_read: >>>receive packet: AA DC 0A 00 44 80 00 00 06 00 00 00 F4 01 5B
2024-05-20 10:34:46,475 INFO: Parser eventParser: syncWord: AA,seqn: DC,len: 10,opcode: 8044,params: [00 00 06 00 00 00 F4 01], check_sum: 5B
2024-05-20 10:34:46,476 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM
2024-05-20 10:34:46,480 INFO: Parser eventParser: app_link_id: [00]
2024-05-20 10:34:46,481 INFO: Parser eventParser: res: [00]
2024-05-20 10:34:46,482 INFO: Parser eventParser: connInterval: [06 00]
2024-05-20 10:34:46,484 INFO: Parser eventParser: connLatency: [00 00]
2024-05-20 10:34:46,484 INFO: Parser eventParser: supTimeout: [F4 01]
2024-05-20 10:34:46,485 INFO: Packet sendPacket: <<<send packet: AA B3 05 00 00 00 44 80 00 84
2024-05-20 10:34:46,888 INFO: AciHostCLI continuously_read: >>>receive packet: AA DD 04 00 10 01 00 00 0E
2024-05-20 10:34:46,889 INFO: Parser eventParser: syncWord: AA,seqn: DD,len: 4,opcode: 0110,params: [00 00], check_sum: 0E
2024-05-20 10:34:46,891 INFO: Parser eventParser: event name: EVENT_ANCS_REGISTER_COMPLETE
2024-05-20 10:34:46,895 INFO: Parser eventParser: app_link_id: [00]
2024-05-20 10:34:46,895 INFO: Parser eventParser: result: [00]
2024-05-20 10:34:46,896 INFO: Packet sendPacket: <<<send packet: AA B4 05 00 00 00 10 01 00 36
2024-05-20 10:34:47,000 INFO: AciHostCLI continuously_read: >>>receive packet: AA DE 0A 00 44 80 00 00 18 00 00 00 F4 01 47
2024-05-20 10:34:47,001 INFO: Parser eventParser: syncWord: AA,seqn: DE,len: 10,opcode: 8044,params: [00 00 18 00 00 00 F4 01], check_sum: 47
2024-05-20 10:34:47,002 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM
2024-05-20 10:34:47,006 INFO: Parser eventParser: app_link_id: [00]
2024-05-20 10:34:47,006 INFO: Parser eventParser: res: [00]
2024-05-20 10:34:47,007 INFO: Parser eventParser: connInterval: [18 00]
2024-05-20 10:34:47,007 INFO: Parser eventParser: connLatency: [00 00]
2024-05-20 10:34:47,009 INFO: Parser eventParser: supTimeout: [F4 01]
2024-05-20 10:34:47,010 INFO: Packet sendPacket: <<<send packet: AA B5 05 00 00 00 44 80 00 82
ACI Host CLI Test: Operate White List
Using the white list, the ACI Device can only receive broadcasts from devices in the white list, or only establish connections with devices in the white list. The CMD_LE_MODIFY_WHITELIST
command allows adding or removing specific devices to and from the white list, and to clear the white list. The CMD_LE_MODIFY_WHITELIST_BY_IDX
command allows adding the device with the specified index in the bond list to the white list, or removing it from the white list.
Note
These commands shall not be used when: Any advertising filter policy uses the white list and advertising is enabled, the scanning filter policy uses the white list and scanning is enabled, or the initiator filter policy uses the white list and an HCI_LE_Create_Connection
or HCI_LE_Extended_Create_Connection
command is outstanding.
2024-05-20 10:37:01,539 INFO: input command: whitelist_id add_idx0
2024-05-20 10:37:01,539 INFO: Parser cmdParser: cmd opcode: 0162 param: [01 00] name: CMD_LE_MODIFY_WIHITLIST_BY_IDX
2024-05-20 10:37:01,540 INFO: Packet sendPacket: <<<send packet: AA 01 04 00 62 01 01 00 97
2024-05-20 10:37:01,561 INFO: AciHostCLI continuously_read: >>>receive packet: AA E6 05 00 00 00 62 01 00 B2
2024-05-20 10:37:01,563 INFO: Parser eventParser: syncWord: AA,seqn: E6,len: 5,opcode: 0000,params: [62 01 00], check_sum: B2
2024-05-20 10:37:01,564 INFO: Parser eventParser: event name: APP_EVENT_ACK
2024-05-20 10:37:01,564 INFO: Parser eventParser: event_id: [62 01]
2024-05-20 10:37:01,565 INFO: Parser eventParser: status: [00]
2024-05-20 10:37:09,630 INFO: input command: whitelist_id rmv_idx0
2024-05-20 10:37:09,631 INFO: Parser cmdParser: cmd opcode: 0162 param: [02 00] name: CMD_LE_MODIFY_WIHITLIST_BY_IDX
2024-05-20 10:37:09,632 INFO: Packet sendPacket: <<<send packet: AA 02 04 00 62 01 02 00 95
2024-05-20 10:37:09,711 WARNING: AciHostCLI retrans: retransmit command whitelist_id rmv_idx0 due to ack timeout! retry: 1
2024-05-20 10:37:09,712 INFO: Packet sendPacket: <<<send packet: AA 02 04 00 62 01 02 00 95
2024-05-20 10:37:09,723 INFO: AciHostCLI continuously_read: >>>receive packet: AA E7 05 00 00 00 62 01 00 B1
2024-05-20 10:37:09,724 INFO: Parser eventParser: syncWord: AA,seqn: E7,len: 5,opcode: 0000,params: [62 01 00], check_sum: B1
2024-05-20 10:37:09,725 INFO: Parser eventParser: event name: APP_EVENT_ACK
2024-05-20 10:37:09,725 INFO: Parser eventParser: event_id: [62 01]
2024-05-20 10:37:09,726 INFO: Parser eventParser: status: [00]
ACI Host CLI Test: Operate Resolving List
Similar to the white list, if the device needs to use the link layer privacy mechanism, a resolving list needs to be stored on the Controller. Using CMD_LE_MODIFY_RESOLVELIST_BY_IDX
, device with specified indexe in the bond list can be added to or removed from the resolving list, and the entire resolving list can be cleared.
To enable/disable resolution of resolvable private addresses in the Controller, please use the command CMD_LE_SET_RESOLUTION
.
Note
These commands shall not be used when:
Advertising (other than periodic advertising) is enabled.
Scanning is enabled.
HCI_LE_Create_Connection
,HCI_LE_Extended_Create_Connection
, orHCI_LE_Periodic_Advertising_Create_Sync
command is outstanding.
2024-05-20 14:02:09,954 INFO: input command: resolvlist_id add_idx0
2024-05-20 14:02:09,955 INFO: Parser cmdParser: cmd opcode: 0163 param: [01 00] name: CMD_LE_MODIFY_RESOLVELIST_BY_IDX
2024-05-20 14:02:09,956 INFO: Packet sendPacket: <<<send packet: AA 01 04 00 63 01 01 00 96
2024-05-20 14:02:10,028 WARNING: AciHostCLI retrans: retransmit command resolvlist_id add_idx0 due to ack timeout! retry: 1
2024-05-20 14:02:10,029 INFO: Packet sendPacket: <<<send packet: AA 01 04 00 63 01 01 00 96
2024-05-20 14:02:10,042 INFO: AciHostCLI continuously_read: >>>receive packet: AA EC 05 00 00 00 63 01 00 AB
2024-05-20 14:02:10,043 INFO: Parser eventParser: syncWord: AA,seqn: EC,len: 5,opcode: 0000,params: [63 01 00], check_sum: AB
2024-05-20 14:02:10,043 INFO: Parser eventParser: event name: APP_EVENT_ACK
2024-05-20 14:02:10,044 INFO: Parser eventParser: event_id: [63 01]
2024-05-20 14:02:10,044 INFO: Parser eventParser: status: [00]
2024-05-20 14:02:18,897 INFO: input command: le_resolution enable
2024-05-20 14:02:18,897 INFO: Parser cmdParser: cmd opcode: 0164 param: [01] name: CMD_LE_SET_RESOLUTION
2024-05-20 14:02:18,898 INFO: Packet sendPacket: <<<send packet: AA 02 03 00 64 01 01 95
2024-05-20 14:02:18,973 WARNING: AciHostCLI retrans: retransmit command le_resolution enable due to ack timeout! retry: 1
2024-05-20 14:02:18,974 INFO: Packet sendPacket: <<<send packet: AA 02 03 00 64 01 01 95
2024-05-20 14:02:18,987 INFO: AciHostCLI continuously_read: >>>receive packet: AA ED 05 00 00 00 64 01 00 A9
2024-05-20 14:02:18,987 INFO: Parser eventParser: syncWord: AA,seqn: ED,len: 5,opcode: 0000,params: [64 01 00], check_sum: A9
2024-05-20 14:02:18,988 INFO: Parser eventParser: event name: APP_EVENT_ACK
2024-05-20 14:02:18,988 INFO: Parser eventParser: event_id: [64 01]
2024-05-20 14:02:18,989 INFO: Parser eventParser: status: [00]
2024-05-20 14:02:22,360 INFO: input command: le_resolution disable
2024-05-20 14:02:22,361 INFO: Parser cmdParser: cmd opcode: 0164 param: [00] name: CMD_LE_SET_RESOLUTION
2024-05-20 14:02:22,362 INFO: Packet sendPacket: <<<send packet: AA 03 03 00 64 01 00 95
2024-05-20 14:02:22,433 WARNING: AciHostCLI retrans: retransmit command le_resolution disable due to ack timeout! retry: 1
2024-05-20 14:02:22,434 INFO: Packet sendPacket: <<<send packet: AA 03 03 00 64 01 00 95
2024-05-20 14:02:22,453 INFO: AciHostCLI continuously_read: >>>receive packet: AA EE 05 00 00 00 64 01 00 A8
2024-05-20 14:02:22,454 INFO: Parser eventParser: syncWord: AA,seqn: EE,len: 5,opcode: 0000,params: [64 01 00], check_sum: A8
2024-05-20 14:02:22,454 INFO: Parser eventParser: event name: APP_EVENT_ACK
2024-05-20 14:02:22,455 INFO: Parser eventParser: event_id: [64 01]
2024-05-20 14:02:22,455 INFO: Parser eventParser: status: [00]
2024-05-20 14:02:30,731 INFO: input command: resolvlist_id rmv_idx0
2024-05-20 14:02:30,732 INFO: Parser cmdParser: cmd opcode: 0163 param: [02 00] name: CMD_LE_MODIFY_RESOLVELIST_BY_IDX
2024-05-20 14:02:30,733 INFO: Packet sendPacket: <<<send packet: AA 04 04 00 63 01 02 00 92
2024-05-20 14:02:30,806 WARNING: AciHostCLI retrans: retransmit command resolvlist_id rmv_idx0 due to ack timeout! retry: 1
2024-05-20 14:02:30,807 INFO: Packet sendPacket: <<<send packet: AA 04 04 00 63 01 02 00 92
2024-05-20 14:02:30,824 INFO: AciHostCLI continuously_read: >>>receive packet: AA EF 05 00 00 00 63 01 00 A8
2024-05-20 14:02:30,824 INFO: Parser eventParser: syncWord: AA,seqn: EF,len: 5,opcode: 0000,params: [63 01 00], check_sum: A8
2024-05-20 14:02:30,825 INFO: Parser eventParser: event name: APP_EVENT_ACK
2024-05-20 14:02:30,825 INFO: Parser eventParser: event_id: [63 01]
2024-05-20 14:02:30,825 INFO: Parser eventParser: status: [00]
Record Function
Bluetooth Audio Transceiver application supports the recording of many audio formats such as PCM, mSBC, SBC, and OPUS. Before using, please configure MIC 1 on the EVB and connect an external MIC.
Record process:
ACI Host CLI Test
The ACI Host CLI CMD for recording are rc start
and rc stop
, and the corresponding UART CMD packet.
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_XM_START_RECORD = 0x8082 |
type = AUDIO_FORMAT_TYPE_PCM(0), sample_rate = 0x00003E80, frame_len = 0x0400, chann_num 1, bit_width = 0x10 |
rc start_pcm |
CMD_XM_STOP_RECORD = 0x8503 |
None |
rc stop |
ACI Host CLI test: Start recording PCM.
An example of recording PCM is provided here. Please refer to ACI_CMD_XM_START_RECORD for recording more formats.
2023-04-03 17:12:12,558 INFO: input command: rc start_pcm 2023-04-03 17:12:12,559 INFO: Parser cmdParser: cmd opcode: 8082 param: [00 80 3E 00 00 00 04 01 10] name: CMD_XM_START_RECORD 2023-04-03 17:12:12,560 INFO: Packet sendPacket: <<<send packet: AA 01 0B 00 02 85 00 80 3E 00 00 00 04 01 10 9A 2023-04-03 17:12:12,572 INFO: AciHostCLI continuously_read: >>>receive packet: AA 03 05 00 00 00 02 85 00 71 2023-04-03 17:12:12,577 INFO: Parser eventParser: syncWord: AA,seqn: 03,len: 5,opcode: 0000,params: [02 85 00], check_sum: 71 2023-04-03 17:12:12,578 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-03 17:12:12,579 INFO: Parser eventParser: event_id: [02 85] 2023-04-03 17:12:12,579 INFO: Parser eventParser: status: [00] 2023-04-03 17:12:12,849 INFO: AciHostCLI continuously_read: >>>receive packet: AA 04 02 04 02 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2023-04-03 17:12:12,850 INFO: Parser eventParser: syncWord: AA,seqn: 04,len: 1026,opcode: 8082,params: [00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00], check_sum: B1 2023-04-03 17:12:12,850 INFO: Parser eventParser: event name: EVENT_XM_RECORDING_DATA 2023-04-03 17:12:12,878 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 02 04 02 85 FD FF F8 FF F2 FF F3 FF F5 FF F2 FF F2 FF F3 FF EE FF ED FF FE FF 08 00 01 00 2023-04-03 17:12:12,879 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 1026,opcode: 8082,params: [FD FF F8 FF F2 FF F3 FF F5 FF F2 FF F2 FF F3 FF EE FF ED FF FE FF 08 00 01 00 06 00 1B 00 27 00], check_sum: 9E 2023-04-03 17:12:12,880 INFO: Parser eventParser: event name: EVENT_XM_RECORDING_DATA
ACI Host CLI test: Stop recording.
2023-04-03 17:12:12,558 INFO: input command: rc stop 2023-04-03 17:14:52,717 INFO: Parser cmdParser: cmd opcode: 8503 param: [] name: CMD_XM_STOP_RECORD 2023-04-03 17:14:52,718 INFO: Packet sendPacket: <<<send packet: AA 02 02 00 03 85 74 2023-04-03 17:14:52,725 INFO: AciHostCLI continuously_read: >>>receive packet: AA BF 05 00 00 00 03 85 00 B4 2023-04-03 17:14:52,730 INFO: Parser eventParser: syncWord: AA,seqn: BF,len: 5,opcode: 0000,params: [03 85 00], check_sum: B4 2023-04-03 17:14:52,731 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-03 17:14:52,732 INFO: Parser eventParser: event_id: [03 85] 2023-04-03 17:14:52,733 INFO: Parser eventParser: status: [00]
LE Audio Function
The current version of Bluetooth Audio Transceiver application includes support for LE Audio functionality. LE Audio typically utilizes BIS or CIS to transmit audio data. In the present version, BIS has been implemented. Please note that the LE Audio module only offers protocol and data pathway. Users need to supply data to the LE Audio module by either the transparent transmission module A2DP Transparent Transmission (BIS Output) or the recording module, enabling the transmission of ISO audio data to external devices.
LE Audio Initiator
Initiator, which is described in CAP SPEC, always operates in CAP Unicast Client role, BAP Broadcast Source role, BAP Scan Assistant role, or CCP Call Control Server role.
Initiator General ACI Host CLI Test
For CIS, it is necessary to establish an LE link, whereas for BIS, it is not mandatory. This chapter delineates the process of establishing an LE link with devices supporting LE Audio Acceptor.
To scan nearby devices supporting LE Audio, ACI Host sends the CMD_LEA_SCAN
to enable the scan procedure.
The current scan results can be displayed by entering the le conn_idx
command. If the device
expected to be connected is a stereo headset, directly input the serial number of the headset
to establish the connection and complete the pairing. If the device to be connected is a pair of
RWS BUDS, input the serial number of either the left or right BUD, and Bluetooth Audio Transceiver application will establish connections for both BUDS simultaneously. Upon completion of the LE Audio-related
service discovery, Bluetooth Audio Transceiver application will report the EVENT_LE_AUDIO_BAP_DISCOVERY_DONE
event.
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_LEA_SCAN(0x3023) |
action = start(0x00) |
lea_scan start |
CMD_LEA_SCAN(0x3023) |
action = stop(0x01) |
lea_scan stop |
LE Audio connection process:
ACI Host CLI test: Start scanning LE Audio devices.
2023-07-17 15:59:35,770 INFO: input command: lea_scan start 2023-07-17 15:59:35,771 INFO: Parser cmdParser: cmd opcode: 3023 param: [00] name: CMD_LEA_SCAN 2023-07-17 15:59:35,771 INFO: Packet sendPacket: <<<send packet: AA 04 03 00 23 30 00 A6 2023-07-17 15:59:35,779 INFO: AciHostCLI continuously_read: >>>receive packet: AA 04 05 00 00 00 23 30 00 A4 2023-07-17 15:59:35,783 INFO: Parser eventParser: syncWord: AA,seqn: 04,len: 5,opcode: 0000,params: [23 30 00], check_sum: A4 2023-07-17 15:59:35,784 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-17 15:59:35,784 INFO: Parser eventParser: event_id: [23 30] 2023-07-17 15:59:35,786 INFO: Parser eventParser: status: [00] 2023-07-17 15:59:39,470 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 34 00 0B 01 01 00 01 61 6C 0D 97 48 E0 12 38 37 36 33 45 46 4C 5F 35 76 5F 52 28 6D 73 62 2023-07-17 15:59:39,470 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 52,opcode: 010B,params: [01 00 01 61 6C 0D 97 48 E0 12 38 37 36 33 45 46 4C 5F 35 76 5F 52 28 6D 73 62 63 29 00 00 00 00], check_sum: AE 2023-07-17 15:59:39,471 INFO: Parser eventParser: event name: APP_EVENT_LE_AUDIO_SCAN_INFO 2023-07-17 15:59:39,471 INFO: Parser eventParser: event_type: [01 00] 2023-07-17 15:59:39,472 INFO: Parser eventParser: addr_type: [01] 2023-07-17 15:59:39,472 INFO: Parser eventParser: addr: [61 6C 0D 97 48 E0] 2023-07-17 15:59:39,472 INFO: Parser eventParser: name_len: [12] 2023-07-17 15:59:39,473 INFO: Parser eventParser: name: [38 37 36 33 45 46 4C 5F 35 76 5F 52 28 6D 73 62 63 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00] 2023-07-17 15:59:39,473 INFO: Parser eventParser: name: 8763EFL_5v_R(msbc) 2023-07-17 15:59:39,474 INFO: Packet sendPacket: <<<send packet: AA 05 05 00 00 00 0B 01 00 EA 2023-07-17 15:59:39,709 INFO: AciHostCLI continuously_read: >>>receive packet: AA 06 34 00 0B 01 01 00 01 A0 DE 13 53 C0 F1 12 38 37 36 33 45 46 4C 5F 35 76 5F 4C 28 6D 73 62 2023-07-17 15:59:39,710 INFO: Parser eventParser: syncWord: AA,seqn: 06,len: 52,opcode: 010B,params: [01 00 01 A0 DE 13 53 C0 F1 12 38 37 36 33 45 46 4C 5F 35 76 5F 4C 28 6D 73 62 63 29 00 00 00 00], check_sum: B7 2023-07-17 15:59:39,711 INFO: Parser eventParser: event name: APP_EVENT_LE_AUDIO_SCAN_INFO 2023-07-17 15:59:39,711 INFO: Parser eventParser: event_type: [01 00] 2023-07-17 15:59:39,712 INFO: Parser eventParser: addr_type: [01] 2023-07-17 15:59:39,712 INFO: Parser eventParser: addr: [A0 DE 13 53 C0 F1] 2023-07-17 15:59:39,713 INFO: Parser eventParser: name_len: [12] 2023-07-17 15:59:39,713 INFO: Parser eventParser: name: [38 37 36 33 45 46 4C 5F 35 76 5F 4C 28 6D 73 62 63 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00] 2023-07-17 15:59:39,714 INFO: Parser eventParser: name: 8763EFL_5v_L(msbc) 2023-07-17 15:59:39,714 INFO: Packet sendPacket: <<<send packet: AA 06 05 00 00 00 0B 01 00 E9
ACI Host CLI test: Stop scanning and showing results.
2023-07-17 15:59:49,718 INFO: input command: lea_scan stop 2023-07-17 15:59:49,719 INFO: Parser cmdParser: cmd opcode: 3023 param: [01] name: CMD_LEA_SCAN 2023-07-17 15:59:49,719 INFO: Packet sendPacket: <<<send packet: AA 07 03 00 23 30 01 A2 2023-07-17 15:59:49,726 INFO: AciHostCLI continuously_read: >>>receive packet: AA 07 05 00 00 00 23 30 00 A1 2023-07-17 15:59:49,727 INFO: Parser eventParser: syncWord: AA,seqn: 07,len: 5,opcode: 0000,params: [23 30 00], check_sum: A1 2023-07-17 15:59:49,730 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-17 15:59:49,731 INFO: Parser eventParser: event_id: [23 30] 2023-07-17 15:59:49,732 INFO: Parser eventParser: status: [00] 2023-07-17 15:59:52,770 INFO: input command: le conn_idx 2023-07-17 15:59:52,770 INFO: Parser cmdParser: device index: 0 addr_type 1 bd_addr: 61 6C 0D 97 48 E0 , name: 8763EFL_5v_R(msbc) 2023-07-17 15:59:52,771 INFO: Parser cmdParser: device index: 1 addr_type 1 bd_addr: A0 DE 13 53 C0 F1 , name: 8763EFL_5v_L(msbc)
ACI Host CLI test: Input the device index to initiate the connection procedure.
2023-07-17 15:59:58,755 INFO: Parser cmdParser: input dev_index: 0 2023-07-17 15:59:58,756 INFO: Parser cmdParser: cmd opcode: 010E param: [03 01 61 6C 0D 97 48 E0 00 E8 03] name: CMD_LE_CREATE_CONN 2023-07-17 15:59:58,756 INFO: Packet sendPacket: <<<send packet: AA 08 0D 00 0E 01 03 01 61 6C 0D 97 48 E0 00 E8 03 54 2023-07-17 15:59:58,774 INFO: AciHostCLI continuously_read: >>>receive packet: AA 08 05 00 00 00 0E 01 00 E4 2023-07-17 15:59:58,775 INFO: Parser eventParser: syncWord: AA,seqn: 08,len: 5,opcode: 0000,params: [0E 01 00], check_sum: E4 2023-07-17 15:59:58,776 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-17 15:59:58,779 INFO: Parser eventParser: event_id: [0E 01] 2023-07-17 15:59:58,780 INFO: Parser eventParser: status: [00] 2023-07-17 15:59:58,798 INFO: AciHostCLI continuously_read: >>>receive packet: AA 09 05 00 07 01 00 02 02 E6 2023-07-17 15:59:58,799 INFO: Parser eventParser: syncWord: AA,seqn: 09,len: 5,opcode: 0107,params: [00 02 02], check_sum: E6 2023-07-17 15:59:58,799 INFO: Parser eventParser: event name: EVENT_LE_PHY_UPD 2023-07-17 15:59:58,800 INFO: Parser eventParser: app_link_id: [00] 2023-07-17 15:59:58,800 INFO: Parser eventParser: tx_phy: [02] 2023-07-17 15:59:58,801 INFO: Parser eventParser: rx_phy: [02] 2023-07-17 15:59:58,801 INFO: Packet sendPacket: <<<send packet: AA 09 05 00 00 00 07 01 00 EA 2023-07-17 15:59:58,814 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0A 03 00 00 01 00 F2 2023-07-17 15:59:58,814 INFO: Parser eventParser: syncWord: AA,seqn: 0A,len: 3,opcode: 0100,params: [00], check_sum: F2 2023-07-17 15:59:58,815 INFO: Parser eventParser: event name: APP_EVENT_LE_CONNECTED 2023-07-17 15:59:58,815 INFO: Parser eventParser: link_id: [00] 2023-07-17 15:59:58,816 INFO: Packet sendPacket: <<<send packet: AA 0A 05 00 00 00 00 01 00 F0 2023-07-17 15:59:58,830 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0B 14 00 43 80 02 00 05 00 01 01 61 6C 0D 97 48 E0 20 00 00 00 E8 03 71 2023-07-17 15:59:58,831 INFO: Parser eventParser: syncWord: AA,seqn: 0B,len: 20,opcode: 8043,params: [02 00 05 00 01 01 61 6C 0D 97 48 E0 20 00 00 00 E8 03], check_sum: 71 2023-07-17 15:59:58,831 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_STATE 2023-07-17 15:59:58,832 INFO: Parser eventParser: link_state: [02] 2023-07-17 15:59:58,832 INFO: Parser eventParser: app_link_id: [00] 2023-07-17 15:59:58,833 INFO: Parser eventParser: conn_handle: [05 00] 2023-07-17 15:59:58,833 INFO: Parser eventParser: role: [01] 2023-07-17 15:59:58,834 INFO: Parser eventParser: remote addr type: [01] 2023-07-17 15:59:58,834 INFO: Parser eventParser: remote addr: [61 6C 0D 97 48 E0] 2023-07-17 15:59:58,834 INFO: Parser eventParser: connInterval: [20 00] 2023-07-17 15:59:58,835 INFO: Parser eventParser: connLatency: [00 00] 2023-07-17 15:59:58,835 INFO: Parser eventParser: supTimeout: [E8 03] 2023-07-17 15:59:58,835 INFO: Packet sendPacket: <<<send packet: AA 0B 05 00 00 00 43 80 00 2D 2023-07-17 15:59:58,845 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0C 05 00 41 80 00 F4 00 3A 2023-07-17 15:59:58,846 INFO: Parser eventParser: syncWord: AA,seqn: 0C,len: 5,opcode: 8041,params: [00 F4 00], check_sum: 3A 2023-07-17 15:59:58,847 INFO: Parser eventParser: event name: EVENT_XM_LE_MTU 2023-07-17 15:59:58,847 INFO: Parser eventParser: mtu_size: [00 F4] 2023-07-17 15:59:58,848 INFO: Packet sendPacket: <<<send packet: AA 0C 05 00 00 00 41 80 00 2E 2023-07-17 16:00:00,299 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0D 0B 00 02 01 00 00 00 00 00 00 00 00 00 E5 2023-07-17 16:00:00,300 INFO: Parser eventParser: syncWord: AA,seqn: 0D,len: 11,opcode: 0102,params: [00 00 00 00 00 00 00 00 00], check_sum: E5 2023-07-17 16:00:00,301 INFO: Parser eventParser: event name: APP_EVENT_LE_PAIR_STATUS 2023-07-17 16:00:00,301 INFO: Parser eventParser: link_id: [00] 2023-07-17 16:00:00,302 INFO: Parser eventParser: cause: [00 00] 2023-07-17 16:00:00,302 INFO: Parser eventParser: resolved_addr: [00 00 00 00 00 00] 2023-07-17 16:00:00,303 INFO: Packet sendPacket: <<<send packet: AA 0D 05 00 00 00 02 01 00 EB 2023-07-17 16:00:05,108 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0E 34 00 0B 01 01 00 01 A0 DE 13 53 C0 F1 12 38 37 36 33 45 46 4C 5F 35 76 5F 4C 28 6D 73 62 2023-07-17 16:00:05,108 INFO: Parser eventParser: syncWord: AA,seqn: 0E,len: 52,opcode: 010B,params: [01 00 01 A0 DE 13 53 C0 F1 12 38 37 36 33 45 46 4C 5F 35 76 5F 4C 28 6D 73 62 63 29 00 00 00 00], check_sum: AF 2023-07-17 16:00:05,109 INFO: Parser eventParser: event name: APP_EVENT_LE_AUDIO_SCAN_INFO 2023-07-17 16:00:05,109 INFO: Parser eventParser: event_type: [01 00] 2023-07-17 16:00:05,110 INFO: Parser eventParser: addr_type: [01] 2023-07-17 16:00:05,110 INFO: Parser eventParser: addr: [A0 DE 13 53 C0 F1] 2023-07-17 16:00:05,111 INFO: Parser eventParser: name_len: [12] 2023-07-17 16:00:05,112 INFO: Parser eventParser: name: [38 37 36 33 45 46 4C 5F 35 76 5F 4C 28 6D 73 62 63 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00] 2023-07-17 16:00:05,112 INFO: Parser eventParser: name: 8763EFL_5v_L(msbc) 2023-07-17 16:00:05,113 INFO: Packet sendPacket: <<<send packet: AA 0E 05 00 00 00 0B 01 00 E1 2023-07-17 16:00:05,155 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0F 05 00 07 01 01 02 02 DF 2023-07-17 16:00:05,156 INFO: Parser eventParser: syncWord: AA,seqn: 0F,len: 5,opcode: 0107,params: [01 02 02], check_sum: DF 2023-07-17 16:00:05,156 INFO: Parser eventParser: event name: EVENT_LE_PHY_UPD 2023-07-17 16:00:05,157 INFO: Parser eventParser: app_link_id: [01] 2023-07-17 16:00:05,157 INFO: Parser eventParser: tx_phy: [02] 2023-07-17 16:00:05,158 INFO: Parser eventParser: rx_phy: [02] 2023-07-17 16:00:05,158 INFO: Packet sendPacket: <<<send packet: AA 0F 05 00 00 00 07 01 00 E4 2023-07-17 16:00:05,171 INFO: AciHostCLI continuously_read: >>>receive packet: AA 10 03 00 00 01 01 EB 2023-07-17 16:00:05,172 INFO: Parser eventParser: syncWord: AA,seqn: 10,len: 3,opcode: 0100,params: [01], check_sum: EB 2023-07-17 16:00:05,173 INFO: Parser eventParser: event name: APP_EVENT_LE_CONNECTED 2023-07-17 16:00:05,173 INFO: Parser eventParser: link_id: [01] 2023-07-17 16:00:05,174 INFO: Packet sendPacket: <<<send packet: AA 10 05 00 00 00 00 01 00 EA 2023-07-17 16:00:05,187 INFO: AciHostCLI continuously_read: >>>receive packet: AA 11 14 00 43 80 02 01 06 00 01 01 A0 DE 13 53 C0 F1 64 00 00 00 F4 01 1F 2023-07-17 16:00:05,188 INFO: Parser eventParser: syncWord: AA,seqn: 11,len: 20,opcode: 8043,params: [02 01 06 00 01 01 A0 DE 13 53 C0 F1 64 00 00 00 F4 01], check_sum: 1F 2023-07-17 16:00:05,189 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_STATE 2023-07-17 16:00:05,189 INFO: Parser eventParser: link_state: [02] 2023-07-17 16:00:05,190 INFO: Parser eventParser: app_link_id: [01] 2023-07-17 16:00:05,190 INFO: Parser eventParser: conn_handle: [06 00] 2023-07-17 16:00:05,191 INFO: Parser eventParser: role: [01] 2023-07-17 16:00:05,191 INFO: Parser eventParser: remote addr type: [01] 2023-07-17 16:00:05,191 INFO: Parser eventParser: remote addr: [A0 DE 13 53 C0 F1] 2023-07-17 16:00:05,192 INFO: Parser eventParser: connInterval: [64 00] 2023-07-17 16:00:05,192 INFO: Parser eventParser: connLatency: [00 00] 2023-07-17 16:00:05,193 INFO: Parser eventParser: supTimeout: [F4 01] 2023-07-17 16:00:05,193 INFO: Packet sendPacket: <<<send packet: AA 11 05 00 00 00 43 80 00 27 2023-07-17 16:00:05,203 INFO: AciHostCLI continuously_read: >>>receive packet: AA 12 03 00 0D 01 00 DD 2023-07-17 16:00:05,204 INFO: Parser eventParser: syncWord: AA,seqn: 12,len: 3,opcode: 010D,params: [00], check_sum: DD 2023-07-17 16:00:05,204 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_DISCOVERY_DONE 2023-07-17 16:00:05,204 INFO: Parser eventParser: link_id: [00] 2023-07-17 16:00:05,205 INFO: Packet sendPacket: <<<send packet: AA 12 05 00 00 00 0D 01 00 DB 2023-07-17 16:00:05,331 INFO: AciHostCLI continuously_read: >>>receive packet: AA 13 05 00 41 80 01 F4 20 30 2023-07-17 16:00:05,332 INFO: Parser eventParser: syncWord: AA,seqn: 13,len: 5,opcode: 8041,params: [01 F4 00], check_sum: 32 2023-07-17 16:00:05,333 INFO: Parser eventParser: event name: EVENT_XM_LE_MTU 2023-07-17 16:00:05,333 INFO: Parser eventParser: mtu_size: [01 F4] 2023-07-17 16:00:05,334 INFO: Packet sendPacket: <<<send packet: AA 13 05 00 00 00 41 80 00 27 2023-07-17 16:00:07,584 INFO: AciHostCLI continuously_read: >>>receive packet: AA 14 0B 00 02 01 01 00 00 00 00 00 00 00 00 DD 2023-07-17 16:00:07,584 INFO: Parser eventParser: syncWord: AA,seqn: 14,len: 11,opcode: 0102,params: [01 00 00 00 00 00 00 00 00], check_sum: DD 2023-07-17 16:00:07,585 INFO: Parser eventParser: event name: APP_EVENT_LE_PAIR_STATUS 2023-07-17 16:00:07,586 INFO: Parser eventParser: link_id: [01] 2023-07-17 16:00:07,586 INFO: Parser eventParser: cause: [00 00] 2023-07-17 16:00:07,587 INFO: Parser eventParser: resolved_addr: [00 00 00 00 00 00] 2023-07-17 16:00:07,587 INFO: Packet sendPacket: <<<send packet: AA 14 05 00 00 00 02 01 00 E4 2023-07-17 16:00:22,950 INFO: AciHostCLI continuously_read: >>>receive packet: AA 15 03 00 0D 01 01 D9 2023-07-17 16:00:22,951 INFO: Parser eventParser: syncWord: AA,seqn: 15,len: 3,opcode: 010D,params: [01], check_sum: D9 2023-07-17 16:00:22,952 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_DISCOVERY_DONE 2023-07-17 16:00:22,952 INFO: Parser eventParser: link_id: [01] 2023-07-17 16:00:22,952 INFO: Packet sendPacket: <<<send packet: AA 15 05 00 00 00 0D 01 00 D8
BIS Initiator Introduction
BIS, which stands for Broadcast Isochronous Channel, is a communication channel utilized in the context of LE Audio. It is responsible for transmitting audio data wirelessly. BIS is designed to support high-quality audio streaming, allowing the transfer of synchronized audio content from a source device (as broadcast source role) to multiple recipient devices simultaneously.
BIS Initiator ACI Host CLI Test
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_LEA_BSRC_INIT(0x3020) |
codec type = CODEC_CFG_ITEM_48_4(48k) |
bsrcinit 48k_1bis |
CMD_LEA_BSRC_INIT(0x3020) |
codec type = CODEC_CFG_ITEM_16_2(16k) |
bsrcinit 16k_1bis |
CMD_LEA_BSRC_INIT(0x3020) |
codec type = CODEC_CFG_ITEM_48_4(48k) |
bsrcinit 48k_2bis |
CMD_LEA_BSRC_INIT(0x3020) |
codec type = CODEC_CFG_ITEM_16_2(16k) |
bsrcinit 16k_2bis |
CMD_LEA_BSRC_START(0x3221) |
None |
bsrcstart x |
CMD_LEA_BSRC_STOP(0x3022) |
release = true |
bsrcstop release |
CMD_LEA_BSRC_STOP(0x3022) |
release = false |
bsrcstop hold |
The ACI Host CLI CMD for BIS are CMD_LEA_BSRC_INIT
, CMD_LEA_BSRC_START
, and CMD_LEA_BSRC_STOP
.
CMD_LEA_BSRC_INIT
is used to initialize the parameters related to BIS, including codec type, BIS
number, encryption mode, ULL mode (Ultra Low Latency mode), and PD (Presentation Delay). The PD
parameter is only effective when ULL mode is enabled. When ULL mode is activated, the following
parameters are specifically used when creating BIG: Packing = Interleaved
, Max Transport Latency = 10 ms
, RTN = 2. Additionally
, the DSP would periodically fetch the anchor point to capture data
at more precise time intervals, aiming for lower and more stable latency. CMD_LEA_BSRC_START
is used
to activate BIS, while CMD_LEA_BSRC_STOP
is used to stop BIS.
ACI Host CLI test: Initialize BIS.
2023-05-31 10:25:21,803 INFO: input command: bsrcinit 48k_2bis 2023-05-31 10:25:21,803 INFO: Parser cmdParser: cmd opcode: 3020 param: [0D 02 00 01 10 27] name: CMD_LEA_BSRC_INIT 2023-05-31 10:25:21,803 INFO: Packet sendPacket: <<<send packet: AA 0C 07 00 20 30 0D 02 00 01 10 27 11 2023-05-31 10:25:21,834 INFO: AciHostCLI continuously_read: >>>receive packet: AA 03 05 00 00 00 20 30 00 C6 2023-05-31 10:25:21,834 INFO: Parser eventParser: syncWord: AA,seqn: 03,len: 5,opcode: 0000,params: [20 30 00], check_sum: C6 2023-05-31 10:25:21,834 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-31 10:25:21,834 INFO: Parser eventParser: event_id: [20 30] 2023-05-31 10:25:21,834 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Start BIS.
2023-05-31 10:25:36,368 INFO: input command: bsrcstart x 2023-05-31 10:25:36,368 INFO: Parser cmdParser: cmd opcode: 3021 param: [] name: CMD_LEA_BSRC_START 2023-05-31 10:25:36,368 INFO: Packet sendPacket: <<<send packet: AA 0D 02 00 21 30 BE 2023-05-31 10:25:36,388 INFO: AciHostCLI continuously_read: >>>receive packet: AA 04 05 00 00 00 21 30 00 C4 2023-05-31 10:25:36,388 INFO: Parser eventParser: syncWord: AA,seqn: 04,len: 5,opcode: 0000,params: [21 30 00], check_sum: C4 2023-05-31 10:25:36,388 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-31 10:25:36,388 INFO: Parser eventParser: event_id: [21 30] 2023-05-31 10:25:36,388 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Stop BIS.
2023-05-31 10:25:50,472 INFO: input command: bsrcstop release 2023-05-31 10:25:50,472 INFO: Parser cmdParser: cmd opcode: 3022 param: [01] name: CMD_LEA_BSRC_STOP 2023-05-31 10:25:50,472 INFO: Packet sendPacket: <<<send packet: AA 0E 03 00 22 30 01 BA 2023-05-31 10:25:50,512 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 05 00 00 00 22 30 00 C2 2023-05-31 10:25:50,512 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 5,opcode: 0000,params: [22 30 00], check_sum: C2 2023-05-31 10:25:50,522 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-31 10:25:50,522 INFO: Parser eventParser: event_id: [22 30] 2023-05-31 10:25:50,522 INFO: Parser eventParser: status: [00]
CIS Initiator Introduction
CIS, which stands for Connected Isochronous Stream, is an audio stream utilized in the context of LE Audio. Unlike BIS, an ACL link must always be present during the life of a CIS.
CIS Initiator ACI Host CLI Test
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_LEA_SCAN = 0x3023 |
type = APP_LEA_SCAN_START(0) |
lea_scan start |
CMD_LEA_SCAN(0x3023) |
type = APP_LEA_SCAN_STOP(1) |
lea_scan stop |
CMD_LEA_CIS_START_MEDIA(0x3024) |
group_idx = 0 |
cis_media start_group_idx_0 |
CMD_LEA_CIS_START_MEDIA(0x3024) |
group_idx = 1 |
cis_media start_group_idx_1 |
CMD_LEA_CIS_START_CONVERSATION(0x3031) |
group_idx = 0 |
cis_conversation start_group_idx_0 |
CMD_LEA_CIS_START_CONVERSATION(0x3031) |
group_idx = 1 |
cis_conversation start_group_idx_1 |
CMD_LEA_CIS_STOP_STREAM(0x3025) |
group_idx = 0, release = false |
cis_stream stop_group_idx_0 |
CMD_LEA_CIS_STOP_STREAM(0x3025) |
group_idx = 0, release = true |
cis_stream release_group_idx_0 |
CMD_LEA_CIS_STOP_STREAM(0x3025) |
group_idx = 1, release = false |
cis_stream stop_group_idx_1 |
CMD_LEA_CIS_STOP_STREAM(0x3025) |
group_idx = 1, release = true |
cis_stream release_group_idx_1 |
For CIS, it is necessary to establish an LE link. Please refer to Initiator General ACI Host CLI Test for connection procedure.
ACI Host CLI test: Start media stream.
2023-12-08 16:23:42,137 INFO: input command: cis_media start_group_idx_0 2023-12-08 16:23:42,137 INFO: Parser cmdParser: cmd opcode: 3024 param: [00] name: CMD_LEA_CIS_START_MEDIA 2023-12-08 16:23:42,137 INFO: Packet sendPacket: <<<send packet: AA 13 03 00 24 30 00 96 2023-12-08 16:23:42,213 WARNING: AciHostCLI retrans: retransmit command cis_media start_group_idx_0 due to ack timeout! retry: 1 2023-12-08 16:23:42,213 INFO: Packet sendPacket: <<<send packet: AA 13 03 00 24 30 00 96 2023-12-08 16:23:42,233 INFO: AciHostCLI continuously_read: >>>receive packet: AA 14 05 00 00 00 24 30 00 93 2023-12-08 16:23:42,233 INFO: Parser eventParser: syncWord: AA,seqn: 14,len: 5,opcode: 0000,params: [24 30 00], check_sum: 93 2023-12-08 16:23:42,233 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-12-08 16:23:42,233 INFO: Parser eventParser: event_id: [24 30] 2023-12-08 16:23:42,233 INFO: Parser eventParser: status: [00] 2023-12-08 16:23:42,233 INFO: AciHostCLI continuously_read: >>>receive packet: AA 15 07 00 41 01 D0 E7 2C 00 01 BE 2023-12-08 16:23:42,233 INFO: Parser eventParser: syncWord: AA,seqn: 15,len: 7,opcode: 0141,params: [D0 E7 2C 00 01], check_sum: BE 2023-12-08 16:23:42,237 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-12-08 16:23:42,237 INFO: Parser eventParser: group_handle: [D0 E7 2C 00] 2023-12-08 16:23:42,237 INFO: Parser eventParser: state: [01] 2023-12-08 16:23:42,237 INFO: Packet sendPacket: <<<send packet: AA 14 05 00 00 00 41 01 00 A5 2023-12-08 16:23:42,249 INFO: AciHostCLI continuously_read: >>>receive packet: AA 16 07 00 41 01 D0 E7 2C 00 03 BB 2023-12-08 16:23:42,249 INFO: Parser eventParser: syncWord: AA,seqn: 16,len: 7,opcode: 0141,params: [D0 E7 2C 00 03], check_sum: BB 2023-12-08 16:23:42,249 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-12-08 16:23:42,249 INFO: Parser eventParser: group_handle: [D0 E7 2C 00] 2023-12-08 16:23:42,249 INFO: Parser eventParser: state: [03] 2023-12-08 16:23:42,249 INFO: Packet sendPacket: <<<send packet: AA 15 05 00 00 00 41 01 00 A4 2023-12-08 16:23:42,616 INFO: AciHostCLI continuously_read: >>>receive packet: AA 17 0A 00 44 80 00 00 18 00 00 00 F4 01 0E 2023-12-08 16:23:42,616 INFO: Parser eventParser: syncWord: AA,seqn: 17,len: 10,opcode: 8044,params: [00 00 18 00 00 00 F4 01], check_sum: 0E 2023-12-08 16:23:42,616 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM 2023-12-08 16:23:42,616 INFO: Parser eventParser: app_link_id: [00] 2023-12-08 16:23:42,616 INFO: Parser eventParser: res: [00] 2023-12-08 16:23:42,616 INFO: Parser eventParser: connInterval: [18 00] 2023-12-08 16:23:42,620 INFO: Parser eventParser: connLatency: [00 00] 2023-12-08 16:23:42,620 INFO: Parser eventParser: supTimeout: [F4 01] 2023-12-08 16:23:42,620 INFO: Packet sendPacket: <<<send packet: AA 16 05 00 00 00 44 80 00 21 2023-12-08 16:23:42,952 INFO: AciHostCLI continuously_read: >>>receive packet: AA 18 0A 00 44 80 00 00 20 00 00 00 F4 01 05 2023-12-08 16:23:42,952 INFO: Parser eventParser: syncWord: AA,seqn: 18,len: 10,opcode: 8044,params: [00 00 20 00 00 00 F4 01], check_sum: 05 2023-12-08 16:23:42,952 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM 2023-12-08 16:23:42,952 INFO: Parser eventParser: app_link_id: [00] 2023-12-08 16:23:42,952 INFO: Parser eventParser: res: [00] 2023-12-08 16:23:42,952 INFO: Parser eventParser: connInterval: [20 00] 2023-12-08 16:23:42,956 INFO: Parser eventParser: connLatency: [00 00] 2023-12-08 16:23:42,956 INFO: Parser eventParser: supTimeout: [F4 01] 2023-12-08 16:23:42,956 INFO: Packet sendPacket: <<<send packet: AA 17 05 00 00 00 44 80 00 20 2023-12-08 16:23:43,685 INFO: AciHostCLI continuously_read: >>>receive packet: AA 19 07 00 41 01 D0 E7 2C 00 04 B7 2023-12-08 16:23:43,685 INFO: Parser eventParser: syncWord: AA,seqn: 19,len: 7,opcode: 0141,params: [D0 E7 2C 00 04], check_sum: B7 2023-12-08 16:23:43,685 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-12-08 16:23:43,685 INFO: Parser eventParser: group_handle: [D0 E7 2C 00] 2023-12-08 16:23:43,685 INFO: Parser eventParser: state: [04] 2023-12-08 16:23:43,689 INFO: Packet sendPacket: <<<send packet: AA 18 05 00 00 00 41 01 00 A1
ACI Host CLI test: Stop media stream.
2023-12-08 16:23:53,705 INFO: input command: cis_stream stop_group_idx_0 2023-12-08 16:23:53,705 INFO: Parser cmdParser: cmd opcode: 3025 param: [00 00] name: CMD_LEA_CIS_STOP_STREAM 2023-12-08 16:23:53,705 INFO: Packet sendPacket: <<<send packet: AA 19 04 00 25 30 00 00 8E 2023-12-08 16:23:53,713 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1A 05 00 00 00 25 30 00 8C 2023-12-08 16:23:53,713 INFO: Parser eventParser: syncWord: AA,seqn: 1A,len: 5,opcode: 0000,params: [25 30 00], check_sum: 8C 2023-12-08 16:23:53,717 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-12-08 16:23:53,717 INFO: Parser eventParser: event_id: [25 30] 2023-12-08 16:23:53,717 INFO: Parser eventParser: status: [00] 2023-12-08 16:23:53,717 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1B 07 00 41 01 D0 E7 2C 00 06 B3 2023-12-08 16:23:53,717 INFO: Parser eventParser: syncWord: AA,seqn: 1B,len: 7,opcode: 0141,params: [D0 E7 2C 00 06], check_sum: B3 2023-12-08 16:23:53,717 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-12-08 16:23:53,717 INFO: Parser eventParser: group_handle: [D0 E7 2C 00] 2023-12-08 16:23:53,721 INFO: Parser eventParser: state: [06] 2023-12-08 16:23:53,721 INFO: Packet sendPacket: <<<send packet: AA 1A 05 00 00 00 41 01 00 9F 2023-12-08 16:23:53,807 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1C 07 00 41 01 D0 E7 2C 00 02 B6 2023-12-08 16:23:53,811 INFO: Parser eventParser: syncWord: AA,seqn: 1C,len: 7,opcode: 0141,params: [D0 E7 2C 00 02], check_sum: B6 2023-12-08 16:23:53,811 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-12-08 16:23:53,811 INFO: Parser eventParser: group_handle: [D0 E7 2C 00] 2023-12-08 16:23:53,811 INFO: Parser eventParser: state: [02] 2023-12-08 16:23:53,811 INFO: Packet sendPacket: <<<send packet: AA 1B 05 00 00 00 41 01 00 9E
ACI Host CLI test: Release media stream.
2023-12-08 16:24:02,218 INFO: input command: cis_stream release_group_idx_0 2023-12-08 16:24:02,218 INFO: Parser cmdParser: cmd opcode: 3025 param: [00 01] name: CMD_LEA_CIS_STOP_STREAM 2023-12-08 16:24:02,218 INFO: Packet sendPacket: <<<send packet: AA 1C 04 00 25 30 00 01 8A 2023-12-08 16:24:02,242 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1D 05 00 00 00 25 30 00 89 2023-12-08 16:24:02,242 INFO: Parser eventParser: syncWord: AA,seqn: 1D,len: 5,opcode: 0000,params: [25 30 00], check_sum: 89 2023-12-08 16:24:02,242 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-12-08 16:24:02,242 INFO: Parser eventParser: event_id: [25 30] 2023-12-08 16:24:02,242 INFO: Parser eventParser: status: [00] 2023-12-08 16:24:02,242 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1E 07 00 41 01 D0 E7 2C 00 07 AF 2023-12-08 16:24:02,242 INFO: Parser eventParser: syncWord: AA,seqn: 1E,len: 7,opcode: 0141,params: [D0 E7 2C 00 07], check_sum: AF 2023-12-08 16:24:02,242 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-12-08 16:24:02,246 INFO: Parser eventParser: group_handle: [D0 E7 2C 00] 2023-12-08 16:24:02,246 INFO: Parser eventParser: state: [07] 2023-12-08 16:24:02,246 INFO: Packet sendPacket: <<<send packet: AA 1D 05 00 00 00 41 01 00 9C 2023-12-08 16:24:02,400 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1F 07 00 41 01 D0 E7 2C 00 01 B4 2023-12-08 16:24:02,400 INFO: Parser eventParser: syncWord: AA,seqn: 1F,len: 7,opcode: 0141,params: [D0 E7 2C 00 01], check_sum: B4 2023-12-08 16:24:02,400 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-12-08 16:24:02,400 INFO: Parser eventParser: group_handle: [D0 E7 2C 00] 2023-12-08 16:24:02,400 INFO: Parser eventParser: state: [01] 2023-12-08 16:24:02,404 INFO: Packet sendPacket: <<<send packet: AA 1E 05 00 00 00 41 01 00 9B 2023-12-08 16:24:02,751 INFO: AciHostCLI continuously_read: >>>receive packet: AA 20 0A 00 44 80 00 00 18 00 00 00 F4 01 05 2023-12-08 16:24:02,751 INFO: Parser eventParser: syncWord: AA,seqn: 20,len: 10,opcode: 8044,params: [00 00 18 00 00 00 F4 01], check_sum: 05 2023-12-08 16:24:02,751 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM 2023-12-08 16:24:02,751 INFO: Parser eventParser: app_link_id: [00] 2023-12-08 16:24:02,751 INFO: Parser eventParser: res: [00] 2023-12-08 16:24:02,755 INFO: Parser eventParser: connInterval: [18 00] 2023-12-08 16:24:02,755 INFO: Parser eventParser: connLatency: [00 00] 2023-12-08 16:24:02,755 INFO: Parser eventParser: supTimeout: [F4 01] 2023-12-08 16:24:02,755 INFO: Packet sendPacket: <<<send packet: AA 1F 05 00 00 00 44 80 00 18
ACI Host CLI test: Start stream conversation.
2023-12-08 16:24:11,884 INFO: input command: cis_conversation start_group_idx_0 2023-12-08 16:24:11,884 INFO: Parser cmdParser: cmd opcode: 3031 param: [00] name: CMD_LEA_CIS_START_CONVERSATION 2023-12-08 16:24:11,884 INFO: Packet sendPacket: <<<send packet: AA 20 03 00 31 30 00 7C 2023-12-08 16:24:11,900 INFO: AciHostCLI continuously_read: >>>receive packet: AA 21 05 00 00 00 31 30 00 79 2023-12-08 16:24:11,900 INFO: Parser eventParser: syncWord: AA,seqn: 21,len: 5,opcode: 0000,params: [31 30 00], check_sum: 79 2023-12-08 16:24:11,900 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-12-08 16:24:11,904 INFO: Parser eventParser: event_id: [31 30] 2023-12-08 16:24:11,904 INFO: Parser eventParser: status: [00] 2023-12-08 16:24:11,904 INFO: AciHostCLI continuously_read: >>>receive packet: AA 22 07 00 41 01 D0 E7 2C 00 01 B1 2023-12-08 16:24:11,904 INFO: Parser eventParser: syncWord: AA,seqn: 22,len: 7,opcode: 0141,params: [D0 E7 2C 00 01], check_sum: B1 2023-12-08 16:24:11,908 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-12-08 16:24:11,908 INFO: Parser eventParser: group_handle: [D0 E7 2C 00] 2023-12-08 16:24:11,908 INFO: Parser eventParser: state: [01] 2023-12-08 16:24:11,908 INFO: Packet sendPacket: <<<send packet: AA 21 05 00 00 00 41 01 00 98 2023-12-08 16:24:11,916 INFO: AciHostCLI continuously_read: >>>receive packet: AA 23 07 00 41 01 D0 E7 2C 00 03 AE 2023-12-08 16:24:11,916 INFO: Parser eventParser: syncWord: AA,seqn: 23,len: 7,opcode: 0141,params: [D0 E7 2C 00 03], check_sum: AE 2023-12-08 16:24:11,916 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-12-08 16:24:11,920 INFO: Parser eventParser: group_handle: [D0 E7 2C 00] 2023-12-08 16:24:11,920 INFO: Parser eventParser: state: [03] 2023-12-08 16:24:11,920 INFO: Packet sendPacket: <<<send packet: AA 22 05 00 00 00 41 01 00 97 2023-12-08 16:24:12,557 INFO: AciHostCLI continuously_read: >>>receive packet: AA 24 0A 00 44 80 00 00 18 00 00 00 F4 01 01 2023-12-08 16:24:12,557 INFO: Parser eventParser: syncWord: AA,seqn: 24,len: 10,opcode: 8044,params: [00 00 18 00 00 00 F4 01], check_sum: 01 2023-12-08 16:24:12,557 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM 2023-12-08 16:24:12,557 INFO: Parser eventParser: app_link_id: [00] 2023-12-08 16:24:12,561 INFO: Parser eventParser: res: [00] 2023-12-08 16:24:12,561 INFO: Parser eventParser: connInterval: [18 00] 2023-12-08 16:24:12,561 INFO: Parser eventParser: connLatency: [00 00] 2023-12-08 16:24:12,561 INFO: Parser eventParser: supTimeout: [F4 01] 2023-12-08 16:24:12,561 INFO: Packet sendPacket: <<<send packet: AA 23 05 00 00 00 44 80 00 14 2023-12-08 16:24:12,921 INFO: AciHostCLI continuously_read: >>>receive packet: AA 25 07 00 41 01 D0 E7 2C 00 04 AB 2023-12-08 16:24:12,925 INFO: Parser eventParser: syncWord: AA,seqn: 25,len: 7,opcode: 0141,params: [D0 E7 2C 00 04], check_sum: AB 2023-12-08 16:24:12,925 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-12-08 16:24:12,925 INFO: Parser eventParser: group_handle: [D0 E7 2C 00] 2023-12-08 16:24:12,925 INFO: Parser eventParser: state: [04] 2023-12-08 16:24:12,925 INFO: Packet sendPacket: <<<send packet: AA 24 05 00 00 00 41 01 00 95
ACI Host CLI test: Stop stream conversation.
2023-12-08 16:24:18,072 INFO: input command: cis_stream stop_group_idx_0 2023-12-08 16:24:18,072 INFO: Parser cmdParser: cmd opcode: 3025 param: [00 00] name: CMD_LEA_CIS_STOP_STREAM 2023-12-08 16:24:18,072 INFO: Packet sendPacket: <<<send packet: AA 25 04 00 25 30 00 00 82 2023-12-08 16:24:18,080 INFO: AciHostCLI continuously_read: >>>receive packet: AA 26 05 00 00 00 25 30 00 80 2023-12-08 16:24:18,084 INFO: Parser eventParser: syncWord: AA,seqn: 26,len: 5,opcode: 0000,params: [25 30 00], check_sum: 80 2023-12-08 16:24:18,084 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-12-08 16:24:18,084 INFO: Parser eventParser: event_id: [25 30] 2023-12-08 16:24:18,084 INFO: Parser eventParser: status: [00] 2023-12-08 16:24:18,084 INFO: AciHostCLI continuously_read: >>>receive packet: AA 27 07 00 41 01 D0 E7 2C 00 06 A7 2023-12-08 16:24:18,084 INFO: Parser eventParser: syncWord: AA,seqn: 27,len: 7,opcode: 0141,params: [D0 E7 2C 00 06], check_sum: A7 2023-12-08 16:24:18,084 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-12-08 16:24:18,084 INFO: Parser eventParser: group_handle: [D0 E7 2C 00] 2023-12-08 16:24:18,088 INFO: Parser eventParser: state: [06] 2023-12-08 16:24:18,088 INFO: Packet sendPacket: <<<send packet: AA 26 05 00 00 00 41 01 00 93 2023-12-08 16:24:18,254 INFO: AciHostCLI continuously_read: >>>receive packet: AA 28 07 00 41 01 D0 E7 2C 00 02 AA 2023-12-08 16:24:18,258 INFO: Parser eventParser: syncWord: AA,seqn: 28,len: 7,opcode: 0141,params: [D0 E7 2C 00 02], check_sum: AA 2023-12-08 16:24:18,258 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-12-08 16:24:18,258 INFO: Parser eventParser: group_handle: [D0 E7 2C 00] 2023-12-08 16:24:18,258 INFO: Parser eventParser: state: [02] 2023-12-08 16:24:18,258 INFO: Packet sendPacket: <<<send packet: AA 27 05 00 00 00 41 01 00 92
ACI Host CLI test: Release stream conversation.
2023-12-08 16:24:23,562 INFO: input command: cis_stream release_group_idx_0 2023-12-08 16:24:23,562 INFO: Parser cmdParser: cmd opcode: 3025 param: [00 01] name: CMD_LEA_CIS_STOP_STREAM 2023-12-08 16:24:23,562 INFO: Packet sendPacket: <<<send packet: AA 28 04 00 25 30 00 01 7E 2023-12-08 16:24:23,574 INFO: AciHostCLI continuously_read: >>>receive packet: AA 29 05 00 00 00 25 30 00 7D 2023-12-08 16:24:23,574 INFO: Parser eventParser: syncWord: AA,seqn: 29,len: 5,opcode: 0000,params: [25 30 00], check_sum: 7D 2023-12-08 16:24:23,574 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-12-08 16:24:23,574 INFO: Parser eventParser: event_id: [25 30] 2023-12-08 16:24:23,574 INFO: Parser eventParser: status: [00] 2023-12-08 16:24:23,574 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2A 07 00 41 01 D0 E7 2C 00 07 A3 2023-12-08 16:24:23,578 INFO: Parser eventParser: syncWord: AA,seqn: 2A,len: 7,opcode: 0141,params: [D0 E7 2C 00 07], check_sum: A3 2023-12-08 16:24:23,578 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-12-08 16:24:23,578 INFO: Parser eventParser: group_handle: [D0 E7 2C 00] 2023-12-08 16:24:23,578 INFO: Parser eventParser: state: [07] 2023-12-08 16:24:23,578 INFO: Packet sendPacket: <<<send packet: AA 29 05 00 00 00 41 01 00 90 2023-12-08 16:24:23,718 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2B 07 00 41 01 D0 E7 2C 00 01 A8 2023-12-08 16:24:23,718 INFO: Parser eventParser: syncWord: AA,seqn: 2B,len: 7,opcode: 0141,params: [D0 E7 2C 00 01], check_sum: A8 2023-12-08 16:24:23,718 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-12-08 16:24:23,718 INFO: Parser eventParser: group_handle: [D0 E7 2C 00] 2023-12-08 16:24:23,718 INFO: Parser eventParser: state: [01] 2023-12-08 16:24:23,718 INFO: Packet sendPacket: <<<send packet: AA 2A 05 00 00 00 41 01 00 8F 2023-12-08 16:24:23,956 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2C 0A 00 44 80 00 00 18 00 00 00 F4 01 F9 2023-12-08 16:24:23,960 INFO: Parser eventParser: syncWord: AA,seqn: 2C,len: 10,opcode: 8044,params: [00 00 18 00 00 00 F4 01], check_sum: F9 2023-12-08 16:24:23,960 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM 2023-12-08 16:24:23,960 INFO: Parser eventParser: app_link_id: [00] 2023-12-08 16:24:23,960 INFO: Parser eventParser: res: [00] 2023-12-08 16:24:23,960 INFO: Parser eventParser: connInterval: [18 00] 2023-12-08 16:24:23,960 INFO: Parser eventParser: connLatency: [00 00] 2023-12-08 16:24:23,964 INFO: Parser eventParser: supTimeout: [F4 01] 2023-12-08 16:24:23,964 INFO: Packet sendPacket: <<<send packet: AA 2B 05 00 00 00 44 80 00 0C
LE Audio Acceptor
Acceptor Introduction
Acceptor, which is described in the CAP SPEC, always operates in the BAP Unicast Server role, BAP Broadcast Sink role, BAP Scan Delegator role, VCP Volume Renderer Role, MICP MIC Device role, or CCP Call Control Client role.
Acceptor General ACI Host CLI Test
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_LEA_ADV_START(0x3250) |
None |
lea_adv_start |
CMD_LEA_ADV_STOP(0x3251) |
None |
lea_adv_stop |
The ACI Host CLI commands for Acceptor are CMD_LEA_ADV_START
and CMD_LEA_ADV_STOP
.
CMD_LEA_ADV_START
is used to start LE Audio advertising and be able to be connected by the Initiator which supports CIS.
CMD_LEA_ADV_STOP
is used to stop LE Audio advertising and the Initiator cannot scan the Acceptor.
ACI Host CLI test: Start LE Audio Advertising.
2023-07-27 11:07:56,017 INFO: input command: lea_adv_start x 2023-07-27 11:07:56,018 INFO: Parser cmdParser: cmd opcode: 3250 param: [] name: CMD_LEA_ADV_START 2023-07-27 11:07:56,019 INFO: Packet sendPacket: <<<send packet: AA 01 02 00 50 32 7B 2023-07-27 11:07:56,029 INFO: AciHostCLI continuously_read: >>>receive packet: AA 02 05 00 00 00 50 32 00 77 2023-07-27 11:07:56,036 INFO: Parser eventParser: syncWord: AA,seqn: 02,len: 5,opcode: 0000,params: [50 32 00], check_sum: 77 2023-07-27 11:07:56,044 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-27 11:07:56,046 INFO: Parser eventParser: event_id: [50 32] 2023-07-27 11:07:56,047 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Stop LE Audio Advertising.
2023-07-27 11:08:38,865 INFO: input command: lea_adv_stop x 2023-07-27 11:08:38,865 INFO: Parser cmdParser: cmd opcode: 3251 param: [] name: CMD_LEA_ADV_STOP 2023-07-27 11:08:38,868 INFO: Packet sendPacket: <<<send packet: AA 09 02 00 51 32 72 2023-07-27 11:08:38,883 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0A 05 00 00 00 51 32 00 6E 2023-07-27 11:08:38,889 INFO: Parser eventParser: syncWord: AA,seqn: 0A,len: 5,opcode: 0000,params: [51 32 00], check_sum: 6E 2023-07-27 11:08:38,892 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-27 11:08:38,895 INFO: Parser eventParser: event_id: [51 32] 2023-07-27 11:08:38,897 INFO: Parser eventParser: status: [00]
BIS Acceptor Introduction
BIS Acceptor, subdivision according to CAP role of the Acceptor, availability in variety broadcast scenarios. Besides being used for receiving Broadcast Isochronous Streams, it can also support scanning for Broadcast Audio Streams autonomously or delegate the scanning to a Commander.
BIS Acceptor ACI Host CLI Test
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_LEA_SYNC_INIT(0x3254) |
bis_mode = random |
bis_sync_init random |
CMD_LEA_SYNC_INIT(0x3254) |
bis_mode = spec |
bis_sync_init spec |
CMD_LEA_SYNC_INIT(0x3254) |
bis_mode = random |
bis_sync_init delegator |
CMD_LEA_SYNC(0x3255) |
sync = true |
bis_sync start |
CMD_LEA_SYNC(0x3255) |
sync = false |
bis_sync stop |
The ACI Host CLI CMD for BIS are CMD_LEA_SYNC_INIT
, CMD_LEA_SYNC
.
CMD_LEA_BSRC_INIT
is used to initialize the BIS parameters, including BIS role, BIS mode, the addr need to sync and only used in SPEC mode.
CMD_LEA_SYNC
is used to sync the broadcast audio stream.
ACI Host CLI test: BIS sync init.
2023-08-04 19:00:22,584 INFO: input command: bis_sync_init random 2023-08-04 19:00:22,584 INFO: Parser cmdParser: cmd opcode: 3254 param: [02 00 00 00 00 00 00 00] name: CMD_LEA_SYNC_INIT 2023-08-04 19:00:22,584 INFO: Packet sendPacket: <<<send packet: AA 04 0A 00 54 32 02 00 00 00 00 00 00 00 6A 2023-08-04 19:00:22,604 INFO: AciHostCLI continuously_read: >>>receive packet: AA 04 05 00 00 00 54 32 00 71 2023-08-04 19:00:22,609 INFO: Parser eventParser: syncWord: AA,seqn: 04,len: 5,opcode: 0000,params: [54 32 00], check_sum: 71 2023-08-04 19:00:22,614 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-08-04 19:00:22,614 INFO: Parser eventParser: event_id: [54 32] 2023-08-04 19:00:22,628 INFO: Parser eventParser: status: [00]
ACI Host CLI test: BIS sync start.
2023-08-04 19:00:29,694 INFO: input command: bis_sync start 2023-08-04 19:00:29,694 INFO: Parser cmdParser: cmd opcode: 3255 param: [00] name: CMD_LEA_SYNC 2023-08-04 19:00:29,694 INFO: Packet sendPacket: <<<send packet: AA 05 03 00 55 32 00 71 2023-08-04 19:00:29,714 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 05 00 00 00 55 32 00 6F 2023-08-04 19:00:29,724 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 5,opcode: 0000,params: [55 32 00], check_sum: 6F 2023-08-04 19:00:29,724 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-08-04 19:00:29,724 INFO: Parser eventParser: event_id: [55 32] 2023-08-04 19:00:29,724 INFO: Parser eventParser: status: [00]
ACI Host CLI test: BIS sync stop.
2023-08-04 19:01:02,725 INFO: input command: bis_sync stop 2023-08-04 19:01:02,725 INFO: Parser cmdParser: cmd opcode: 3255 param: [01] name: CMD_LEA_SYNC 2023-08-04 19:01:02,725 INFO: Packet sendPacket: <<<send packet: AA 06 03 00 55 32 01 6F 2023-08-04 19:01:02,745 INFO: AciHostCLI continuously_read: >>>receive packet: AA 06 05 00 00 00 55 32 00 6E 2023-08-04 19:01:02,745 INFO: Parser eventParser: syncWord: AA,seqn: 06,len: 5,opcode: 0000,params: [55 32 00], check_sum: 6E 2023-08-04 19:01:02,745 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-08-04 19:01:02,745 INFO: Parser eventParser: event_id: [55 32] 2023-08-04 19:01:02,755 INFO: Parser eventParser: status: [00]
CIS Acceptor Introduction
CIS, which stands for Unicast Isochronous Channel, is a logical transport for connected devices that allows sending and receiving isochronous data. For a CIS, an acknowledgment protocol is available to increase packet delivery dependability. This chapter describes how to use the CIS Acceptor and can be connected to remote devices. Actually, the CIS Acceptor can control the remote device’s music player and telephone call by MCP and CCP profiles. It will notify VCS audio volume to Initiator when local volume or SPK mute/unmute changes.
CIS Acceptor ACI Host CLI Test
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_LEA_CCP_CALL_CP |
conn_id=0 |
lea_call_cp accept |
CMD_LEA_CCP_CALL_CP |
conn_id=0 |
lea_call_cp terminate |
CMD_LEA_CCP_CALL_CP |
conn_id=0 |
lea_call_cp local_hold |
CMD_LEA_CCP_CALL_CP |
conn_id=0 |
lea_call_cp local_retrieve |
CMD_LEA_CCP_CALL_CP |
conn_id=0 |
lea_call_cp originate |
CMD_LEA_CCP_CALL_CP |
conn_id=0 |
lea_call_cp join |
CMD_LEA_MCP_MEDIA_CP |
conn_id=0 |
lea_media_cp play |
CMD_LEA_MCP_MEDIA_CP |
conn_id=0 |
lea_media_cp pause |
CMD_LEA_MCP_MEDIA_CP |
conn_id=0 |
lea_media_cp fast_rewind |
CMD_LEA_MCP_MEDIA_CP |
conn_id=0 |
lea_media_cp fast_forward |
CMD_LEA_MCP_MEDIA_CP |
conn_id=0 |
lea_media_cp stop |
CMD_LEA_MCP_MEDIA_CP |
conn_id=0 |
lea_media_cp previous_track |
CMD_LEA_MCP_MEDIA_CP |
conn_id=0 |
lea_media_cp next_track |
CMD_LEA_VCS_SET |
conn_id=0 |
lea_vcs vol_up |
CMD_LEA_VCS_SET |
conn_id=0 |
lea_vcs vol_down |
CMD_LEA_VCS_SET |
conn_id=0 |
lea_vcs spk_mute |
CMD_LEA_VCS_SET |
conn_id=0 |
lea_vcs spk_unmute |
The ACI Host CLI CMD for CIS Acceptor is CMD_LEA_CCP_CALL_CP
, CMD_LEA_MCP_MEDIA_CP
and CMD_LEA_VCS_SET
:
CMD_LEA_CCP_CALL_CP
is used to control the remote device’s telephone call when they are connected to LE Audio. And it can send accept, terminate, local hold, local retrieve, originate and join commands by CCP profile.CMD_LEA_MCP_MEDIA_CP
is used to control the remote device’s active music player when they are connected to LE Audio. And it can send play, pause, stop, fast rewind, fast forward, previous track, and next track commands by the MCP profile.CMD_LEA_VCS_SET
is used to change the volume of the local device’s audio and the CIS Acceptor will notify the VCS audio volume state to the remote device.
ACI Host CLI test: CCP accept.
2023-07-27 14:16:42,829 INFO: input command: lea_call_cp accept 2023-07-27 14:16:42,830 INFO: Parser cmdParser: cmd opcode: 3252 param: [00 00] name: CMD_LEA_CCP_CALL_CP 2023-07-27 14:16:42,831 INFO: Packet sendPacket: <<<send packet: AA 17 04 00 52 32 00 00 60 2023-07-27 14:16:42,849 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0B 05 00 00 00 52 32 00 6B 2023-07-27 14:16:42,858 INFO: Parser eventParser: syncWord: AA,seqn: 0B,len: 5,opcode: 0000,params: [52 32 00], check_sum: 6B 2023-07-27 14:16:42,862 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-27 14:16:42,865 INFO: Parser eventParser: event_id: [52 32] 2023-07-27 14:16:42,867 INFO: Parser eventParser: status: [00] 2023-07-27 14:16:44,691 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1E 04 00 52 32 00 04 56 2023-07-27 14:16:44,692 INFO: Parser eventParser: syncWord: AA,seqn: 1E,len: 4,opcode: 3252,params: [00 04], check_sum: 56 2023-07-27 14:16:44,694 INFO: Packet sendPacket: <<<send packet: AA 0B 05 00 00 00 52 32 00 6C
ACI Host CLI test: CCP terminate.
2023-07-27 14:17:24,536 INFO: input command: lea_call_cp terminate 2023-07-27 14:17:24,536 INFO: Parser cmdParser: cmd opcode: 3252 param: [00 01] name: CMD_LEA_CCP_CALL_CP 2023-07-27 14:17:24,537 INFO: Packet sendPacket: <<<send packet: AA 1A 04 00 52 32 00 01 5D 2023-07-27 14:17:24,556 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0E 05 00 00 00 52 32 00 69 2023-07-27 14:17:24,559 INFO: Parser eventParser: syncWord: AA,seqn: 0E,len: 5,opcode: 0000,params: [52 32 00], check_sum: 69 2023-07-27 14:17:24,560 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-27 14:17:24,561 INFO: Parser eventParser: event_id: [52 32] 2023-07-27 14:17:24,562 INFO: Parser eventParser: status: [00] 2023-07-27 14:17:26,922 INFO: AciHostCLI continuously_read: >>>receive packet: AA 20 04 00 52 32 00 00 58 2023-07-27 14:17:26,923 INFO: Parser eventParser: syncWord: AA,seqn: 20,len: 4,opcode: 3252,params: [00 00], check_sum: 58 2023-07-27 14:17:26,924 INFO: Packet sendPacket: <<<send packet: AA 0D 05 00 00 00 52 32 00 6A
ACI Host CLI test: CCP local hold.
2023-07-27 14:17:00,880 INFO: input command: lea_call_cp local_hold 2023-07-27 14:17:00,880 INFO: Parser cmdParser: cmd opcode: 3252 param: [00 02] name: CMD_LEA_CCP_CALL_CP 2023-07-27 14:17:00,882 INFO: Packet sendPacket: <<<send packet: AA 18 04 00 52 32 00 02 5E 2023-07-27 14:17:00,903 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0C 05 00 00 00 52 32 00 6B 2023-07-27 14:17:00,909 INFO: Parser eventParser: syncWord: AA,seqn: 0C,len: 5,opcode: 0000,params: [52 32 00], check_sum: 6B 2023-07-27 14:17:00,918 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-27 14:17:00,920 INFO: Parser eventParser: event_id: [52 32] 2023-07-27 14:17:00,921 INFO: Parser eventParser: status: [00]
ACI Host CLI test: CCP local retrieve.
2023-07-27 14:17:08,153 INFO: input command: lea_call_cp local_retrieve 2023-07-27 14:17:08,154 INFO: Parser cmdParser: cmd opcode: 3252 param: [00 03] name: CMD_LEA_CCP_CALL_CP 2023-07-27 14:17:08,155 INFO: Packet sendPacket: <<<send packet: AA 19 04 00 52 32 00 03 5C 2023-07-27 14:17:08,172 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0D 05 00 00 00 52 32 00 6A 2023-07-27 14:17:08,176 INFO: Parser eventParser: syncWord: AA,seqn: 0D,len: 5,opcode: 0000,params: [52 32 00], check_sum: 6A 2023-07-27 14:17:08,178 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-27 14:17:08,184 INFO: Parser eventParser: event_id: [52 32] 2023-07-27 14:17:08,186 INFO: Parser eventParser: status: [00]
ACI Host CLI test: CCP originate.
ACI Host CLI test: CCP join.
ACI Host CLI test: MCP play.
2023-07-27 12:00:52,509 INFO: input command: lea_media_cp play 2023-07-27 12:00:52,510 INFO: Parser cmdParser: cmd opcode: 3253 param: [00 01] name: CMD_LEA_MCP_MEDIA_CP 2023-07-27 12:00:52,511 INFO: Packet sendPacket: <<<send packet: AA 01 04 00 53 32 00 01 75 2023-07-27 12:00:52,531 INFO: AciHostCLI continuously_read: >>>receive packet: AA 25 05 00 00 00 53 32 00 51 2023-07-27 12:00:52,535 INFO: Parser eventParser: syncWord: AA,seqn: 25,len: 5,opcode: 0000,params: [53 32 00], check_sum: 51 2023-07-27 12:00:52,542 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-27 12:00:52,544 INFO: Parser eventParser: event_id: [53 32] 2023-07-27 12:00:52,546 INFO: Parser eventParser: status: [00] 2023-07-27 12:00:52,570 INFO: AciHostCLI continuously_read: >>>receive packet: AA 26 04 00 53 32 00 01 50 2023-07-27 12:00:52,572 INFO: Parser eventParser: syncWord: AA,seqn: 26,len: 4,opcode: 3253,params: [00 01], check_sum: 50 2023-07-27 12:00:52,573 INFO: Packet sendPacket: <<<send packet: AA 02 05 00 00 00 53 32 00 74
ACI Host CLI test: MCP pause.
2023-07-27 12:04:41,402 INFO: input command: lea_media_cp pause 2023-07-27 12:04:41,403 INFO: Parser cmdParser: cmd opcode: 3253 param: [00 02] name: CMD_LEA_MCP_MEDIA_CP 2023-07-27 12:04:41,404 INFO: Packet sendPacket: <<<send packet: AA 03 04 00 53 32 00 02 72 2023-07-27 12:04:41,417 INFO: AciHostCLI continuously_read: >>>receive packet: AA 27 05 00 00 00 53 32 00 4F 2023-07-27 12:04:41,419 INFO: Parser eventParser: syncWord: AA,seqn: 27,len: 5,opcode: 0000,params: [53 32 00], check_sum: 4F 2023-07-27 12:04:41,426 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-27 12:04:41,428 INFO: Parser eventParser: event_id: [53 32] 2023-07-27 12:04:41,429 INFO: Parser eventParser: status: [00] 2023-07-27 12:04:41,497 INFO: AciHostCLI continuously_read: >>>receive packet: AA 28 04 00 53 32 00 02 4D 2023-07-27 12:04:41,498 INFO: Parser eventParser: syncWord: AA,seqn: 28,len: 4,opcode: 3253,params: [00 02], check_sum: 4D 2023-07-27 12:04:41,499 INFO: Packet sendPacket: <<<send packet: AA 04 05 00 00 00 53 32 00 72
ACI Host CLI test: MCP fast rewind.
2023-07-27 12:05:01,473 INFO: input command: lea_media_cp fast_rewind 2023-07-27 12:05:01,474 INFO: Parser cmdParser: cmd opcode: 3253 param: [00 03] name: CMD_LEA_MCP_MEDIA_CP 2023-07-27 12:05:01,476 INFO: Packet sendPacket: <<<send packet: AA 05 04 00 53 32 00 03 6F 2023-07-27 12:05:01,497 INFO: AciHostCLI continuously_read: >>>receive packet: AA 29 05 00 00 00 53 32 00 4D 2023-07-27 12:05:01,500 INFO: Parser eventParser: syncWord: AA,seqn: 29,len: 5,opcode: 0000,params: [53 32 00], check_sum: 4D 2023-07-27 12:05:01,501 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-27 12:05:01,504 INFO: Parser eventParser: event_id: [53 32] 2023-07-27 12:05:01,505 INFO: Parser eventParser: status: [00] 2023-07-27 12:05:01,573 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2A 04 00 53 32 00 03 4A 2023-07-27 12:05:01,574 INFO: Parser eventParser: syncWord: AA,seqn: 2A,len: 4,opcode: 3253,params: [00 03], check_sum: 4A 2023-07-27 12:05:01,575 INFO: Packet sendPacket: <<<send packet: AA 06 05 00 00 00 53 32 00 70
ACI Host CLI test: MCP fast forward.
2023-07-27 12:05:17,450 INFO: input command: lea_media_cp fast_forward 2023-07-27 12:05:17,450 INFO: Parser cmdParser: cmd opcode: 3253 param: [00 04] name: CMD_LEA_MCP_MEDIA_CP 2023-07-27 12:05:17,452 INFO: Packet sendPacket: <<<send packet: AA 07 04 00 53 32 00 04 6C 2023-07-27 12:05:17,463 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2B 05 00 00 00 53 32 00 4B 2023-07-27 12:05:17,470 INFO: Parser eventParser: syncWord: AA,seqn: 2B,len: 5,opcode: 0000,params: [53 32 00], check_sum: 4B 2023-07-27 12:05:17,471 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-27 12:05:17,473 INFO: Parser eventParser: event_id: [53 32] 2023-07-27 12:05:17,473 INFO: Parser eventParser: status: [00] 2023-07-27 12:05:17,620 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2C 04 00 53 32 00 03 48 2023-07-27 12:05:17,621 INFO: Parser eventParser: syncWord: AA,seqn: 2C,len: 4,opcode: 3253,params: [00 01], check_sum: 48 2023-07-27 12:05:17,622 INFO: Packet sendPacket: <<<send packet: AA 08 05 00 00 00 53 32 00 6E
ACI Host CLI test: MCP stop.
2023-07-27 12:07:08,855 INFO: input command: lea_media_cp stop 2023-07-27 12:07:08,856 INFO: Parser cmdParser: cmd opcode: 3253 param: [00 05] name: CMD_LEA_MCP_MEDIA_CP 2023-07-27 12:07:08,857 INFO: Packet sendPacket: <<<send packet: AA 1A 04 00 53 32 00 05 58 2023-07-27 12:07:08,874 INFO: AciHostCLI continuously_read: >>>receive packet: AA 3E 05 00 00 00 53 32 00 38 2023-07-27 12:07:08,876 INFO: Parser eventParser: syncWord: AA,seqn: 3E,len: 5,opcode: 0000,params: [53 32 00], check_sum: 38 2023-07-27 12:07:08,878 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-27 12:07:08,880 INFO: Parser eventParser: event_id: [53 32] 2023-07-27 12:07:08,881 INFO: Parser eventParser: status: [00] 2023-07-27 12:07:11,332 INFO: AciHostCLI continuously_read: >>>receive packet: AA 3F 04 00 53 32 00 02 36 2023-07-27 12:07:11,334 INFO: Parser eventParser: syncWord: AA,seqn: 3F,len: 4,opcode: 3253,params: [00 02], check_sum: 36 2023-07-27 12:07:11,336 INFO: Packet sendPacket: <<<send packet: AA 1B 05 00 00 00 53 32 00 5B
ACI Host CLI test: MCP previous track.
2023-07-27 12:07:54,069 INFO: input command: lea_media_cp previous_track 2023-07-27 12:07:54,070 INFO: Parser cmdParser: cmd opcode: 3253 param: [00 30] name: CMD_LEA_MCP_MEDIA_CP 2023-07-27 12:07:54,072 INFO: Packet sendPacket: <<<send packet: AA 1F 04 00 53 32 00 30 28 2023-07-27 12:07:54,094 INFO: AciHostCLI continuously_read: >>>receive packet: AA 43 05 00 00 00 53 32 00 33 2023-07-27 12:07:54,097 INFO: Parser eventParser: syncWord: AA,seqn: 43,len: 5,opcode: 0000,params: [53 32 00], check_sum: 33 2023-07-27 12:07:54,099 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-27 12:07:54,100 INFO: Parser eventParser: event_id: [53 32] 2023-07-27 12:07:54,101 INFO: Parser eventParser: status: [00]
ACI Host CLI test: MCP next track.
2023-07-27 12:08:05,519 INFO: input command: lea_media_cp next_track 2023-07-27 12:08:05,519 INFO: Parser cmdParser: cmd opcode: 3253 param: [00 31] name: CMD_LEA_MCP_MEDIA_CP 2023-07-27 12:08:05,520 INFO: Packet sendPacket: <<<send packet: AA 20 04 00 53 32 00 31 26 2023-07-27 12:08:05,540 INFO: AciHostCLI continuously_read: >>>receive packet: AA 44 05 00 00 00 53 32 00 32 2023-07-27 12:08:05,543 INFO: Parser eventParser: syncWord: AA,seqn: 44,len: 5,opcode: 0000,params: [53 32 00], check_sum: 32 2023-07-27 12:08:05,543 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-27 12:08:05,544 INFO: Parser eventParser: event_id: [53 32] 2023-07-27 12:08:05,545 INFO: Parser eventParser: status: [00]
ACI Host CLI test: VCS volume up.
2024-02-28 15:31:52,825 INFO: input command: lea_vcs vol_up 2024-02-28 15:31:52,827 INFO: Parser cmdParser: cmd opcode: 3256 param: [00 00] name: CMD_LEA_VCS_SET_CP 2024-02-28 15:31:52,829 INFO: Packet sendPacket: <<<send packet: AA 26 04 00 56 32 00 00 4E 2024-02-28 15:31:52,852 INFO: AciHostCLI continuously_read: >>>receive packet: AA 25 03 00 20 00 01 B7 2024-02-28 15:31:52,856 INFO: Parser eventParser: syncWord: AA,seqn: 25,len: 3,opcode: 0020,params: [01], check_sum: B7 2024-02-28 15:31:52,859 INFO: Parser eventParser: event name: EVENT_AUDIO_VOL_CHANGE 2024-02-28 15:31:52,872 INFO: Packet sendPacket: <<<send packet: AA 27 05 00 00 00 20 00 00 B4 2024-02-28 15:31:52,882 INFO: AciHostCLI continuously_read: >>>receive packet: AA 26 05 00 00 00 56 32 00 4D 2024-02-28 15:31:52,885 INFO: Parser eventParser: syncWord: AA,seqn: 26,len: 5,opcode: 0000,params: [56 32 00], check_sum: 4D 2024-02-28 15:31:52,887 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-02-28 15:31:52,889 INFO: Parser eventParser: event_id: [56 32] 2024-02-28 15:31:52,891 INFO: Parser eventParser: status: [00]
ACI Host CLI test: VCS volume down.
2024-02-28 15:31:46,154 INFO: input command: lea_vcs vol_down 2024-02-28 15:31:46,156 INFO: Parser cmdParser: cmd opcode: 3256 param: [00 01] name: CMD_LEA_VCS_SET_CP 2024-02-28 15:31:46,158 INFO: Packet sendPacket: <<<send packet: AA 23 04 00 56 32 00 01 50 2024-02-28 15:31:46,173 INFO: AciHostCLI continuously_read: >>>receive packet: AA 22 03 00 20 00 04 B7 2024-02-28 15:31:46,176 INFO: Parser eventParser: syncWord: AA,seqn: 22,len: 3,opcode: 0020,params: [04], check_sum: B7 2024-02-28 15:31:46,180 INFO: Parser eventParser: event name: EVENT_AUDIO_VOL_CHANGE 2024-02-28 15:31:46,182 INFO: Packet sendPacket: <<<send packet: AA 24 05 00 00 00 20 00 00 B7 2024-02-28 15:31:46,188 INFO: AciHostCLI continuously_read: >>>receive packet: AA 23 05 00 00 00 56 32 00 50 2024-02-28 15:31:46,190 INFO: Parser eventParser: syncWord: AA,seqn: 23,len: 5,opcode: 0000,params: [56 32 00], check_sum: 50 2024-02-28 15:31:46,191 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-02-28 15:31:46,193 INFO: Parser eventParser: event_id: [56 32] 2024-02-28 15:31:46,194 INFO: Parser eventParser: status: [00]
ACI Host CLI test: VCS SPK mute.
2024-02-28 15:32:02,346 INFO: input command: lea_vcs spk_mute 2024-02-28 15:32:02,346 INFO: Parser cmdParser: cmd opcode: 3256 param: [00 02] name: CMD_LEA_VCS_SET_CP 2024-02-28 15:32:02,348 INFO: Packet sendPacket: <<<send packet: AA 2F 04 00 56 32 00 02 43 2024-02-28 15:32:02,371 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2F 05 00 00 00 56 32 00 44 2024-02-28 15:32:02,373 INFO: Parser eventParser: syncWord: AA,seqn: 2F,len: 5,opcode: 0000,params: [56 32 00], check_sum: 44 2024-02-28 15:32:02,375 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-02-28 15:32:02,377 INFO: Parser eventParser: event_id: [56 32] 2024-02-28 15:32:02,378 INFO: Parser eventParser: status: [00]
ACI Host CLI test: VCS SPK unmute.
2024-02-28 15:32:06,691 INFO: input command: lea_vcs spk_unmute 2024-02-28 15:32:06,692 INFO: Parser cmdParser: cmd opcode: 3256 param: [00 03] name: CMD_LEA_VCS_SET_CP 2024-02-28 15:32:06,695 INFO: Packet sendPacket: <<<send packet: AA 30 04 00 56 32 00 03 41 2024-02-28 15:32:06,720 INFO: AciHostCLI continuously_read: >>>receive packet: AA 30 05 00 00 00 56 32 00 43 2024-02-28 15:32:06,726 INFO: Parser eventParser: syncWord: AA,seqn: 30,len: 5,opcode: 0000,params: [56 32 00], check_sum: 43 2024-02-28 15:32:06,729 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-02-28 15:32:06,732 INFO: Parser eventParser: event_id: [56 32] 2024-02-28 15:32:06,738 INFO: Parser eventParser: status: [00]
Bluetooth Audio Transmitter
This chapter introduces the functionality of the bt_audio_transmitter
application scenario. This functionality is enabled by opening the macro definition F_APP_BT_AUDIO_TRANSMITTER_DEMO_SUPPORT
in app_flags.h
. This chapter describes how to use these functions and the flow of how to test them, including the MSCs of the ACI Device and ACI Host interaction, and the commands used by ACI Host.
Source Play Function
Based on the scenario introduced in Bluetooth Audio Transmitter, Bluetooth Audio Transceiver application supports source play function,
which can transmit MIC, line-in, USB, SD card signal to BUDs through HFP, A2DP or BIS/CIS. These input and output
methods can be combined in various ways by set_route_in
CMD and set_route_out
CMD.
This chapter presents three combinations as examples:
Using MIC as the source and HFP as the output MIC Source Play.
Using line-in as the source and A2DP as the output Line-in Source Play (A2DP Output).
Using line-in as the source and BIS as the output Line-in Source Play (BIS Output).
Using line-in as the source and CIS as the output Line-in Source Play (CIS Output).
Using USB as the source and BIS as the output USB Source Play (BIS Output).
Using SD card as the source and local play as the output SD Card Source Play.
Using SD card as the source and BIS/CIS as the output SD Card Source Play (BIS/CIS Output).
Using line-in/I2S as the source and multilink A2DP as the output Multilink A2DP Source Play.
MIC Source Play
Before using, configure MIC 1 on the EVB and connect an external MIC. After connecting the MIC and starting the recording, the recorded data will be sent to the connected BUD via HFP. The MIC source playback process is:
ACI Host CLI Test
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_SRC_PLAY_SET_SRC_ROUTE(0x3300) |
action = mic(0x01, 0x00) |
set_route_in mic |
CMD_SRC_PLAY_SET_PLAY_ROUTE(0x3302) |
action = hfp_ag(0x02) |
set_route_out hfp_ag |
CMD_SRC_PLAY_ROUTE_IN_START(0x3304) |
None |
route_in start |
CMD_SRC_PLAY_ROUTE_IN_STOP(0x3305) |
None |
route_in stop |
CMD_SRC_PLAY_ROUTE_OUT_START(0x3306) |
None |
route_out start |
CMD_SRC_PLAY_ROUTE_OUT_STOP(0x3307) |
None |
route_out stop |
The ACI Host sends CMD_SRC_PLAY_SET_SRC_ROUTE
to ACI Device to set the MIC input route, sends CMD_SRC_PLAY_SET_PLAY_ROUTE
to set HFP output route, sends CMD_SRC_PLAY_ROUTE_IN_START
or CMD_SRC_PLAY_ROUTE_IN_STOP
to start or stop the MIC input route, and sends CMD_SRC_PLAY_ROUTE_OUT_START
or CMD_SRC_PLAY_ROUTE_OUT_STOP
to start or stop the HFP output route.
ACI Host CLI test: Connect ACI Device to BUD.
Please refer to Connect to BUD.
ACI Host CLI test: Input
set_route_in mic
.2023-04-18 18:35:04,933 INFO: input command: set_route_in mic 2023-04-18 18:35:04,933 INFO: Parser cmdParser: cmd opcode: 3300 param: [01 00] name: CMD_SRC_PLAY_SET_SRC_ROUTE 2023-04-18 18:35:04,934 INFO: Packet sendPacket: <<<send packet: AA 10 03 00 00 33 01 00 B9 2023-04-18 18:35:04,956 INFO: AciHostCLI continuously_read: >>>receive packet: AA 10 05 00 00 00 00 33 00 B8 2023-04-18 18:35:04,963 INFO: Parser eventParser: syncWord: AA,seqn: 10,len: 5,opcode: 0000,params: [00 33 00], check_sum: B8 2023-04-18 18:35:04,966 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-18 18:35:04,983 INFO: Parser eventParser: event_id: [00 33] 2023-04-18 18:35:04,986 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
set_route_out hfp_ag
.2023-04-18 18:35:18,259 INFO: input command: set_route_out hfp_ag 2023-04-18 18:35:18,260 INFO: Parser cmdParser: cmd opcode: 3302 param: [02] name: CMD_SRC_PLAY_SET_PLAY_ROUTE 2023-04-18 18:35:18,262 INFO: Packet sendPacket: <<<send packet: AA 11 03 00 02 33 02 B5 2023-04-18 18:35:18,279 INFO: AciHostCLI continuously_read: >>>receive packet: AA 11 05 00 00 00 02 33 00 B5 2023-04-18 18:35:18,284 INFO: Parser eventParser: syncWord: AA,seqn: 11,len: 5,opcode: 0000,params: [02 33 00], check_sum: B5 2023-04-18 18:35:18,285 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-18 18:35:18,286 INFO: Parser eventParser: event_id: [02 33] 2023-04-18 18:35:18,287 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_out start
.2023-04-18 18:35:29,323 INFO: input command: route_out start 2023-04-18 18:35:29,324 INFO: Parser cmdParser: cmd opcode: 3306 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_START 2023-04-18 18:35:29,326 INFO: Packet sendPacket: <<<send packet: AA 12 02 00 06 33 B3 2023-04-18 18:35:29,338 INFO: AciHostCLI continuously_read: >>>receive packet: AA 12 05 00 00 00 06 33 00 B0 2023-04-18 18:35:29,339 INFO: Parser eventParser: syncWord: AA,seqn: 12,len: 5,opcode: 0000,params: [06 33 00], check_sum: B0 2023-04-18 18:35:29,347 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-18 18:35:29,351 INFO: Parser eventParser: event_id: [06 33] 2023-04-18 18:35:29,353 INFO: Parser eventParser: status: [00] 2023-04-18 18:35:29,539 INFO: AciHostCLI continuously_read: >>>receive packet: AA 13 04 00 38 03 00 02 AC 2023-04-18 18:35:29,540 INFO: Parser eventParser: syncWord: AA,seqn: 13,len: 4,opcode: 0338,params: [00 02], check_sum: AC 2023-04-18 18:35:29,542 INFO: Packet sendPacket: <<<send packet: AA 13 05 00 00 00 38 03 00 AD 2023-04-18 18:35:29,555 INFO: AciHostCLI continuously_read: >>>receive packet: AA 14 04 00 00 03 00 01 E4 2023-04-18 18:35:29,556 INFO: Parser eventParser: syncWord: AA,seqn: 14,len: 4,opcode: 0300,params: [00 01], check_sum: E4 2023-04-18 18:35:29,557 INFO: Parser eventParser: event name: APP_EVENT_SCO_STATE 2023-04-18 18:35:29,561 INFO: Parser eventParser: app_link_id: [00] 2023-04-18 18:35:29,563 INFO: Parser eventParser: state: [01] 2023-04-18 18:35:29,565 INFO: Packet sendPacket: <<<send packet: AA 14 05 00 00 00 00 03 00 E4
ACI Host CLI test: Input
route_in start
.2023-04-18 18:35:43,561 INFO: input command: route_in start 2023-04-18 18:35:43,562 INFO: Parser cmdParser: cmd opcode: 3304 param: [] name: CMD_SRC_PLAY_ROUTE_IN_START 2023-04-18 18:35:43,563 INFO: Packet sendPacket: <<<send packet: AA 15 02 00 04 33 B2 2023-04-18 18:35:43,597 INFO: AciHostCLI continuously_read: >>>receive packet: AA 15 05 00 00 00 04 33 00 AF 2023-04-18 18:35:43,610 INFO: Parser eventParser: syncWord: AA,seqn: 15,len: 5,opcode: 0000,params: [04 33 00], check_sum: AF 2023-04-18 18:35:43,612 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-18 18:35:43,614 INFO: Parser eventParser: event_id: [04 33] 2023-04-18 18:35:43,615 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_in stop
.2023-04-18 18:36:05,128 INFO: input command: route_in stop 2023-04-18 18:36:05,128 INFO: Parser cmdParser: cmd opcode: 3305 param: [] name: CMD_SRC_PLAY_ROUTE_IN_STOP 2023-04-18 18:36:05,130 INFO: Packet sendPacket: <<<send packet: AA 16 02 00 05 33 B0 2023-04-18 18:36:05,145 INFO: AciHostCLI continuously_read: >>>receive packet: AA 16 05 00 00 00 05 33 00 AD 2023-04-18 18:36:05,166 INFO: Parser eventParser: syncWord: AA,seqn: 16,len: 5,opcode: 0000,params: [05 33 00], check_sum: AD 2023-04-18 18:36:05,167 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-18 18:36:05,168 INFO: Parser eventParser: event_id: [05 33] 2023-04-18 18:36:05,170 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_out stop
.2023-04-18 18:36:32,207 INFO: input command: route_out stop 2023-04-18 18:36:32,208 INFO: Parser cmdParser: cmd opcode: 3307 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_STOP 2023-04-18 18:36:32,210 INFO: Packet sendPacket: <<<send packet: AA 18 02 00 07 33 AC 2023-04-18 18:36:32,221 INFO: AciHostCLI continuously_read: >>>receive packet: AA 18 05 00 00 00 07 33 00 A9 2023-04-18 18:36:32,227 INFO: Parser eventParser: syncWord: AA,seqn: 18,len: 5,opcode: 0000,params: [07 33 00], check_sum: A9 2023-04-18 18:36:32,230 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-18 18:36:32,232 INFO: Parser eventParser: event_id: [07 33] 2023-04-18 18:36:32,233 INFO: Parser eventParser: status: [00] 2023-04-18 18:36:32,285 INFO: AciHostCLI continuously_read: >>>receive packet: AA 19 04 00 00 03 00 00 E0 2023-04-18 18:36:32,286 INFO: Parser eventParser: syncWord: AA,seqn: 19,len: 4,opcode: 0300,params: [00 00], check_sum: E0 2023-04-18 18:36:32,287 INFO: Parser eventParser: event name: APP_EVENT_SCO_STATE 2023-04-18 18:36:32,288 INFO: Parser eventParser: app_link_id: [00] 2023-04-18 18:36:32,288 INFO: Parser eventParser: state: [00] 2023-04-18 18:36:32,290 INFO: Packet sendPacket: <<<send packet: AA 19 05 00 00 00 00 03 00 DF
Line-in Source Play (A2DP Output)
Before using, please configure MIC 2 on the EVB and connect to PC through line-in. After line-in is connected and music on PC is started, the music data will be sent to the connected BUD through A2DP.
Line-in source play (A2DP output) process:
ACI Host CLI Test
The ACI Host sends CMD_SRC_PLAY_SET_SRC_ROUTE
to ACI Device to set the line-in input route, sends CMD_SRC_PLAY_SET_PLAY_ROUTE
to set A2DP output route, sends CMD_SRC_PLAY_ROUTE_IN_START/STOP
to start or stop the line-in input route, and sends CMD_SRC_PLAY_ROUTE_OUT_START/STOP
to start or stop the A2DP output route.
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_SRC_PLAY_SET_SRC_ROUTE(0x3300) |
action = linein(0x02, 0x00) |
set_route_in linein |
CMD_SRC_PLAY_SET_PLAY_ROUTE(0x3302) |
action = a2dp(0x01) |
set_route_out a2dp |
CMD_SRC_PLAY_ROUTE_IN_START(0x3304) |
route_in start |
|
CMD_SRC_PLAY_ROUTE_IN_STOP(0x3305) |
None |
route_in stop |
CMD_SRC_PLAY_ROUTE_OUT_START(0x3306) |
None |
route_out start |
CMD_SRC_PLAY_ROUTE_OUT_STOP(0x3307) |
None |
route_out stop |
ACI Host CLI test: Connect ACI Device to BUD.
Please refer to Connect to BUD.
ACI Host CLI test: Input
set_route_in line-in
.2023-04-18 18:37:54,643 INFO: input command: set_route_in linein 2023-04-18 18:37:54,643 INFO: Parser cmdParser: cmd opcode: 3300 param: [02 00] name: CMD_SRC_PLAY_SET_SRC_ROUTE 2023-04-18 18:37:54,645 INFO: Packet sendPacket: <<<send packet: AA 29 03 00 00 33 02 00 9F 2023-04-18 18:37:54,658 INFO: AciHostCLI continuously_read: >>>receive packet: AA 10 05 00 00 00 00 33 00 B8 2023-04-18 18:37:54,663 INFO: Parser eventParser: syncWord: AA,seqn: 10,len: 5,opcode: 0000,params: [00 33 00], check_sum: B8 2023-04-18 18:37:54,667 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-18 18:37:54,670 INFO: Parser eventParser: event_id: [00 33] 2023-04-18 18:37:54,672 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
set_route_out a2dp
.2023-04-18 18:38:07,087 INFO: input command: set_route_out a2dp 2023-04-18 18:38:07,088 INFO: Parser cmdParser: cmd opcode: 3302 param: [01] name: CMD_SRC_PLAY_SET_PLAY_ROUTE 2023-04-18 18:38:07,090 INFO: Packet sendPacket: <<<send packet: AA 2A 03 00 02 33 01 9D 2023-04-18 18:38:07,101 INFO: AciHostCLI continuously_read: >>>receive packet: AA 11 05 00 00 00 02 33 00 B5 2023-04-18 18:38:07,113 INFO: Parser eventParser: syncWord: AA,seqn: 11,len: 5,opcode: 0000,params: [02 33 00], check_sum: B5 2023-04-18 18:38:07,116 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-18 18:38:07,116 INFO: Parser eventParser: event_id: [02 33] 2023-04-18 18:38:07,117 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_out start
.2023-04-18 18:38:23,684 INFO: input command: route_out start 2023-04-18 18:38:23,685 INFO: Parser cmdParser: cmd opcode: 3306 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_START 2023-04-18 18:38:23,685 INFO: Packet sendPacket: <<<send packet: AA 2B 02 00 06 33 9A 2023-04-18 18:38:23,699 INFO: AciHostCLI continuously_read: >>>receive packet: AA 12 05 00 00 00 06 33 00 B0 2023-04-18 18:38:23,702 INFO: Parser eventParser: syncWord: AA,seqn: 12,len: 5,opcode: 0000,params: [06 33 00], check_sum: B0 2023-04-18 18:38:23,708 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-18 18:38:23,708 INFO: Parser eventParser: event_id: [06 33] 2023-04-18 18:38:23,709 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_in start
.2023-04-18 18:38:26,773 INFO: input command: route_in start 2023-04-18 18:38:26,774 INFO: Parser cmdParser: cmd opcode: 3304 param: [] name: CMD_SRC_PLAY_ROUTE_IN_START 2023-04-18 18:38:26,775 INFO: Packet sendPacket: <<<send packet: AA 2C 02 00 04 33 9B 2023-04-18 18:38:26,796 INFO: AciHostCLI continuously_read: >>>receive packet: AA 13 05 00 00 00 04 33 00 B1 2023-04-18 18:38:26,798 INFO: Parser eventParser: syncWord: AA,seqn: 13,len: 5,opcode: 0000,params: [04 33 00], check_sum: B1 2023-04-18 18:38:26,798 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-18 18:38:26,799 INFO: Parser eventParser: event_id: [04 33] 2023-04-18 18:38:26,800 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_in stop
.2023-04-18 18:39:21,706 INFO: input command: route_in stop 2023-04-18 18:39:21,707 INFO: Parser cmdParser: cmd opcode: 3305 param: [] name: CMD_SRC_PLAY_ROUTE_IN_STOP 2023-04-18 18:39:21,708 INFO: Packet sendPacket: <<<send packet: AA 2D 02 00 05 33 99 2023-04-18 18:39:21,712 INFO: AciHostCLI continuously_read: >>>receive packet: AA 14 05 00 00 00 05 33 00 AF 2023-04-18 18:39:21,719 INFO: Parser eventParser: syncWord: AA,seqn: 14,len: 5,opcode: 0000,params: [05 33 00], check_sum: AF 2023-04-18 18:39:21,723 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-18 18:39:21,723 INFO: Parser eventParser: event_id: [05 33] 2023-04-18 18:39:21,726 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_out stop
.2023-04-18 18:39:44,974 INFO: input command: route_out stop 2023-04-18 18:39:44,974 INFO: Parser cmdParser: cmd opcode: 3307 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_STOP 2023-04-18 18:39:44,976 INFO: Packet sendPacket: <<<send packet: AA 2F 02 00 07 33 95 2023-04-18 18:39:45,044 INFO: AciHostCLI continuously_read: >>>receive packet: AA 16 05 00 00 00 07 33 00 AB 2023-04-18 18:39:45,046 INFO: Parser eventParser: syncWord: AA,seqn: 16,len: 5,opcode: 0000,params: [07 33 00], check_sum: AB 2023-04-18 18:39:45,047 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-18 18:39:45,052 INFO: Parser eventParser: event_id: [07 33] 2023-04-18 18:39:45,055 INFO: Parser eventParser: status: [00]
Line-in Source Play (BIS Output)
Before using, please configure MIC 2 on the EVB and connect to PC through line-in. After line-in is connected and music on the PC is started, the music data could be sent to the BUD(s) through BIS.
BIS supports configuring codec type (48k/16k), BIS number (1 BIS containing dual-channel data or 2 BIS containing separate L and R channel data), ULL mode (E2E Latency < 30ms), and other parameters. For details, please refer to ACI_CMD_LEA_BSRC_INIT.
Line-in source play (BIS Output) process:
ACI Host CLI Test
When using BIS as output path, it is necessary to initialize BIS first through CMD_LEA_BSRC_INIT
.
The ACI Host sends CMD_SRC_PLAY_SET_SRC_ROUTE
to ACI Device to set the line-in input route, sends
CMD_SRC_PLAY_SET_PLAY_ROUTE
to set BIS output route, sends CMD_SRC_PLAY_ROUTE_IN_START/STOP
to
start or stop the line-in input route, and sends CMD_SRC_PLAY_ROUTE_OUT_START/STOP
(other than
CMD_LEA_BSRC_START/STOP
) to start or stop the BIS output route.
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_LEA_BSRC_INIT(0x3020) |
codec type = CODEC_CFG_ITEM_48_4(48k) |
bsrcinit 48k_2bis |
CMD_SRC_PLAY_SET_SRC_ROUTE(0x3300) |
action = linein(0x02, 0x00) |
set_route_in linein |
CMD_SRC_PLAY_SET_PLAY_ROUTE(0x3302) |
action = BIS(0x03) |
set_route_out bis |
CMD_SRC_PLAY_ROUTE_IN_START(0x3304) |
None |
route_in start |
CMD_SRC_PLAY_ROUTE_IN_STOP(0x3305) |
None |
route_in stop |
CMD_SRC_PLAY_ROUTE_OUT_START(0x3306) |
None |
route_out start |
CMD_SRC_PLAY_ROUTE_OUT_STOP(0x3307) |
None |
route_out stop |
ACI Host CLI test: Initialize BIS.
2023-05-31 10:25:21,803 INFO: input command: bsrcinit 48k_2bis 2023-05-31 10:25:21,803 INFO: Parser cmdParser: cmd opcode: 3020 param: [0D 02 00 01 10 27] name: CMD_LEA_BSRC_INIT 2023-05-31 10:25:21,803 INFO: Packet sendPacket: <<<send packet: AA 0C 07 00 20 30 0D 02 00 01 10 27 11 2023-05-31 10:25:21,834 INFO: AciHostCLI continuously_read: >>>receive packet: AA 03 05 00 00 00 20 30 00 C6 2023-05-31 10:25:21,834 INFO: Parser eventParser: syncWord: AA,seqn: 03,len: 5,opcode: 0000,params: [20 30 00], check_sum: C6 2023-05-31 10:25:21,834 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-31 10:25:21,834 INFO: Parser eventParser: event_id: [20 30] 2023-05-31 10:25:21,834 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
set_route_out bis
.2023-05-31 10:24:33,516 INFO: input command: set_route_out bis 2023-05-31 10:24:33,516 INFO: Parser cmdParser: cmd opcode: 3302 param: [03] name: CMD_SRC_PLAY_SET_PLAY_ROUTE 2023-05-31 10:24:33,526 INFO: Packet sendPacket: <<<send packet: AA 04 03 00 02 33 03 C1 2023-05-31 10:24:33,546 INFO: AciHostCLI continuously_read: >>>receive packet: AA 04 05 00 00 00 02 33 00 C2 2023-05-31 10:24:33,546 INFO: Parser eventParser: syncWord: AA,seqn: 04,len: 5,opcode: 0000,params: [02 33 00], check_sum: C2 2023-05-31 10:24:33,546 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-31 10:24:33,546 INFO: Parser eventParser: event_id: [02 33] 2023-05-31 10:24:33,546 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
set_route_in line-in
.2023-05-31 10:24:36,385 INFO: input command: set_route_in linein 2023-05-31 10:24:36,385 INFO: Parser cmdParser: cmd opcode: 3300 param: [02 00] name: CMD_SRC_PLAY_SET_SRC_ROUTE 2023-05-31 10:24:36,385 INFO: Packet sendPacket: <<<send packet: AA 05 03 00 00 33 02 00 C3 2023-05-31 10:24:36,405 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 05 00 00 00 00 33 00 C3 2023-05-31 10:24:36,405 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 5,opcode: 0000,params: [00 33 00], check_sum: C3 2023-05-31 10:24:36,405 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-31 10:24:36,405 INFO: Parser eventParser: event_id: [00 33] 2023-05-31 10:24:36,415 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_out start
.2023-05-31 10:24:39,606 INFO: input command: route_out start 2023-05-31 10:24:39,616 INFO: Parser cmdParser: cmd opcode: 3306 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_START 2023-05-31 10:24:39,616 INFO: Packet sendPacket: <<<send packet: AA 06 02 00 06 33 BF 2023-05-31 10:24:39,626 INFO: AciHostCLI continuously_read: >>>receive packet: AA 06 05 00 00 00 06 33 00 BC 2023-05-31 10:24:39,626 INFO: Parser eventParser: syncWord: AA,seqn: 06,len: 5,opcode: 0000,params: [06 33 00], check_sum: BC 2023-05-31 10:24:39,626 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-31 10:24:39,626 INFO: Parser eventParser: event_id: [06 33] 2023-05-31 10:24:39,626 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_in start
.2023-05-31 10:24:42,685 INFO: input command: route_in start 2023-05-31 10:24:42,695 INFO: Parser cmdParser: cmd opcode: 3304 param: [] name: CMD_SRC_PLAY_ROUTE_IN_START 2023-05-31 10:24:42,695 INFO: Packet sendPacket: <<<send packet: AA 07 02 00 04 33 C0 2023-05-31 10:24:42,755 INFO: AciHostCLI continuously_read: >>>receive packet: AA 07 05 00 00 00 04 33 00 BD 2023-05-31 10:24:42,755 INFO: Parser eventParser: syncWord: AA,seqn: 07,len: 5,opcode: 0000,params: [04 33 00], check_sum: BD 2023-05-31 10:24:42,755 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-31 10:24:42,755 INFO: Parser eventParser: event_id: [04 33] 2023-05-31 10:24:42,755 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_in stop
.2023-05-31 10:24:50,746 INFO: input command: route_in stop 2023-05-31 10:24:50,746 INFO: Parser cmdParser: cmd opcode: 3305 param: [] name: CMD_SRC_PLAY_ROUTE_IN_STOP 2023-05-31 10:24:50,746 INFO: Packet sendPacket: <<<send packet: AA 08 02 00 05 33 BE 2023-05-31 10:24:50,766 INFO: AciHostCLI continuously_read: >>>receive packet: AA 08 05 00 00 00 05 33 00 BB 2023-05-31 10:24:50,766 INFO: Parser eventParser: syncWord: AA,seqn: 08,len: 5,opcode: 0000,params: [05 33 00], check_sum: BB 2023-05-31 10:24:50,766 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-31 10:24:50,766 INFO: Parser eventParser: event_id: [05 33] 2023-05-31 10:24:50,766 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_out stop
.2023-05-31 10:25:04,644 INFO: input command: route_out stop 2023-05-31 10:25:04,644 INFO: Parser cmdParser: cmd opcode: 3307 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_STOP 2023-05-31 10:25:04,644 INFO: Packet sendPacket: <<<send packet: AA 09 02 00 07 33 BB 2023-05-31 10:25:04,664 INFO: AciHostCLI continuously_read: >>>receive packet: AA 09 05 00 00 00 07 33 00 B8 2023-05-31 10:25:04,664 INFO: Parser eventParser: syncWord: AA,seqn: 09,len: 5,opcode: 0000,params: [07 33 00], check_sum: B8 2023-05-31 10:25:04,674 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-31 10:25:04,674 INFO: Parser eventParser: event_id: [07 33] 2023-05-31 10:25:04,674 INFO: Parser eventParser: status: [00]
Line-in Source Play (CIS Output)
Before using, please configure MIC 2 on the EVB and connect to PC through line-in. After line-in is connected and music on PC is started, the music data can be sent to the connected BUD(s) through CIS.
In this scenario, CIS supports only the downlink direction of the datapath. The codec type is
determined through negotiation (refer to app_lea_ini_select_media_prefer_codec()
). In ULL mode
(configured through the CMD_LEA_CIS_ULL_MODE
command, and E2E Latency < 30ms), 48_1
is preferred,
while in non-ULL mode, 48_6
takes precedence.
CIS connection process: Please refer to ACI Host CLI Test: Advertising.
Line-in source play (CIS Output) process:
ACI Host CLI Test
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_SRC_PLAY_SET_SRC_ROUTE(0x3300) |
action = linein(0x02, 0x00) |
set_route_in linein |
CMD_SRC_PLAY_SET_PLAY_ROUTE(0x3302) |
action = cis(0x04) |
set_route_out cis |
CMD_SRC_PLAY_ROUTE_IN_START(0x3304) |
None |
route_in start |
CMD_SRC_PLAY_ROUTE_IN_STOP(0x3305) |
None |
route_in stop |
CMD_SRC_PLAY_ROUTE_OUT_START(0x3306) |
None |
route_out start |
CMD_SRC_PLAY_ROUTE_OUT_STOP(0x3307) |
None |
route_out stop |
For CIS, it is necessary to establish an LE link. Please refer to Initiator General ACI Host CLI Test for connection procedure.
The ACI Host sends CMD_SRC_PLAY_SET_SRC_ROUTE
to ACI Device to set the line-in input route, sends
CMD_SRC_PLAY_SET_PLAY_ROUTE
to set CIS output route, sends CMD_SRC_PLAY_ROUTE_IN_START/STOP
to
start or stop the line-in input route, and sends CMD_SRC_PLAY_ROUTE_OUT_START/STOP
to start or stop
the CIS output route.
ACI Host CLI test: Input
set_route_in line-in
.2023-07-17 16:00:30,147 INFO: input command: set_route_in linein 2023-07-17 16:00:30,147 INFO: Parser cmdParser: cmd opcode: 3300 param: [02 00] name: CMD_SRC_PLAY_SET_SRC_ROUTE 2023-07-17 16:00:30,148 INFO: Packet sendPacket: <<<send packet: AA 16 03 00 00 33 02 00 B2 2023-07-17 16:00:30,154 INFO: AciHostCLI continuously_read: >>>receive packet: AA 16 05 00 00 00 00 33 00 B2 2023-07-17 16:00:30,155 INFO: Parser eventParser: syncWord: AA,seqn: 16,len: 5,opcode: 0000,params: [00 33 00], check_sum: B2 2023-07-17 16:00:30,158 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-17 16:00:30,159 INFO: Parser eventParser: event_id: [00 33] 2023-07-17 16:00:30,160 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
set_route_out cis
.2023-07-17 16:00:34,130 INFO: input command: set_route_out cis 2023-07-17 16:00:34,130 INFO: Parser cmdParser: cmd opcode: 3302 param: [04] name: CMD_SRC_PLAY_SET_PLAY_ROUTE 2023-07-17 16:00:34,131 INFO: Packet sendPacket: <<<send packet: AA 17 03 00 02 33 04 AD 2023-07-17 16:00:34,148 INFO: AciHostCLI continuously_read: >>>receive packet: AA 17 05 00 00 00 02 33 00 AF 2023-07-17 16:00:34,149 INFO: Parser eventParser: syncWord: AA,seqn: 17,len: 5,opcode: 0000,params: [02 33 00], check_sum: AF 2023-07-17 16:00:34,149 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-17 16:00:34,150 INFO: Parser eventParser: event_id: [02 33] 2023-07-17 16:00:34,150 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_out start
and the BAP state will transition to state 4 (AUDIO_STREAM_STATE_STREAMING
).2023-07-17 16:00:37,182 INFO: input command: route_out start 2023-07-17 16:00:37,182 INFO: Parser cmdParser: cmd opcode: 3306 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_START 2023-07-17 16:00:37,183 INFO: Packet sendPacket: <<<send packet: AA 18 02 00 06 33 AD 2023-07-17 16:00:37,199 INFO: AciHostCLI continuously_read: >>>receive packet: AA 18 05 00 00 00 06 33 00 AA 2023-07-17 16:00:37,199 INFO: Parser eventParser: syncWord: AA,seqn: 18,len: 5,opcode: 0000,params: [06 33 00], check_sum: AA 2023-07-17 16:00:37,200 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-17 16:00:37,201 INFO: Parser eventParser: event_id: [06 33] 2023-07-17 16:00:37,201 INFO: Parser eventParser: status: [00] 2023-07-17 16:00:37,202 INFO: AciHostCLI continuously_read: >>>receive packet: AA 19 07 00 0C 01 90 B3 2C 00 01 63 2023-07-17 16:00:37,202 INFO: Parser eventParser: syncWord: AA,seqn: 19,len: 7,opcode: 010C,params: [90 B3 2C 00 01], check_sum: 63 2023-07-17 16:00:37,203 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-07-17 16:00:37,203 INFO: Parser eventParser: group_handle: [90 B3 2C 00] 2023-07-17 16:00:37,203 INFO: Parser eventParser: state: [01] 2023-07-17 16:00:37,204 INFO: Packet sendPacket: <<<send packet: AA 19 05 00 00 00 0C 01 00 D5 2023-07-17 16:00:37,215 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1A 07 00 0C 01 90 B3 2C 00 03 60 2023-07-17 16:00:37,215 INFO: Parser eventParser: syncWord: AA,seqn: 1A,len: 7,opcode: 010C,params: [90 B3 2C 00 03], check_sum: 60 2023-07-17 16:00:37,216 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-07-17 16:00:37,216 INFO: Parser eventParser: group_handle: [90 B3 2C 00] 2023-07-17 16:00:37,217 INFO: Parser eventParser: state: [03] 2023-07-17 16:00:37,217 INFO: Packet sendPacket: <<<send packet: AA 1A 05 00 00 00 0C 01 00 D4 2023-07-17 16:00:38,365 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1B 0A 00 44 80 00 00 24 00 00 00 E8 03 08 2023-07-17 16:00:38,366 INFO: Parser eventParser: syncWord: AA,seqn: 1B,len: 10,opcode: 8044,params: [00 00 24 00 00 00 E8 03], check_sum: 08 2023-07-17 16:00:38,367 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM 2023-07-17 16:00:38,367 INFO: Parser eventParser: app_link_id: [00] 2023-07-17 16:00:38,367 INFO: Parser eventParser: res: [00] 2023-07-17 16:00:38,368 INFO: Parser eventParser: connInterval: [24 00] 2023-07-17 16:00:38,368 INFO: Parser eventParser: connLatency: [00 00] 2023-07-17 16:00:38,369 INFO: Parser eventParser: supTimeout: [E8 03] 2023-07-17 16:00:38,370 INFO: Packet sendPacket: <<<send packet: AA 1B 05 00 00 00 44 80 00 1C 2023-07-17 16:00:39,595 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1C 0A 00 44 80 01 00 6C 00 00 00 F4 01 B4 2023-07-17 16:00:39,596 INFO: Parser eventParser: syncWord: AA,seqn: 1C,len: 10,opcode: 8044,params: [01 00 6C 00 00 00 F4 01], check_sum: B4 2023-07-17 16:00:39,596 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM 2023-07-17 16:00:39,597 INFO: Parser eventParser: app_link_id: [01] 2023-07-17 16:00:39,597 INFO: Parser eventParser: res: [00] 2023-07-17 16:00:39,597 INFO: Parser eventParser: connInterval: [6C 00] 2023-07-17 16:00:39,598 INFO: Parser eventParser: connLatency: [00 00] 2023-07-17 16:00:39,598 INFO: Parser eventParser: supTimeout: [F4 01] 2023-07-17 16:00:39,599 INFO: Packet sendPacket: <<<send packet: AA 1C 05 00 00 00 44 80 00 1B 2023-07-17 16:00:41,000 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1D 0A 00 44 80 01 00 24 00 00 00 F4 01 FB 2023-07-17 16:00:41,001 INFO: Parser eventParser: syncWord: AA,seqn: 1D,len: 10,opcode: 8044,params: [01 00 24 00 00 00 F4 01], check_sum: FB 2023-07-17 16:00:41,002 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM 2023-07-17 16:00:41,002 INFO: Parser eventParser: app_link_id: [01] 2023-07-17 16:00:41,003 INFO: Parser eventParser: res: [00] 2023-07-17 16:00:41,003 INFO: Parser eventParser: connInterval: [24 00] 2023-07-17 16:00:41,003 INFO: Parser eventParser: connLatency: [00 00] 2023-07-17 16:00:41,004 INFO: Parser eventParser: supTimeout: [F4 01] 2023-07-17 16:00:41,004 INFO: Packet sendPacket: <<<send packet: AA 1D 05 00 00 00 44 80 00 1A 2023-07-17 16:00:41,448 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1E 07 00 0C 01 90 B3 2C 00 04 5B 2023-07-17 16:00:41,449 INFO: Parser eventParser: syncWord: AA,seqn: 1E,len: 7,opcode: 010C,params: [90 B3 2C 00 04], check_sum: 5B 2023-07-17 16:00:41,449 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-07-17 16:00:41,450 INFO: Parser eventParser: group_handle: [90 B3 2C 00] 2023-07-17 16:00:41,451 INFO: Parser eventParser: state: [04] 2023-07-17 16:00:41,451 INFO: Packet sendPacket: <<<send packet: AA 1E 05 00 00 00 0C 01 00 D0
ACI Host CLI test: Input
route_in start
.2023-07-17 16:00:45,813 INFO: input command: route_in start 2023-07-17 16:00:45,814 INFO: Parser cmdParser: cmd opcode: 3304 param: [] name: CMD_SRC_PLAY_ROUTE_IN_START 2023-07-17 16:00:45,814 INFO: Packet sendPacket: <<<send packet: AA 1F 02 00 04 33 A8 2023-07-17 16:00:45,873 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1F 05 00 00 00 04 33 00 A5 2023-07-17 16:00:45,874 INFO: Parser eventParser: syncWord: AA,seqn: 1F,len: 5,opcode: 0000,params: [04 33 00], check_sum: A5 2023-07-17 16:00:45,874 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-17 16:00:45,875 INFO: Parser eventParser: event_id: [04 33] 2023-07-17 16:00:45,875 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_out stop
, and the BAP state will transition to state 1 (AUDIO_STREAM_STATE_IDLE_CONFIGURED
).2023-07-17 16:07:29,020 INFO: input command: route_out stop 2023-07-17 16:07:29,020 INFO: Parser cmdParser: cmd opcode: 3307 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_STOP 2023-07-17 16:07:29,021 INFO: Packet sendPacket: <<<send packet: AA 01 02 00 07 33 C3 2023-07-17 16:07:29,041 INFO: AciHostCLI continuously_read: >>>receive packet: AA 20 05 00 00 00 07 33 00 A1 2023-07-17 16:07:29,042 INFO: Parser eventParser: syncWord: AA,seqn: 20,len: 5,opcode: 0000,params: [07 33 00], check_sum: A1 2023-07-17 16:07:29,043 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-17 16:07:29,043 INFO: Parser eventParser: event_id: [07 33] 2023-07-17 16:07:29,044 INFO: Parser eventParser: status: [00] 2023-07-17 16:07:29,044 INFO: AciHostCLI continuously_read: >>>receive packet: AA 21 07 00 0C 01 90 B3 2C 00 07 55 2023-07-17 16:07:29,045 INFO: Parser eventParser: syncWord: AA,seqn: 21,len: 7,opcode: 010C,params: [90 B3 2C 00 07], check_sum: 55 2023-07-17 16:07:29,045 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-07-17 16:07:29,045 INFO: Parser eventParser: group_handle: [90 B3 2C 00] 2023-07-17 16:07:29,046 INFO: Parser eventParser: state: [07] 2023-07-17 16:07:29,046 INFO: Packet sendPacket: <<<send packet: AA 02 05 00 00 00 0C 01 00 EC 2023-07-17 16:07:29,265 INFO: AciHostCLI continuously_read: >>>receive packet: AA 22 07 00 0C 01 90 B3 2C 00 01 5A 2023-07-17 16:07:29,265 INFO: Parser eventParser: syncWord: AA,seqn: 22,len: 7,opcode: 010C,params: [90 B3 2C 00 01], check_sum: 5A 2023-07-17 16:07:29,266 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2023-07-17 16:07:29,266 INFO: Parser eventParser: group_handle: [90 B3 2C 00] 2023-07-17 16:07:29,267 INFO: Parser eventParser: state: [01] 2023-07-17 16:07:29,267 INFO: Packet sendPacket: <<<send packet: AA 03 05 00 00 00 0C 01 00 EB
ACI Host CLI test: Input
route_in stop
.2023-07-17 16:07:33,327 INFO: input command: route_in stop 2023-07-17 16:07:33,327 INFO: Parser cmdParser: cmd opcode: 3305 param: [] name: CMD_SRC_PLAY_ROUTE_IN_STOP 2023-07-17 16:07:33,328 INFO: Packet sendPacket: <<<send packet: AA 04 02 00 05 33 C2 2023-07-17 16:07:33,338 INFO: AciHostCLI continuously_read: >>>receive packet: AA 23 05 00 00 00 05 33 00 A0 2023-07-17 16:07:33,339 INFO: Parser eventParser: syncWord: AA,seqn: 23,len: 5,opcode: 0000,params: [05 33 00], check_sum: A0 2023-07-17 16:07:33,340 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-17 16:07:33,340 INFO: Parser eventParser: event_id: [05 33] 2023-07-17 16:07:33,341 INFO: Parser eventParser: status: [00]
USB Source Play (BIS Output)
Before using, please connect EVB to PC through USB, select EVB as the audio device. After USB cable is connected and music on PC is started, the music data could be sent to the BUD(s) through BIS.
BIS supports configuring codec type (48k/16k), BIS number (1 BIS containing dual-channel data or 2 BIS containing separate L and R channel data), ULL mode (E2E Latency < 30ms), and other parameters. For details, please refer to ACI_CMD_LEA_BSRC_INIT.
USB source play (BIS Output) process:
ACI Host CLI Test
When using BIS as the output path, it is necessary to initialize BIS firstly through CMD_LEA_BSRC_INIT
.
The ACI Host sends CMD_SRC_PLAY_SET_SRC_ROUTE
to ACI Device to set the USB input route, sends
CMD_SRC_PLAY_SET_PLAY_ROUTE
to set BIS output route, sends CMD_SRC_PLAY_ROUTE_IN_START/STOP
to
start or stop the USB input route, and sends CMD_SRC_PLAY_ROUTE_OUT_START/STOP
(other than
CMD_LEA_BSRC_START/STOP
) to start or stop the BIS output route.
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_LEA_BSRC_INIT(0x3020) |
codec type = CODEC_CFG_ITEM_48_4(48k) |
bsrcinit 48k_2bis |
CMD_SRC_PLAY_SET_SRC_ROUTE(0x3300) |
action = usb_ds(0x03, 0x01) |
set_route_in usb_ds |
CMD_SRC_PLAY_SET_PLAY_ROUTE(0x3302) |
action = bis(0x03) |
set_route_out bis |
CMD_SRC_PLAY_ROUTE_IN_START(0x3304) |
None |
route_in start |
CMD_SRC_PLAY_ROUTE_IN_STOP(0x3305) |
None |
route_in stop |
CMD_SRC_PLAY_ROUTE_OUT_START(0x3306) |
None |
route_out start |
CMD_SRC_PLAY_ROUTE_OUT_STOP(0x3307) |
None |
route_out stop |
ACI Host CLI test: Initialize BIS.
2023-09-13 10:35:17,929 INFO: input command: bsrcinit 48k_2bis 2023-09-13 10:35:17,930 INFO: Parser cmdParser: cmd opcode: 3020 param: [0B 02 00 00 10 27] name: CMD_LEA_BSRC_INIT 2023-09-13 10:35:17,931 INFO: Packet sendPacket: <<<send packet: AA 09 08 00 20 30 0B 02 00 00 10 27 5B 2023-09-13 10:35:17,940 INFO: AciHostCLI continuously_read: >>>receive packet: AA 04 05 00 00 00 20 30 00 A7 2023-09-13 10:35:17,943 INFO: Parser eventParser: syncWord: AA,seqn: 04,len: 5,opcode: 0000,params: [20 30 00], check_sum: A7 2023-09-13 10:35:17,944 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-09-13 10:35:17,944 INFO: Parser eventParser: event_id: [20 30] 2023-09-13 10:35:17,945 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
set_route_out bis
.2023-09-13 10:35:30,605 INFO: input command: set_route_out bis 2023-09-13 10:35:30,605 INFO: Parser cmdParser: cmd opcode: 3302 param: [03] name: CMD_SRC_PLAY_SET_PLAY_ROUTE 2023-09-13 10:35:30,606 INFO: Packet sendPacket: <<<send packet: AA 0B 03 00 02 33 03 BA 2023-09-13 10:35:30,617 INFO: AciHostCLI continuously_read: >>>receive packet: AA 06 05 00 00 00 02 33 00 C0 2023-09-13 10:35:30,617 INFO: Parser eventParser: syncWord: AA,seqn: 06,len: 5,opcode: 0000,params: [02 33 00], check_sum: C0 2023-09-13 10:35:30,618 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-09-13 10:35:30,620 INFO: Parser eventParser: event_id: [02 33] 2023-09-13 10:35:30,620 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
set_route_in usb
.2023-09-13 10:35:27,473 INFO: input command: set_route_in usb 2023-09-13 10:35:27,473 INFO: Parser cmdParser: cmd opcode: 3300 param: [03 01] name: CMD_SRC_PLAY_SET_SRC_ROUTE 2023-09-13 10:35:27,474 INFO: Packet sendPacket: <<<send packet: AA 0A 03 00 00 33 03 01 BD 2023-09-13 10:35:27,485 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 05 00 00 00 00 33 00 C3 2023-09-13 10:35:27,487 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 5,opcode: 0000,params: [00 33 00], check_sum: C3 2023-09-13 10:35:27,488 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-09-13 10:35:27,489 INFO: Parser eventParser: event_id: [00 33] 2023-09-13 10:35:27,490 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_out start
.2023-09-13 10:35:33,528 INFO: input command: route_out start 2023-09-13 10:35:33,529 INFO: Parser cmdParser: cmd opcode: 3306 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_START 2023-09-13 10:35:33,529 INFO: Packet sendPacket: <<<send packet: AA 0C 02 00 06 33 B9 2023-09-13 10:35:33,539 INFO: AciHostCLI continuously_read: >>>receive packet: AA 07 05 00 00 00 06 33 00 BB 2023-09-13 10:35:33,546 INFO: Parser eventParser: syncWord: AA,seqn: 07,len: 5,opcode: 0000,params: [06 33 00], check_sum: BB 2023-09-13 10:35:33,546 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-09-13 10:35:33,547 INFO: Parser eventParser: event_id: [06 33] 2023-09-13 10:35:33,548 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_in start
.2023-09-13 10:35:35,952 INFO: input command: route_in start 2023-09-13 10:35:35,952 INFO: Parser cmdParser: cmd opcode: 3304 param: [] name: CMD_SRC_PLAY_ROUTE_IN_START 2023-09-13 10:35:35,953 INFO: Packet sendPacket: <<<send packet: AA 0D 02 00 04 33 BA 2023-09-13 10:35:35,962 INFO: AciHostCLI continuously_read: >>>receive packet: AA 08 05 00 00 00 04 33 00 BC 2023-09-13 10:35:35,965 INFO: Parser eventParser: syncWord: AA,seqn: 08,len: 5,opcode: 0000,params: [04 33 00], check_sum: BC 2023-09-13 10:35:35,966 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-09-13 10:35:35,966 INFO: Parser eventParser: event_id: [04 33] 2023-09-13 10:35:35,967 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_in stop
.2023-09-13 11:24:27,143 INFO: input command: route_in stop 2023-09-13 11:24:27,143 INFO: Parser cmdParser: cmd opcode: 3305 param: [] name: CMD_SRC_PLAY_ROUTE_IN_STOP 2023-09-13 11:24:27,143 INFO: Packet sendPacket: <<<send packet: AA 0E 02 00 05 33 B8 2023-09-13 11:24:27,152 INFO: AciHostCLI continuously_read: >>>receive packet: AA 08 05 00 00 00 05 33 00 BB 2023-09-13 11:24:27,157 INFO: Parser eventParser: syncWord: AA,seqn: 08,len: 5,opcode: 0000,params: [05 33 00], check_sum: BB 2023-09-13 11:24:27,157 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-09-13 11:24:27,158 INFO: Parser eventParser: event_id: [05 33] 2023-09-13 11:24:27,159 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_out stop
.2023-09-13 11:23:57,789 INFO: input command: route_out stop 2023-09-13 11:23:57,789 INFO: Parser cmdParser: cmd opcode: 3307 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_STOP 2023-09-13 11:23:57,790 INFO: Packet sendPacket: <<<send packet: AA 0B 02 00 07 33 B9 2023-09-13 11:23:57,798 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 05 00 00 00 07 33 00 BC 2023-09-13 11:23:57,803 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 5,opcode: 0000,params: [07 33 00], check_sum: BC 2023-09-13 11:23:57,804 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-09-13 11:23:57,804 INFO: Parser eventParser: event_id: [07 33] 2023-09-13 11:23:57,805 INFO: Parser eventParser: status: [00]
USB Source Play (CIS Output)
Before using, please connect EVB to PC through USB, select EVB as the audio device. After USB cable is connected and music on PC is started, the music data could be sent to the BUD(s) through CIS.
In this scenario, CIS only sets up the downlink direction of the datapath. The codec type is
determined through negotiation (refer to app_lea_ini_select_media_prefer_codec()
). In ULL mode
(configured through the CMD_LEA_CIS_ULL_MODE
command, and E2E Latency < 30ms), 48_1
is preferred,
while in non-ULL mode, 48_6
takes precedence.
CIS connection process: Please refer to ACI Host CLI Test: Advertising.
USB source play (CIS Output) process:
ACI Host CLI Test
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_LEA_SCAN(0x3023) |
action = start(0x00) |
lea_scan start |
CMD_LEA_SCAN(0x3023) |
action = stop(0x01) |
lea_scan stop |
CMD_SRC_PLAY_SET_SRC_ROUTE(0x3300) |
action = usb_ds(0x03, 0x01) |
set_route_in usb_ds |
CMD_SRC_PLAY_SET_PLAY_ROUTE(0x3302) |
action = cis(0x04) |
set_route_out cis |
CMD_SRC_PLAY_ROUTE_IN_START(0x3304) |
None |
route_in start |
CMD_SRC_PLAY_ROUTE_IN_STOP(0x3305) |
None |
route_in stop |
CMD_SRC_PLAY_ROUTE_OUT_START(0x3306) |
None |
route_out start |
CMD_SRC_PLAY_ROUTE_OUT_STOP(0x3307) |
None |
route_out stop |
For CIS, it is necessary to establish an LE link. Please refer to Initiator General ACI Host CLI Test for connection procedure.
ACI Host CLI test: Input
set_route_in usb_ds
.2024-01-23 17:19:23,499 INFO: input command: set_route_in usb_ds 2024-01-23 17:19:23,500 INFO: Parser cmdParser: cmd opcode: 3300 param: [03 01] name: CMD_SRC_PLAY_SET_SRC_ROUTE 2024-01-23 17:19:23,501 INFO: Packet sendPacket: <<<send packet: AA 29 04 00 00 33 03 01 9C 2024-01-23 17:19:23,514 INFO: AciHostCLI continuously_read: >>>receive packet: AA 23 05 00 00 00 00 33 00 A5 2024-01-23 17:19:23,515 INFO: Parser eventParser: syncWord: AA,seqn: 23,len: 5,opcode: 0000,params: [00 33 00], check_sum: A5 2024-01-23 17:19:23,515 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-01-23 17:19:23,516 INFO: Parser eventParser: event_id: [00 33] 2024-01-23 17:19:23,516 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
set_route_out cis
.2024-01-23 17:19:25,989 INFO: input command: set_route_out cis 2024-01-23 17:19:25,990 INFO: Parser cmdParser: cmd opcode: 3302 param: [04] name: CMD_SRC_PLAY_SET_PLAY_ROUTE 2024-01-23 17:19:25,991 INFO: Packet sendPacket: <<<send packet: AA 2A 03 00 02 33 04 9A 2024-01-23 17:19:26,003 INFO: AciHostCLI continuously_read: >>>receive packet: AA 24 05 00 00 00 02 33 00 A2 2024-01-23 17:19:26,007 INFO: Parser eventParser: syncWord: AA,seqn: 24,len: 5,opcode: 0000,params: [02 33 00], check_sum: A2 2024-01-23 17:19:26,009 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-01-23 17:19:26,009 INFO: Parser eventParser: event_id: [02 33] 2024-01-23 17:19:26,010 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_out start
.2024-01-23 17:19:27,670 INFO: Parser cmdParser: cmd opcode: 3306 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_START 2024-01-23 17:19:27,671 INFO: Packet sendPacket: <<<send packet: AA 2B 02 00 06 33 9A 2024-01-23 17:19:27,679 INFO: AciHostCLI continuously_read: >>>receive packet: AA 25 05 00 00 00 06 33 00 9D 2024-01-23 17:19:27,679 INFO: Parser eventParser: syncWord: AA,seqn: 25,len: 5,opcode: 0000,params: [06 33 00], check_sum: 9D 2024-01-23 17:19:27,680 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-01-23 17:19:27,681 INFO: Parser eventParser: event_id: [06 33] 2024-01-23 17:19:27,682 INFO: Parser eventParser: status: [00] 2024-01-23 17:19:27,685 INFO: AciHostCLI continuously_read: >>>receive packet: AA 26 07 00 41 01 A8 E1 2C 00 01 DB 2024-01-23 17:19:27,686 INFO: Parser eventParser: syncWord: AA,seqn: 26,len: 7,opcode: 0141,params: [A8 E1 2C 00 01], check_sum: DB 2024-01-23 17:19:27,686 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2024-01-23 17:19:27,687 INFO: Parser eventParser: group_handle: [A8 E1 2C 00] 2024-01-23 17:19:27,687 INFO: Parser eventParser: state: [01] 2024-01-23 17:19:27,690 INFO: Packet sendPacket: <<<send packet: AA 2C 05 00 00 00 41 01 00 8D 2024-01-23 17:19:27,694 INFO: AciHostCLI continuously_read: >>>receive packet: AA 27 07 00 41 01 A8 E1 2C 00 03 D8 2024-01-23 17:19:27,695 INFO: Parser eventParser: syncWord: AA,seqn: 27,len: 7,opcode: 0141,params: [A8 E1 2C 00 03], check_sum: D8 2024-01-23 17:19:27,698 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2024-01-23 17:19:27,699 INFO: Parser eventParser: group_handle: [A8 E1 2C 00] 2024-01-23 17:19:27,699 INFO: Parser eventParser: state: [03] 2024-01-23 17:19:27,700 INFO: Packet sendPacket: <<<send packet: AA 2D 05 00 00 00 41 01 00 8C 2024-01-23 17:19:28,092 INFO: AciHostCLI continuously_read: >>>receive packet: AA 28 0A 00 44 80 00 00 18 00 00 00 F4 01 FD 2024-01-23 17:19:28,093 INFO: Parser eventParser: syncWord: AA,seqn: 28,len: 10,opcode: 8044,params: [00 00 18 00 00 00 F4 01], check_sum: FD 2024-01-23 17:19:28,093 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM 2024-01-23 17:19:28,094 INFO: Parser eventParser: app_link_id: [00] 2024-01-23 17:19:28,095 INFO: Parser eventParser: res: [00] 2024-01-23 17:19:28,096 INFO: Parser eventParser: connInterval: [18 00] 2024-01-23 17:19:28,096 INFO: Parser eventParser: connLatency: [00 00] 2024-01-23 17:19:28,097 INFO: Parser eventParser: supTimeout: [F4 01] 2024-01-23 17:19:28,097 INFO: Packet sendPacket: <<<send packet: AA 2E 05 00 00 00 44 80 00 09 2024-01-23 17:19:28,411 INFO: AciHostCLI continuously_read: >>>receive packet: AA 29 0A 00 44 80 00 00 20 00 00 00 F4 01 F4 2024-01-23 17:19:28,412 INFO: Parser eventParser: syncWord: AA,seqn: 29,len: 10,opcode: 8044,params: [00 00 20 00 00 00 F4 01], check_sum: F4 2024-01-23 17:19:28,415 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM 2024-01-23 17:19:28,415 INFO: Parser eventParser: app_link_id: [00] 2024-01-23 17:19:28,416 INFO: Parser eventParser: res: [00] 2024-01-23 17:19:28,416 INFO: Parser eventParser: connInterval: [20 00] 2024-01-23 17:19:28,417 INFO: Parser eventParser: connLatency: [00 00] 2024-01-23 17:19:28,417 INFO: Parser eventParser: supTimeout: [F4 01] 2024-01-23 17:19:28,418 INFO: Packet sendPacket: <<<send packet: AA 2F 05 00 00 00 44 80 00 08 2024-01-23 17:19:28,811 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2A 07 00 41 01 A8 E1 2C 00 04 D4 2024-01-23 17:19:28,811 INFO: Parser eventParser: syncWord: AA,seqn: 2A,len: 7,opcode: 0141,params: [A8 E1 2C 00 04], check_sum: D4 2024-01-23 17:19:28,812 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2024-01-23 17:19:28,812 INFO: Parser eventParser: group_handle: [A8 E1 2C 00] 2024-01-23 17:19:28,814 INFO: Parser eventParser: state: [04] 2024-01-23 17:19:28,815 INFO: Packet sendPacket: <<<send packet: AA 30 05 00 00 00 41 01 00 89
ACI Host CLI test: Input
route_in start
.2024-01-23 17:19:30,390 INFO: input command: route_in start 2024-01-23 17:19:30,390 INFO: Parser cmdParser: cmd opcode: 3304 param: [] name: CMD_SRC_PLAY_ROUTE_IN_START 2024-01-23 17:19:30,391 INFO: Packet sendPacket: <<<send packet: AA 31 02 00 04 33 96 2024-01-23 17:19:30,422 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2B 05 00 00 00 04 33 00 99 2024-01-23 17:19:30,423 INFO: Parser eventParser: syncWord: AA,seqn: 2B,len: 5,opcode: 0000,params: [04 33 00], check_sum: 99 2024-01-23 17:19:30,425 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-01-23 17:19:30,427 INFO: Parser eventParser: event_id: [04 33] 2024-01-23 17:19:30,431 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_out stop
.2024-01-23 17:19:35,613 INFO: input command: route_out stop 2024-01-23 17:19:35,613 INFO: Parser cmdParser: cmd opcode: 3307 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_STOP 2024-01-23 17:19:35,614 INFO: Packet sendPacket: <<<send packet: AA 32 02 00 07 33 92 2024-01-23 17:19:35,622 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2C 05 00 00 00 07 33 00 95 2024-01-23 17:19:35,623 INFO: Parser eventParser: syncWord: AA,seqn: 2C,len: 5,opcode: 0000,params: [07 33 00], check_sum: 95 2024-01-23 17:19:35,626 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-01-23 17:19:35,627 INFO: Parser eventParser: event_id: [07 33] 2024-01-23 17:19:35,628 INFO: Parser eventParser: status: [00] 2024-01-23 17:19:35,629 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2D 07 00 41 01 A8 E1 2C 00 07 CE 2024-01-23 17:19:35,629 INFO: Parser eventParser: syncWord: AA,seqn: 2D,len: 7,opcode: 0141,params: [A8 E1 2C 00 07], check_sum: CE 2024-01-23 17:19:35,630 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2024-01-23 17:19:35,633 INFO: Parser eventParser: group_handle: [A8 E1 2C 00] 2024-01-23 17:19:35,634 INFO: Parser eventParser: state: [07] 2024-01-23 17:19:35,635 INFO: Packet sendPacket: <<<send packet: AA 33 05 00 00 00 41 01 00 86 2024-01-23 17:19:35,814 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2E 07 00 41 01 A8 E1 2C 00 01 D3 2024-01-23 17:19:35,815 INFO: Parser eventParser: syncWord: AA,seqn: 2E,len: 7,opcode: 0141,params: [A8 E1 2C 00 01], check_sum: D3 2024-01-23 17:19:35,816 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2024-01-23 17:19:35,820 INFO: Parser eventParser: group_handle: [A8 E1 2C 00] 2024-01-23 17:19:35,821 INFO: Parser eventParser: state: [01] 2024-01-23 17:19:35,823 INFO: Packet sendPacket: <<<send packet: AA 34 05 00 00 00 41 01 00 85 2024-01-23 17:19:36,132 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2F 0A 00 44 80 00 00 18 00 00 00 F4 01 F6 2024-01-23 17:19:36,134 INFO: Parser eventParser: syncWord: AA,seqn: 2F,len: 10,opcode: 8044,params: [00 00 18 00 00 00 F4 01], check_sum: F6 2024-01-23 17:19:36,134 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM 2024-01-23 17:19:36,135 INFO: Parser eventParser: app_link_id: [00] 2024-01-23 17:19:36,135 INFO: Parser eventParser: res: [00] 2024-01-23 17:19:36,136 INFO: Parser eventParser: connInterval: [18 00] 2024-01-23 17:19:36,137 INFO: Parser eventParser: connLatency: [00 00] 2024-01-23 17:19:36,137 INFO: Parser eventParser: supTimeout: [F4 01] 2024-01-23 17:19:36,138 INFO: Packet sendPacket: <<<send packet: AA 35 05 00 00 00 44 80 00 02
ACI Host CLI test: Input
route_in stop
.2024-01-23 17:19:37,889 INFO: input command: route_in stop 2024-01-23 17:19:37,890 INFO: Parser cmdParser: cmd opcode: 3305 param: [] name: CMD_SRC_PLAY_ROUTE_IN_STOP 2024-01-23 17:19:37,890 INFO: Packet sendPacket: <<<send packet: AA 36 02 00 05 33 90 2024-01-23 17:19:37,904 INFO: AciHostCLI continuously_read: >>>receive packet: AA 30 05 00 00 00 05 33 00 93 2024-01-23 17:19:37,904 INFO: Parser eventParser: syncWord: AA,seqn: 30,len: 5,opcode: 0000,params: [05 33 00], check_sum: 93 2024-01-23 17:19:37,905 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-01-23 17:19:37,905 INFO: Parser eventParser: event_id: [05 33] 2024-01-23 17:19:37,906 INFO: Parser eventParser: status: [00]
USB Source Play (CIS Input and Output)
Before using, please connect the EVB and PC through USB and select the EVB as the audio device. Once the USB cable is connected, calls or simultaneous recording and playing of music can be initiated on the PC. The USB downstream data, transferred to the EVB, can be sent to BUD(s) through the CIS, and the data received from the BUD(s) through CIS can be transmitted upstream to the PC through USB.
In this scenario, CIS will set up both downlink and uplink directions of the datapaths. The codec type is
determined through negotiation (refer to app_lea_ini_select_conversation_prefer_codec()
), and
16_2
is preferred.
CIS connection process: Please refer to ACI Host CLI Test: Advertising.
USB source play (CIS Input and Output) process:
ACI Host CLI Test
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_LEA_SCAN(0x3023) |
action = start(0x00) |
lea_scan start |
CMD_LEA_SCAN(0x3023) |
action = stop(0x01) |
lea_scan stop |
CMD_SRC_PLAY_SET_SRC_ROUTE(0x3300) |
action = usb_ds_us(0x03, 0x03) |
set_route_in usb_ds_us |
CMD_SRC_PLAY_SET_PLAY_ROUTE(0x3302) |
action = cis(0x04) |
set_route_out cis |
CMD_SRC_PLAY_ROUTE_IN_START(0x3304) |
None |
route_in start |
CMD_SRC_PLAY_ROUTE_IN_STOP(0x3305) |
None |
route_in stop |
CMD_SRC_PLAY_ROUTE_OUT_START(0x3306) |
None |
route_out start |
CMD_SRC_PLAY_ROUTE_OUT_STOP(0x3307) |
None |
route_out stop |
For CIS, it is necessary to establish an LE link. Please refer to Initiator General ACI Host CLI Test for the connection procedure.
In addition, in the CIS input and output mode, it is necessary to establish a call using call control commands (such as incoming call and accept call) before initiating start CIS.
ACI Host CLI test: Input
set_route_in usb_ds_us
.2024-01-23 17:18:40,848 INFO: input command: set_route_in usb_ds_us 2024-01-23 17:18:40,849 INFO: Parser cmdParser: cmd opcode: 3300 param: [03 03] name: CMD_SRC_PLAY_SET_SRC_ROUTE 2024-01-23 17:18:40,850 INFO: Packet sendPacket: <<<send packet: AA 19 04 00 00 33 03 03 AA 2024-01-23 17:18:40,857 INFO: AciHostCLI continuously_read: >>>receive packet: AA 13 05 00 00 00 00 33 00 B5 2024-01-23 17:18:40,858 INFO: Parser eventParser: syncWord: AA,seqn: 13,len: 5,opcode: 0000,params: [00 33 00], check_sum: B5 2024-01-23 17:18:40,860 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-01-23 17:18:40,863 INFO: Parser eventParser: event_id: [00 33] 2024-01-23 17:18:40,866 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
set_route_out cis
.2024-01-23 17:18:42,952 INFO: input command: set_route_out cis 2024-01-23 17:18:42,952 INFO: Parser cmdParser: cmd opcode: 3302 param: [04] name: CMD_SRC_PLAY_SET_PLAY_ROUTE 2024-01-23 17:18:42,953 INFO: Packet sendPacket: <<<send packet: AA 1A 03 00 02 33 04 AA 2024-01-23 17:18:42,960 INFO: AciHostCLI continuously_read: >>>receive packet: AA 14 05 00 00 00 02 33 00 B2 2024-01-23 17:18:42,961 INFO: Parser eventParser: syncWord: AA,seqn: 14,len: 5,opcode: 0000,params: [02 33 00], check_sum: B2 2024-01-23 17:18:42,962 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-01-23 17:18:42,966 INFO: Parser eventParser: event_id: [02 33] 2024-01-23 17:18:42,968 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Call control procedure (incoming call and accept call).
2024-01-23 17:18:54,685 INFO: input command: ccp_action incomingcall 2024-01-23 17:18:54,686 INFO: Parser cmdParser: cmd opcode: 3032 param: [05 00] name: CMD_LEA_CCP_ACTION 2024-01-23 17:18:54,687 INFO: Packet sendPacket: <<<send packet: AA 1B 04 00 32 30 05 00 7A 2024-01-23 17:18:54,701 INFO: AciHostCLI continuously_read: >>>receive packet: AA 15 03 00 48 01 01 9E 2024-01-23 17:18:54,701 INFO: Parser eventParser: syncWord: AA,seqn: 15,len: 3,opcode: 0148,params: [01], check_sum: 9E 2024-01-23 17:18:54,702 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_CCP_CREATE_CALL 2024-01-23 17:18:54,702 INFO: Parser eventParser: call_index: [01] 2024-01-23 17:18:54,703 INFO: Packet sendPacket: <<<send packet: AA 1C 05 00 00 00 48 01 00 96 2024-01-23 17:18:54,717 INFO: AciHostCLI continuously_read: >>>receive packet: AA 16 05 00 00 00 32 30 00 83 2024-01-23 17:18:54,718 INFO: Parser eventParser: syncWord: AA,seqn: 16,len: 5,opcode: 0000,params: [32 30 00], check_sum: 83 2024-01-23 17:18:54,718 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-01-23 17:18:54,719 INFO: Parser eventParser: event_id: [32 30] 2024-01-23 17:18:54,719 INFO: Parser eventParser: status: [00] 2024-01-23 17:18:56,312 INFO: input command: ccp_action accept1 2024-01-23 17:18:56,313 INFO: Parser cmdParser: cmd opcode: 3032 param: [14 01] name: CMD_LEA_CCP_ACTION 2024-01-23 17:18:56,314 INFO: Packet sendPacket: <<<send packet: AA 1D 04 00 32 30 14 01 68 2024-01-23 17:18:56,329 INFO: AciHostCLI continuously_read: >>>receive packet: AA 17 05 00 00 00 32 30 00 82 2024-01-23 17:18:56,330 INFO: Parser eventParser: syncWord: AA,seqn: 17,len: 5,opcode: 0000,params: [32 30 00], check_sum: 82 2024-01-23 17:18:56,332 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-01-23 17:18:56,333 INFO: Parser eventParser: event_id: [32 30] 2024-01-23 17:18:56,333 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_out start
.2024-01-23 17:19:06,596 INFO: input command: route_out start 2024-01-23 17:19:06,597 INFO: Parser cmdParser: cmd opcode: 3306 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_START 2024-01-23 17:19:06,598 INFO: Packet sendPacket: <<<send packet: AA 1E 02 00 06 33 A7 2024-01-23 17:19:06,619 INFO: AciHostCLI continuously_read: >>>receive packet: AA 18 05 00 00 00 06 33 00 AA 2024-01-23 17:19:06,620 INFO: Parser eventParser: syncWord: AA,seqn: 18,len: 5,opcode: 0000,params: [06 33 00], check_sum: AA 2024-01-23 17:19:06,620 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-01-23 17:19:06,621 INFO: Parser eventParser: event_id: [06 33] 2024-01-23 17:19:06,621 INFO: Parser eventParser: status: [00] 2024-01-23 17:19:06,622 INFO: AciHostCLI continuously_read: >>>receive packet: AA 19 07 00 41 01 A8 E1 2C 00 01 E8 2024-01-23 17:19:06,622 INFO: Parser eventParser: syncWord: AA,seqn: 19,len: 7,opcode: 0141,params: [A8 E1 2C 00 01], check_sum: E8 2024-01-23 17:19:06,623 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2024-01-23 17:19:06,624 INFO: Parser eventParser: group_handle: [A8 E1 2C 00] 2024-01-23 17:19:06,625 INFO: Parser eventParser: state: [01] 2024-01-23 17:19:06,626 INFO: Packet sendPacket: <<<send packet: AA 1F 05 00 00 00 41 01 00 9A 2024-01-23 17:19:06,635 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1A 07 00 41 01 A8 E1 2C 00 03 E5 2024-01-23 17:19:06,636 INFO: Parser eventParser: syncWord: AA,seqn: 1A,len: 7,opcode: 0141,params: [A8 E1 2C 00 03], check_sum: E5 2024-01-23 17:19:06,637 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2024-01-23 17:19:06,638 INFO: Parser eventParser: group_handle: [A8 E1 2C 00] 2024-01-23 17:19:06,639 INFO: Parser eventParser: state: [03] 2024-01-23 17:19:06,640 INFO: Packet sendPacket: <<<send packet: AA 20 05 00 00 00 41 01 00 99 2024-01-23 17:19:07,002 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1B 0A 00 44 80 00 00 18 00 00 00 F4 01 0A 2024-01-23 17:19:07,003 INFO: Parser eventParser: syncWord: AA,seqn: 1B,len: 10,opcode: 8044,params: [00 00 18 00 00 00 F4 01], check_sum: 0A 2024-01-23 17:19:07,006 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM 2024-01-23 17:19:07,009 INFO: Parser eventParser: app_link_id: [00] 2024-01-23 17:19:07,010 INFO: Parser eventParser: res: [00] 2024-01-23 17:19:07,011 INFO: Parser eventParser: connInterval: [18 00] 2024-01-23 17:19:07,011 INFO: Parser eventParser: connLatency: [00 00] 2024-01-23 17:19:07,012 INFO: Parser eventParser: supTimeout: [F4 01] 2024-01-23 17:19:07,013 INFO: Packet sendPacket: <<<send packet: AA 21 05 00 00 00 44 80 00 16 2024-01-23 17:19:07,257 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1C 07 00 41 01 A8 E1 2C 00 04 E2 2024-01-23 17:19:07,258 INFO: Parser eventParser: syncWord: AA,seqn: 1C,len: 7,opcode: 0141,params: [A8 E1 2C 00 04], check_sum: E2 2024-01-23 17:19:07,259 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2024-01-23 17:19:07,260 INFO: Parser eventParser: group_handle: [A8 E1 2C 00] 2024-01-23 17:19:07,261 INFO: Parser eventParser: state: [04] 2024-01-23 17:19:07,263 INFO: Packet sendPacket: <<<send packet: AA 22 05 00 00 00 41 01 00 97
ACI Host CLI test: Input
route_in start
.2024-01-23 17:19:08,892 INFO: input command: route_in start 2024-01-23 17:19:08,893 INFO: Parser cmdParser: cmd opcode: 3304 param: [] name: CMD_SRC_PLAY_ROUTE_IN_START 2024-01-23 17:19:08,894 INFO: Packet sendPacket: <<<send packet: AA 23 02 00 04 33 A4 2024-01-23 17:19:08,948 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1D 05 00 00 00 04 33 00 A7 2024-01-23 17:19:08,948 INFO: Parser eventParser: syncWord: AA,seqn: 1D,len: 5,opcode: 0000,params: [04 33 00], check_sum: A7 2024-01-23 17:19:08,949 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-01-23 17:19:08,949 INFO: Parser eventParser: event_id: [04 33] 2024-01-23 17:19:08,950 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_out stop
.2024-01-23 17:19:15,611 INFO: input command: route_out stop 2024-01-23 17:19:15,612 INFO: Parser cmdParser: cmd opcode: 3307 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_STOP 2024-01-23 17:19:15,613 INFO: Packet sendPacket: <<<send packet: AA 24 02 00 07 33 A0 2024-01-23 17:19:15,633 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1E 05 00 00 00 07 33 00 A3 2024-01-23 17:19:15,634 INFO: Parser eventParser: syncWord: AA,seqn: 1E,len: 5,opcode: 0000,params: [07 33 00], check_sum: A3 2024-01-23 17:19:15,634 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-01-23 17:19:15,635 INFO: Parser eventParser: event_id: [07 33] 2024-01-23 17:19:15,636 INFO: Parser eventParser: status: [00] 2024-01-23 17:19:15,636 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1F 07 00 41 01 A8 E1 2C 00 07 DC 2024-01-23 17:19:15,637 INFO: Parser eventParser: syncWord: AA,seqn: 1F,len: 7,opcode: 0141,params: [A8 E1 2C 00 07], check_sum: DC 2024-01-23 17:19:15,637 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2024-01-23 17:19:15,639 INFO: Parser eventParser: group_handle: [A8 E1 2C 00] 2024-01-23 17:19:15,639 INFO: Parser eventParser: state: [07] 2024-01-23 17:19:15,640 INFO: Packet sendPacket: <<<send packet: AA 25 05 00 00 00 41 01 00 94 2024-01-23 17:19:15,808 INFO: AciHostCLI continuously_read: >>>receive packet: AA 20 07 00 41 01 A8 E1 2C 00 01 E1 2024-01-23 17:19:15,809 INFO: Parser eventParser: syncWord: AA,seqn: 20,len: 7,opcode: 0141,params: [A8 E1 2C 00 01], check_sum: E1 2024-01-23 17:19:15,810 INFO: Parser eventParser: event name: EVENT_LE_AUDIO_BAP_STATE 2024-01-23 17:19:15,811 INFO: Parser eventParser: group_handle: [A8 E1 2C 00] 2024-01-23 17:19:15,811 INFO: Parser eventParser: state: [01] 2024-01-23 17:19:15,812 INFO: Packet sendPacket: <<<send packet: AA 26 05 00 00 00 41 01 00 93 2024-01-23 17:19:16,032 INFO: AciHostCLI continuously_read: >>>receive packet: AA 21 0A 00 44 80 00 00 18 00 00 00 F4 01 04 2024-01-23 17:19:16,033 INFO: Parser eventParser: syncWord: AA,seqn: 21,len: 10,opcode: 8044,params: [00 00 18 00 00 00 F4 01], check_sum: 04 2024-01-23 17:19:16,034 INFO: Parser eventParser: event name: EVENT_XM_LE_CON_PARAM 2024-01-23 17:19:16,035 INFO: Parser eventParser: app_link_id: [00] 2024-01-23 17:19:16,038 INFO: Parser eventParser: res: [00] 2024-01-23 17:19:16,039 INFO: Parser eventParser: connInterval: [18 00] 2024-01-23 17:19:16,040 INFO: Parser eventParser: connLatency: [00 00] 2024-01-23 17:19:16,041 INFO: Parser eventParser: supTimeout: [F4 01] 2024-01-23 17:19:16,041 INFO: Packet sendPacket: <<<send packet: AA 27 05 00 00 00 44 80 00 10
ACI Host CLI test: Input
route_in stop
.2024-01-23 17:19:17,316 INFO: input command: route_in stop 2024-01-23 17:19:17,317 INFO: Parser cmdParser: cmd opcode: 3305 param: [] name: CMD_SRC_PLAY_ROUTE_IN_STOP 2024-01-23 17:19:17,318 INFO: Packet sendPacket: <<<send packet: AA 28 02 00 05 33 9E 2024-01-23 17:19:17,326 INFO: AciHostCLI continuously_read: >>>receive packet: AA 22 05 00 00 00 05 33 00 A1 2024-01-23 17:19:17,327 INFO: Parser eventParser: syncWord: AA,seqn: 22,len: 5,opcode: 0000,params: [05 33 00], check_sum: A1 2024-01-23 17:19:17,331 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-01-23 17:19:17,334 INFO: Parser eventParser: event_id: [05 33] 2024-01-23 17:19:17,336 INFO: Parser eventParser: status: [00]
SD Card Source Play
Before using, please rework the LDO on SD card slot of EVB. Please create a folder named audio
under the root directory and place the file named 8kbps_8kHz.mp3
in it. Then, insert the SD card into the corresponding card slot.
Note
DSP bin under release bin\bank0
should be downloaded.
After the SD card is inserted, the SD card source play can be started. SD card source play process:
ACI Host CLI Test
The ACI Host sends CMD_SRC_PLAY_SET_SRC_ROUTE
to the ACI Device to set the SD card input route, sends CMD_SRC_PLAY_SET_PLAY_ROUTE
to set the local output route, sends CMD_SRC_PLAY_ROUTE_IN_START/STOP
to start or stop the SD card input route, and sends CMD_SRC_PLAY_ROUTE_OUT_START/STOP
to start or stop the local output route.
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_SRC_PLAY_SET_SRC_ROUTE(0x3300) |
action = sd_card(0x04, 0x00) |
set_route_in sd_card |
CMD_SRC_PLAY_SET_PLAY_ROUTE(0x3302) |
action = local(0x05) |
set_route_out local |
CMD_SRC_PLAY_ROUTE_IN_START(0x3304) |
None |
route_in start |
CMD_SRC_PLAY_ROUTE_IN_STOP(0x3305) |
None |
route_in stop |
CMD_SRC_PLAY_ROUTE_OUT_START(0x3306) |
None |
route_out start |
CMD_SRC_PLAY_ROUTE_OUT_STOP(0x3307) |
None |
route_out stop |
ACI Host CLI test: Insert SD card to EVB.
ACI Host CLI test: Input
set_route_in sd_card
.2023-11-08 15:34:24,936 INFO: input command: set_route_in sd_card 2023-11-08 15:34:24,936 INFO: Parser cmdParser: cmd opcode: 3300 param: [04 00] name: CMD_SRC_PLAY_SET_SRC_ROUTE 2023-11-08 15:34:24,937 INFO: Packet sendPacket: <<<send packet: AA 03 04 00 00 33 04 00 C2 2023-11-08 15:34:24,945 INFO: AciHostCLI continuously_read: >>>receive packet: AA 03 05 00 00 00 00 33 02 C3 2023-11-08 15:34:24,946 INFO: Parser eventParser: syncWord: AA,seqn: 03,len: 5,opcode: 0000,params: [00 33 02], check_sum: C3 2023-11-08 15:34:24,947 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-11-08 15:34:24,947 INFO: Parser eventParser: event_id: [00 33] 2023-11-08 15:34:24,947 INFO: Parser eventParser: status: [02]
ACI Host CLI test: Input
set_route_out local
.2023-11-08 15:35:32,279 INFO: input command: set_route_out local 2023-11-08 15:35:32,280 INFO: Parser cmdParser: cmd opcode: 3302 param: [05] name: CMD_SRC_PLAY_SET_PLAY_ROUTE 2023-11-08 15:35:32,280 INFO: Packet sendPacket: <<<send packet: AA 04 03 00 02 33 05 BF 2023-11-08 15:35:32,368 INFO: AciHostCLI continuously_read: >>>receive packet: AA 04 05 00 00 00 02 33 02 C0 2023-11-08 15:35:32,368 INFO: Parser eventParser: syncWord: AA,seqn: 04,len: 5,opcode: 0000,params: [02 33 02], check_sum: C0 2023-11-08 15:35:32,369 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-11-08 15:35:32,369 INFO: Parser eventParser: event_id: [02 33] 2023-11-08 15:35:32,369 INFO: Parser eventParser: status: [02]
ACI Host CLI test: Input
route_out start
.2023-11-08 15:36:03,687 INFO: input command: route_out start 2023-11-08 15:36:03,687 INFO: Parser cmdParser: cmd opcode: 3306 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_START 2023-11-08 15:36:03,688 INFO: Packet sendPacket: <<<send packet: AA 05 02 00 06 33 C0 2023-11-08 15:36:03,834 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 05 00 00 00 06 33 02 BB 2023-11-08 15:36:03,835 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 5,opcode: 0000,params: [06 33 02], check_sum: BB 2023-11-08 15:36:03,835 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-11-08 15:36:03,835 INFO: Parser eventParser: event_id: [06 33] 2023-11-08 15:36:03,835 INFO: Parser eventParser: status: [02]
ACI Host CLI test: Input
route_in start
.2023-11-08 15:36:52,159 INFO: input command: route_in start 2023-11-08 15:36:52,159 INFO: Parser cmdParser: cmd opcode: 3304 param: [] name: CMD_SRC_PLAY_ROUTE_IN_START 2023-11-08 15:36:52,160 INFO: Packet sendPacket: <<<send packet: AA 01 02 00 04 33 C6 2023-11-08 15:36:52,165 INFO: AciHostCLI continuously_read: >>>receive packet: AA 06 05 00 00 00 04 33 02 BC 2023-11-08 15:36:52,166 INFO: Parser eventParser: syncWord: AA,seqn: 06,len: 5,opcode: 0000,params: [04 33 02], check_sum: BC 2023-11-08 15:36:52,169 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-11-08 15:36:52,171 INFO: Parser eventParser: event_id: [04 33] 2023-11-08 15:36:52,171 INFO: Parser eventParser: status: [02]
ACI Host CLI test: Input
route_out stop
.2023-11-08 15:37:08,533 INFO: input command: route_out stop 2023-11-08 15:37:08,534 INFO: Parser cmdParser: cmd opcode: 3307 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_STOP 2023-11-08 15:37:08,534 INFO: Packet sendPacket: <<<send packet: AA 03 02 00 07 33 C1 2023-11-08 15:37:08,542 INFO: AciHostCLI continuously_read: >>>receive packet: AA 08 05 00 00 00 07 33 02 B7 2023-11-08 15:37:08,543 INFO: Parser eventParser: syncWord: AA,seqn: 08,len: 5,opcode: 0000,params: [07 33 02], check_sum: B7 2023-11-08 15:37:08,544 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-11-08 15:37:08,544 INFO: Parser eventParser: event_id: [07 33] 2023-11-08 15:37:08,544 INFO: Parser eventParser: status: [02]
ACI Host CLI test: Input
route_in stop
.2023-11-08 15:37:23,015 INFO: input command: route_in stop 2023-11-08 15:37:23,015 INFO: Parser cmdParser: cmd opcode: 3305 param: [] name: CMD_SRC_PLAY_ROUTE_IN_STOP 2023-11-08 15:37:23,015 INFO: Packet sendPacket: <<<send packet: AA 05 02 00 05 33 C1 2023-11-08 15:37:23,023 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0A 05 00 00 00 05 33 02 B7 2023-11-08 15:37:23,028 INFO: Parser eventParser: syncWord: AA,seqn: 0A,len: 5,opcode: 0000,params: [05 33 02], check_sum: B7 2023-11-08 15:37:23,029 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-11-08 15:37:23,030 INFO: Parser eventParser: event_id: [05 33] 2023-11-08 15:37:23,030 INFO: Parser eventParser: status: [02]
SD Card Source Play(BIS/CIS Output)
Before using, please make preparations as described in SD Card Source Play. The music data could be sent to the BUD(s) through BIS.
Note
DSP bin under release bin\DSP_Image\cs_leaaudio_pipe_stereo
should be downloaded.
After SD card is inserted, the SD card source play can be started. SD card source play process:
ACI Host CLI Test
When using BIS as output path, it is necessary to initialize BIS firstly through CMD_LEA_BSRC_INIT
. The ACI Host sends CMD_SRC_PLAY_SET_SRC_ROUTE
to ACI Device to set the SD card input route, sends CMD_SRC_PLAY_SET_PLAY_ROUTE
to set BIS/CIS output route, sends CMD_SRC_PLAY_ROUTE_IN_START/STOP
to start or stop the SD card input route, and sends CMD_SRC_PLAY_ROUTE_OUT_START/STOP
to start or stop the BIS output route.
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_LEA_BSRC_INIT(0x3020) |
codec type = CODEC_CFG_ITEM_48_4(48k) |
bsrcinit 48k_2bis |
CMD_SRC_PLAY_SET_SRC_ROUTE(0x3300) |
action = sd_card(0x04, 0x00) |
set_route_in sd_card |
CMD_SRC_PLAY_SET_PLAY_ROUTE(0x3302) |
action = bis(0x03) |
set_route_out bis |
CMD_SRC_PLAY_SET_PLAY_ROUTE(0x3302) |
action = cis(0x04) |
set_route_out cis |
CMD_SRC_PLAY_ROUTE_IN_START(0x3304) |
None |
route_in start |
CMD_SRC_PLAY_ROUTE_IN_STOP(0x3305) |
None |
route_in stop |
CMD_SRC_PLAY_ROUTE_OUT_START(0x3306) |
None |
route_out start |
CMD_SRC_PLAY_ROUTE_OUT_STOP(0x3307) |
None |
route_out stop |
For CIS, it is necessary to establish an LE link. Please refer to Initiator General ACI Host CLI Test for connection procedure.
ACI Host CLI test: Insert SD card to EVB.
ACI Host CLI test: Initialize BIS.
2023-11-09 11:27:18,506 INFO: input command: bsrcinit 48k_2bis 2023-11-09 11:27:18,507 INFO: Parser cmdParser: cmd opcode: 3020 param: [0B 02 00 00 10 27] name: CMD_LEA_BSRC_INIT 2023-11-09 11:27:18,507 INFO: Packet sendPacket: <<<send packet: AA 02 08 00 20 30 0B 02 00 00 10 27 62 2023-11-09 11:27:18,585 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0C 05 00 00 00 20 30 00 9F 2023-11-09 11:27:18,585 INFO: Parser eventParser: syncWord: AA,seqn: 0C,len: 5,opcode: 0000,params: [20 30 00], check_sum: 9F 2023-11-09 11:27:18,586 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-11-09 11:27:18,586 INFO: Parser eventParser: event_id: [20 30] 2023-11-09 11:27:18,586 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
set_route_out bis/cis
.If choose BIS:
2023-11-09 11:28:14,714 INFO: input command: set_route_out bis 2023-11-09 11:28:14,715 INFO: Parser cmdParser: cmd opcode: 3302 param: [03] name: CMD_SRC_PLAY_SET_PLAY_ROUTE 2023-11-09 11:28:14,715 INFO: Packet sendPacket: <<<send packet: AA 03 03 00 02 33 03 C2 2023-11-09 11:28:14,725 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0D 05 00 00 00 02 33 02 B7 2023-11-09 11:28:14,727 INFO: Parser eventParser: syncWord: AA,seqn: 0D,len: 5,opcode: 0000,params: [02 33 02], check_sum: B7 2023-11-09 11:28:14,727 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-11-09 11:28:14,727 INFO: Parser eventParser: event_id: [02 33] 2023-11-09 11:28:14,727 INFO: Parser eventParser: status: [02]
If choose CIS:
2023-11-10 10:27:00,869 INFO: input command: set_route_out cis 2023-11-10 10:27:00,870 INFO: Parser cmdParser: cmd opcode: 3302 param: [04] name: CMD_SRC_PLAY_SET_PLAY_ROUTE 2023-11-10 10:27:00,870 INFO: Packet sendPacket: <<<send packet: AA 0F 03 00 02 33 04 B5 2023-11-10 10:27:00,876 INFO: AciHostCLI continuously_read: >>>receive packet: AA 19 05 00 00 00 02 33 02 AB 2023-11-10 10:27:00,876 INFO: Parser eventParser: syncWord: AA,seqn: 19,len: 5,opcode: 0000,params: [02 33 02], check_sum: AB 2023-11-10 10:27:00,876 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-11-10 10:27:00,877 INFO: Parser eventParser: event_id: [02 33] 2023-11-10 10:27:00,879 INFO: Parser eventParser: status: [02]
ACI Host CLI test: Input
set_route_in sd_card
.2023-11-09 11:28:32,673 INFO: input command: set_route_in sd_card 2023-11-09 11:28:32,674 INFO: Parser cmdParser: cmd opcode: 3300 param: [04 00] name: CMD_SRC_PLAY_SET_SRC_ROUTE 2023-11-09 11:28:32,676 INFO: Packet sendPacket: <<<send packet: AA 05 04 00 00 33 04 00 C0 2023-11-09 11:28:32,751 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0F 05 00 00 00 00 33 02 B7 2023-11-09 11:28:32,751 INFO: Parser eventParser: syncWord: AA,seqn: 0F,len: 5,opcode: 0000,params: [00 33 02], check_sum: B7 2023-11-09 11:28:32,751 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-11-09 11:28:32,751 INFO: Parser eventParser: event_id: [00 33] 2023-11-09 11:28:32,752 INFO: Parser eventParser: status: [02]
ACI Host CLI test: Input
route_out start
.2023-11-09 11:28:51,593 INFO: input command: route_out start 2023-11-09 11:28:51,594 INFO: Parser cmdParser: cmd opcode: 3306 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_START 2023-11-09 11:28:51,594 INFO: Packet sendPacket: <<<send packet: AA 07 02 00 06 33 BE 2023-11-09 11:28:51,607 INFO: AciHostCLI continuously_read: >>>receive packet: AA 11 05 00 00 00 06 33 02 AF 2023-11-09 11:28:51,608 INFO: Parser eventParser: syncWord: AA,seqn: 11,len: 5,opcode: 0000,params: [06 33 02], check_sum: AF 2023-11-09 11:28:51,608 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-11-09 11:28:51,608 INFO: Parser eventParser: event_id: [06 33] 2023-11-09 11:28:51,608 INFO: Parser eventParser: status: [02]
ACI Host CLI test: Input
route_in start
.2023-11-09 11:29:17,530 INFO: input command: route_in start 2023-11-09 11:29:17,530 INFO: Parser cmdParser: cmd opcode: 3304 param: [] name: CMD_SRC_PLAY_ROUTE_IN_START 2023-11-09 11:29:17,531 INFO: Packet sendPacket: <<<send packet: AA 09 02 00 04 33 BE 2023-11-09 11:29:17,545 INFO: AciHostCLI continuously_read: >>>receive packet: AA 13 05 00 00 00 04 33 02 AF 2023-11-09 11:29:17,545 INFO: Parser eventParser: syncWord: AA,seqn: 13,len: 5,opcode: 0000,params: [04 33 02], check_sum: AF 2023-11-09 11:29:17,545 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-11-09 11:29:17,545 INFO: Parser eventParser: event_id: [04 33] 2023-11-09 11:29:17,546 INFO: Parser eventParser: status: [02]
ACI Host CLI test: Input
route_out stop
.2023-11-09 11:29:45,331 INFO: input command: route_out stop 2023-11-09 11:29:45,332 INFO: Parser cmdParser: cmd opcode: 3307 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_STOP 2023-11-09 11:29:45,332 INFO: Packet sendPacket: <<<send packet: AA 0B 02 00 07 33 B9 2023-11-09 11:29:45,338 INFO: AciHostCLI continuously_read: >>>receive packet: AA 15 05 00 00 00 07 33 02 AA 2023-11-09 11:29:45,343 INFO: Parser eventParser: syncWord: AA,seqn: 15,len: 5,opcode: 0000,params: [07 33 02], check_sum: AA 2023-11-09 11:29:45,343 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-11-09 11:29:45,344 INFO: Parser eventParser: event_id: [07 33] 2023-11-09 11:29:45,346 INFO: Parser eventParser: status: [02]
ACI Host CLI test: Input
route_in stop
.2023-11-09 11:29:56,073 INFO: input command: route_in stop 2023-11-09 11:29:56,074 INFO: Parser cmdParser: cmd opcode: 3305 param: [] name: CMD_SRC_PLAY_ROUTE_IN_STOP 2023-11-09 11:29:56,074 INFO: Packet sendPacket: <<<send packet: AA 0D 02 00 05 33 B9 2023-11-09 11:29:56,115 INFO: AciHostCLI continuously_read: >>>receive packet: AA 17 05 00 00 00 05 33 02 AA 2023-11-09 11:29:56,116 INFO: Parser eventParser: syncWord: AA,seqn: 17,len: 5,opcode: 0000,params: [05 33 02], check_sum: AA 2023-11-09 11:29:56,116 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-11-09 11:29:56,118 INFO: Parser eventParser: event_id: [05 33] 2023-11-09 11:29:56,118 INFO: Parser eventParser: status: [02]
Multilink A2DP Source Play
Before using, please configure MIC 2 on the EVB and connect to PC through line-in or I2S. Two BUDs need to be connected to EVB. After line-in is connected and music on PC is started, the music data will be sent to the connected BUDs through multi-A2DP.
Multi-A2DP Source play process:
ACI Host CLI Test
The ACI Host sends CMD_SRC_PLAY_SET_SRC_ROUTE
to ACI Device to set the line-in or I2S input route, sends CMD_SRC_PLAY_SET_PLAY_ROUTE
to set multi-A2DP output route, sends CMD_SRC_PLAY_ROUTE_IN_START/STOP
to start or stop the line-in input route, and sents CMD_SRC_PLAY_ROUTE_OUT_START/STOP
to start or stop the multi-A2DP output route.
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_SRC_PLAY_SET_SRC_ROUTE(0x3300) |
action = linein(0x02, 0x00) |
set_route_in linein |
CMD_SRC_PLAY_SET_SRC_ROUTE(0x3300) |
action = i2s(0x06, 0x00) |
set_route_in i2s |
CMD_SRC_PLAY_SET_PLAY_ROUTE(0x3302) |
action = multi-A2DP(0x02) |
set_route_out multi_a2dp |
CMD_SRC_PLAY_ROUTE_IN_START(0x3304) |
None |
route_in start |
CMD_SRC_PLAY_ROUTE_IN_STOP(0x3305) |
None |
route_in stop |
CMD_SRC_PLAY_ROUTE_OUT_START(0x3306) |
None |
route_out start |
CMD_SRC_PLAY_ROUTE_OUT_STOP(0x3307) |
None |
route_out stop |
ACI Host CLI test: Connect ACI Device to BUD.
Please refer to Connect to BUD.
ACI Host CLI test: Input
set route_in
.If set route_in as line-in:
2024-02-02 11:08:52,505 INFO: input command: set_route_in linein 2024-02-02 11:08:52,506 INFO: Parser cmdParser: cmd opcode: 3300 param: [02 00] name: CMD_SRC_PLAY_SET_SRC_ROUTE 2024-02-02 11:08:52,507 INFO: Packet sendPacket: <<<send packet: AA 05 04 00 00 33 02 00 C2 2024-02-02 11:08:52,524 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 05 00 00 00 00 33 00 C3 2024-02-02 11:08:52,525 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 5,opcode: 0000,params: [00 33 00], check_sum: C3 2024-02-02 11:08:52,530 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-02-02 11:08:52,543 INFO: Parser eventParser: event_id: [00 33] 2024-02-02 11:08:52,545 INFO: Parser eventParser: status: [00]
If set route_in as I2S:
2024-02-05 10:25:38,424 INFO: input command: set_route_in i2s 2024-02-05 10:25:38,425 INFO: Parser cmdParser: cmd opcode: 3300 param: [06 00] name: CMD_SRC_PLAY_SET_SRC_ROUTE 2024-02-05 10:25:38,425 INFO: Packet sendPacket: <<<send packet: AA 05 04 00 00 33 06 00 BE 2024-02-05 10:25:38,441 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 05 00 00 00 00 33 00 C3 2024-02-05 10:25:38,447 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 5,opcode: 0000,params: [00 33 00], check_sum: C3 2024-02-05 10:25:38,456 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-02-05 10:25:38,460 INFO: Parser eventParser: event_id: [00 33] 2024-02-05 10:25:38,463 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
set_route_out multi_a2dp
.2024-02-02 11:08:55,383 INFO: input command: set_route_out multi_a2dp 2024-02-02 11:08:55,384 INFO: Parser cmdParser: cmd opcode: 3302 param: [06] name: CMD_SRC_PLAY_SET_PLAY_ROUTE 2024-02-02 11:08:55,385 INFO: Packet sendPacket: <<<send packet: AA 06 03 00 02 33 06 BC 2024-02-02 11:08:55,398 INFO: AciHostCLI continuously_read: >>>receive packet: AA 06 05 00 00 00 02 33 00 C0 2024-02-02 11:08:55,408 INFO: Parser eventParser: syncWord: AA,seqn: 06,len: 5,opcode: 0000,params: [02 33 00], check_sum: C0 2024-02-02 11:08:55,409 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-02-02 11:08:55,411 INFO: Parser eventParser: event_id: [02 33] 2024-02-02 11:08:55,414 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_out start
.2024-02-02 11:09:01,260 INFO: input command: route_out start 2024-02-02 11:09:01,264 INFO: Parser cmdParser: cmd opcode: 3306 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_START 2024-02-02 11:09:01,266 INFO: Packet sendPacket: <<<send packet: AA 08 02 00 06 33 BD 2024-02-02 11:09:01,278 INFO: AciHostCLI continuously_read: >>>receive packet: AA 08 05 00 00 00 06 33 00 BA 2024-02-02 11:09:01,281 INFO: Parser eventParser: syncWord: AA,seqn: 08,len: 5,opcode: 0000,params: [06 33 00], check_sum: BA 2024-02-02 11:09:01,285 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-02-02 11:09:01,289 INFO: Parser eventParser: event_id: [06 33] 2024-02-02 11:09:01,296 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_in start
.2024-02-02 11:09:07,967 INFO: input command: route_in start 2024-02-02 11:09:07,968 INFO: Parser cmdParser: cmd opcode: 3304 param: [] name: CMD_SRC_PLAY_ROUTE_IN_START 2024-02-02 11:09:07,969 INFO: Packet sendPacket: <<<send packet: AA 0A 02 00 04 33 BD 2024-02-02 11:09:07,977 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0B 05 00 00 00 04 33 00 B9 2024-02-02 11:09:07,980 INFO: Parser eventParser: syncWord: AA,seqn: 0B,len: 5,opcode: 0000,params: [04 33 00], check_sum: B9 2024-02-02 11:09:07,983 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-02-02 11:09:07,985 INFO: Parser eventParser: event_id: [04 33] 2024-02-02 11:09:07,991 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_out stop
.2024-02-02 11:09:17,534 INFO: input command: route_out stop 2024-02-02 11:09:17,535 INFO: Parser cmdParser: cmd opcode: 3307 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_STOP 2024-02-02 11:09:17,535 INFO: Packet sendPacket: <<<send packet: AA 0B 02 00 07 33 B9 2024-02-02 11:09:17,544 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0C 05 00 00 00 07 33 00 B5 2024-02-02 11:09:17,546 INFO: Parser eventParser: syncWord: AA,seqn: 0C,len: 5,opcode: 0000,params: [07 33 00], check_sum: B5 2024-02-02 11:09:17,551 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-02-02 11:09:17,552 INFO: Parser eventParser: event_id: [07 33] 2024-02-02 11:09:17,554 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_in stop
.2024-02-02 11:09:20,598 INFO: input command: route_in stop 2024-02-02 11:09:20,599 INFO: Parser cmdParser: cmd opcode: 3305 param: [] name: CMD_SRC_PLAY_ROUTE_IN_STOP 2024-02-02 11:09:20,599 INFO: Packet sendPacket: <<<send packet: AA 0C 02 00 05 33 BA 2024-02-02 11:09:20,614 INFO: AciHostCLI continuously_read: >>>receive packet: AA 0D 05 00 00 00 05 33 00 B6 2024-02-02 11:09:20,615 INFO: Parser eventParser: syncWord: AA,seqn: 0D,len: 5,opcode: 0000,params: [05 33 00], check_sum: B6 2024-02-02 11:09:20,616 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-02-02 11:09:20,618 INFO: Parser eventParser: event_id: [05 33] 2024-02-02 11:09:20,624 INFO: Parser eventParser: status: [00]
Bluetooth Audio Receiver
This chapter introduces the functionality of the bt_audio_receiver
application scenario. This functionality is enabled by opening the macro definition F_APP_BT_AUDIO_RECEIVER_DEMO_SUPPORT
in app_flags.h
. This chapter describes how to use these functions and the flow of how to test them, including the MSCs of the ACI Device and ACI Host interaction, and the commands used by ACI Host.
HFP Function
ACI Host CLI Test
Command |
Parameters |
ACI Host CLI CMD |
Description |
---|---|---|---|
CMD_MMI = 0x0004 |
action = MMI_HF_ANSWER_CALL(0x0003) |
mmi answer |
Answer an incoming call. |
CMD_MMI = 0x0004 |
action = MMI_HF_REJECT_CALL(0x0004) |
mmi reject |
Reject an incoming call. |
CMD_BT_HFP_DIAL_WITH_NUMBER = 0x001B |
number = {…} |
call 10086 |
HFP dial with number ‘10086’. |
MAP Function
Based on the scenario introduced in Connect to Phone, MAP can be used to combine the messaging capabilities of a messaging server device and the user interface capabilities of a client device for browsing, reading, and sending messages.
Before using the MAP function, it is necessary to enable ‘Message access’ on Android devices, and enable ‘Show Notifications’ on iOS devices.
MAP process:
As introduced in the figure, after the MAP connection is established, the device will set a folder
to root\telecom\msg
. The parameters of CMD_MAP_GET_MESSAGE
need to be
set according to the handle
value of the specific message in the message list.
ACI Host CLI Test
The ACI Host uses CMD_MAP_CONNECT
with a status parameter to the ACI Device to establish a MAP connection, uses CMD_MAP_GET_FOLDER_LISTING
, CMD_MAP_GET_MESSAGE_LISTING
, and CMD_MAP_GET_MESSAGE
to get folders and messages, and uses CMD_MAP_REG_MSG_NOTIFICATION
to register message notifications.
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_MAP_CONNECT(0x3801) |
action = map_connect |
map connect |
CMD_MAP_GET_FOLDER_LISTING(0x3802) |
action = get_folder_list(0x0A) |
map get folder list |
CMD_MAP_DISCONNECT(0x3803) |
action = map_disconnect |
map disconnect |
CMD_MAP_GET_MESSAGE_LISTING(0x3805) |
action = get_msg_list(0x0A) |
map get msg list |
CMD_MAP_REG_MSG_NOTIFICATION(0x3809) |
action = reg_msg_note(0x01) |
map reg msg note |
CMD_MAP_GET_MESSAGE(0x380A) |
action = get_msg(handle_length, handle) |
map get msg |
CMD_MAP_PUSH_MESSAGE(0x3810) |
action = push_msg(msg_length,msg) |
map push msg |
ACI Host CLI test: Connect ACI Device to Phone.
Please refer to Connect to Phone.
ACI Host CLI test: MAP connect.
2023-03-08 14:40:07,573 INFO: input command: map connect 2023-03-08 14:40:07,574 INFO: Parser cmdParser: cmd opcode: 3801 param: [] name: CMD_MAP_CONNECT 2023-03-08 14:40:07,575 INFO: Packet sendPacket: <<<send packet: AA 1B 02 00 01 38 AA 2023-03-08 14:40:07,579 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1B 05 00 00 00 01 38 00 A7 2023-03-08 14:40:07,579 INFO: Parser eventParser: syncWord: AA,seqn: 1B,len: 5,opcode: 0000,params: [01 38 00], check_sum: A7 2023-03-08 14:40:07,580 INFO: Parser eventParser: event name: EVENT_ACK 2023-03-08 14:40:07,580 INFO: Parser eventParser: event_id: [01 38] 2023-03-08 14:40:07,580 INFO: Parser eventParser: status: [00] 2023-03-08 14:40:07,804 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1C 09 00 24 09 00 41 AF 7B 6C 32 20 85 2023-03-08 14:40:07,804 INFO: Parser eventParser: syncWord: AA,seqn: 1C,len: 9,opcode: 0924,params: [00 41 AF 7B 6C 32 20], check_sum: 85 2023-03-08 14:40:07,806 INFO: Parser eventParser: event name: EVENT_SERVICES_SEARCH_STATE 2023-03-08 14:40:07,807 INFO: Packet sendPacket: <<<send packet: AA 1C 05 00 00 00 24 09 00 B2
ACI Host CLI test: MAP get folder list.
2023-03-08 14:40:32,790 INFO: input command: map get_folder_list 2023-03-08 14:40:32,791 INFO: Parser cmdParser: cmd opcode: 3802 param: [0A 00] name: CMD_MAP_GET_FOLDER_LISTING 2023-03-08 14:40:32,792 INFO: Packet sendPacket: <<<send packet: AA 1D 04 00 02 38 0A 00 9B 2023-03-08 14:40:32,803 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1D 05 00 00 00 02 38 00 A4 2023-03-08 14:40:32,804 INFO: Parser eventParser: syncWord: AA,seqn: 1D,len: 5,opcode: 0000,params: [02 38 00], check_sum: A4 2023-03-08 14:40:32,804 INFO: Parser eventParser: event name: EVENT_ACK 2023-03-08 14:40:32,804 INFO: Parser eventParser: event_id: [02 38] 2023-03-08 14:40:32,805 INFO: Parser eventParser: status: [00] 2023-03-08 14:40:33,208 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1E FA 00 04 38 3C 3F 78 6D 6C 20 76 65 72 73 69 6F 6E 3D 27 31 2E 30 27 20 65 6E 63 6F 64 69 2023-03-08 14:40:33,209 INFO: Parser eventParser: syncWord: AA,seqn: 1E,len: 250,opcode: 3804,params: [3C 3F 78 6D 6C 20 76 65 72 73 69 6F 6E 3D 27 31 2E 30 27 20 65 6E 63 6F 64 69 6E 67 3D 27 75 74], check_sum: C3 2023-03-08 14:40:33,210 INFO: Packet sendPacket: <<<send packet: AA 1E 05 00 00 00 04 38 00 A1
ACI Host CLI test: MAP get message list.
2023-03-08 14:41:04,092 INFO: input command: map get_msg_list 2023-03-08 14:41:04,093 INFO: Parser cmdParser: cmd opcode: 3805 param: [0A 00] name: CMD_MAP_GET_MESSAGE_LISTING 2023-03-08 14:41:04,095 INFO: Packet sendPacket: <<<send packet: AA 1F 04 00 05 38 0A 00 96 2023-03-08 14:41:04,108 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1F 05 00 00 00 05 38 00 9F 2023-03-08 14:41:04,109 INFO: Parser eventParser: syncWord: AA,seqn: 1F,len: 5,opcode: 0000,params: [05 38 00], check_sum: 9F 2023-03-08 14:41:04,109 INFO: Parser eventParser: event name: EVENT_ACK 2023-03-08 14:41:04,109 INFO: Parser eventParser: event_id: [05 38] 2023-03-08 14:41:04,110 INFO: Parser eventParser: status: [00] 2023-03-08 14:41:05,232 INFO: AciHostCLI continuously_read: >>>receive packet: AA 20 CA 03 06 38 3C 3F 78 6D 6C 20 76 65 72 73 69 6F 6E 3D 27 31 2E 30 27 20 65 6E 63 6F 64 69 2023-03-08 14:41:05,232 INFO: Parser eventParser: syncWord: AA,seqn: 20,len: 970,opcode: 3806,params: [3C 3F 78 6D 6C 20 76 65 72 73 69 6F 6E 3D 27 31 2E 30 27 20 65 6E 63 6F 64 69 6E 67 3D 27 75 74], check_sum: 6B 2023-03-08 14:41:05,234 INFO: Packet sendPacket: <<<send packet: AA 20 05 00 00 00 06 38 00 9D 2023-03-08 14:41:05,267 INFO: AciHostCLI continuously_read: >>>receive packet: AA 21 CA 03 06 38 31 34 36 31 32 22 20 73 65 6E 64 65 72 5F 61 64 64 72 65 73 73 69 6E 67 3D 22 2023-03-08 14:41:05,268 INFO: Parser eventParser: syncWord: AA,seqn: 21,len: 970,opcode: 3806,params: [31 34 36 31 32 22 20 73 65 6E 64 65 72 5F 61 64 64 72 65 73 73 69 6E 67 3D 22 31 30 36 35 39 31], check_sum: 3E 2023-03-08 14:41:05,269 INFO: Packet sendPacket: <<<send packet: AA 21 05 00 00 00 06 38 00 9C 2023-03-08 14:41:05,378 INFO: AciHostCLI continuously_read: >>>receive packet: AA 22 CA 03 06 38 3D 22 6E 6F 22 20 70 72 6F 74 65 63 74 65 64 3D 22 6E 6F 22 20 2F 3E 0A 20 20 2023-03-08 14:41:05,379 INFO: Parser eventParser: syncWord: AA,seqn: 22,len: 970,opcode: 3806,params: [3D 22 6E 6F 22 20 70 72 6F 74 65 63 74 65 64 3D 22 6E 6F 22 20 2F 3E 0A 20 20 20 20 3C 6D 73 67], check_sum: D5 2023-03-08 14:41:05,381 INFO: Packet sendPacket: <<<send packet: AA 22 05 00 00 00 06 38 00 9B 2023-03-08 14:41:05,401 INFO: AciHostCLI continuously_read: >>>receive packet: AA 23 B6 03 07 38 65 6E 64 65 72 5F 61 64 64 72 65 73 73 69 6E 67 3D 22 31 30 36 35 39 33 31 31 2023-03-08 14:41:05,403 INFO: Parser eventParser: syncWord: AA,seqn: 23,len: 950,opcode: 3807,params: [65 6E 64 65 72 5F 61 64 64 72 65 73 73 69 6E 67 3D 22 31 30 36 35 39 33 31 31 31 33 22 20 72 65], check_sum: 10 2023-03-08 14:41:05,405 INFO: Packet sendPacket: <<<send packet: AA 23 05 00 00 00 07 38 00 99
ACI Host CLI test: MAP get message.
2023-03-08 14:41:34,092 INFO: input command: map get_msg 2023-03-08 14:41:34,093 INFO: Parser cmdParser: cmd opcode: 380A param: [22 00 30 00 30 00 34 00 30 00 30 00 30 00 30 00 30 00 30 00 30 00 30 00 30 00 30 00 30 00 42 00] name: CMD_MAP_GET_MESSAGE 2023-03-08 14:41:34,093 INFO: Packet sendPacket: <<<send packet: AA 24 24 00 0A 38 22 00 30 00 30 00 34 00 30 00 30 00 30 00 30 00 30 00 30 00 30 00 30 00 30 00 2023-03-08 14:41:34,107 INFO: AciHostCLI continuously_read: >>>receive packet: AA 24 05 00 00 00 0A 38 00 95 2023-03-08 14:41:34,108 INFO: Parser eventParser: syncWord: AA,seqn: 24,len: 5,opcode: 0000,params: [0A 38 00], check_sum: 95 2023-03-08 14:41:34,108 INFO: Parser eventParser: event name: EVENT_ACK 2023-03-08 14:41:34,108 INFO: Parser eventParser: event_id: [0A 38] 2023-03-08 14:41:34,108 INFO: Parser eventParser: status: [00] 2023-03-08 14:41:34,460 INFO: AciHostCLI continuously_read: >>>receive packet: AA 25 1B 01 0C 38 42 45 47 49 4E 3A 42 4D 53 47 0D 0A 56 45 52 53 49 4F 4E 3A 31 2E 30 0D 0A 53 2023-03-08 14:41:34,460 INFO: Parser eventParser: syncWord: AA,seqn: 25,len: 283,opcode: 380C,params: [42 45 47 49 4E 3A 42 4D 53 47 0D 0A 56 45 52 53 49 4F 4E 3A 31 2E 30 0D 0A 53 54 41 54 55 53 3A], check_sum: 62 2023-03-08 14:41:34,461 INFO: Packet sendPacket: <<<send packet: AA 25 05 00 00 00 0C 38 00 92
ACI Host CLI test: MAP register notification.
2023-03-08 14:43:32,651 INFO: input command: map reg_msg_note 2023-03-08 14:43:32,653 INFO: Parser cmdParser: cmd opcode: 3809 param: [01] name: CMD_MAP_REG_MSG_NOTIFICATION 2023-03-08 14:43:32,654 INFO: Packet sendPacket: <<<send packet: AA 05 03 00 09 38 01 B6 2023-03-08 14:43:32,672 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2A 05 00 00 00 09 38 00 90 2023-03-08 14:43:32,673 INFO: Parser eventParser: syncWord: AA,seqn: 2A,len: 5,opcode: 0000,params: [09 38 00], check_sum: 90 2023-03-08 14:43:32,673 INFO: Parser eventParser: event name: EVENT_ACK 2023-03-08 14:43:32,674 INFO: Parser eventParser: event_id: [09 38] 2023-03-08 14:43:32,674 INFO: Parser eventParser: status: [00]
ACI Host CLI test: MAP push message.
2023-03-08 14:42:49,284 INFO: input command: map push_msg 2023-03-08 14:42:49,287 INFO: Parser cmdParser: cmd opcode: 3810 param: [F8 00 42 45 47 49 4E 3A 42 4D 53 47 0D 0A 56 45 52 53 49 4F 4E 3A 31 2E 30 0D 0A 53 54 41 54 55] name: CMD_MAP_PUSH_MESSAGE 2023-03-08 14:42:49,289 INFO: Packet sendPacket: <<<send packet: AA 03 FC 00 10 38 F8 00 42 45 47 49 4E 3A 42 4D 53 47 0D 0A 56 45 52 53 49 4F 4E 3A 31 2E 30 0D 2023-03-08 14:42:49,296 INFO: AciHostCLI continuously_read: >>>receive packet: AA 28 05 00 00 00 10 38 00 8B 2023-03-08 14:42:49,296 INFO: Parser eventParser: syncWord: AA,seqn: 28,len: 5,opcode: 0000,params: [10 38 00], check_sum: 8B 2023-03-08 14:42:49,296 INFO: Parser eventParser: event name: EVENT_ACK 2023-03-08 14:42:49,297 INFO: Parser eventParser: event_id: [10 38] 2023-03-08 14:42:49,297 INFO: Parser eventParser: status: [00]
ACI Host CLI test: MAP disconnect.
2023-03-08 19:15:22,350 INFO: input command: map disconnect 2023-03-08 19:15:22,353 INFO: Parser cmdParser: cmd opcode: 3803 param: [] name: CMD_MAP_DISCONNECT 2023-03-08 19:15:22,354 INFO: Packet sendPacket: <<<send packet: AA 39 02 00 03 38 8A 2023-03-08 19:15:22,368 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2E 05 00 00 00 03 38 00 92 2023-03-08 19:15:22,371 INFO: Parser eventParser: syncWord: AA,seqn: 2E,len: 5,opcode: 0000,params: [03 38 00], check_sum: 92 2023-03-08 19:15:22,373 INFO: Parser eventParser: event name: EVENT_ACK 2023-03-08 19:15:22,373 INFO: Parser eventParser: event_id: [03 38] 2023-03-08 19:15:22,374 INFO: Parser eventParser: status: [00]
PBAP Function
Based on the scenario introduced in Connect to Phone, PBAP can be used to pull phone book objects and combined call history from the server device.
Before using the PBAP function, Android phones need to open ‘Contact access’, and iOS phones need to open ‘Sync Contacts’.
PBAP process:
As introduced in the figure, after the PBAP connection is established, the device will set a folder to root\telecom\pb
. The folder will be set to root\telecom\cch
when the device uses CMD_PBAP_DOWNLOAD
with download_cch
action.
ACI Host CLI Test
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_PBAP_DOWNLOAD(0x0420) |
action = download_all(0x03) |
pbap download_all |
CMD_PBAP_DOWNLOAD(0x0420) |
action = download_PB(0x04) |
pbap download_PB |
CMD_PBAP_DOWNLOAD(0x0420) |
action = download_cch(0x05) |
pbap download_cch |
CMD_PBAP_CONNECT(0x0423) |
action = pbap_connect |
pbap connect |
CMD_PBAP_DISCONNECT(0x0426) |
action = pbap_disconnect |
pbap disconnect |
The ACI Host uses CMD_PBAP_CONNECT
to ACI Device to establish PBAP connection, and uses CMD_PBAP_DOWNLOAD
to get phonebook and call history.
ACI Host CLI test: Connect ACI Device to Phone.
Please refer to Connect to Phone.
ACI Host CLI test: PBAP connect.
2023-03-09 16:53:57,753 INFO: input command: pbap connect 2023-03-09 16:53:57,753 INFO: Parser cmdParser: cmd opcode: 0423 param: [] name: CMD_PBAP_CONNECT 2023-03-09 16:53:57,754 INFO: Packet sendPacket: <<<send packet: AA 44 02 00 23 04 83 2023-03-09 16:53:57,762 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1E 05 00 00 00 23 04 00 A6 2023-03-09 16:53:57,763 INFO: Parser eventParser: syncWord: AA,seqn: 1E,len: 5,opcode: 0000,params: [23 04 00], check_sum: A6 2023-03-09 16:53:57,763 INFO: Parser eventParser: event name: EVENT_ACK 2023-03-09 16:53:57,763 INFO: Parser eventParser: event_id: [23 04] 2023-03-09 16:53:57,763 INFO: Parser eventParser: status: [00] 2023-03-09 16:53:58,003 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1F 09 00 24 09 00 41 AF 7B 6C 32 20 82 2023-03-09 16:53:58,003 INFO: Parser eventParser: syncWord: AA,seqn: 1F,len: 9,opcode: 0924,params: [00 41 AF 7B 6C 32 20], check_sum: 82 2023-03-09 16:53:58,004 INFO: Parser eventParser: event name: EVENT_SERVICES_SEARCH_STATE 2023-03-09 16:53:58,004 INFO: Packet sendPacket: <<<send packet: AA 45 05 00 00 00 24 09 00 89
ACI Host CLI test: PBAP download_PB.
2023-03-09 16:54:40,282 INFO: input command: pbap download_PB 2023-03-09 16:54:40,283 INFO: Parser cmdParser: cmd opcode: 0420 param: [04] name: CMD_PBAP_DOWNLOAD 2023-03-09 16:54:40,283 INFO: Packet sendPacket: <<<send packet: AA 05 03 00 20 04 04 C0 2023-03-09 16:54:40,298 INFO: AciHostCLI continuously_read: >>>receive packet: AA 24 05 00 00 00 20 04 00 A3 2023-03-09 16:54:40,299 INFO: Parser eventParser: syncWord: AA,seqn: 24,len: 5,opcode: 0000,params: [20 04 00], check_sum: A3 2023-03-09 16:54:40,299 INFO: Parser eventParser: event name: EVENT_ACK 2023-03-09 16:54:40,299 INFO: Parser eventParser: event_id: [20 04] 2023-03-09 16:54:40,299 INFO: Parser eventParser: status: [00] 2023-03-09 16:54:40,426 INFO: AciHostCLI continuously_read: >>>receive packet: AA 25 13 00 02 05 07 02 00 00 00 02 00 C0 F8 EF 2C 41 AF 7B 6C 32 20 BA 2023-03-09 16:54:40,427 INFO: Parser eventParser: syncWord: AA,seqn: 25,len: 19,opcode: 0502,params: [07 02 00 00 00 02 00 C0 F8 EF 2C 41 AF 7B 6C 32 20], check_sum: BA 2023-03-09 16:54:40,427 INFO: Parser eventParser: event name: EVENT_PBAP_DOWNLOAD_START 2023-03-09 16:54:40,428 INFO: Packet sendPacket: <<<send packet: AA 06 05 00 00 00 02 05 00 EE 2023-03-09 16:54:40,633 INFO: AciHostCLI continuously_read: >>>receive packet: AA 26 66 00 00 05 62 00 42 45 47 49 4E 3A 56 43 41 52 44 0D 0A 56 45 52 53 49 4F 4E 3A 32 2E 31 2023-03-09 16:54:40,634 INFO: Parser eventParser: syncWord: AA,seqn: 26,len: 102,opcode: 0500,params: [62 00 42 45 47 49 4E 3A 56 43 41 52 44 0D 0A 56 45 52 53 49 4F 4E 3A 32 2E 31 0D 0A 46 4E 3B 43], check_sum: B9 2023-03-09 16:54:40,635 INFO: Parser eventParser: event name: EVENT_PBAP_REPORT_DATA 2023-03-09 16:54:40,635 INFO: Packet sendPacket: <<<send packet: AA 07 05 00 00 00 00 05 00 EF 2023-03-09 16:54:40,652 INFO: AciHostCLI continuously_read: >>>receive packet: AA 27 43 00 00 05 3F 00 42 45 47 49 4E 3A 56 43 41 52 44 0D 0A 56 45 52 53 49 4F 4E 3A 32 2E 31 2023-03-09 16:54:40,668 INFO: Parser eventParser: syncWord: AA,seqn: 28,len: 9,opcode: 0503,params: [07 41 AF 7B 6C 32 20], check_sum: 97 2023-03-09 16:54:40,669 INFO: Parser eventParser: event name: EVENT_PBAP_DOWNLOAD_CMPL 2023-03-09 16:54:40,669 INFO: Packet sendPacket: <<<send packet: AA 09 05 00 00 00 03 05 00 EA
ACI Host CLI test: PBAP download_cch.
2023-03-09 16:55:19,105 INFO: input command: pbap download_cch 2023-03-09 16:55:19,106 INFO: Parser cmdParser: cmd opcode: 0420 param: [05] name: CMD_PBAP_DOWNLOAD 2023-03-09 16:55:19,107 INFO: Packet sendPacket: <<<send packet: AA 0D 03 00 20 04 05 B7 2023-03-09 16:55:19,124 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2C 05 00 00 00 20 04 00 9B 2023-03-09 16:55:19,124 INFO: Parser eventParser: syncWord: AA,seqn: 2C,len: 5,opcode: 0000,params: [20 04 00], check_sum: 9B 2023-03-09 16:55:19,125 INFO: Parser eventParser: event name: EVENT_ACK 2023-03-09 16:55:19,125 INFO: Parser eventParser: event_id: [20 04] 2023-03-09 16:55:19,125 INFO: Parser eventParser: status: [00] 2023-03-09 16:55:19,524 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2D 13 00 02 05 04 2C 01 00 00 2C 01 B7 B8 C4 2C 41 AF 7B 6C 32 20 D3 2023-03-09 16:55:19,525 INFO: Parser eventParser: syncWord: AA,seqn: 2D,len: 19,opcode: 0502,params: [04 2C 01 00 00 2C 01 B7 B8 C4 2C 41 AF 7B 6C 32 20], check_sum: D3 2023-03-09 16:55:19,526 INFO: Parser eventParser: event name: EVENT_PBAP_DOWNLOAD_START 2023-03-09 16:55:19,526 INFO: Packet sendPacket: <<<send packet: AA 0E 05 00 00 00 02 05 00 E6 2023-03-09 16:55:20,158 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2E 76 00 00 05 72 00 42 45 47 49 4E 3A 56 43 41 52 44 0D 0A 56 45 52 53 49 4F 4E 3A 32 2E 31 2023-03-09 16:55:20,159 INFO: Parser eventParser: syncWord: AA,seqn: 2E,len: 118,opcode: 0500,params: [72 00 42 45 47 49 4E 3A 56 43 41 52 44 0D 0A 56 45 52 53 49 4F 4E 3A 32 2E 31 0D 0A 46 4E 3A 0D], check_sum: A4 2023-03-09 16:55:20,159 INFO: Parser eventParser: event name: EVENT_PBAP_REPORT_DATA 2023-03-09 16:55:20,160 INFO: Packet sendPacket: <<<send packet: AA 0F 05 00 00 00 00 05 00 E7 2023-03-09 16:55:20,177 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2F 76 00 00 05 72 00 42 45 47 49 4E 3A 56 43 41 52 44 0D 0A 56 45 52 53 49 4F 4E 3A 32 2E 31 2023-03-09 16:55:20,177 INFO: Parser eventParser: syncWord: AA,seqn: 2F,len: 118,opcode: 0500,params: [72 00 42 45 47 49 4E 3A 56 43 41 52 44 0D 0A 56 45 52 53 49 4F 4E 3A 32 2E 31 0D 0A 46 4E 3A 0D], check_sum: 94 2023-03-09 16:55:20,178 INFO: Parser eventParser: event name: EVENT_PBAP_REPORT_DATA 2023-03-09 16:55:20,178 INFO: Packet sendPacket: <<<send packet: AA 10 05 00 00 00 00 05 00 E6 //PBAP keeps reporting data ... 2023-03-09 16:55:40,239 INFO: AciHostCLI continuously_read: >>>receive packet: AA 7B 09 00 03 05 04 41 AF 7B 6C 32 20 47 2023-03-09 16:55:40,240 INFO: Parser eventParser: syncWord: AA,seqn: 7B,len: 9,opcode: 0503,params: [04 41 AF 7B 6C 32 20], check_sum: 47 2023-03-09 16:55:40,240 INFO: Parser eventParser: event name: EVENT_PBAP_DOWNLOAD_CMPL 2023-03-09 16:55:40,240 INFO: Packet sendPacket: <<<send packet: AA 5B 05 00 00 00 03 05 00 98
ACI Host CLI test: PBAP download_all.
2023-03-09 16:56:56,241 INFO: input command: pbap download_all 2023-03-09 16:56:56,242 INFO: Parser cmdParser: cmd opcode: 0420 param: [03] name: CMD_PBAP_DOWNLOAD 2023-03-09 16:56:56,242 INFO: Packet sendPacket: <<<send packet: AA 5C 03 00 20 04 03 6A 2023-03-09 16:56:56,262 INFO: AciHostCLI continuously_read: >>>receive packet: AA 7C 05 00 00 00 20 04 00 4B 2023-03-09 16:56:56,263 INFO: Parser eventParser: syncWord: AA,seqn: 7C,len: 5,opcode: 0000,params: [20 04 00], check_sum: 4B 2023-03-09 16:56:56,264 INFO: Parser eventParser: event name: EVENT_ACK 2023-03-09 16:56:56,265 INFO: Parser eventParser: event_id: [20 04] 2023-03-09 16:56:56,265 INFO: Parser eventParser: status: [00] 2023-03-09 16:56:56,821 INFO: AciHostCLI continuously_read: >>>receive packet: AA 7D 13 00 02 05 07 02 00 00 00 02 00 6A 08 C5 2C 41 AF 7B 6C 32 20 D2 2023-03-09 16:56:56,822 INFO: Parser eventParser: syncWord: AA,seqn: 7D,len: 19,opcode: 0502,params: [07 02 00 00 00 02 00 6A 08 C5 2C 41 AF 7B 6C 32 20], check_sum: D2 2023-03-09 16:56:56,822 INFO: Parser eventParser: event name: EVENT_PBAP_DOWNLOAD_START 2023-03-09 16:56:56,822 INFO: Packet sendPacket: <<<send packet: AA 5D 05 00 00 00 02 05 00 97 2023-03-09 16:56:57,027 INFO: AciHostCLI continuously_read: >>>receive packet: AA 7E 66 00 00 05 62 00 42 45 47 49 4E 3A 56 43 41 52 44 0D 0A 56 45 52 53 49 4F 4E 3A 32 2E 31 2023-03-09 16:56:57,028 INFO: Parser eventParser: syncWord: AA,seqn: 7E,len: 102,opcode: 0500,params: [62 00 42 45 47 49 4E 3A 56 43 41 52 44 0D 0A 56 45 52 53 49 4F 4E 3A 32 2E 31 0D 0A 46 4E 3B 43], check_sum: 61 2023-03-09 16:56:57,028 INFO: Parser eventParser: event name: EVENT_PBAP_REPORT_DATA 2023-03-09 16:56:57,029 INFO: Packet sendPacket: <<<send packet: AA 5E 05 00 00 00 00 05 00 98 //PBAP keep reporting data ... 2023-03-09 16:57:18,438 INFO: AciHostCLI continuously_read: >>>receive packet: AA D2 09 00 03 05 04 41 AF 7B 6C 32 20 F0 2023-03-09 16:57:18,438 INFO: Parser eventParser: syncWord: AA,seqn: D2,len: 9,opcode: 0503,params: [04 41 AF 7B 6C 32 20], check_sum: F0 2023-03-09 16:57:18,438 INFO: Parser eventParser: event name: EVENT_PBAP_DOWNLOAD_CMPL 2023-03-09 16:57:18,439 INFO: Packet sendPacket: <<<send packet: AA B1 05 00 00 00 03 05 00 42
ACI Host CLI test: PBAP disconnect.
2023-03-09 17:33:30,246 INFO: input command: pbap disconnect 2023-03-09 17:33:30,247 INFO: Parser cmdParser: cmd opcode: 0426 param: [] name: CMD_PBAP_DISCONNECT 2023-03-09 17:33:30,248 INFO: Packet sendPacket: <<<send packet: AA 38 02 00 26 04 8C 2023-03-09 17:33:30,265 INFO: AciHostCLI continuously_read: >>>receive packet: AA 38 05 00 00 00 26 04 00 89 2023-03-09 17:33:30,265 INFO: Parser eventParser: syncWord: AA,seqn: 38,len: 5,opcode: 0000,params: [26 04 00], check_sum: 89 2023-03-09 17:33:30,266 INFO: Parser eventParser: event name: EVENT_ACK 2023-03-09 17:33:30,266 INFO: Parser eventParser: event_id: [26 04] 2023-03-09 17:33:30,266 INFO: Parser eventParser: status: [00] 2023-03-09 17:33:30,361 INFO: AciHostCLI continuously_read: >>>receive packet: AA 39 0B 00 04 00 40 41 AF 7B 6C 32 20 00 00 4F 2023-03-09 17:33:30,361 INFO: Parser eventParser: syncWord: AA,seqn: 39,len: 11,opcode: 0004,params: [40 41 AF 7B 6C 32 20 00 00], check_sum: 4F 2023-03-09 17:33:30,362 INFO: Parser eventParser: event name: EVENT_DISCONNECT_STATUS 2023-03-09 17:33:30,362 INFO: Parser eventParser: link_id: [40] 2023-03-09 17:33:30,362 INFO: Parser eventParser: profile: [41] 2023-03-09 17:33:30,362 INFO: Parser eventParser: bd_addr: [AF 7B 6C 32 20 00] 2023-03-09 17:33:30,362 INFO: Parser eventParser: cause: [00] 2023-03-09 17:33:30,363 INFO: Packet sendPacket: <<<send packet: AA 39 05 00 00 00 04 00 00 BE
CIS Acceptor Function
Firstly, CIS Acceptor needs to start LE Audio advertising, and then CIS Initiator can scan and connect it. After the LE Audio link is connected, CIS Acceptor can control remote media player and telephone call.
CIS Acceptor connection process:
CIS Acceptor media/call control process:
ACI Host CLI Test
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_LEA_ADV_START(0x3250) |
lea_adv_start |
|
CMD_LEA_ADV_STOP |
None |
lea_adv_stop |
CMD_LEA_CCP_CALL_CP |
conn_id=0 |
lea_call_cp accept |
CMD_LEA_CCP_CALL_CP |
conn_id=0 |
lea_call_cp terminate |
CMD_LEA_CCP_CALL_CP |
conn_id=0 |
lea_call_cp local_hold |
CMD_LEA_CCP_CALL_CP |
conn_id=0 |
lea_call_cp local_retrieve |
CMD_LEA_CCP_CALL_CP |
conn_id=0 |
lea_call_cp originate |
CMD_LEA_CCP_CALL_CP |
conn_id=0 |
lea_call_cp join |
CMD_LEA_MCP_MEDIA_CP |
conn_id=0 |
lea_media_cp play |
CMD_LEA_MCP_MEDIA_CP |
conn_id=0 |
lea_media_cp pause |
CMD_LEA_MCP_MEDIA_CP |
conn_id=0 |
lea_media_cp fast_rewind |
CMD_LEA_MCP_MEDIA_CP |
conn_id=0 |
lea_media_cp fast_forward |
CMD_LEA_MCP_MEDIA_CP |
conn_id=0 |
lea_media_cp stop |
CMD_LEA_MCP_MEDIA_CP |
conn_id=0 |
lea_media_cp previous_track |
CMD_LEA_MCP_MEDIA_CP |
conn_id=0 |
lea_media_cp next_track |
CMD_LEA_VCS_SET |
conn_id=0 |
lea_vcs vol_up |
CMD_LEA_VCS_SET |
conn_id=0 |
lea_vcs vol_down |
CMD_LEA_VCS_SET |
conn_id=0 |
lea_vcs spk_mute |
CMD_LEA_VCS_SET |
conn_id=0 |
lea_vcs spk_unmute |
For detailed information, please refer to CIS Acceptor ACI Host CLI Test.
BIS Acceptor Function
If an assistant exists, the sink could connect with an assistant and ask the assistant to assist it for scanning and get the extended advertising and periodic advertising info. If the assistant doesn’t exist, the sink needs to sync the source autonomously.
BIS sync establish process:
ACI Host CLI Test
Please refer to LE Audio Acceptor.
Bluetooth Audio Transceiver
This chapter introduces the functionality of the bt_audio_transceiver
application scenario. This functionality is enabled by opening the macro definition F_APP_BT_AUDIO_TRANSCEIVER_DEMO_SUPPORT
in app_flags.h
. This chapter describes how to use these functions and the flow of how to test them, including the MSCs of the ACI Device and ACI Host interaction, and the commands used by ACI Host.
A2DP Transparent Transmission (A2DP Output)
Two typical application scenarios are introduced in chapter Bluetooth Audio Transceiver. Based on the A2DP scenario, A2DP data can be transferred from the Phone, through ACI Device 1 and ACI Device 2, to the Headset. This function is called A2DP Transparent Transmission.
A2DP Transparent Transmission process:
ACI Device 1 and ACI Device 2 transmit data through SPI. The SPI role of ACI Device 1 is master and
that of ACI Device 2 is the slave. Please set flag F_APP_SPI_ROLE_MASTER
on ACI Device 1 and set
flag F_APP_SPI_ROLE_SLAVE
on ACI Device 2 to enable SPI before building the application.
The AVDTP data format between Phone and ACI Device 1 may be different from that between ACI Device 2 and Headset. To solve this mismatch, the Audio Pipe is introduced on ACI Device 2 to convert the format in the route of Phone -> ACI Device 1 to that in the route of ACI Device 2 -> Headset.
ACI Host CLI Test
Before using the function, the hardware environment needs to be configured.
Bluetooth address modification: Use the MCUConfig Tool to modify the Bluetooth address of ACI Device 2 to make it different from ACI Device 1.
SPI wiring preparation: The recommended connection is P0_0(SPI_SCK)
, P1_0(SPI_MOSI)
, P0_1(SPI_MISO)
, P1_1(SPI_CS)
, P2_1(PIN_GPIO)
and GND
of ACI Device 1 and ACI Device 2. Developers can connect according to the pin settings in board.h
.
The play route of Device 2 should be configured to A2DP Source through CMD_A2DP_XMIT_SET_ROUTE_OUT
.
The ACI Host sends CMD_A2DP_XMIT_ROUTE_OUT_CTRL
with status param to ACI Device 2 to start or stop
processing and sending data to Headset. The corresponding UART CMD packet and tool log are as follows:
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_A2DP_XMIT_SET_ROUTE_OUT(0x3223) |
action = XMIT_PLAY_ROUTE_A2DP_SRC(0) |
a2dpxmitroute a2dpsrc |
CMD_A2DP_XMIT_ROUTE_OUT_CTRL(0x3220) |
action = XMIT_PLAY_STATE_START(0) |
a2dpxmitctrl start |
CMD_A2DP_XMIT_ROUTE_OUT_CTRL(0x3220) |
action = XMIT_PLAY_STATE_IDLE(1) |
a2dpxmitctrl stop |
ACI Host CLI test (ACI Device 2): Initiate ACI Device 2 as SPI slave.
2023-05-15 14:53:17,075 INFO: input command: spiinit slave 2023-05-15 14:53:17,075 INFO: Parser cmdParser: cmd opcode: 3020 param: [01] name: CMD_SPI_INIT 2023-05-15 14:53:17,076 INFO: Packet sendPacket: <<<send packet: AA 03 03 00 20 30 01 C8 2023-05-15 14:53:17,082 INFO: AciHostCLI continuously_read: >>>receive packet: AA 03 05 00 00 00 20 30 00 C7 2023-05-15 14:53:17,083 INFO: Parser eventParser: syncWord: AA,seqn: 03,len: 5,opcode: 0000,params: [20 30 00], check_sum: C7 2023-05-15 14:53:17,086 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-15 14:53:17,087 INFO: Parser eventParser: event_id: [20 30] 2023-05-15 14:53:17,087 INFO: Parser eventParser: status: [00]
ACI Host CLI test (ACI Device 1): Initiate ACI Device 1 as SPI master.
2023-05-15 14:53:20,655 INFO: input command: spiinit master 2023-05-15 14:53:20,655 INFO: Parser cmdParser: cmd opcode: 3100 param: [00] name: CMD_SPI_INIT 2023-05-15 14:53:20,656 INFO: Packet sendPacket: <<<send packet: AA 03 03 00 20 30 00 C9 2023-05-15 14:53:20,670 INFO: AciHostCLI continuously_read: >>>receive packet: AA 03 05 00 00 00 20 30 00 C7 2023-05-15 14:53:20,671 INFO: Parser eventParser: syncWord: AA,seqn: 03,len: 5,opcode: 0000,params: [20 30 00], check_sum: C7 2023-05-15 14:53:20,671 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-15 14:53:20,672 INFO: Parser eventParser: event_id: [20 30] 2023-05-15 14:53:20,672 INFO: Parser eventParser: status: [00]
ACI Host CLI test (ACI Device 1): Connect ACI Device 1 to Phone.
Please refer to Connect to Phone.
ACI Host CLI test (ACI Device 2): Connect Headset to ACI Device 2.
Please refer to Connect to BUD.
Phone starts to play music.
ACI Host CLI test (ACI Device 2): Start or stop transmitting data to Headset.
Use CMD
a2dpxmitroute a2dpsrc
to configure the output data route to A2DP Source, and inputa2dpxmitctrl start
to let the Headset get incoming music data from the Phone, inputa2dpxmitctrl stop
, no data will be transmitted to the Headset, music will stop.2023-05-15 14:53:58,736 INFO: input command: a2dpxmitroute a2dpsrc 2023-05-15 14:53:58,737 INFO: Parser cmdParser: cmd opcode: 3223 param: [00] name: CMD_A2DP_XMIT_SET_ROUTE_OUT 2023-05-15 14:53:58,737 INFO: Packet sendPacket: <<<send packet: AA 12 03 00 23 32 00 B5 2023-05-15 14:53:58,748 INFO: AciHostCLI continuously_read: >>>receive packet: AA 12 05 00 00 00 23 32 00 B3 2023-05-15 14:53:58,749 INFO: Parser eventParser: syncWord: AA,seqn: 12,len: 5,opcode: 0000,params: [23 32 00], check_sum: B3 2023-05-15 14:53:58,749 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-15 14:53:58,750 INFO: Parser eventParser: event_id: [23 32] 2023-05-15 14:53:58,750 INFO: Parser eventParser: status: [00] 2023-05-15 14:54:01,482 INFO: input command: a2dpxmitctrl start 2023-05-15 14:54:01,483 INFO: Parser cmdParser: cmd opcode: 3220 param: [00] name: CMD_A2DP_XMIT_ROUTE_OUT_CTRL 2023-05-15 14:54:01,483 INFO: Packet sendPacket: <<<send packet: AA 13 03 00 20 32 00 B7 2023-05-15 14:54:01,499 INFO: AciHostCLI continuously_read: >>>receive packet: AA 13 05 00 00 00 20 32 00 B5 2023-05-15 14:54:01,499 INFO: Parser eventParser: syncWord: AA,seqn: 13,len: 5,opcode: 0000,params: [20 32 00], check_sum: B5 2023-05-15 14:54:01,500 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-15 14:54:01,500 INFO: Parser eventParser: event_id: [20 32] 2023-05-15 14:54:01,501 INFO: Parser eventParser: status: [00] 2023-05-15 14:54:11,089 INFO: input command: a2dpxmitctrl stop 2023-05-15 14:54:11,089 INFO: Parser cmdParser: cmd opcode: 3220 param: [01] name: CMD_A2DP_XMIT_ROUTE_OUT_CTRL 2023-05-15 14:54:11,090 INFO: Packet sendPacket: <<<send packet: AA 14 03 00 20 32 01 B5 2023-05-15 14:54:11,097 INFO: AciHostCLI continuously_read: >>>receive packet: AA 14 05 00 00 00 20 32 00 B4 2023-05-15 14:54:11,101 INFO: Parser eventParser: syncWord: AA,seqn: 14,len: 5,opcode: 0000,params: [20 32 00], check_sum: B4 2023-05-15 14:54:11,103 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-15 14:54:11,104 INFO: Parser eventParser: event_id: [20 32] 2023-05-15 14:54:11,104 INFO: Parser eventParser: status: [00]
A2DP Transparent Transmission (BIS Output)
LE Audio is a new Bluetooth wireless standard for transmitting audio. LE Audio operates on the Bluetooth Low Energy radio, which is different from Classic Audio (like A2DP or HFP) operates on the Bluetooth Classic radio. LE Audio transmits stream through BIS (Broadcast Isochronous Streams) or CIS (Connected Isochronous Streams). Currently, Bluetooth Audio Transceiver application supports broadcasting audio through BIS.
As a broadcaster, the audio data for broadcasting is necessary. Based on the typical A2DP scenario (refer to Bluetooth Audio Transceiver), we use the AVDTP data received from the Phone by ACI Device 1 as the raw data for ACI Device 2. The received AVDTP data would be converted to LC3 format supported by LE Audio through the Audio Pipe. On ACI Device 2, a BIG with 1 or 2 BIS would be set up and broadcast the converted LC3 data externally. The topology is shown in the figure below.
Before enabling the broadcast source feature, please ensure that the LE isochronous function and PA function are enabled in MCUConfig Tool, and at least 1 BIG, 2 BIS and 1 PA are set up.
Broadcast Source process:
ACI Host CLI Test
The ACI Host sends CMD_LEA_BSRC_INIT
to ACI Device 2 to configure the codec type, BIS number and
encryption mode. The play route of Device 2 should be configured to BIS through
CMD_A2DP_XMIT_SET_ROUTE_OUT
and the ACI Host sends CMD_A2DP_XMIT_ROUTE_OUT_CTRL
with status param
to ACI Device 2 to start or stop processing and sending data to Headset.
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_LEA_BSRC_INIT(0x3020) |
codec type = CODEC_CFG_ITEM_48_4(48k) |
bsrcinit 48k_1bis |
CMD_LEA_BSRC_INIT(0x3020) |
codec type = CODEC_CFG_ITEM_16_2(16k) |
bsrcinit 16k_1bis |
CMD_LEA_BSRC_INIT(0x3020) |
codec type = CODEC_CFG_ITEM_48_4(48k) |
bsrcinit 48k_2bis |
CMD_LEA_BSRC_INIT(0x3020) |
codec type = CODEC_CFG_ITEM_16_2(16k) |
bsrcinit 16k_2bis |
CMD_A2DP_XMIT_SET_ROUTE_OUT(0x3223) |
action = XMIT_PLAY_ROUTE_A2DP_SRC(0) |
a2dpxmitroute bis |
CMD_A2DP_XMIT_ROUTE_OUT_CTRL(0x3220) |
action = XMIT_PLAY_STATE_START(0) |
a2dpxmitctrl start |
CMD_A2DP_XMIT_ROUTE_OUT_CTRL(0x3220) |
action = XMIT_PLAY_STATE_IDLE(1) |
a2dpxmitctrl stop |
The corresponding UART CMD packet and tool log are as follows:
ACI Host CLI test (ACI Device 2): Initiate ACI Device 2 as SPI slave.
2023-05-15 14:53:17,075 INFO: input command: spiinit slave 2023-05-15 14:53:17,075 INFO: Parser cmdParser: cmd opcode: 3100 param: [01] name: CMD_SPI_INIT 2023-05-15 14:53:17,076 INFO: Packet sendPacket: <<<send packet: AA 03 03 00 20 30 01 C8 2023-05-15 14:53:17,082 INFO: AciHostCLI continuously_read: >>>receive packet: AA 03 05 00 00 00 20 30 00 C7 2023-05-15 14:53:17,083 INFO: Parser eventParser: syncWord: AA,seqn: 03,len: 5,opcode: 0000,params: [20 30 00], check_sum: C7 2023-05-15 14:53:17,086 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-15 14:53:17,087 INFO: Parser eventParser: event_id: [20 30] 2023-05-15 14:53:17,087 INFO: Parser eventParser: status: [00]
ACI Host CLI test (ACI Device 1): Initiate ACI Device 1 as SPI master.
2023-05-15 14:53:20,655 INFO: input command: spiinit master 2023-05-15 14:53:20,655 INFO: Parser cmdParser: cmd opcode: 3100 param: [00] name: CMD_SPI_INIT 2023-05-15 14:53:20,656 INFO: Packet sendPacket: <<<send packet: AA 03 03 00 20 30 00 C9 2023-05-15 14:53:20,670 INFO: AciHostCLI continuously_read: >>>receive packet: AA 03 05 00 00 00 20 30 00 C7 2023-05-15 14:53:20,671 INFO: Parser eventParser: syncWord: AA,seqn: 03,len: 5,opcode: 0000,params: [20 30 00], check_sum: C7 2023-05-15 14:53:20,671 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-15 14:53:20,672 INFO: Parser eventParser: event_id: [20 30] 2023-05-15 14:53:20,672 INFO: Parser eventParser: status: [00]
ACI Host CLI test (ACI Device 2): Initiate broadcast source.
2023-05-15 14:53:25,753 INFO: input command: bsrcinit 48k_1bis 2023-05-15 14:53:25,753 INFO: Parser cmdParser: cmd opcode: 3020 param: [0D 01 00 01 10 27] name: CMD_LEA_BSRC_INIT 2023-05-15 14:53:25,754 INFO: Packet sendPacket: <<<send packet: AA 04 05 00 20 30 0D 01 00 01 10 27 B7 2023-05-15 14:53:25,766 INFO: AciHostCLI continuously_read: >>>receive packet: AA 04 05 00 00 00 20 30 00 C5 2023-05-15 14:53:25,767 INFO: Parser eventParser: syncWord: AA,seqn: 04,len: 5,opcode: 0000,params: [20 30 00], check_sum: C5 2023-05-15 14:53:25,768 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-15 14:53:25,768 INFO: Parser eventParser: event_id: [20 30] 2023-05-15 14:53:25,769 INFO: Parser eventParser: status: [00]
ACI Host CLI test (ACI Device 1): Connect ACI Device 1 to Phone.
Please refer to Connect to Phone.
Use CMD
a2dpxmitroute bis
to config the output data route to BIS, and inputa2dpxmitctrl start
to let Headset to get incoming music data from the Phone. If you inputa2dpxmitctrl stop
, no data will be transmitted to Headset, music will stop.ACI Host CLI test (ACI Device 1): Start streaming.
2023-05-15 14:54:16,535 INFO: input command: a2dpxmitroute bis 2023-05-15 14:54:16,535 INFO: Parser cmdParser: cmd opcode: 3223 param: [01] name: CMD_A2DP_XMIT_SET_ROUTE_OUT 2023-05-15 14:54:16,536 INFO: Packet sendPacket: <<<send packet: AA 15 03 00 23 32 01 B1 2023-05-15 14:54:16,549 INFO: AciHostCLI continuously_read: >>>receive packet: AA 15 05 00 00 00 23 32 00 B0 2023-05-15 14:54:16,550 INFO: Parser eventParser: syncWord: AA,seqn: 15,len: 5,opcode: 0000,params: [23 32 00], check_sum: B0 2023-05-15 14:54:16,551 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-15 14:54:16,551 INFO: Parser eventParser: event_id: [23 32] 2023-05-15 14:54:16,552 INFO: Parser eventParser: status: [00]
ACI Host CLI test (ACI Device 1): Start streaming.
2023-05-15 14:54:26,384 INFO: input command: a2dpxmitctrl start 2023-05-15 14:54:26,384 INFO: Parser cmdParser: cmd opcode: 3220 param: [00] name: CMD_A2DP_XMIT_ROUTE_OUT_CTRL 2023-05-15 14:54:26,385 INFO: Packet sendPacket: <<<send packet: AA 16 03 00 20 32 00 B4 2023-05-15 14:54:26,402 INFO: AciHostCLI continuously_read: >>>receive packet: AA 16 05 00 00 00 20 32 00 B2 2023-05-15 14:54:26,403 INFO: Parser eventParser: syncWord: AA,seqn: 16,len: 5,opcode: 0000,params: [20 32 00], check_sum: B2 2023-05-15 14:54:26,404 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-15 14:54:26,404 INFO: Parser eventParser: event_id: [20 32] 2023-05-15 14:54:26,404 INFO: Parser eventParser: status: [00]
ACI Host CLI test (ACI Device 1): Stop streaming.
2023-05-15 14:54:48,305 INFO: input command: a2dpxmitctrl stop 2023-05-15 14:54:48,305 INFO: Parser cmdParser: cmd opcode: 3220 param: [01] name: CMD_A2DP_XMIT_ROUTE_OUT_CTRL 2023-05-15 14:54:48,306 INFO: Packet sendPacket: <<<send packet: AA 17 03 00 20 32 01 B2 2023-05-15 14:54:48,314 INFO: AciHostCLI continuously_read: >>>receive packet: AA 17 05 00 00 00 20 32 00 B1 2023-05-15 14:54:48,316 INFO: Parser eventParser: syncWord: AA,seqn: 17,len: 5,opcode: 0000,params: [20 32 00], check_sum: B1 2023-05-15 14:54:48,319 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-15 14:54:48,320 INFO: Parser eventParser: event_id: [20 32] 2023-05-15 14:54:48,321 INFO: Parser eventParser: status: [00]
HFP Transparent Transmission
Based on the SCO scenario introduced in chapter Bluetooth Audio Transceiver, HFP transparent transmission can be realized by transmitting SCO data from the Phone, through ACI Device 1 and ACI Device 2, to the Headset.
ACI Device 1 and ACI Device 2 transmit data through SPI. The SPI role of ACI Device 1 is master and that of ACI Device 2 is the slave.
Similar to 6.1.1, please set the flag F_APP_SPI_ROLE_MASTER
on ACI Device 1 and set the flag F_APP_SPI_ROLE_SLAVE
on ACI Device 2 before building.
HFP Transparent Transmission process:
In addition, the operations of answering, hanging up, muting MIC, increasing or decreasing SPK volume can be realized only by host.
HFP Transparent Transmission host control process:
ACI Host CLI Test (HFP Transfer)
Before using the function, the hardware environment needs to be configured.
Bluetooth address modification: Use MCUConfig Tool to modify the Bluetooth address of ACI Device 2 to make it different from ACI Device 1.
SPI wiring preparation: The recommended connection is P0_0(SPI_SCK)
, P1_0(SPI_MOSI)
, P0_1(SPI_MISO)
, P1_1(SPI_CS)
, P2_1(PIN_GPIO)
and GND
of ACI Device 1 and ACI Device 2. Developers can connect according to the pin settings in board.h
.
The ACI Host sends SPI_AG_SCO_CONNECT
with status param to ACI Device 2 to connect the SCO link between ACI Device 2 and the Headset to send data.
Correspondingly, the ACI Host sends SPI_AG_SCO_DISCONNECT
to ACI Device 2 to disconnect the SCO link between ACI Device 2 and the Headset. The ACI Host CLI commands are hfpag conn
and hfpag disconn
.
If the phone supports outband ringtone, commands such as hfpag call_incoming
, hfpag call_answer
and hfpag call_terminate
are required to make the Headset simulate playing/stopping the ringtone and dropping calls.
The corresponding UART CMD packet and tool log are as follows:
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_HFP_AG_CONNECT_SCO(0x0480) |
action = SPI_AG_SCO_CONNECT(0) |
hfpag conn_0 |
CMD_HFP_AG_DISCONNECT_SCO(0x0481) |
action = SPI_AG_SCO_DISCONNECT(0) |
hfpag disconn_0 |
CMD_HFP_AG_CALL_INCOMING(0x0482) |
action = NOTIFY_INCOMING_CALL(0) |
hfpag call_incoming |
CMD_HFP_AG_CALL_ANSWER(0x0483) |
action = ANSWER_INCOMING_CALL(0) |
hfpag call_answer |
CMD_HFP_AG_CALL_TERMINATE(0x0484) |
action = TERMINATE_CALL(0) |
hfpag call_terminate |
CMD_HFP_AG_MIC_GAIN_LEVEL_SET(0x0488) |
action = MIC_MUTE(0x00) |
hfpag mic_mute |
CMD_HFP_AG_MIC_GAIN_LEVEL_SET(0x0488) |
action = MIC_UNMUTE(0x0A) |
hfpag mic_unmute |
CMD_HFP_AG_SPEAKER_GAIN_LEVEL_SET(0x0489) |
action = SPK_VOL_DOWN(0x00) |
hfpag spk_vol_up |
CMD_HFP_AG_SPEAKER_GAIN_LEVEL_SET(0x0489) |
action = SPK_VOL_UP(0x00) |
hfpag spk_vol_down |
CMD_MMI(0x0004) |
action = ANSWER_CALL(0x03) |
mmi answer_call |
CMD_MMI(0x0004) |
action = REJECT_CALL(0x04) |
mmi reject_call |
CMD_MMI(0x0004) |
action = END_CALL(0x05) |
mmi end_active_call |
ACI Host CLI test (ACI Device 2): Initiate ACI Device 2 as SPI slave.
Please refer to ACI Host CLI Test.
ACI Host CLI test (ACI Device 1): Initiate ACI Device 1 as SPI master.
Please refer to ACI Host CLI Test.
ACI Host CLI test (ACI Device 1): Connect ACI Device 1 to Phone.
Please refer to Connect to Phone.
ACI Host CLI test (ACI Device 2): Connect Headset to ACI Device 2.
Please refer to Connect to BUD.
Call the Phone connected to ACI Device 1.
ACI Host CLI test (ACI Device 2): Connect or disconnect the SCO link between ACI Device 2 and Headset.
If input
hfpag conn_0
, the Headset will be able to hear incoming sounds from the Phone MIC and make calls, if inputhfpag disconn_0
, Headset will disconnect the SCO.2023-03-06 14:34:07,113 INFO: input command: hfpag conn_0 2023-03-06 14:34:07,115 INFO: Parser cmdParser: cmd opcode: 0480 param: [00] name: CMD_HFP_AG_CONNECT_SCO 2023-03-06 14:34:07,116 INFO: Packet sendPacket: <<<send packet: AA 10 03 00 80 04 00 E4 2023-03-06 14:34:07,129 INFO: AciHostCLI continuously_read: >>>receive packet: AA 10 05 00 00 00 80 04 00 E2 2023-03-06 14:34:07,129 INFO: Parser eventParser: syncWord: AA,seqn: 10,len: 5,opcode: 0000,params: [80 04 00], check_sum: E2 2023-03-06 14:34:07,130 INFO: Parser eventParser: event name: EVENT_ACK 2023-03-06 14:34:07,130 INFO: Parser eventParser: event_id: [80 04] 2023-03-06 14:34:07,130 INFO: Parser eventParser: status: [00] 2023-03-06 16:44:30,416 INFO: input command: hfpag disconn_0 2023-03-06 16:44:30,419 INFO: Parser cmdParser: cmd opcode: 0481 param: [00] name: CMD_HFP_AG_DISCONNECT_SCO 2023-03-06 16:44:30,422 INFO: Packet sendPacket: <<<send packet: AA 1C 03 00 81 04 00 D7 2023-03-06 16:44:30,426 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1C 05 00 00 00 81 04 00 D5 2023-03-06 16:44:30,427 INFO: Parser eventParser: syncWord: AA,seqn: 1C,len: 5,opcode: 0000,params: [81 04 00], check_sum: D5 2023-03-06 16:44:30,427 INFO: Parser eventParser: event name: EVENT_ACK 2023-03-06 16:44:30,427 INFO: Parser eventParser: event_id: [81 04] 2023-03-06 16:44:30,428 INFO: Parser eventParser: status: [00]
If the phone supports outband ringtones, ACI Device 2 should perform the following operations when the phone receives a call:
ACI Host CLI test (ACI Device 2): Make Headset play ring to simulate incoming call.
2023-05-17 09:46:17,157 INFO: input command: hfpag call_incoming 2023-05-17 09:46:17,158 INFO: Parser cmdParser: cmd opcode: 0482 param: [00 81] name: CMD_HFP_AG_CALL_INCOMING 2023-05-17 09:46:17,159 INFO: Packet sendPacket: <<<send packet: AA 27 04 00 82 04 00 81 49 2023-05-17 09:46:17,169 INFO: AciHostCLI continuously_read: >>>receive packet: AA 27 04 00 35 03 00 01 9C 2023-05-17 09:46:17,172 INFO: Parser eventParser: syncWord: AA,seqn: 27,len: 4,opcode: 0335,params: [00 01], check_sum: 9C 2023-05-17 09:46:17,174 INFO: Packet sendPacket: <<<send packet: AA 28 05 00 00 00 35 03 00 9B 2023-05-17 09:46:17,184 INFO: AciHostCLI continuously_read: >>>receive packet: AA 28 05 00 00 00 82 04 00 C8 2023-05-17 09:46:17,185 INFO: Parser eventParser: syncWord: AA,seqn: 28,len: 5,opcode: 0000,params: [82 04 00], check_sum: C8 2023-05-17 09:46:17,186 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-17 09:46:17,186 INFO: Parser eventParser: event_id: [82 04] 2023-05-17 09:46:17,186 INFO: Parser eventParser: status: [00]
Pick up Phone call.
ACI Host CLI test (ACI Device 2): Answer Phone call.
2023-05-17 09:46:34,693 INFO: input command: hfpag call_answer 2023-05-17 09:46:34,693 INFO: Parser cmdParser: cmd opcode: 0483 param: [00] name: CMD_HFP_AG_CALL_ANSWER 2023-05-17 09:46:34,694 INFO: Packet sendPacket: <<<send packet: AA 29 03 00 83 04 00 C8 2023-05-17 09:46:34,712 INFO: AciHostCLI continuously_read: >>>receive packet: AA 29 04 00 35 03 00 03 98 2023-05-17 09:46:34,717 INFO: Parser eventParser: syncWord: AA,seqn: 29,len: 4,opcode: 0335,params: [00 03], check_sum: 98 2023-05-17 09:46:34,719 INFO: Packet sendPacket: <<<send packet: AA 2A 05 00 00 00 35 03 00 99 2023-05-17 09:46:34,728 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2A 05 00 00 00 83 04 00 C5 2023-05-17 09:46:34,728 INFO: Parser eventParser: syncWord: AA,seqn: 2A,len: 5,opcode: 0000,params: [83 04 00], check_sum: C5 2023-05-17 09:46:34,729 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-17 09:46:34,729 INFO: Parser eventParser: event_id: [83 04] 2023-05-17 09:46:34,730 INFO: Parser eventParser: status: [00] 2023-05-17 09:46:35,895 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2B 04 00 38 03 00 02 94 2023-05-17 09:46:35,897 INFO: Parser eventParser: syncWord: AA,seqn: 2B,len: 4,opcode: 0338,params: [00 02], check_sum: 94 2023-05-17 09:46:35,901 INFO: Packet sendPacket: <<<send packet: AA 2B 05 00 00 00 38 03 00 95 2023-05-17 09:46:35,911 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2C 04 00 00 03 00 01 CC 2023-05-17 09:46:35,912 INFO: Parser eventParser: syncWord: AA,seqn: 2C,len: 4,opcode: 0300,params: [00 01], check_sum: CC 2023-05-17 09:46:35,913 INFO: Parser eventParser: event name: APP_EVENT_SCO_STATE 2023-05-17 09:46:35,914 INFO: Parser eventParser: app_link_id: [00] 2023-05-17 09:46:35,914 INFO: Parser eventParser: state: [01] 2023-05-17 09:46:35,915 INFO: Packet sendPacket: <<<send packet: AA 2C 05 00 00 00 00 03 00 CC
Hang up Phone call.
ACI Host CLI test (ACI Device 2): Notify Headset that Phone call is terminated.
2023-05-17 09:47:02,069 INFO: input command: hfpag call_terminate 2023-05-17 09:47:02,069 INFO: Parser cmdParser: cmd opcode: 0484 param: [00] name: CMD_HFP_AG_CALL_TERMINATE 2023-05-17 09:47:02,070 INFO: Packet sendPacket: <<<send packet: AA 2D 03 00 84 04 00 C3 2023-05-17 09:47:02,076 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2D 04 00 35 03 00 00 97 2023-05-17 09:47:02,077 INFO: Parser eventParser: syncWord: AA,seqn: 2D,len: 4,opcode: 0335,params: [00 00], check_sum: 97 2023-05-17 09:47:02,082 INFO: Packet sendPacket: <<<send packet: AA 2E 05 00 00 00 35 03 00 95 2023-05-17 09:47:02,091 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2E 05 00 00 00 84 04 00 C0 2023-05-17 09:47:02,094 INFO: Parser eventParser: syncWord: AA,seqn: 2E,len: 5,opcode: 0000,params: [84 04 00], check_sum: C0 2023-05-17 09:47:02,095 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-17 09:47:02,095 INFO: Parser eventParser: event_id: [84 04] 2023-05-17 09:47:02,096 INFO: Parser eventParser: status: [00]
If only host control is used, the following operations need to be performed:
ACI Host CLI test (ACI Device 1): Answer call.
2023-05-31 14:46:35,990 INFO: input command: mmi answer_call 2023-05-31 14:46:35,990 INFO: Parser cmdParser: cmd opcode: 0004 param: [00 03] name: CMD_MMI 2023-05-31 14:46:35,991 INFO: Packet sendPacket: <<<send packet: AA 01 04 00 04 00 00 03 F4 2023-05-31 14:46:36,009 INFO: AciHostCLI continuously_read: >>>receive packet: AA 03 05 00 00 00 04 00 00 F4 2023-05-31 14:46:36,011 INFO: Parser eventParser: syncWord: AA,seqn: 03,len: 5,opcode: 0000,params: [04 00 00], check_sum: F4 2023-05-31 14:46:36,012 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-31 14:46:36,013 INFO: Parser eventParser: event_id: [04 00] 2023-05-31 14:46:36,013 INFO: Parser eventParser: status: [00]
ACI Host CLI test (ACI Device 1): Reject call.
2023-05-31 16:06:51,592 INFO: input command: mmi reject_call 2023-05-31 16:06:51,596 INFO: Parser cmdParser: cmd opcode: 0004 param: [00 04] name: CMD_MMI 2023-05-31 16:06:51,598 INFO: Packet sendPacket: <<<send packet: AA 02 04 00 04 00 00 04 F2 2023-05-31 16:06:51,613 INFO: AciHostCLI continuously_read: >>>receive packet: AA 04 05 00 00 00 04 00 00 F3 2023-05-31 16:06:51,614 INFO: Parser eventParser: syncWord: AA,seqn: 04,len: 5,opcode: 0000,params: [04 00 00], check_sum: F3 2023-05-31 16:06:51,615 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-31 16:06:51,615 INFO: Parser eventParser: event_id: [04 00] 2023-05-31 16:06:51,616 INFO: Parser eventParser: status: [00]
ACI Host CLI test (ACI Device 2): Mute MIC.
2023-05-31 16:20:02,818 INFO: input command: hfpag mic_mute 2023-05-31 16:20:02,819 INFO: Parser cmdParser: cmd opcode: 0488 param: [00 00] name: CMD_HFP_AG_MIC_GAIN_LEVEL_SET 2023-05-31 16:20:02,819 INFO: Packet sendPacket: <<<send packet: AA 03 04 00 88 04 00 00 E8 2023-05-31 16:20:02,827 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 05 00 00 00 88 04 00 E5 2023-05-31 16:20:02,830 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 5,opcode: 0000,params: [88 04 00], check_sum: E5 2023-05-31 16:20:02,831 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-31 16:20:02,832 INFO: Parser eventParser: event_id: [88 04] 2023-05-31 16:20:02,832 INFO: Parser eventParser: status: [00]
ACI Host CLI test (ACI Device 2): Unmute MIC.
2023-05-31 16:21:04,073 INFO: input command: hfpag mic_unmute 2023-05-31 16:21:04,073 INFO: Parser cmdParser: cmd opcode: 0488 param: [00 0A] name: CMD_HFP_AG_MIC_GAIN_LEVEL_SET 2023-05-31 16:21:04,074 INFO: Packet sendPacket: <<<send packet: AA 04 04 00 88 04 00 0A DD 2023-05-31 16:21:04,080 INFO: AciHostCLI continuously_read: >>>receive packet: AA 06 05 00 00 00 88 04 00 E4 2023-05-31 16:21:04,082 INFO: Parser eventParser: syncWord: AA,seqn: 06,len: 5,opcode: 0000,params: [88 04 00], check_sum: E4 2023-05-31 16:21:04,089 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-31 16:21:04,090 INFO: Parser eventParser: event_id: [88 04] 2023-05-31 16:21:04,091 INFO: Parser eventParser: status: [00]
ACI Host CLI test (ACI Device 2): SPK volume up.
2023-05-31 17:09:29,143 INFO: input command: hfpag spk_vol_up 2023-05-31 17:09:29,144 INFO: Parser cmdParser: cmd opcode: 0489 param: [00 0A] name: CMD_HFP_AG_SPEAKER_GAIN_LEVEL_SET 2023-05-31 17:09:29,146 INFO: Packet sendPacket: <<<send packet: AA 05 04 00 89 04 00 0A DB 2023-05-31 17:09:29,158 INFO: AciHostCLI continuously_read: >>>receive packet: AA 07 05 00 00 00 89 04 00 E2 2023-05-31 17:09:29,159 INFO: Parser eventParser: syncWord: AA,seqn: 07,len: 5,opcode: 0000,params: [89 04 00], check_sum: E2 2023-05-31 17:09:29,160 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-31 17:09:29,160 INFO: Parser eventParser: event_id: [89 04] 2023-05-31 17:09:29,161 INFO: Parser eventParser: status: [00]
ACI Host CLI test (ACI Device 2): SPK volume down.
2023-05-31 17:10:32,765 INFO: input command: hfpag spk_vol_down 2023-05-31 17:10:32,766 INFO: Parser cmdParser: cmd opcode: 0489 param: [00 00] name: CMD_HFP_AG_SPEAKER_GAIN_LEVEL_SET 2023-05-31 17:10:32,767 INFO: Packet sendPacket: <<<send packet: AA 06 04 00 89 04 00 00 E4 2023-05-31 17:10:32,780 INFO: AciHostCLI continuously_read: >>>receive packet: AA 08 05 00 00 00 89 04 00 E1 2023-05-31 17:10:32,794 INFO: Parser eventParser: syncWord: AA,seqn: 08,len: 5,opcode: 0000,params: [89 04 00], check_sum: E1 2023-05-31 17:10:32,795 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-31 17:10:32,795 INFO: Parser eventParser: event_id: [89 04] 2023-05-31 17:10:32,796 INFO: Parser eventParser: status: [00]
ACI Host CLI test (ACI Device 1): End call.
2023-05-31 17:17:47,759 INFO: input command: mmi end_active_call 2023-05-31 17:17:47,759 INFO: Parser cmdParser: cmd opcode: 0004 param: [00 05] name: CMD_MMI 2023-05-31 17:17:47,760 INFO: Packet sendPacket: <<<send packet: AA 07 04 00 04 00 00 05 EC 2023-05-31 17:17:47,774 INFO: AciHostCLI continuously_read: >>>receive packet: AA 09 05 00 00 00 04 00 00 EE 2023-05-31 17:17:47,787 INFO: Parser eventParser: syncWord: AA,seqn: 09,len: 5,opcode: 0000,params: [04 00 00], check_sum: EE 2023-05-31 17:17:47,787 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-05-31 17:17:47,788 INFO: Parser eventParser: event_id: [04 00] 2023-05-31 17:17:47,788 INFO: Parser eventParser: status: [00]
Bluetooth Audio Transmitter MP3
This chapter introduces the functionality of the bt_audio_transmitter_mp3
application scenario. This functionality is enabled by opening the macro definition F_APP_BT_AUDIO_TRANSMITTER_MP3_DEMO_SUPPORT
in app_flags.h
. This chapter describes how to use these functions and the flow of how to test them, including the MSCs of the ACI Device and ACI Host interaction, and the commands used by ACI Host.
Music Play Function
The interactive process of music playing is analyzed in this chapter, the format of music playing is MP3.
Prerequisites
Music playing process:
ACI Host CLI test: Session open.
The ACI Host sends
CMD_XM_MUSIC
command withMUSIC_SESSION_OPEN
to start the music-playing process. The ACI Host CLI CMD for starting music playing ismusic open
, the corresponding UART CMD packet and tool log are as follows:Command
Parameters
ACI Host CLI CMD
CMD_XM_MUSIC = 0x8080
type = MUSIC_SESSION_OPEN(0), seq = 0
music open
2023-01-12 14:08:20,013 INFO: input command: music open 2023-01-12 14:08:20,014 INFO: Parser cmdParser: cmd opcode: 8080 param: [00 00] name: CMD_XM_MUSIC 2023-01-12 14:08:20,014 INFO: Packet sendPacket: <<<send packet: AA 04 04 00 80 80 00 00 73 2023-01-12 14:08:20,026 INFO: AciHostCLI continuously_read: >>>receive packet: AA 04 05 00 00 00 80 80 00 72 2023-01-12 14:08:20,027 INFO: Parser eventParser: syncWord: AA,seqn: 04,len: 5,opcode: 0000,params: [80 80 00], check_sum: 72 2023-01-12 14:08:20,028 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-01-12 14:08:20,029 INFO: Parser eventParser: event_id: [80 80] 2023-01-12 14:08:20,030 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Session send xxx frame.
ACI Device requests the first music data frame through
EVENT_XM_MUSIC_REQ_FRAME
. Afterward, ACI Device will continue to request music data frames throughEVENT_APP_EVENT_ACK(0x0000)
with statusCMD_SET_STATUS_MUSIC_REQ(8)
.2023-01-12 14:08:20,030 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 02 00 00 85 74 2023-01-12 14:08:20,031 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 2,opcode: 8500,params: [], check_sum: 74 2023-01-12 14:08:20,031 INFO: Parser eventParser: event name: EVENT_XM_MUSIC_REQ_FRAME 2023-01-12 14:08:20,032 INFO: Packet sendPacket: <<<send packet: AA 05 05 00 00 00 00 85 00 71 2023-01-12 14:08:20,032 INFO: Music get_data: 00000000: 49 44 33 03 00 00 00 00 00 52 54 50 45 32 00 00 00 07 00 00 00 A4 FD A4 4F A7 BB 54 49 54 32 00 2023-01-12 14:08:20,033 INFO: Parser cmdParser: cmd opcode: 8080 param: [05 00 49 44 33 03 00 00 00 00 00 52 54 50 45 32 00 00 00 07 00 00 00 A4 FD A4 4F A7 BB 54 49 54] name: CMD_XM_MUSIC 2023-01-12 14:08:20,036 INFO: Packet sendPacket: <<<send packet: AA 06 04 02 00 85 05 00 49 44 33 03 00 00 00 00 00 52 54 50 45 32 00 00 00 07 00 00 00 A4 FD A4 2023-01-12 14:08:20,042 INFO: AciHostCLI continuously_read: >>>receive packet: AA 06 05 00 00 00 00 80 80 68 2023-01-12 14:08:20,043 INFO: Parser eventParser: syncWord: AA,seqn: 06,len: 5,opcode: 0000,params: [80 80 08], check_sum: 68 2023-01-12 14:08:20,043 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-01-12 14:08:20,044 INFO: Parser eventParser: event_id: [80 80] 2023-01-12 14:08:20,044 INFO: Parser eventParser: status: [08]
ACI Host CLI test: Session close.
The ACI Host sends
Session Close
to end the music playing process normally. The ACI Host CLI CMD for stopping music playing ismusic close
, the corresponding UART CMD packet and tool log are as follows:Command
Parameters
ACI Host CLI CMD
CMD_XM_MUSIC = 0x8080
type = MUSIC_SESSION_CLOSE(4), seq = 0
music close
2023-01-12 14:19:04,386 INFO: Parser cmdParser: cmd opcode: 8080 param: [04 00] name: CMD_XM_MUSIC 2023-01-12 14:19:04,386 INFO: Packet sendPacket: <<<send packet: AA 90 04 00 80 80 04 00 E3 2023-01-12 14:19:04,398 INFO: AciHostCLI continuously_read: >>>receive packet: AA 3F 05 00 00 00 80 80 00 37 2023-01-12 14:19:04,399 INFO: Parser eventParser: syncWord: AA,seqn: 3F,len: 5,opcode: 0000,params: [80 80 00], check_sum: 37 2023-01-12 14:19:04,400 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-01-12 14:19:04,400 INFO: Parser eventParser: event_id: [80 80] 2023-01-12 14:19:04,400 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Session abort.
If the ACK status is not
CMD_SET_STATUS_COMPLETE(0)
orCMD_SET_STATUS_MUSIC_REQ(8)
during playback, the ACI Host will sendSession Abort
to stop the music playing process immediately. The ACI Host CLI CMD for stopping music playing ismusic abort
, the corresponding UART CMD packet and tool log are as follows:Command
Parameters
ACI Host CLI CMD
CMD_XM_MUSIC = 0x8080
type = MUSIC_SESSION_ABORT(3), seq = 0
music abort
2023-01-12 14:24:17,764 INFO: input command: music abort 2023-01-12 14:24:17,765 INFO: Parser cmdParser: cmd opcode: 8080 param: [03 00] name: CMD_XM_MUSIC 2023-01-12 14:24:17,765 INFO: Packet sendPacket: <<<send packet: AA 31 04 00 00 85 03 00 43 2023-01-12 14:24:17,774 INFO: AciHostCLI continuously_read: >>>receive packet: AA 71 0A 00 0B 00 00 00 00 00 00 00 00 00 7A 2023-01-12 14:24:17,774 INFO: Parser eventParser: syncWord: AA,seqn: 71,len: 10,opcode: 000B,params: [00 00 00 00 00 00 00 00], check_sum: 7A 2023-01-12 14:24:17,775 INFO: Parser eventParser: event name: EVENT_PLAYER_STATUS 2023-01-12 14:24:17,775 INFO: Parser eventParser: bd_addr: [00 00 00 00 00 00] 2023-01-12 14:24:17,775 INFO: Parser eventParser: play_status: [00] 2023-01-12 14:24:17,776 INFO: Parser eventParser: play_mode: [00] 2023-01-12 14:24:17,776 INFO: Packet sendPacket: <<<send packet: AA 32 05 00 00 00 0B 00 00 BE 2023-01-12 14:24:17,790 INFO: AciHostCLI continuously_read: >>>receive packet: AA 72 05 00 00 00 00 85 00 04 2023-01-12 14:24:17,790 INFO: Parser eventParser: syncWord: AA,seqn: 72,len: 5,opcode: 0000,params: [00 85 00], check_sum: 04 2023-01-12 14:24:17,791 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-01-12 14:24:17,791 INFO: Parser eventParser: event_id: [00 85] 2023-01-12 14:24:17,791 INFO: Parser eventParser: status: [00]
ACI Host CLI Test
The played music directory is tool\AciHostCLI-Common_SDK\music
.
Local Playback
Command |
Parameters |
ACI Host CLI CMD |
Description |
---|---|---|---|
CMD_XM_MMI = 0x8004 |
action = XM_MMI_MODE_LOCAL_PLAY(1) |
xmmi local |
Switch to local playback mode for music play. |
Connect and configure a SPK to EVB.
ACI Host CLI test: Enter local playback mode.
Input xmmi local.
2023-04-23 18:48:59,335 INFO: input command: xmmi local 2023-04-23 18:48:59,337 INFO: Parser cmdParser: cmd opcode: 8004 param: [01] name: CMD_XM_MMI 2023-04-23 18:48:59,338 INFO: Packet sendPacket: <<<send packet: AA 01 03 00 04 80 01 77 2023-04-23 18:48:59,342 INFO: AciHostCLI continuously_read: >>>receive packet: AA 57 05 00 00 00 04 80 00 20 2023-04-23 18:48:59,355 INFO: Parser eventParser: syncWord: AA,seqn: 57,len: 5,opcode: 0000,params: [04 80 00], check_sum: 20 2023-04-23 18:48:59,357 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-23 18:48:59,360 INFO: Parser eventParser: event_id: [04 80] 2023-04-23 18:48:59,367 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Music open.
Input music open, then the played music can be heard from SPK.
ACI Host CLI test: Music close.
Input music close, then the played music will be stopped.
A2DP Source Playback
Command |
Parameters |
ACI Host CLI CMD |
Description |
---|---|---|---|
CMD_XM_MMI = 0x8004 |
action = XM_MMI_MODE_A2DP_SOURCE(2) |
xmmi source |
Switch to A2DP Source mode for music play. |
ACI Host CLI test: Connect ACI Device to BUD.
Please refer to Connect to BUD.
ACI Host CLI test: Enter A2DP Source playback mode.
Input xmmi source.
2023-04-23 18:50:20,276 INFO: input command: xmmi source 2023-04-23 18:50:20,278 INFO: Parser cmdParser: cmd opcode: 8004 param: [02] name: CMD_XM_MMI 2023-04-23 18:50:20,280 INFO: Packet sendPacket: <<<send packet: AA 02 03 00 04 80 02 75 2023-04-23 18:50:20,281 INFO: AciHostCLI continuously_read: >>>receive packet: AA 58 05 00 00 00 04 80 00 1F 2023-04-23 18:50:20,301 INFO: Parser eventParser: syncWord: AA,seqn: 58,len: 5,opcode: 0000,params: [04 80 00], check_sum: 1F 2023-04-23 18:50:20,316 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-04-23 18:50:20,323 INFO: Parser eventParser: event_id: [04 80] 2023-04-23 18:50:20,326 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Music open.
Input music open, then the played music can be heard from BUD.
ACI Host CLI test: Music close.
Input music close, then the played music will be stopped.
Bluetooth Audio Intergrated Transceiver
This chapter introduces the functionality of the bt_audio_intergrated_transceiver application scenario. This functionality is enabled by opening the macro definition F_APP_BT_AUDIO_TRANSCEIVER_DEMO_SUPPORT
and F_APP_INTEGRATED_TRANSCEIVER
in app_flags.h
. This chapter describes how to use these functions and the flow of how to test them, including the MSCs of the ACI Device and ACI Host interaction, and the commands used by ACI Host.
A2DP Intergrated Transceiver Transmission (A2DP Output)
Two typical transmit scenarios are introduced in chapter Bluetooth Audio Intergrated Transceiver. Based on the A2DP transmission, A2DP data can be transferred from the Phone, through ACI Device to the Headset.
A2DP intergrated transceiver transmission process:
Before using the function, please config the BR/EDR link numbers in ‘System Configuration’ by MCUConfig Tool.
AciHostCLI Test
The ACI Host sends CMD_SRC_PLAY_SET_SRC_ROUTE
to ACI Device to set the A2DP input route, sends CMD_SRC_PLAY_SET_PLAY_ROUTE
to set A2DP output route, sends CMD_SRC_PLAY_ROUTE_IN_START/STOP
to start or stop the A2DP input route, and sends CMD_SRC_PLAY_ROUTE_OUT_START/STOP
to start or stop the A2DP output route.
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_SRC_PLAY_SET_SRC_ROUTE(0x3300) |
action = a2dp(0x07, 0x00) |
set_route_in a2dp |
CMD_SRC_PLAY_SET_PLAY_ROUTE(0x3302) |
action = a2dp(0x01) |
set_route_out a2dp |
CMD_SRC_PLAY_ROUTE_IN_START(0x3304) |
None |
route_in start |
CMD_SRC_PLAY_ROUTE_IN_STOP(0x3305) |
None |
route_in stop |
CMD_SRC_PLAY_ROUTE_OUT_START(0x3306) |
None |
route_out start |
CMD_SRC_PLAY_ROUTE_OUT_STOP(0x3307) |
None |
route_out stop |
ACI Host CLI test: Connect ACI Device to Phone.
Please refer to Connect to Phone.
ACI Host CLI test: Connect ACI Device to BUD.
Please refer to Connect to BUD.
ACI Host CLI test: Input
set_route_in a2dp
.2024-10-30 14:43:09,715 INFO: input command: set_route_in a2dp 2024-10-30 14:43:09,716 INFO: Parser cmdParser: cmd opcode: 3300 param: [07 00] name: CMD_SRC_PLAY_SET_SRC_ROUTE 2024-10-30 14:43:09,716 INFO: Packet sendPacket: <<<send packet: AA 54 04 00 00 33 07 00 6E 2024-10-30 14:43:09,788 WARNING: AciHostCLI retrans: retransmit command set_route_in a2dp due to ack timeout! retry: 1 2024-10-30 14:43:09,789 INFO: Packet sendPacket: <<<send packet: AA 54 04 00 00 33 07 00 6E 2024-10-30 14:43:09,803 INFO: AciHostCLI continuously_read: >>>receive packet: AA 4A 05 00 00 00 00 33 00 7E 2024-10-30 14:43:09,804 INFO: Parser eventParser: syncWord: AA,seqn: 4A,len: 5,opcode: 0000,params: [00 33 00], check_sum: 7E 2024-10-30 14:43:09,804 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-10-30 14:43:09,805 INFO: Parser eventParser: event_id: [00 33] 2024-10-30 14:43:09,805 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
set_route_out a2dp
.2024-10-30 14:43:14,178 INFO: input command: set_route_out a2dp 2024-10-30 14:43:14,179 INFO: Parser cmdParser: cmd opcode: 3302 param: [01] name: CMD_SRC_PLAY_SET_PLAY_ROUTE 2024-10-30 14:43:14,179 INFO: Packet sendPacket: <<<send packet: AA 55 03 00 02 33 01 72 2024-10-30 14:43:14,250 WARNING: AciHostCLI retrans: retransmit command set_route_out a2dp due to ack timeout! retry: 1 2024-10-30 14:43:14,251 INFO: Packet sendPacket: <<<send packet: AA 55 03 00 02 33 01 72 2024-10-30 14:43:14,260 INFO: AciHostCLI continuously_read: >>>receive packet: AA 4B 05 00 00 00 02 33 00 7B 2024-10-30 14:43:14,261 INFO: Parser eventParser: syncWord: AA,seqn: 4B,len: 5,opcode: 0000,params: [02 33 00], check_sum: 7B 2024-10-30 14:43:14,261 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-10-30 14:43:14,261 INFO: Parser eventParser: event_id: [02 33] 2024-10-30 14:43:14,261 INFO: Parser eventParser: status: [00]
Play music on Phone, then ACI Host will receive
APP_EVENT_AVRCP_PLAYER_STATUS
andEVENT_TRACK_CHANGED
.2024-10-30 14:43:33,319 INFO: AciHostCLI continuously_read: >>>receive packet: AA 4C 0A 00 0B 00 41 AF 7B 6C 32 20 01 00 75 2024-10-30 14:43:33,320 INFO: Parser eventParser: syncWord: AA,seqn: 4C,len: 10,opcode: 000B,params: [41 AF 7B 6C 32 20 01 00], check_sum: 75 2024-10-30 14:43:33,320 INFO: Parser eventParser: event name: APP_EVENT_AVRCP_PLAYER_STATUS 2024-10-30 14:43:33,320 INFO: Parser eventParser: bd_addr: [41 AF 7B 6C 32 20] 2024-10-30 14:43:33,322 INFO: Parser eventParser: play_status: [01] 2024-10-30 14:43:33,322 INFO: Parser eventParser: play_mode: [00] 2024-10-30 14:43:33,323 INFO: Packet sendPacket: <<<send packet: AA 56 05 00 00 00 0B 00 00 9A 2024-10-30 14:43:33,335 INFO: AciHostCLI continuously_read: >>>receive packet: AA 4D 10 00 21 00 41 AF 7B 6C 32 20 00 00 00 00 00 00 00 00 59 2024-10-30 14:43:33,336 INFO: Parser eventParser: syncWord: AA,seqn: 4D,len: 16,opcode: 0021,params: [41 AF 7B 6C 32 20 00 00 00 00 00 00 00 00], check_sum: 59 2024-10-30 14:43:33,336 INFO: Parser eventParser: event name: EVENT_TRACK_CHANGED 2024-10-30 14:43:33,337 INFO: Packet sendPacket: <<<send packet: AA 57 05 00 00 00 21 00 00 83
ACI Host CLI test: Input
route_out start
.2024-10-30 14:43:38,276 INFO: input command: route_out start 2024-10-30 14:43:38,276 INFO: Parser cmdParser: cmd opcode: 3306 param: [] name: CMD_SRC_PLAY_ROUTE_OUT_START 2024-10-30 14:43:38,277 INFO: Packet sendPacket: <<<send packet: AA 58 02 00 06 33 6D 2024-10-30 14:43:38,287 INFO: AciHostCLI continuously_read: >>>receive packet: AA 4E 05 00 00 00 06 33 00 74 2024-10-30 14:43:38,288 INFO: Parser eventParser: syncWord: AA,seqn: 4E,len: 5,opcode: 0000,params: [06 33 00], check_sum: 74 2024-10-30 14:43:38,288 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-10-30 14:43:38,288 INFO: Parser eventParser: event_id: [06 33] 2024-10-30 14:43:38,288 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Input
route_in start
.2024-10-30 14:43:40,239 INFO: input command: route_in start 2024-10-30 14:43:40,240 INFO: Parser cmdParser: cmd opcode: 3304 param: [] name: CMD_SRC_PLAY_ROUTE_IN_START 2024-10-30 14:43:40,240 INFO: Packet sendPacket: <<<send packet: AA 59 02 00 04 33 6E 2024-10-30 14:43:40,252 INFO: AciHostCLI continuously_read: >>>receive packet: AA 4F 05 00 00 00 04 33 00 75 2024-10-30 14:43:40,253 INFO: Parser eventParser: syncWord: AA,seqn: 4F,len: 5,opcode: 0000,params: [04 33 00], check_sum: 75 2024-10-30 14:43:40,253 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-10-30 14:43:40,253 INFO: Parser eventParser: event_id: [04 33] 2024-10-30 14:43:40,254 INFO: Parser eventParser: status: [00]
HFP Intergrated Transceiver Transmission
Based on the HFP transmission, SCO data can be transferred from the Phone, through ACI Device to the Headset. HFP intergrated transceiver transmission process:
AciHostCLI Test
ACI Host sends CMD_HFP_AG_CONNECT_SCO
to ACI Device to connect the SCO link between ACI Device and Headset to send data. ACI Host sends CMD_HFP_AG_DISCONNECT_SCO
to ACI Device to disconnect the SCO link between ACI Device and the Headset. ACI Host CLI commands are hfpag conn
and hfpag disconn
. Before using the function, inquiry and page scan should be set as disable. Since there are two SCO links in this scenario, CMD_SRC_PLAY_SET_MULTI_ESCO
is used to support the coexistence of two links.
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_HFP_AG_CONNECT_SCO(0x0480) |
action = SCO_CONNECT(0x01) |
hfpag conn_1 |
CMD_HFP_AG_DISCONNECT_SCO(0x0481) |
action = SCO_DISCONNECT(0x01) |
hfpag disconn_1 |
CMD_SRC_PLAY_SET_MULTI_ESCO(0x3310) |
action = Active(0x01, 0x02) |
set_multi_esco active |
CMD_XM_SET_MODE = 0x0030 |
device_mode = BT_DEVICE_MODE_IDLE(0) |
mode idle |
ACI Host CLI test: Connect ACI Device to Phone.
Please refer to Connect to Phone.
ACI Host CLI test: Connect ACI Device to BUD.
Please refer to Connect to BUD.
ACI Host CLI test: Disable inquiry scan and page scan.
2024-10-31 11:18:32,485 INFO: input command: mode idle 2024-10-31 11:18:32,486 INFO: Parser cmdParser: cmd opcode: 0030 param: [00] name: CMD_XM_SET_MODE 2024-10-31 11:18:32,486 INFO: Packet sendPacket: <<<send packet: AA 1D 03 00 30 00 00 B0 2024-10-31 11:18:32,495 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1C 05 00 00 00 30 00 00 AF 2024-10-31 11:18:32,496 INFO: Parser eventParser: syncWord: AA,seqn: 1C,len: 5,opcode: 0000,params: [30 00 00], check_sum: AF 2024-10-31 11:18:32,497 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-10-31 11:18:32,497 INFO: Parser eventParser: event_id: [30 00] 2024-10-31 11:18:32,497 INFO: Parser eventParser: status: [00]
ACI Host CLI test: Set multilink SCO active.
2024-10-31 11:18:42,533 INFO: input command: set_multi_esco active 2024-10-31 11:18:42,534 INFO: Parser cmdParser: cmd opcode: 3310 param: [01 02] name: CMD_SRC_PLAY_SET_MULTI_ESCO 2024-10-31 11:18:42,534 INFO: Packet sendPacket: <<<send packet: AA 1E 04 00 10 33 01 02 98 2024-10-31 11:18:42,623 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1D 05 00 00 00 10 33 00 9B 2024-10-31 11:18:42,624 INFO: Parser eventParser: syncWord: AA,seqn: 1D,len: 5,opcode: 0000,params: [10 33 00], check_sum: 9B 2024-10-31 11:18:42,624 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-10-31 11:18:42,624 INFO: Parser eventParser: event_id: [10 33] 2024-10-31 11:18:42,625 INFO: Parser eventParser: status: [00]
Call the Phone connected to ACI Device.
2024-10-31 11:18:52,144 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1E 04 00 0A 00 00 02 D2 2024-10-31 11:18:52,144 INFO: Parser eventParser: syncWord: AA,seqn: 1E,len: 4,opcode: 000A,params: [00 02], check_sum: D2 2024-10-31 11:18:52,147 INFO: Parser eventParser: event name: APP_EVENT_HFP_CALL_STATUS 2024-10-31 11:18:52,148 INFO: Parser eventParser: link_id: [00] 2024-10-31 11:18:52,148 INFO: Parser eventParser: status: [02] 2024-10-31 11:18:52,149 INFO: Packet sendPacket: <<<send packet: AA 1F 05 00 00 00 0A 00 00 D2 2024-10-31 11:18:53,646 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1F 1D 00 07 04 00 01 01 04 00 00 81 31 35 39 36 32 31 37 33 35 38 30 00 00 00 00 00 00 00 00 2024-10-31 11:18:53,646 INFO: Parser eventParser: syncWord: AA,seqn: 1F,len: 29,opcode: 0407,params: [00 01 01 04 00 00 81 31 35 39 36 32 31 37 33 35 38 30 00 00 00 00 00 00 00 00 00], check_sum: F3 2024-10-31 11:18:53,648 INFO: Parser eventParser: event name: EVENT_CURRENT_CALLS 2024-10-31 11:18:53,649 INFO: Packet sendPacket: <<<send packet: AA 20 05 00 00 00 07 04 00 D0 2024-10-31 11:18:53,805 INFO: AciHostCLI continuously_read: >>>receive packet: AA 20 04 00 00 04 00 02 D6 2024-10-31 11:18:53,806 INFO: Parser eventParser: syncWord: AA,seqn: 20,len: 4,opcode: 0400,params: [00 02], check_sum: D6 2024-10-31 11:18:53,806 INFO: Parser eventParser: event name: APP_EVENT_SCO_STATE 2024-10-31 11:18:53,807 INFO: Parser eventParser: link_id: [00] 2024-10-31 11:18:53,808 INFO: Parser eventParser: state: [02] 2024-10-31 11:18:53,809 INFO: Packet sendPacket: <<<send packet: AA 21 05 00 00 00 00 04 00 D6 2024-10-31 11:18:53,821 INFO: AciHostCLI continuously_read: >>>receive packet: AA 21 04 00 00 04 00 01 D6 2024-10-31 11:18:53,821 INFO: Parser eventParser: syncWord: AA,seqn: 21,len: 4,opcode: 0400,params: [00 01], check_sum: D6 2024-10-31 11:18:53,822 INFO: Parser eventParser: event name: APP_EVENT_SCO_STATE 2024-10-31 11:18:53,822 INFO: Parser eventParser: link_id: [00] 2024-10-31 11:18:53,822 INFO: Parser eventParser: state: [01]
ACI Host CLI test: Connect the SCO link between ACI Device and Headset.
2024-10-31 11:19:01,258 INFO: input command: hfpag conn_1 2024-10-31 11:19:01,258 INFO: Parser cmdParser: cmd opcode: 0480 param: [01] name: CMD_HFP_AG_CONNECT_SCO 2024-10-31 11:19:01,259 INFO: Packet sendPacket: <<<send packet: AA 2A 03 00 80 04 01 4E 2024-10-31 11:19:01,266 INFO: AciHostCLI continuously_read: >>>receive packet: AA 27 05 00 00 00 80 04 00 50 2024-10-31 11:19:01,272 INFO: Parser eventParser: syncWord: AA,seqn: 27,len: 5,opcode: 0000,params: [80 04 00], check_sum: 50 2024-10-31 11:19:01,275 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-10-31 11:19:01,276 INFO: Parser eventParser: event_id: [80 04] 2024-10-31 11:19:01,276 INFO: Parser eventParser: status: [00] 2024-10-31 11:19:01,458 INFO: AciHostCLI continuously_read: >>>receive packet: AA 28 04 00 88 03 01 02 46 2024-10-31 11:19:01,458 INFO: Parser eventParser: syncWord: AA,seqn: 28,len: 4,opcode: 0388,params: [01 02], check_sum: 46 2024-10-31 11:19:01,459 INFO: Packet sendPacket: <<<send packet: AA 2B 05 00 00 00 88 03 00 45 2024-10-31 11:19:01,474 INFO: AciHostCLI continuously_read: >>>receive packet: AA 29 04 00 00 04 01 01 CD 2024-10-31 11:19:01,474 INFO: Parser eventParser: syncWord: AA,seqn: 29,len: 4,opcode: 0400,params: [01 01], check_sum: CD 2024-10-31 11:19:01,476 INFO: Parser eventParser: event name: APP_EVENT_SCO_STATE 2024-10-31 11:19:01,476 INFO: Parser eventParser: link_id: [01] 2024-10-31 11:19:01,477 INFO: Parser eventParser: state: [01] 2024-10-31 11:19:01,477 INFO: Packet sendPacket: <<<send packet: AA 2C 05 00 00 00 00 04 00 CB
Hang up Phone call.
2024-10-31 11:19:09,365 INFO: AciHostCLI continuously_read: >>>receive packet: AA 2F 1D 00 07 04 00 01 01 00 00 00 81 31 35 39 36 32 31 37 33 35 38 30 00 00 00 00 00 00 00 00 2024-10-31 11:19:09,366 INFO: Parser eventParser: syncWord: AA,seqn: 2F,len: 29,opcode: 0407,params: [00 01 01 00 00 00 81 31 35 39 36 32 31 37 33 35 38 30 00 00 00 00 00 00 00 00 00], check_sum: E7 2024-10-31 11:19:09,368 INFO: Parser eventParser: event name: EVENT_CURRENT_CALLS 2024-10-31 11:19:09,371 INFO: Packet sendPacket: <<<send packet: AA 32 05 00 00 00 07 04 00 BE 2024-10-31 11:19:10,435 INFO: AciHostCLI continuously_read: >>>receive packet: AA 30 04 00 00 04 00 00 C8 2024-10-31 11:19:10,436 INFO: Parser eventParser: syncWord: AA,seqn: 30,len: 4,opcode: 0400,params: [00 00], check_sum: C8 2024-10-31 11:19:10,436 INFO: Parser eventParser: event name: APP_EVENT_SCO_STATE 2024-10-31 11:19:10,437 INFO: Parser eventParser: link_id: [00] 2024-10-31 11:19:10,438 INFO: Parser eventParser: state: [00] 2024-10-31 11:19:10,438 INFO: Packet sendPacket: <<<send packet: AA 33 05 00 00 00 00 04 00 C4 2024-10-31 11:19:10,564 INFO: AciHostCLI continuously_read: >>>receive packet: AA 31 04 00 0A 00 00 00 C1 2024-10-31 11:19:10,564 INFO: Parser eventParser: syncWord: AA,seqn: 31,len: 4,opcode: 000A,params: [00 00], check_sum: C1 2024-10-31 11:19:10,572 INFO: Parser eventParser: event name: APP_EVENT_HFP_CALL_STATUS 2024-10-31 11:19:10,572 INFO: Parser eventParser: link_id: [00] 2024-10-31 11:19:10,573 INFO: Parser eventParser: status: [00] 2024-10-31 11:19:10,574 INFO: Packet sendPacket: <<<send packet: AA 34 05 00 00 00 0A 00 00 BD
ACI Host CLI test: Disconnect the SCO link between ACI Device and Headset.
2024-10-31 11:19:16,368 INFO: input command: hfpag disconn_1 2024-10-31 11:19:16,368 INFO: Parser cmdParser: cmd opcode: 0481 param: [01] name: CMD_HFP_AG_DISCONNECT_SCO 2024-10-31 11:19:16,369 INFO: Packet sendPacket: <<<send packet: AA 35 03 00 81 04 01 42 2024-10-31 11:19:16,403 INFO: AciHostCLI continuously_read: >>>receive packet: AA 32 05 00 00 00 81 04 00 44 2024-10-31 11:19:16,406 INFO: Parser eventParser: syncWord: AA,seqn: 32,len: 5,opcode: 0000,params: [81 04 00], check_sum: 44 2024-10-31 11:19:16,409 INFO: Parser eventParser: event name: APP_EVENT_ACK 2024-10-31 11:19:16,409 INFO: Parser eventParser: event_id: [81 04] 2024-10-31 11:19:16,410 INFO: Parser eventParser: status: [00] 2024-10-31 11:19:16,442 INFO: AciHostCLI continuously_read: >>>receive packet: AA 33 04 00 00 04 01 00 C4 2024-10-31 11:19:16,443 INFO: Parser eventParser: syncWord: AA,seqn: 33,len: 4,opcode: 0400,params: [01 00], check_sum: C4 2024-10-31 11:19:16,443 INFO: Parser eventParser: event name: APP_EVENT_SCO_STATE 2024-10-31 11:19:16,444 INFO: Parser eventParser: link_id: [01] 2024-10-31 11:19:16,444 INFO: Parser eventParser: state: [00] 2024-10-31 11:19:16,445 INFO: Packet sendPacket: <<<send packet: AA 36 05 00 00 00 00 04 00 C1
UART DFU
Introduction
DFU (Device Firmware Upgrade) function allows for seamless firmware updates. Bluetooth Audio Transceiver has incorporated a comprehensive DFU system based on UART. This system enables users to upgrade devices effortlessly through the utilization of the ACI Host CLI Tool. By placing the designated upgrade package into a specified folder and configuring the file name and version number, users can execute the device update with a single command.
Prepare the Upgrade Package
In order to perform a DFU process, it is necessary to prepare an upgrade package. The creation of the upgrade package can be accomplished using the MPPG tool. This involves two main steps:
Generating the OTA header image. During this process, please ensure the appropriate version number is filled in (this version number will later need to be entered in the
config.yml
file in ACI Host CLI Tool). For detailed instructions, refer to Prepare the Image to Update.Packing the generated OTA header image with other images to be upgraded. For detailed instructions, refer to Pack Whole Image.
Once the upgrade package is prepared, place it in the sdk\tool\AciHostCLI-v1.x.x.xx-Common_SDK\dfu
folder. Then, open the config.yml
file and fill in the upgrade package’s file name and version number.
Upon completing the aforementioned steps, simply enter the command dfu start
in the ACI Host to
initiate the upgrade process for your device.
ACI Host CLI Test
The ACI Host sends CMD_UART_DFU
with various opcodes to execute specific functions. This includes
using the UART_DFU_START_REQ
opcode to initiate the DFU, the UART_DFU_DATA_IND
opcode to
transmit data packets, the UART_DFU_REBOOT
opcode to reboot the device, and the UART_DFU_ABORT
opcode to terminate the DFU. The device side sends the EVENT_DFU_START_RSP
event to confirm the
initiation of the DFU, the EVENT_DFU_DATA_REQ
event to request data packets, and the
EVENT_DFU_RESULT
event to notify the ACI Host of the upgrade result.
Command |
Parameters |
ACI Host CLI CMD |
---|---|---|
CMD_UART_DFU(0x3270) |
opcode = UART_DFU_START_REQ(0x0000) |
dfu start |
CMD_UART_DFU(0x3270) |
opcode = UART_DFU_DATA_IND(0x0001) |
None |
CMD_UART_DFU(0x3270) |
opcode = UART_DFU_ABORT(0x0002) |
dfu abort |
CMD_UART_DFU(0x3270) |
opcode = UART_DFU_REBOOT(0x0003) |
None |
ACI Host CLI test: Start DFU.
2023-10-27 17:51:21,440 INFO: input command: dfu start 2023-10-27 17:51:21,573 INFO: DFU open: file_size 2434320 2023-10-27 17:51:21,574 INFO: Parser cmdParser: cmd opcode: 3270 param: [00 00 02 00 00 00] name: CMD_UART_DFU 2023-10-27 17:51:21,575 INFO: Packet sendPacket: <<<send packet: AA 06 08 00 70 32 00 00 02 00 00 00 4E 2023-10-27 17:51:21,647 WARNING: AciHostCLI retrans: retransmit command dfu start due to ack timeout! retry: 1 2023-10-27 17:51:21,648 INFO: Packet sendPacket: <<<send packet: AA 06 08 00 70 32 00 00 02 00 00 00 4E 2023-10-27 17:51:21,660 INFO: AciHostCLI continuously_read: >>>receive packet: AA 04 05 00 00 00 70 32 00 55 2023-10-27 17:51:21,661 INFO: Parser eventParser: syncWord: AA,seqn: 04,len: 5,opcode: 0000,params: [70 32 00], check_sum: 55 2023-10-27 17:51:21,661 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-10-27 17:51:21,662 INFO: Parser eventParser: event_id: [70 32] 2023-10-27 17:51:21,663 INFO: Parser eventParser: status: [00] 2023-10-27 17:51:21,663 INFO: AciHostCLI continuously_read: >>>receive packet: AA 05 03 00 60 31 01 66 2023-10-27 17:51:21,664 INFO: Parser eventParser: syncWord: AA,seqn: 05,len: 3,opcode: 3160,params: [01], check_sum: 66 2023-10-27 17:51:21,665 INFO: Parser eventParser: event name: EVENT_DFU_START_RSP 2023-10-27 17:51:21,665 INFO: Parser eventParser: status: [01] 2023-10-27 17:51:21,666 INFO: DFU handle_duf_rsp: self.state dfuState.STARTED 2023-10-27 17:51:21,667 INFO: Packet sendPacket: <<<send packet: AA 07 05 00 00 00 60 31 00 63
ACI Host CLI test: Transmit data.
2023-10-27 17:51:21,676 INFO: AciHostCLI continuously_read: >>>receive packet: AA 06 08 00 61 31 00 00 00 00 48 00 18 2023-10-27 17:51:21,677 INFO: Parser eventParser: syncWord: AA,seqn: 06,len: 8,opcode: 3161,params: [00 00 00 00 48 00], check_sum: 18 2023-10-27 17:51:21,677 INFO: Parser eventParser: event name: EVENT_DFU_DATA_REQ 2023-10-27 17:51:21,678 INFO: Parser eventParser: offset: [00 00 00 00] 2023-10-27 17:51:21,679 INFO: Parser eventParser: length: [48 00] 2023-10-27 17:51:21,679 INFO: DFU handle_duf_rsp: next offset 0, length 72 2023-10-27 17:51:21,680 INFO: Packet sendPacket: <<<send packet: AA 08 05 00 00 00 61 31 00 61 2023-10-27 17:51:21,680 INFO: Parser cmdParser: cmd opcode: 3270 param: [01 00 47 4D 54 F3 24 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 82 0B EC 03 06 01 00 00 00 00 00 00 00 00 00 00 00 00 EC 03 06 00 00 00 00 00 00 00 00 00 00 00 00 00] name: CMD_UART_DFU 2023-10-27 17:51:21,681 INFO: Packet sendPacket: <<<send packet: AA 09 4C 00 70 32 01 00 47 4D 54 F3 24 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2023-10-27 17:51:21,692 INFO: AciHostCLI continuously_read: >>>receive packet: AA 07 05 00 00 00 70 32 00 52 2023-10-27 17:51:21,693 INFO: Parser eventParser: syncWord: AA,seqn: 07,len: 5,opcode: 0000,params: [70 32 00], check_sum: 52 2023-10-27 17:51:21,693 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-10-27 17:51:21,694 INFO: Parser eventParser: event_id: [70 32] 2023-10-27 17:51:21,694 INFO: Parser eventParser: status: [00] .... 2023-10-27 17:53:08,591 INFO: AciHostCLI continuously_read: >>>receive packet: AA 84 08 00 61 31 F0 F2 24 00 64 00 78 2023-10-27 17:53:08,592 INFO: Parser eventParser: syncWord: AA,seqn: 84,len: 8,opcode: 3161,params: [F0 F2 24 00 64 00], check_sum: 78 2023-10-27 17:53:08,592 INFO: Parser eventParser: event name: EVENT_DFU_DATA_REQ 2023-10-27 17:53:08,593 INFO: Parser eventParser: offset: [F0 F2 24 00] 2023-10-27 17:53:08,593 INFO: Parser eventParser: length: [64 00] 2023-10-27 17:53:08,593 INFO: DFU handle_duf_rsp: next offset 2421488, length 100 2023-10-27 17:53:08,594 INFO: Packet sendPacket: <<<send packet: AA 5E 05 00 00 00 61 31 00 0B 2023-10-27 17:53:08,594 INFO: Parser cmdParser: cmd opcode: 3270 param: [01 00 4F 52 28 00 B0 21 28 00 38 3F 28 00 6C 3E 28 00 A8 28 28 00 24 89 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 06 01 02 06 01 A0 00 FF FF FF FF 1F 00 92 02 94 02 96 02 09 11 19 21 29 31 39 41 49 51 59 61 69 71 79 7F F4 01] name: CMD_UART_DFU 2023-10-27 17:53:08,595 INFO: Packet sendPacket: <<<send packet: AA 5F 68 00 70 32 01 00 4F 52 28 00 B0 21 28 00 38 3F 28 00 6C 3E 28 00 A8 28 28 00 24 89 28 00 2023-10-27 17:53:08,603 INFO: AciHostCLI continuously_read: >>>receive packet: AA 85 05 00 00 00 70 32 00 D4 2023-10-27 17:53:08,604 INFO: Parser eventParser: syncWord: AA,seqn: 85,len: 5,opcode: 0000,params: [70 32 00], check_sum: D4 2023-10-27 17:53:08,605 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-10-27 17:53:08,606 INFO: Parser eventParser: event_id: [70 32] 2023-10-27 17:53:08,606 INFO: Parser eventParser: status: [00]
ACI Host CLI test: DFU successfully.
2023-10-27 17:53:09,099 INFO: Parser eventParser: syncWord: AA,seqn: 86,len: 3,opcode: 3162,params: [01], check_sum: E3 2023-10-27 17:53:09,100 INFO: Parser eventParser: event name: EVENT_DFU_RESULT 2023-10-27 17:53:09,101 INFO: Parser eventParser: result: [01] 2023-10-27 17:53:09,101 WARNING: DFU handle_dfu_result: result True, note True!!! 2023-10-27 17:53:09,102 INFO: Packet sendPacket: <<<send packet: AA 60 05 00 00 00 62 31 00 08 2023-10-27 17:53:09,103 INFO: DFU finish_dfu!!! 2023-10-27 17:53:09,103 INFO: Parser cmdParser: cmd opcode: 3270 param: [03 00] name: CMD_UART_DFU 2023-10-27 17:53:09,104 INFO: Packet sendPacket: <<<send packet: AA 61 04 00 70 32 03 00 F6 2023-10-27 17:53:09,176 WARNING: AciHostCLI retrans: retransmit command dfu reboot due to ack timeout! retry: 1 2023-10-27 17:53:09,177 INFO: Packet sendPacket: <<<send packet: AA 61 04 00 70 32 03 00 F6 2023-10-27 17:53:09,179 INFO: AciHostCLI continuously_read: >>>receive packet: AA 87 05 00 00 00 70 32 00 D2 2023-10-27 17:53:09,179 INFO: Parser eventParser: syncWord: AA,seqn: 87,len: 5,opcode: 0000,params: [70 32 00], check_sum: D2 2023-10-27 17:53:09,180 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-10-27 17:53:09,180 INFO: Parser eventParser: event_id: [70 32] 2023-10-27 17:53:09,181 INFO: Parser eventParser: status: [00] 2023-10-27 17:53:09,834 INFO: AciHostCLI continuously_read: >>>receive packet: AA 01 08 00 23 00 15 03 77 56 22 03 CA 2023-10-27 17:53:09,835 INFO: Parser eventParser: syncWord: AA,seqn: 01,len: 8,opcode: 0023,params: [15 03 77 56 22 03], check_sum: CA 2023-10-27 17:53:09,835 INFO: Parser eventParser: event name: EVENT_BT_READY 2023-10-27 17:53:09,836 INFO: Parser eventParser: factory_addr: [15 03 77 56 22 03] 2023-10-27 17:53:09,837 INFO: Packet sendPacket: <<<send packet: AA 62 05 00 00 00 23 00 00 76 2023-10-27 17:53:09,849 INFO: AciHostCLI continuously_read: >>>receive packet: AA 02 03 00 07 00 01 F3 2023-10-27 17:53:09,850 INFO: Parser eventParser: syncWord: AA,seqn: 02,len: 3,opcode: 0007,params: [01], check_sum: F3 2023-10-27 17:53:09,851 INFO: Parser eventParser: event name: EVENT_DEVICE_STATE 2023-10-27 17:53:09,851 INFO: Parser eventParser: device_state: [01] 2023-10-27 17:53:09,852 INFO: Packet sendPacket: <<<send packet: AA 63 05 00 00 00 07 00 00 91
The following charts focus on the design SPEC of Bluetooth Audio Transceiver
. It is written to help users easily and completely understand the code flow of the application. The following topics are included:
Software Architecture.
Firmware Initialization and Configuration (includes Flash and FTL).
Memory (includes Global and Heap).
Flash.
IO.
OTA.
DLPS.
Code Flow (including main functions of typical scenarios, such as transmitter, receiver, transceiver, and transmitter_mp3).
Before studying the content of this article, it is highly recommended to first study the following documents:
Software Architecture
Please refer to SDK User Guide for more details.
Firmware Initialization and Configuration
Initialization and Main Application Loop
This procedure develops an application for Bluetooth/Bluetooth Low Energy audio on the RTL87x3E Series platforms. The main
procedure is to be carried out in the following steps:
Call the
ram_config()
API to configure DSP to share 80KB RAM with MCU.Call the
log_module_trace_set()
API to disable some trace logs during system initialization.Call the
APP_PRINT_INFO2()
API to print the wake-up reason, compile time, and restart reason.Call the
os_msg_queue_create()
API to create a message and event queue for task communication.Call the
app_init_timer()
API to initialize APP timer.Call the
pm_cpu_freq_init()
API to initialize CPU freq module.Call the
app_cfg_init()
API to initialize the configuration.Call the
board_init()
API to initialize PINMUX and pad settings.Call the
app_bt_gap_init()
API to initialize GAP parameters of Bluetooth and Bluetooth Low Energy.Call the
framework_init()
API to initialize the System Manager, Remote Manager, Bluetooth Manager and Audio Manager. This is done using the following steps:Call the
sys_mgr_init()
API to initialize system.Call the
remote_mgr_init()
API to initialize remote.Call the
bt_mgr_init()
API to initialize Bluetooth.Call the
audio_mgr_init()
API to initialize audio.
Call the
app_ota_init()
API to initialize OTA.Call the
driver_init()
API to initialize the drivers. This is done using the following steps:Call the
app_adp_init()
API to init adaptor.Call the
app_console_init()
API to initialize console.Call the
app_charger_init()
API to initialize charger.Call the
app_line_in_driver_init()
API to initialize line-in.Call the
app_amp_init()
API to init AMP.Call the
app_qdec_driver_init()
API to initialize QDEC.Call the
app_dlps_system_wakeup_clear_rtc_int()
API to init RTC.Call the
ext_flash_init()
API to init external flash.
Call the
app_auto_power_off_init()
API to initialize the auto power off module.Call the
app_audio_init()
API to initialize audio, such as initializing EQ, setting VP language, setting volume, etc.Call the
app_mmi_init()
API to initialize MMI.Call the
app_test_init()
API to initialize test.Call the
app_gap_init()
API to initialize GAP.Call the
app_ble_gap_init()
API to initialize Bluetooth Low Energy GAP.Call the
app_bt_policy_init()
API to initialize Bluetooth policy.Call the
app_ble_client_init()
API to initialize LE client.Call the
gatt_svc_init()
API to initialize GATT service.Call the profile init APIs to initialize Bluetooth profiles. This is done using the following steps:
Call the
app_hfp_init()
API to initialize HFP.Call the
app_avrcp_init()
API to initialize AVRCP.Call the
app_a2dp_init()
API to initialize A2DP.Call the
app_sdp_init()
API to initialize SDP.Call the
app_spp_init()
API to initialize SPP.Call the
app_pbap_init()
API to initialize PBAP.Call the
app_hid_init()
API to initialize HID.Call the
app_iap_init()
API to initialize iAP.
Call the
app_ble_service_init()
APIs to initialize Bluetooth Low Energy Services. This is done using the following steps:Call the
transmit_srv_add()
API to initialize transmit service.Call the
ota_add_service()
API to initialize OTA service.Call the
bas_add_service()
API to initialize battery service.
Call the
app_lea_acc_profile_init()
API to initialize LE Audio service and profiles.Call the
os_task_create()
API to create a new task and add it to the list of tasks that are ready to run.Call the
os_sched_start()
API to start the RTOS kernel scheduler.
Configuration
Some parameters are configured through the MCUConfig Tool, and once configured, they are saved in the APP Config Image, the location and size of which is specified by the flash map file. Some parameters need to be saved to be used the next time the system boots up, and these configurations are saved in the FTL.
Configuration in Flash
The flash map file is located in
sdk\bin\rtl87x3e\flash_map_config\4M\flash_4M\flash_map.h
.
The corresponding configurations are as follows:
#define BANK0_APP_CFG_ADDR 0x021F0000
#define BANK0_APP_CFG_SIZE 0x00002000 *//8K Bytes*
The APP Config Image, which is 8 KBytes (defined as BANK0_APP_CFG_SIZE
), contains the following sections that are pre-allocated fields and cannot be modified:
#define APP_CONFIG_OFFSET 0
#define APP_CONFIG_SIZE 1024
#define APP_LED_OFFSET (APP_CONFIG_OFFSET + APP_CONFIG_SIZE)
#define APP_LED_SIZE 512
#define SYS_CONFIG_OFFSET (APP_LED_OFFSET + APP_LED_SIZE)
#define SYS_CONFIG_SIZE 512
#define APP_CONFIG2_OFFSET (SYS_CONFIG_OFFSET + SYS_CONFIG_SIZE)
#define APP_CONFIG2_SIZE 512
#define TONE_DATA_OFFSET 4096 //Rsv 4K for APP parameter for better flash control
#define TONE_DATA_SIZE 3072
The variables corresponding to APP_CONFIG_OFFSET
and APP_CONFIG_SIZE
are defined as follows:
Only device_name_legacy_default
and device_name_le_default
are generated through MCUConfig Tool configuration, while all other fields are configured and initialized through app_cfg_init()
.
typedef struct
{
uint32_t sync_word;
uint8_t device_name_legacy_default[DEVICE_NAME_MAX_LEN]; //this field offset is fixed, SHALL NOT modify
uint8_t device_name_le_default[DEVICE_NAME_MAX_LEN]; //this field offset is fixed, SHALL NOT modify
...
...
} T_APP_CFG_CONST;
Configuration in FTL
The areas used by FTL are defined as follows, and users can extend new areas according to their product needs.
//FTL start
#define APP_RW_DATA_ADDR 3072
#define APP_RW_DATA_SIZE 360
#define FACTORY_RESET_OFFSET 124
#define GCSS_ATT_TBL_INFO_ADDR (APP_RW_DATA_ADDR + APP_RW_DATA_SIZE)
#define GCSS_ATT_TBL_INFO_SIZE (30 * 16)
#define APP_FINDMY_INFO_ADDR (GCSS_ATT_TBL_INFO_ADDR + GCSS_ATT_TBL_INFO_SIZE)
#define APP_FINDMY_INFO_SIZE 320
//FTL end
The variables corresponding to APP_RW_DATA_ADDR
and APP_RW_DATA_SIZE
are defined as follows:
typedef struct
{
T_APP_CFG_NV_HDR hdr;
//offset: 8
uint8_t device_name_legacy[40];
uint8_t device_name_le[40];
uint8_t le_single_random_addr[6];
...
...
} T_APP_CFG_NV;
Memory
The available size of Global and Heap memory used by the application is configured in:
sdk\board\evb\bt_audio_trx\inc\rtl87x3e\mem_config.h
.
Users can adjust the parameters according to the product memory usage requirements.
MCU Memory
#define APP_RAM_TEXT_SIZE (5*1024)
#define APP_GLOBAL_SIZE (14*1024)
DSP Share Memory
#define DSP_SHM_TOTAL_SIZE 80 * 1024
#define DSP_SHM_GLOBAL_SIZE 10 * 1024
#define DSP_SHM_HEAP_ADDR DSP_SHM_GLOBAL_ADDR + DSP_SHM_GLOBAL_SIZE
#define DSP_SHM_HEAP_SIZE (DSP_SHM_TOTAL_SIZE - DSP_SHM_GLOBAL_SIZE)
How to Check the Memory Usage
The use of Global and TEXT RAM can be confirmed by the following file:
sdk\board\evb\bt_audio_trx\bin\rtl87x3e\flash_4M_dualbank\bank0\bt_audio_trx_bank0.map
.
Execution Region RAM_TEXT (Exec base: 0x00208800, Load base: 0x0214351c, Size: 0x000014a0, Max: 0x00002800, ABSOLUTE)
Execution Region RAM_GLOBAL (Exec base: 0x002c0000, Load base: 0x02139868, Size: 0x000021b8, Max: 0x00003800, ABSOLUTE)
Execution Region SHARE_RAM_DATA (Exec base: 0x00300000, Load base: 0x0213a0ec, Size: 0x00000000, Max: 0x00002800, ABSOLUTE)
The use of Heap RAM can be confirmed by the following log:
APP_PRINT_WARN1("app_task unused memory: %d", mem_peek());
Flash
APP Image in Flash Map
The flash map file is located in
sdk\bin\rtl87x3e\flash_map_config\4M\flash_4M\flash_map.h
. The maximum size of the APP image is defined by BANK0_APP_SIZE
.
#define BANK0_APP_ADDR 0x02099000
#define BANK0_APP_SIZE 0x000CD000 *//820K Bytes*
How to Check APP Image Size Used
The actual size of the APP image used can be confirmed by the following file:
sdk\board\evb\bt_audio_trx\bin\rtl87x3e\flash_4M_dualbank\bank0\bt_audio_trx_bank0.map
.
Load Region LOAD_FLASH **//Base: 0x0086e000, Size: 0x0008eeb8, Max: 0x000c8000, ABSOLUTE*
IO
IO Resource
GPIO
In some scenarios that do not need to play voice prompts and tones, some analog pins can be released to be used as GPIO.
Taking the LOUT_P
pin as an example, the following three steps are mainly required:
Remove the SPK setting.
Use the MCUConfig Tool to remove the SPK setting of the audio on the
Audio Route
page. This ensures the pad ofLOUT_P
will not be configured.
Mute voice prompts and tones.
Open the macro of
F_APP_DISABLE_NOTIFICATION_SUPPORT
inapp_flags.h
.#define F_APP_USER_EQ_SUPPORT 1 //open #define F_APP_DISABLE_NOTIFICATION_SUPPORT 1 #define F_APP_MONITOR_MEMORY_AND_TIMER 0
Set
AVCC
driver.Set
AVCC_DRV
toAlways active
on the System Configuration page.
DMA
DMA Resources
Currently, there are a total of 9 DMA channels available for use. Some channels are already utilized or reserved for DSP and log UART purposes. There are 3 channels currently unoccupied. In addition to this, the DSP reserved channel 8 is not used by DSP and is also available for APP use.
Channel |
State |
---|---|
GDMA_Channel 0 |
Idle |
GDMA_Channel 1 |
Idle |
GDMA_Channel 2 |
DSP reserved |
GDMA_Channel 3 |
DSP reserved |
GDMA_Channel 4 |
DSP reserved |
GDMA_Channel 5 |
DSP reserved |
GDMA_Channel 6 |
Idle |
GDMA_Channel 7 |
Log UART |
GDMA_Channel 8 |
DSP reserved, can be used for APP. |
DMA Current Usage
UART With ACI Host.
For MP3 Transmitter Application (
F_APP_BT_AUDIO_TRANSMITTER_MP3_DEMO_SUPPORT
), due to substantial audio data stream, the UART will dynamically request 2 channels.static void app_console_uart_init(void) { ... console_uart_config.uart_rx_dma_enable = false; console_uart_config.uart_tx_dma_enable = false; #if F_APP_BT_AUDIO_TRANSMITTER_MP3_DEMO_SUPPORT console_uart_config.uart_tx_dma_enable = true; console_uart_config.uart_rx_dma_enable = true; #endif ... }
SPI.
In the case of the Transceiver Application (
F_APP_BT_AUDIO_TRANSCEIVER_DEMO_SUPPORT
), SPI TX dynamically requests 1 channel, while SPI RX utilizes channel 8, which is reserved for DMA purposes.// SPI TX void app_spi_master_init(void) { ... if (!GDMA_channel_request(&spi_tx_dma_ch_num, app_spi_master_tx_dma_handler, true)) { APP_PRINT_ERROR0("app_spi_master_init: tx channel request fail"); return; } ... }
// SPI RX static uint8_t spi_rx_dma_ch_num = 8; #define SPI_RX_DMA_CHANNEL_NUM spi_rx_dma_ch_num static void app_spi_master_dma_rx_init(void *readbuf) { ... GDMA_InitStruct.GDMA_ChannelNum = SPI_RX_DMA_CHANNEL_NUM; ... GDMA_INTConfig(SPI_RX_DMA_CHANNEL_NUM, GDMA_INT_Transfer, ENABLE); }
Key
The Key module supports two types of keys: MFB and GPIO keys. On the EVB, it can accommodate up to 1 MFB and 8 GPIO keys. Typically, MFB is utilized for power on and power off functionalities, while GPIO keys are mapped to MMI (Man-Machine Interface) features.
The configuration for key module functionalities is defined in app_key_cfg.c
. Users have the
flexibility to configure various aspects, including enabling or disabling key functionality,
mapping keys to GPIO, and associating keys with MMI functions.
Refer to T_MMI_ACTION
in app_mmi.h
for a comprehensive list of all supported MMI interfaces.
This enumeration provides details on the various MMI actions that can be utilized for configuring
and mapping functionalities to different key scenarios.
typedef enum
{
MMI_NULL = 0x00,
MMI_HF_END_OUTGOING_CALL = 0x02,
...
MMI_TOTAL
} T_MMI_ACTION;
MFB
To enable the MFB functionality, set app_key_cfg.mfb_replace_key0
to 1.
void app_key_cfg_init(void)
{
...
app_key_cfg.mfb_replace_key0 = 1;
...
}
In the power off state, different durations of long-pressing the MFB key can achieve power on, enter pairing mode, and factory reset. Modify the following configurations for specific duration definitions (The unit is 100 ms):
void app_key_cfg_init(void)
{
...
app_key_cfg.key_power_on_interval = 25;
app_key_cfg.key_enter_pairing_interval = 60;
app_key_cfg.key_factory_reset_interval = 90;
...
}
In the power on state, a long-pressing of the MFB key allows for shutting down. The duration to trigger the shutdown key can be configured through key_power_off_interval
.
void app_key_cfg_init(void)
{
...
app_key_cfg.key_power_off_interval = 30;
...
}
GPIO Key
Hardware Configurations
To utilize GPIO Keys, first, map the keys to the required GPIOs. This can be achieved by modifying
key_pinmux[8]
, where these GPIOs can be configured for key 0 to key 7. Enable the keys through
key_enable_mask
. For instance, configure the GPIO for key 1 as P0_1
, key 2 as P1_0
, and enable both
key 1 and key 2.
void app_key_cfg_init(void)
{
...
uint8_t key_pinmux[8] = {0xFF, P0_1, P1_0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
memcpy(app_key_cfg.key_pinmux, key_pinmux, sizeof(key_pinmux));
app_key_cfg.key_enable_mask = KEY1_MASK | KEY2_MASK;
...
}
It’s essential to note that keys are default low-active. Depending on the circuitry, if the key is
high-active, include the corresponding key mask in key_high_active_mask
.
void app_key_cfg_init(void)
{
...
app_key_cfg.key_high_active_mask = KEY2_MASK | KEY4_MASK | KEY6_MASK;
...
}
Operation Modes of Keys
GPIO keys support various operation modes, categorized based on key scenario into short click, long press, and multiple clicks. They are further distinguished by the number of keys as single key and combine key. Specifically, there are six operation modes:
Mode 1:single key + short click.
Mode 2:single key + long press.
Mode 3:single key + multiple clicks (2/3/4/5 clicks).
Mode 4:combine key + short click.
Mode 5:combine key + long press.
Mode 6:combine key + multiple clicks (2/3/4/5 clicks).
The trigger duration for long press is configured through key_long_press_interval
, and the
detection duration for multiple clicks is configured through key_multi_click_interval
.
void app_key_cfg_init(void)
{
...
app_key_cfg.key_long_press_interval = 20;
app_key_cfg.key_multi_click_interval = 3;
...
}
For operation mode 2, long repeat functionality is supported. This means that when holding down
the key for an extended period, the corresponding MMI function can be triggered multiple times. The
interval for triggering is configured through key_long_press_repeat_interval
. The corresponding
keys are configured through key_long_press_repeat_mask
.
void app_key_cfg_init(void)
{
...
app_key_cfg.key_long_press_repeat_interval = 4;
app_key_cfg.key_long_press_repeat_mask = KEY_NULL;
...
}
The mapping of different operation modes to MMI functions is maintained through tables. The modes 1 and 2 are part of the basic functionality maintained by the key table, while modes 2 to 6 are considered hybrid functionality and are maintained by the hybrid key table.
Key Table
As depicted in the figure, the key_table is a multidimensional array of size 2 x 9 x 8.
key_table[0]
corresponds to the short click table, and key_table[1]
corresponds to the long
press table. Different MMI functions can be assigned to keys under different call statuses.
There are a total of 9 call statuses, defined as follows:
enum key_table_call_status
{
CALL_IDLE,
VOICE_DIAL,
INCOMING_CALL,
OUT_GOING_CALL,
CALL_ACTIVE,
CALL_ACTIVE_WITH_CALL_WAITING,
CALL_ACTIVE_WITH_CALL_HOLD,
MULTI_CALL_ACTIVE_WITH_CALL_WAITING,
MULTI_CALL_ACTIVE_WITH_CALL_HOLD,
};
For example, MMI_DEV_MIC_VOL_UP
can be configured to be triggered by a short press of key 1 in
the CALL_IDLE
status and MMI_DEV_MIC_VOL_DOWN
can be triggered by a long press of key 1 in
the CALL_IDLE
status.
void app_key_cfg_init(void)
{
...
// sample of single key short click
app_key_cfg.key_table[SHORT_CLICK][CALL_IDLE][KEY_1] = MMI_DEV_MIC_VOL_UP;
// sample of single key long press
app_key_cfg.key_table[LONG_PRESS][CALL_IDLE][KEY_1] = MMI_DEV_MIC_VOL_DOWN;
...
}
Hybrid Key Table
As illustrated in the figure below, the hybrid key table is a multidimensional array of size 9 x 8. Different MMI functions can be assigned to different hybrid types under various call statuses.
Hybrid types consist of a hybrid mask and hybrid scenario. The hybrid mask defines the key
combination, and the hybrid scenario defines the operation mode. All hybrid types are defined
through hybrid_key_mapping
, supporting a maximum of 8 hybrid types.
For example, configure the following:
Trigger
MMI_DEV_MIC_VOL_DOWN
by operatingHYBRID_TYPE_0
(double-clicking key 1) in theCALL_IDLE
status.Trigger
MMI_START_ROLESWAP
by operatingHYBRID_TYPE_1
(triple-clicking key 1) in theCALL_IDLE
status.Trigger
MMI_DEV_MIC_VOL_DOWN
by simultaneously short pressing key 1 and key 2 (HYBRID_TYPE_2
) while in theCALL_IDLE
status.void app_key_cfg_init(void) { ... // sample of double click app_key_cfg.hybrid_key_table[CALL_IDLE][HYBRID_TYPE_0] = MMI_DEV_MIC_VOL_DOWN; app_key_cfg.hybrid_key_mapping[HYBRID_TYPE_0][HYBRID_MASK] = KEY1_MASK; app_key_cfg.hybrid_key_mapping[HYBRID_TYPE_0][HYBRID_SCENARIO] = HYBRID_KEY_2_CLICK; // sample of triple click app_key_cfg.hybrid_key_table[CALL_IDLE][HYBRID_TYPE_1] = MMI_START_ROLESWAP; app_key_cfg.hybrid_key_mapping[HYBRID_TYPE_1][HYBRID_MASK] = KEY1_MASK; app_key_cfg.hybrid_key_mapping[HYBRID_TYPE_1][HYBRID_SCENARIO] = HYBRID_KEY_3_CLICK; // sample of combine key single click app_key_cfg.hybrid_key_table[CALL_IDLE][HYBRID_TYPE_2] = MMI_DEV_MIC_VOL_DOWN; app_key_cfg.hybrid_key_mapping[HYBRID_TYPE_2][HYBRID_MASK] = KEY1_MASK | KEY2_MASK; app_key_cfg.hybrid_key_mapping[HYBRID_TYPE_2][HYBRID_SCENARIO] = HYBRID_KEY_SHORT_PRESS; ... }
OTA
Refer to OTA for details.
DLPS
Please refer to Low Power Mode for details.
Code Flow
This chapter describes the code flow of some of the main functions.
Basic Function
Power On/Off and Factory Reset
Functions such as power on, power off, and factory reset are realized by transmitting MMI commands through UART.
These commands are centrally processed in app_cmd_general.c
, and the used APIs are introduced as follows:
void app_cmd_general_cmd_handle(uint8_t *cmd_ptr, uint16_t cmd_len, uint8_t cmd_path,
uint8_t app_idx, uint8_t *ack_pkt)
{
uint16_t cmd_id = (uint16_t)(cmd_ptr[0] | (cmd_ptr[1] << 8));
switch (cmd_id)
{
case CMD_MMI:
...
app_mmi_handle_action(cmd_ptr[3]);
...
}
break;
}
APP handles key messages in function app_mmi_handle_action()
. The user triggers the specific key process, then the device would perform the related action.
If the device performs power on, it will call sys_mgr_power_on()
after judging the device state under case MMI_DEV_POWER_ON
.
void app_mmi_handle_action(uint8_t action)
{
...
switch (action)
{
case MMI_DEV_POWER_ON:
{
if (app_db.device_state == APP_DEVICE_STATE_OFF_ING)
{
if (app_bt_policy_get_b2s_connected_num())
{
app_bt_policy_disconnect_all_link();
}
app_mmi_modify_reboot_check_times(REBOOT_CHECK_POWER_ON_MAX_TIMES);
}
else if (app_db.device_state == APP_DEVICE_STATE_OFF)
{
if (!app_db.is_long_press_power_on_play_vp && !mp_hci_test_mode_is_running())
{
app_audio_tone_type_play(TONE_POWER_ON, false, false);
}
app_db.is_long_press_power_on_play_vp = false;
sys_mgr_power_on();
}
}
break;
...
}
}
If the device performs power off, it will call app_mmi_power_off()
which encapsulates sys_mgr_power_off()
after judging device state under case MMI_DEV_POWER_OFF
.
case MMI_DEV_POWER_OFF:
{
...
if (app_db.device_state == APP_DEVICE_STATE_ON)
{
...
app_device_state_change(APP_DEVICE_STATE_OFF_ING);
app_dlps_disable(APP_DLPS_ENTER_CHECK_WAIT_RESET);
...
app_stop_timer(&timer_idx_reboot_check);
app_mmi_reboot_check_timer_start(500);
app_timer_register_pm_excluded(&timer_idx_reboot_check);
if (mp_hci_test_mode_is_running())
{
mp_hci_test_mmi_handle_action(action);
}
else
{
app_sniff_mode_disable_all();
//power off
app_mmi_power_off();
}
}
}
break;
If the device performs a factory reset, it will call sys_mgr_power_off()
after checking the factory reset behavior.
case MMI_DEV_FACTORY_RESET:
{
app_dlps_disable(APP_DLPS_ENTER_CHECK_WAIT_RESET);
app_mmi_check_factory_reset_behavior(action);
...
app_stop_timer(&timer_idx_reboot_check);
app_mmi_reboot_check_timer_start(500);
app_db.waiting_factory_reset = true;
if (app_db.device_state == APP_DEVICE_STATE_ON)
{
app_device_state_change(APP_DEVICE_STATE_OFF_ING);
app_sniff_mode_disable_all();
sys_mgr_power_off();
}
}
Bluetooth Connection and Linkback
The device utilizes CMD_BT_CREATE_CONNECTION
to establish a Bluetooth connection, and CMD_XM_USER_CFM_REQ
to confirm the connection request from another device.
APIs that can be referred to are as follows.
The APIs called in app_cmd_br.c
are declared in br_cmd_handle()
, developers can enter the profiles to be connected in ACI Host CLI Tool (please refer to Connection and Linkback Function).
The specific profile mask can refer to app_link_util.h
, which can be adjusted according to needs.
void br_cmd_handle(uint8_t *cmd_ptr, uint16_t cmd_len, uint8_t cmd_path, uint8_t app_idx,
uint8_t *ack_pkt)
{
uint16_t cmd_id = (uint16_t)(cmd_ptr[0] | (cmd_ptr[1] << 8));
switch (cmd_id)
{
...
case CMD_BT_CREATE_CONNECTION:
{
struct
{
uint16_t cmd_id;
uint32_t profile_mask;
uint8_t addr[6];
} __attribute__((packed)) *CMD = (typeof(CMD))cmd_ptr;
...
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
linkback_todo_queue_insert_normal_node(CMD->addr, CMD->profile_mask,
app_cfg_const.timer_linkback_timeout * 1000, 0);
linkback_run();
}
break;
...
}
}
After inserting a normal linkback node, the linkback node information will be checked, then the profiles to be connected will be placed in
p_item->linkback_node.plan_profs
in linkback_todo_queue_all_node()
.
void linkback_todo_queue_insert_normal_node(uint8_t *bd_addr, uint32_t plan_profs,
uint32_t retry_timeout, bool is_group_member)
{
T_LINKBACK_NODE_ITEM *p_item;
p_item = linkback_todo_queue_find_node_item(bd_addr);
...
linkback_todo_queue_all_node();
}
The linkback process runs and checks the status of linkback_active_node
. After confirming that the node exists and the doing profile is not 0, linkback_profile_connect_start()
will continue to be executed.
Then, the linkback_active_node_step_suc_adjust_remain_profs()
/linkback_active_node_step_fail_adjust_remain_profs()
will be returned according to the result of linkback_profile_search_start()
.
void linkback_run(void)
{
T_LINKBACK_NODE node;
uint32_t profs;
...
if (b2s_connected_find_node(linkback_active_node.linkback_node.bd_addr, &profs))
{
if (profs & linkback_active_node.doing_prof)
{
ENGAGE_PRINT_TRACE1("linkback_run: prof 0x%08x, already connected",
linkback_active_node.doing_prof);
linkback_active_node_step_suc_adjust_remain_profs();
goto RETRY;
}
...
}
...
if (linkback_profile_is_need_search(linkback_active_node.doing_prof))
{
if (!linkback_profile_search_start(linkback_active_node.linkback_node.bd_addr,
linkback_active_node.doing_prof, linkback_active_node.linkback_node.is_special))
{
linkback_active_node_step_fail_adjust_remain_profs();
goto RETRY;
}
...
}
else
{
if (linkback_profile_connect_start(linkback_active_node.linkback_node.bd_addr,
linkback_active_node.doing_prof, &linkback_active_node.linkback_conn_param))
{
goto EXIT;
}
else
{
linkback_active_node_step_fail_adjust_remain_profs();
goto RETRY;
}
}
}
After link is established, Bluetooth stack will report BT_EVENT_LINK_USER_CONFIRMATION_REQ
, which requires the device to confirm.
The device needs to enter CMD_XM_USER_CFM_REQ
to confirm the connection request in
app_customer_bt_handle_cmd()
.
Note
When cfm
is 0x01, it means confirm request. When cfm
is 0x00, it means reject request.
void app_customer_bt_handle_cmd(uint8_t app_idx, T_CMD_PATH cmd_path, uint8_t *cmd_ptr,
uint16_t cmd_len, uint8_t *ack_pkt)
{
uint16_t cmd_id = (uint16_t)(cmd_ptr[0] | (cmd_ptr[1] << 8));
switch (cmd_id)
{
...
case CMD_XM_USER_CFM_REQ:
{
...
cfm = cmd_ptr[3];
if (cfm == 0x00)
{
gap_br_user_cfm_req_cfm(app_db.br_link[app_index].bd_addr, GAP_CFM_CAUSE_REJECT);
...
}
else if (cfm == 0x01)
{
gap_br_user_cfm_req_cfm(app_db.br_link[app_index].bd_addr, GAP_CFM_CAUSE_ACCEPT);
}
}
break;
}
}
Bluetooth Low Energy
All Bluetooth Low Energy commands are processed in app_cmd_ble_handle
in app_cmd_ble.c
, while events are processed by a number of functions in app_rpt_ble.c
.
Advertising
Advertising is the first step to Bluetooth Low Energy connection (as a peripheral). Furthermore, it can convey a bit of information by itself with scan response.
Create an advertisement.
Go through the command
CMD_XM_LE_ADV_CREATE
inapp_cmd_ble.c
, it calls static functionadv_create
. Theadv_create
function callsble_ext_adv_mgr_init_adv_params()
which creates an advertisement in the lower layer.It also calls
ble_ext_adv_mgr_register_callback()
to get advertisement states from the lower layer. In the end,adv_create
saves advertisement information inp_elem
toble.advs.q. Handle
is the most important member ofp_elem
which was always referenced as a parameter for other commands.static uint8_t adv_create(ADV_PARAMS *p_params) { ADV_Q_ELEM *p_elem = calloc(1, sizeof(*p_elem)); if (p_params->adv_data) { memcpy(p_elem->adv_data, p_params->adv_data, p_params->adv_data_len); p_elem->adv_data_len = p_params->adv_data_len; } if (p_params->scan_rsp) { memcpy(p_elem->scan_rsp, p_params->scan_rsp, p_params->scan_rsp_len); p_elem->scan_rsp_len = p_params->scan_rsp_len; } p_elem->state = BLE_EXT_ADV_MGR_ADV_DISABLED; ble_ext_adv_mgr_init_adv_params(&p_elem->handle, p_params->adv_prop, p_params->interval_min, p_params->interval_max, p_params->own_addr_type, p_params->peer_addr_type, p_params->peer_addr, GAP_ADV_FILTER_ANY, p_elem->adv_data_len, p_elem->adv_data, p_elem->scan_rsp_len, p_elem->scan_rsp, p_params->own_addr); APP_PRINT_TRACE2("app_customer_ble adv_create: adv_data %b, le_single_random_addr %s", TRACE_BINARY(sizeof(p_elem->adv_data), p_elem->adv_data), TRACE_BDADDR(app_cfg_nv.le_single_random_addr)); /* set adv event handle callback for further process*/ ble_ext_adv_mgr_register_callback(adv_callback, p_elem->handle); os_queue_in(&ble.advs.q, p_elem); //save adv information by p_elem in ble.advs.q return p_elem->handle; }
Start an advertisement.
Glance over the
CMD_XM_LE_START_ADVERTISING
command, and you will find a wrapper function calledadv_start
, which requires a handle and triggersble_ext_adv_mgr_enable
to enable advertising.static bool adv_start(uint8_t handle, uint16_t duration_10ms) { ADV_Q_ELEM *p_adv_elem = find_adv_elem_by_hdl(handle); if (p_adv_elem) { if (p_adv_elem->state == BLE_EXT_ADV_MGR_ADV_DISABLED) { if (ble_ext_adv_mgr_enable(handle, duration_10ms) == GAP_CAUSE_SUCCESS) { return true; } else { return false; } } else { APP_PRINT_TRACE0("customer_adv_start: Already started"); return true; } } return false; }
Check the state of an advertisement.
As the description above,
adv_callback
registered byble_ext_adv_mgr_register_callback()
will check advertisement states from the lower layer. In the case ofBLE_EXT_ADV_STATE_CHANGE
, it gets the advertising state fromcb_data.p_ble_state_change->state
. The enumeration definition is as follows:typedef enum { BLE_EXT_ADV_MGR_ADV_DISABLED,/**< when call api ble_ext_adv_mgr_disable, the application adv state will be set to BLE_EXT_ADV_MGR_ADV_DISABLED*/ BLE_EXT_ADV_MGR_ADV_ENABLED, /**< when call api ble_ext_adv_mgr_enable, the application adv state will be set to BLE_EXT_ADV_MGR_ADV_ENABLED*/ } T_BLE_EXT_ADV_MGR_STATE;
At last, the
adv_callback
function will update the state inp_elem
inble.advs.q
.if (p_adv_elem) { p_adv_elem->state = cb_data.p_ble_state_change->state; ...... }
Scan response.
Scan response is set as a parameter for
CMD_XM_LE_ADV_CREATE
.
Connection Establishment
The connection establishment process involves two flows, corresponding to the two roles: Peripheral and Central.
Connection establishments for Peripheral.
Peripheral means the device is advertising when creating a connection. The event
EVENT_XM_LE_CON_STATE
will report a connection state (LE_LINK_STATE
). The enumeration is described below. Besides, it also gives the connection parameters such asconn_interval
,conn_latency
andsup_tout
.typedef enum { LE_LINK_STATE_DISCONNECTED, LE_LINK_STATE_CONNECTING, LE_LINK_STATE_CONNECTED, LE_LINK_STATE_DISCONNECTING, } LE_LINK_STATE;
void app_rpt_ble_conn_cmpl(T_APP_LE_LINK *p_link) { ...... le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &rpt.conn_interval, p_link->conn_id); le_get_conn_param(GAP_PARAM_CONN_LATENCY, &rpt.conn_latency, p_link->conn_id); le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &rpt.sup_tout, p_link->conn_id); app_report_event(CMD_PATH_UART, EVENT_XM_LE_CON_STATE, 0, (uint8_t *)&rpt, sizeof(rpt)); }
Scanning for Central.
Central means that the device should scan advertisements from Peripheral and then initiate connection creation.
Ble_scan_start
starts scanning for Peripheral’s advertisements with scan parameters and a callback to get scan information. The example code is as follows:void app_lea_ini_scan_start(void) { APP_PRINT_INFO0("app_ble_scan_start"); BLE_SCAN_PARAM param; param.own_addr_type = GAP_LOCAL_ADDR_LE_PUBLIC; param.phys = GAP_EXT_SCAN_PHYS_1M_BIT; param.ext_filter_policy = GAP_SCAN_FILTER_ANY; param.ext_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; param.scan_param_1m.scan_type = GAP_SCAN_MODE_PASSIVE; param.scan_param_1m.scan_interval = 0x140; param.scan_param_1m.scan_window = 0xD0; param.scan_param_coded.scan_type = GAP_SCAN_MODE_PASSIVE; param.scan_param_coded.scan_interval = 0x0050; param.scan_param_coded.scan_window = 0x0025; if (ble_scan_start(&app_lea_ini_scan_handle, app_lea_ini_scan_cb, ¶m, NULL)) { app_lea_clear_scan_dev(); } }
The scan results are reported in the callback registered by
ble_scan_start
. The scan information is defined inBLE_SCAN_EVT_DATA
.typedef union { T_LE_EXT_ADV_REPORT_INFO *report; } BLE_SCAN_EVT_DATA;
Connection establishments for Central.
Typically, a connection is initiated after obtaining the scan information of the desired device from the aforementioned scanning process.
Le_connect
inCMD_LE_CREATE_CONN
initiates a connection and the key parameter isbd_addr
received fromT_LE_EXT_ADV_REPORT_INFO
. The connection state reporting is the same as described in establishments for peripheral.
Audio Tone Play
When configuring audio tone/VP playback, it is necessary to check the index in the MCUConfig Tool first, and initialize the index pointed to by VP in app_audio_tone_cfg_init()
. The tone index must correspond to the tone type parameters.
The index position in the MCUConfig Tool is shown below.
void app_audio_tone_cfg_init(void)
{
memset(&app_audio_tone_cfg, TONE_INVALID_INDEX, sizeof(T_APP_AUDIO_TONE_CFG));
app_audio_tone_cfg.tone_link_connected = 0x8c;
app_audio_tone_cfg.tone_hf_call_in = 0x8d;
app_audio_tone_cfg.tone_pairing = 0x90;
app_audio_tone_cfg.tone_link_disconnect = 0x97;
app_audio_tone_cfg.tone_power_off = 0x9b;
app_audio_tone_cfg.tone_power_on = 0x9c;
}
Users can play VP by calling app_audio_tone_type_play()
, where tone_type
corresponds to T_APP_AUDIO_TONE_TYPE
, and TONE_POWER_ON
can be selected as the power on tone. The tone_index
corresponds to the index in app_audio_tone_cfg
above. According to the size of VOICE_PROMPT_INDEX
and tone_index
, it will be judged to ringtone_play()
or voice_prompt_play()
. If TONE_POWER_ON
is selected, it will go to voice_prompt_play()
.
Note
If a new WAV file is placed under the voice prompt folder path (tool\MCUConfigTool-vx.xxx.xxx.x-Common_SDK\Voice Prompt
), it may be inserted between the existing indexes, which will cause the index in the tool to change and not correspond to the index in the code. Therefore, the code index needs to be modified based on the index in the tool.
typedef enum
{
TONE_POWER_ON, //0x00
TONE_POWER_OFF, //0x01
...
} T_APP_AUDIO_TONE_TYPE;
#define VOICE_PROMPT_INDEX 0x80
#define TONE_INVALID_INDEX 0xFF
bool app_audio_tone_type_play(T_APP_AUDIO_TONE_TYPE tone_type, bool flush, bool relay)
{
bool ret = false;
uint8_t tone_index = TONE_INVALID_INDEX;
int8_t check_result = 0;
...
tone_index = app_audio_get_tone_index(tone_type);
check_result = app_audio_tone_play_check(tone_type, tone_index);
APP_PRINT_INFO6("app_audio_tone_type_play: tone_type 0x%02x, tone_index 0x%02x, state=%d, index=0x%02x, flush=%d, check_result = %d",
tone_type,
tone_index,
app_db.tone_vp_status.state,
app_db.tone_vp_status.index,
flush,
check_result);
...
if (tone_index < VOICE_PROMPT_INDEX)
{
if (flush)
{
ringtone_cancel(tone_index, true);
}
ret = ringtone_play(tone_index, relay);
}
else if (tone_index < TONE_INVALID_INDEX)
{
if (flush)
{
voice_prompt_cancel(tone_index - VOICE_PROMPT_INDEX, true);
}
ret = voice_prompt_play(tone_index - VOICE_PROMPT_INDEX,
(T_VOICE_PROMPT_LANGUAGE_ID)app_cfg_nv.voice_prompt_language,
relay);
}
return ret;
}
For example, users can use it in app_mmi.c
. When using the mmi pwron
CMD to boot, call app_audio_tone_type_play()
in case MMI_DEV_POWER_ON
, fill in the parameters with TONE_POWER_ON
, and then the VP can be played during the boot operation.
case MMI_DEV_POWER_ON:
{
if (app_db.device_state == APP_DEVICE_STATE_OFF_ING)
{
if (app_bt_policy_get_b2s_connected_num())
{
app_bt_policy_disconnect_all_link();
}
app_mmi_modify_reboot_check_times(REBOOT_CHECK_POWER_ON_MAX_TIMES);
}
else if (app_db.device_state == APP_DEVICE_STATE_OFF)
{
if (!app_db.is_long_press_power_on_play_vp && !mp_hci_test_mode_is_running())
{
app_audio_tone_type_play(TONE_POWER_ON, false, false);
}
app_db.is_long_press_power_on_play_vp = false;
sys_mgr_power_on();
}
}
break;
Bluetooth Audio Transmitter
Source Play
Source play function, which can transmit MIC or line-in signal to BUDs through HFP, A2DP, or BIS.
These two input methods and three output methods can be combined in various ways by set_route_in
and set_route_out
.
The file path of the source play function is: src\sample\bt_audio_trx\source_play
.
The functions of each file are as follows:
app_src_play.c
includes selection and switching of source play input source and output source, and play/stop of output source.app_src_play_a2dp.c
includes processing when the output source is A2DP.app_src_play_hfp.c
includes processing when the output source is HFP.app_src_play_cmd.c
encapsulates the APIs mentioned above as commands.
The input and output paths are defined in the following structures in app_src_play.h
:
//input route
typedef enum
{
SOURCE_ROUTE_MIC = 1,
SOURCE_ROUTE_LINE_IN = 2,
SOURCE_ROUTE_USB = 3,
SOURCE_ROUTE_SD_CARD = 4,
SOURCE_ROUTE_INVALID = 0xFF
} T_SOURCE_ROUTE;
//output route
typedef enum
{
PLAY_ROUTE_A2DP = 1,
PLAY_ROUTE_HFP_AG = 2,
PLAY_ROUTE_BIS = 3,
PLAY_ROUTE_CIS = 4,
PLAY_ROUTE_LOCAL = 5,
PLAY_ROUTE_INVALID = 0xFF
} T_PLAY_ROUTE;
MIC/Line-in Source Play Input Route
The MIC/line-in input adopts the record path, the input path can be set by modifying the device
parameter in audio_track_create()
.
The source_play
structure:
static struct
{
T_PLAY_ROUTE play_route;
struct
{
T_SOURCE_ROUTE src_route;
T_AUDIO_TRACK_HANDLE handle;
uint8_t default_volume;
} record;
} source_play
Set and get source input route:
void app_src_play_set_src_route(T_SOURCE_ROUTE src_route)
{
APP_PRINT_INFO1("app_src_play_set_src_route: src_route %d", src_route);
source_play.record.src_route = src_route;
}
//set and get input source route via CMD
void app_src_play_handle_cmd_set(uint8_t app_idx, uint8_t cmd_path, uint8_t *cmd_ptr,
uint16_t cmd_len, uint8_t *ack_pkt)
{
uint16_t cmd_id = (uint16_t)(cmd_ptr[0] | (cmd_ptr[1] << 8));
...
switch (cmd_id)
{
case CMD_SRC_PLAY_SET_SRC_ROUTE:
{
uint8_t src_route = cmd_ptr[2];
app_src_play_set_src_route((T_SOURCE_ROUTE)src_route);
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
case CMD_SRC_PLAY_GET_SRC_ROUTE:
{
ack_pkt[2] = app_src_play_get_src_route();
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
...
}
}
Modify device parameter of audio track due to src_route
.
static void record_start(void)
{
...
if (source_play.record.src_route == SOURCE_ROUTE_MIC)
{
device = AUDIO_DEVICE_IN_MIC;
}
else if (source_play.record.src_route == SOURCE_ROUTE_LINE_IN)
{
device = AUDIO_DEVICE_IN_AUX;
}
}
USB Source Play Input Route
The USB input adopts the pipe path, the input path can be set by modifying the device
parameter in audio_pipe_create()
.
The source_play
structure:
typedef struct
{
T_PLAY_ROUTE play_route;
struct
{
T_SOURCE_ROUTE src_route;
T_AUDIO_PIPE_HANDLE handle;
T_RING_BUFFER src_rbuf;
uint8_t *src_fill_buf;
uint16_t src_fill_len;
uint8_t *snk_drain_buf;
uint8_t default_volume;
uint16_t seq_num;
uint8_t state;
} pipe;
} T_SOURCE_PIPE_PLAY;
Set and get source input route:
void app_src_play_set_src_route(T_SOURCE_ROUTE src_route)
{
APP_PRINT_INFO1("app_src_play_set_src_route: src_route %d", src_route);
source_play.record.src_route = src_route;
}
//set and get input source route via CMD
void app_src_play_handle_cmd_set(uint8_t app_idx, uint8_t cmd_path, uint8_t *cmd_ptr,
uint16_t cmd_len, uint8_t *ack_pkt)
{
uint16_t cmd_id = (uint16_t)(cmd_ptr[0] | (cmd_ptr[1] << 8));
...
switch (cmd_id)
{
case CMD_SRC_PLAY_SET_SRC_ROUTE:
{
uint8_t src_route = cmd_ptr[2];
app_src_play_set_src_route((T_SOURCE_ROUTE)src_route);
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
case CMD_SRC_PLAY_GET_SRC_ROUTE:
{
ack_pkt[2] = app_src_play_get_src_route();
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
...
}
}
SD Card Source Play Input Route
Input format information from SD card that requires the use of file system to read audio files in app_src_play_sd_start(uint8_t play_route)
.
bool app_src_play_sd_start(uint8_t play_route)
{
uint8_t err_code = 0;
T_FILE_FORMAT_INFO file_format_info;
uint32_t playback_offset = 0;
uint16_t name_len = 0;
//select a file TEMP_FILE_NAME_STRING
if (sd.fs_handle == NULL)
{
// init file system and get sd.fs_handle
uint8_t res = app_src_playback_open_and_get_file_info(SINGLE_FILE, (uint8_t *)TEMP_FILE_NAME_STRING,
&name_len, &playback_offset);
if (res != PLAYBACK_SUCCESS)
{
err_code = 1;
goto ERR;
}
}
else
{
uint8_t *p_file_name = audio_fs_get_filename(sd.fs_handle);
name_len = audio_fs_get_filenameLen(sd.fs_handle);
// memcpy((uint8_t *)TEMP_FILE_NAME_STRING, p_file_name, name_len);
playback_offset = audio_fs_get_file_offset(sd.fs_handle);
}
app_src_sd_card_dlps_disable(APP_SD_DLPS_ENTER_CHECK_PLAYING);
app_src_sd_card_power_down_disable(APP_SD_POWER_DOWN_ENTER_CHECK_PLAYBACK);
// read file header to get format for
if (app_src_play_sd_get_file_format(&file_format_info) == false)
{
err_code = 2;
return false;
}
if (play_route == PLAY_ROUTE_INVALID)
{
err_code = 3;
return false;
}
else if (play_route == PLAY_ROUTE_LOCAL)
{
app_src_play_sd_local_start(&file_format_info);
}
else if (play_route == PLAY_ROUTE_BIS ||
play_route == PLAY_ROUTE_CIS)
{
app_src_play_sd_pipe_start(&file_format_info);
}
return true;
ERR:
APP_PRINT_ERROR1("app_src_play_sd_start: err_code %d", -err_code);
return false;
}
MIC/Line-in Source Play Output Route
Similar to input source, source play output route can be set as HFP, A2DP or BIS.
Set and get source output route:
void app_src_play_set_play_route(T_PLAY_ROUTE play_route)
{
APP_PRINT_INFO1("app_src_play_set_play_route: play_route %d", play_route);
source_play.play_route = play_route;
}
//set and get output source route via CMD
void app_src_play_handle_cmd_set(uint8_t app_idx, uint8_t cmd_path, uint8_t *cmd_ptr,
uint16_t cmd_len, uint8_t *ack_pkt)
{
uint16_t cmd_id = (uint16_t)(cmd_ptr[0] | (cmd_ptr[1] << 8));
...
switch (cmd_id)
{
...
case CMD_SRC_PLAY_SET_PLAY_ROUTE:
{
uint8_t play_route = cmd_ptr[2];
app_src_play_set_play_route((T_PLAY_ROUTE)play_route);
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
case CMD_SRC_PLAY_GET_PLAY_ROUTE:
{
ack_pkt[2] = app_src_play_get_play_route();
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
...
}
}
Create and start audio_track
after configurations,
record_read_cb
will process the MIC/line-in input source data to convert to the format specified in the source output route.
static void record_start(void)
{
APP_PRINT_TRACE0("record_start!!");
uint32_t device = 0;
T_AUDIO_FORMAT_INFO format_info;
if (source_play.play_route == PLAY_ROUTE_A2DP)
{
if (!app_src_play_get_a2dp_format((uint8_t *)&format_info))
{
APP_PRINT_ERROR0("record_start: a2dp format info does not exist");
return;
}
app_src_play_print_a2dp_format("record_start", format_info);
}
else if (source_play.play_route == PLAY_ROUTE_HFP_AG)
{
if (!app_src_play_get_hfp_format((uint8_t *)&format_info))
{
APP_PRINT_ERROR0("record_start: hfp format info does not exist");
return;
}
app_src_play_print_hfp_format("record_start", format_info);
}
else if (source_play.play_route == PLAY_ROUTE_BIS)
{
#if BAP_BROADCAST_SOURCE
if (!app_lea_get_data_format((uint8_t *)&format_info))
{
APP_PRINT_ERROR0("record_start: lc3 format info does not exist");
return;
}
#endif
// app_src_play_print_hfp_format("record_start", format_info);
}
else if (source_play.play_route == PLAY_ROUTE_CIS)
{
if (!app_lea_get_data_format((uint8_t *)&format_info))
{
APP_PRINT_ERROR0("record_start: lc3 format info does not exist");
return;
}
}
...
source_play.record.handle = audio_track_create(AUDIO_STREAM_TYPE_RECORD,
AUDIO_STREAM_MODE_NORMAL,
AUDIO_STREAM_USAGE_LOCAL,
format_info,
0,
source_play.record.default_volume,
device,
NULL,
record_read_cb);
if (source_play.record.handle == NULL)
{
APP_PRINT_ERROR0("app_customer_mic_record record_start: handle is NULL");
return;
}
audio_track_start(source_play.record.handle);
}
static bool record_read_cb(T_AUDIO_TRACK_HANDLE handle,
uint32_t *timestamp,
uint16_t *seq_num,
T_AUDIO_STREAM_STATUS *status,
uint8_t *frame_num,
void *buf,
uint16_t required_len,
uint16_t *actual_len)
{
{
mic_dump_record_data("app_mic_record_read_cb", buf, required_len);
uint8_t actual_frame_num = *frame_num;
if (source_play.record.handle)
{
if (source_play.play_route == PLAY_ROUTE_A2DP)
{
uint8_t res = app_src_play_a2dp_handle_data(buf, required_len, actual_frame_num);
}
else if (source_play.play_route == PLAY_ROUTE_HFP_AG)
{
app_src_play_hfp_send_sco(buf, required_len);
}
else if (source_play.play_route == PLAY_ROUTE_BIS ||
source_play.play_route == PLAY_ROUTE_CIS)
{
#if (BAP_BROADCAST_SOURCE || BAP_UNICAST_CLIENT)
app_lea_iso_data_send(buf, required_len, true, *timestamp, *seq_num);
#endif
}
}
}
*actual_len = required_len;
return true;
}
pipe_encode_cb
will process the USB input source data to convert to the format specified in the source output route.
static void usb_pipe_start(void)
{
T_AUDIO_FORMAT_INFO src_info;
T_AUDIO_FORMAT_INFO snk_info;
uint16_t src_len = 0;
if (source_play.play_route == PLAY_ROUTE_A2DP)
{
if (!app_src_play_get_a2dp_format((uint8_t *)&snk_info))
{
APP_PRINT_ERROR0("usb_pipe_start: a2dp format info does not exist");
return;
}
app_src_play_print_a2dp_format("usb_pipe_start", snk_info);
}
else if (source_play.play_route == PLAY_ROUTE_HFP_AG)
{
if (!app_src_play_get_hfp_format((uint8_t *)&snk_info))
{
APP_PRINT_ERROR0("usb_pipe_start: hfp format info does not exist");
return;
}
app_src_play_print_hfp_format("usb_pipe_start", snk_info);
}
else if (source_play.play_route == PLAY_ROUTE_BIS)
{
#if BAP_BROADCAST_SOURCE
if (!app_lea_get_data_format((uint8_t *)&snk_info))
{
APP_PRINT_ERROR0("usb_pipe_start: lc3 format info does not exist");
return;
}
#endif
// app_src_play_print_hfp_format("record_start", format_info);
}
else if (source_play.play_route == PLAY_ROUTE_CIS)
{
if (!app_lea_get_data_format((uint8_t *)&snk_info))
{
APP_PRINT_ERROR0("usb_pipe_start: lc3 format info does not exist");
return;
}
}
else
{
APP_PRINT_ERROR1("usb_pipe_start: play_route", source_pipe_play.play_route);
return;
}
if (source_pipe_play.pipe.handle != NULL)
{
APP_PRINT_ERROR0("usb_pipe_start: already started");
return;
}
src_info.type = AUDIO_FORMAT_TYPE_PCM;
src_info.frame_num = 1;
src_info.attr.pcm.sample_rate = 48000;
/*FIXME: frame_length due to snk_format*/
src_info.attr.pcm.chann_num = 2;
src_info.attr.pcm.bit_width = 16;
APP_PRINT_INFO1("usb_pipe_start: snk type %x", snk_info.type);
switch (snk_info.type)
{
case AUDIO_FORMAT_TYPE_LC3:
{
src_len = 512;
snk_info.frame_num = 1;
src_lea_db.lea_data_buf = calloc(1, snk_info.attr.lc3.frame_length * 2);
if (src_lea_db.lea_data_buf == NULL)
{
APP_PRINT_ERROR0("usb_pipe_start: lea_data_buf NULL");
return;
}
src_lea_db.frame_len = snk_info.attr.lc3.frame_length;
if (snk_info.attr.lc3.frame_duration == AUDIO_LC3_FRAME_DURATION_7_5_MS)
{
src_lea_db.frame_duration = 7500;
}
else
{
src_lea_db.frame_duration = 10000;
}
}
break;
case AUDIO_FORMAT_TYPE_SBC:
{
src_len = 512;
snk_info.frame_num = 1;
}
break;
case AUDIO_FORMAT_TYPE_MSBC:
{
src_len = 720;
snk_info.frame_num = 1;
}
break;
default:
return;
}
/*Frame length per channel in octets for encoding or decoding.*/
src_info.attr.pcm.frame_length = src_len / src_info.attr.pcm.chann_num;
source_pipe_play.pipe.src_fill_buf = calloc(1, src_len);
if (source_pipe_play.pipe.src_fill_buf == NULL)
{
APP_PRINT_ERROR0("usb_pipe_start: src_fill_buf NULL");
usb_pipe_buf_release();
return;
}
source_pipe_play.pipe.src_fill_len = src_len;
source_pipe_play.pipe.snk_drain_buf = calloc(1, PIPE_DRAIN_BUF_LEN);
if (source_pipe_play.pipe.snk_drain_buf == NULL)
{
APP_PRINT_ERROR0("usb_pipe_start: snk_drain_buf NULL");
usb_pipe_buf_release();
return;
}
source_pipe_play.pipe.handle = audio_pipe_create(src_info,
snk_info,
source_pipe_play.pipe.default_volume,
pipe_encode_cb);
if (!source_pipe_play.pipe.handle)
{
APP_PRINT_ERROR0("usb_pipe_start: pipe.handle NULL");
usb_pipe_buf_release();
return;
}
}
static bool pipe_encode_cb(T_AUDIO_PIPE_HANDLE handle, T_AUDIO_PIPE_EVENT event, uint32_t param)
{
if (handle != source_pipe_play.pipe.handle)
{
return true;
}
if ((event != AUDIO_PIPE_EVENT_DATA_IND) && (event != AUDIO_PIPE_EVENT_DATA_FILLED))
{
APP_PRINT_INFO2("pipe_encode_cb: handle %x event %x", handle, event);
}
switch (event)
{
case AUDIO_PIPE_EVENT_RELEASED:
{
source_pipe_play.pipe.state = PIPE_STATE_IDLE;
usb_pipe_buf_release();
source_pipe_play.pipe.handle = NULL;
}
break;
case AUDIO_PIPE_EVENT_CREATED:
{
source_pipe_play.pipe.state = PIPE_STATE_CREATED;
audio_pipe_start(source_pipe_play.pipe.handle);
}
break;
case AUDIO_PIPE_EVENT_STARTED:
{
source_pipe_play.pipe.state = PIPE_STATE_STARTED;
}
break;
case AUDIO_PIPE_EVENT_STOPPED:
{
source_pipe_play.pipe.state = PIPE_STATE_CREATED;
}
break;
case AUDIO_PIPE_EVENT_DATA_IND:
{
pipe_handle_data_ind();
}
break;
case AUDIO_PIPE_EVENT_DATA_FILLED:
{
pipe_handle_data_filled();
}
break;
case AUDIO_PIPE_EVENT_MIXED:
break;
case AUDIO_PIPE_EVENT_DEMIXED:
break;
default:
break;
}
return true;
}
When the play_route
is set to A2DP, record_read_cb
will call app_src_play_a2dp_handle_data
,
the A2DP output format will be saved by app_src_play_save_a2dp_format
when Bluetooth reports BT_EVENT_A2DP_CONFIG_CMPL
in app_audio_bt_cback
.
void app_src_play_save_a2dp_format(uint8_t *format_info)
{
if (!a2dp_play.a2dp_format_ready)
{
memcpy(&a2dp_play.a2dp_format, format_info, sizeof(T_AUDIO_FORMAT_INFO));
a2dp_play.a2dp_format.attr.sbc.bitpool = 0x22;
a2dp_play.a2dp_format_ready = true;
}
app_src_play_print_a2dp_format("app_src_play_save_a2dp_format: ",
a2dp_play.a2dp_format);
}
uint16_t app_src_play_a2dp_handle_data(uint8_t *p_data, uint16_t data_len, uint8_t frame_number)
{
uint16_t res = SRC_PLAY_A2DP_SUCCESS;
if (ring_buffer_write(&a2dp_play.ring_buf, p_data, data_len))
{
a2dp_play.num_frame_buf++;
}
else
{
res = SRC_PLAY_A2DP_ERR_RINGBUF;
APP_PRINT_ERROR0("xiaoai_process_voice_data: xiaoai_record.voice_buf is full, drop pkt");
}
if (a2dp_play.num_frame_buf == A2DP_PACKET_FRAME_NUM)
{
a2dp_play.num_frame_buf = 0;
uint16_t data_len_to_send = data_len * A2DP_PACKET_FRAME_NUM;
uint8_t *p_data_to_send = malloc(data_len_to_send);
if (p_data_to_send)
{
uint32_t actual_len = ring_buffer_read(&a2dp_play.ring_buf, data_len_to_send, p_data_to_send);
APP_PRINT_INFO1("app_src_play_a2dp_handle_data: actual_len %d sent", actual_len);
res = app_src_play_a2dp_send_data(p_data_to_send, data_len_to_send, A2DP_PACKET_FRAME_NUM);
free(p_data_to_send);
}
else
{
res = SRC_PLAY_A2DP_ERR_RAM;
}
}
return res;
}
When the play_route
is set to HFP, record_read_cb
will call app_src_play_hfp_send_sco
.
The HFP output format will be saved by app_src_play_save_hfp_format
when Bluetooth reports BT_EVENT_SCO_CONN_CMPL
in app_audio_bt_cback
.
void app_src_play_save_hfp_format(uint8_t *format_info)
{
if (!hfp_play.hfp_format_ready)
{
memcpy(&hfp_play.hfp_format, format_info, sizeof(T_AUDIO_FORMAT_INFO));
hfp_play.hfp_format_ready = true;
}
app_src_play_print_hfp_format("app_src_play_save_hfp_format: ",
hfp_play.hfp_format);
}
void app_src_play_hfp_send_sco(uint8_t *p_data, uint16_t len)
{
uint8_t active_hf_idx = app_hfp_get_active_idx();
T_APP_BR_LINK *p_link;
p_link = app_link_find_br_link(app_db.br_link[active_hf_idx].bd_addr);
if (p_link == NULL)
{
APP_PRINT_ERROR0("app_src_play_hfp_send_sco: no br link found");
return;
}
hfp_seq_num++;
if (p_link->sco.duplicate_fst_data)
{
p_link->sco.duplicate_fst_data = false;
bt_sco_data_send(p_link->bd_addr, hfp_seq_num - 1, p_data, len);
}
bt_sco_data_send(p_link->bd_addr, hfp_seq_num, p_data, len);
}
When the play_route
is set to BIS/CIS, record_read_cb
will call app_lea_iso_data_send
.
The BIS output format will be saved by app_lea_save_data_format
in app_lea_handle_bis_data_path_setup
.
The CIS output format will be saved by app_lea_save_data_format
in app_lea_handle_cis_data_path_setup
.
static void app_lea_save_data_format(T_APP_LEA_ISO_CHANN *p_iso_chann)
{
save_format.type = AUDIO_FORMAT_TYPE_LC3;
codec_max_sdu_len_get(&p_iso_chann->codec_data, &p_iso_chann->iso_sdu_len);
//always get two-channel data but send data according to bis/cis num
save_format.attr.lc3.chann_location = AUDIO_CHANNEL_LOCATION_SL | AUDIO_CHANNEL_LOCATION_SR;
save_format.attr.lc3.sample_rate = app_lea_get_sample_rate(p_iso_chann);
save_format.attr.lc3.frame_length = p_iso_chann->codec_data.octets_per_codec_frame;
if (p_iso_chann->codec_data.frame_duration == FRAME_DURATION_CFG_7_5_MS)
{
save_format.attr.lc3.frame_duration = AUDIO_LC3_FRAME_DURATION_7_5_MS;
}
else
{
save_format.attr.lc3.frame_duration = AUDIO_LC3_FRAME_DURATION_10_MS;
}
save_format.attr.lc3.presentation_delay = p_iso_chann->presentation_delay;
}
void app_lea_iso_data_send(uint8_t *p_data, uint16_t len, bool ext_flag, uint32_t ts, uint16_t seq)
{
T_GAP_CAUSE cause = GAP_CAUSE_SUCCESS;
T_APP_LEA_ISO_CHANN *p_iso_chann = NULL;
uint8_t chnl_cnt = 0;
uint32_t time_stamp = 0;
uint16_t seq_num = 0;
for (uint8_t i = 0; i < app_db.iso_input_queue.count; i++)
{
p_iso_chann = (T_APP_LEA_ISO_CHANN *)os_queue_peek(&app_db.iso_input_queue, i);
if (p_iso_chann->codec_data.audio_channel_allocation == AUDIO_LOCATION_MONO)
{
chnl_cnt = 1;
}
else
{
chnl_cnt = __builtin_popcount(p_iso_chann->codec_data.audio_channel_allocation);
}
if (ext_flag)
{
time_stamp = ts;
seq_num = seq;
}
else
{
time_stamp = (p_iso_chann->time_stamp + p_iso_chann->pkt_seq_num) *
(p_iso_chann->sdu_interval * 1000);
seq_num = p_iso_chann->pkt_seq_num;
}
if (chnl_cnt == 2)
{
cause = gap_iso_send_data(p_data,
p_iso_chann->iso_conn_handle,
len,
false,
time_stamp,
seq_num);
}
else if (chnl_cnt == 1)
{
if (p_iso_chann->codec_data.audio_channel_allocation & (AUDIO_LOCATION_FL |
AUDIO_LOCATION_SIL))
{
cause = gap_iso_send_data(p_data,
p_iso_chann->iso_conn_handle,
len / 2,
0,
time_stamp,
seq_num);
}
else
{
cause = gap_iso_send_data(p_data + (len / 2),
p_iso_chann->iso_conn_handle,
len / 2,
0,
time_stamp,
seq_num);
}
}
p_iso_chann->pkt_seq_num++;
if (cause != GAP_CAUSE_SUCCESS)
{
APP_PRINT_ERROR1("app_lea_iso_data_send: failed, cause 0x%x", cause);
}
}
return;
}
SD Card Source Play Output Route
Similar to the input source, the SD card source play output route can be set as local play, BIS, or CIS.
bool app_src_play_sd_start(uint8_t play_route)
{
...
if (play_route == PLAY_ROUTE_INVALID)
{
err_code = 3;
return false;
}
else if (play_route == PLAY_ROUTE_LOCAL)
{
app_src_play_sd_local_start(&file_format_info);
}
else if (play_route == PLAY_ROUTE_BIS ||
play_route == PLAY_ROUTE_CIS)
{
app_src_play_sd_pipe_start(&file_format_info);
}
}
If choosing the play route as PLAY_ROUTE_LOCAL
, the local start is set in app_src_play_sd_local_start()
.
static void app_src_play_sd_local_start(T_FILE_FORMAT_INFO *file_format)
{
if (sd.local_play.handle != NULL)
{
audio_track_release(sd.local_play.handle);
sd.local_play.handle = NULL;
}
T_LOCALPLAY_SET_INFO set_play_info;
app_src_play_sd_set_local_play_info(file_format, &set_play_info);
sd.local_play.play_monitor.put_data_time_ms = set_play_info.play_duration;
sd.local_play.play_monitor.preq_pkts = set_play_info.preq_pkts;
sd.local_play.handle = audio_track_create(AUDIO_STREAM_TYPE_PLAYBACK, //stream_type
AUDIO_STREAM_MODE_NORMAL, // mode
AUDIO_STREAM_USAGE_SNOOP, // usage
file_format->format_info, //format_info
sd.local_play.volume, //volume
0,
AUDIO_DEVICE_OUT_SPK, // device
NULL,
NULL);
if (sd.local_play.handle != NULL)
{
audio_track_latency_set(sd.local_play.handle, set_play_info.latency, true);
audio_track_threshold_set(sd.local_play.handle, set_play_info.upper_level,
set_play_info.lower_level);
sd.local_play.play_monitor.delay_stop_ms = set_play_info.latency;
}
sd.op_next_action = SD_STOPPED_IDLE_ACTION;
// app_src_playback_volume_set(sd.local_play.volume);
sd.local_play.play_state = SD_PLAY_STATE_PLAY;
sd.local_play.play_monitor.local_track_state = PLAYBACK_TRACK_STATE_CLEAR;
sd.local_play.play_monitor.sec_track_state = PLAYBACK_TRACK_STATE_CLEAR;
sd.local_play.play_monitor.buffer_state = PLAYBACK_BUF_NORMAL;
audio_track_start(sd.local_play.handle);
}
If choose to play the route as PLAY_ROUTE_BIS
or PLAY_ROUTE_CIS
, the route start is set in app_src_play_sd_pipe_start()
.
void app_src_play_sd_pipe_start(T_FILE_FORMAT_INFO *file_format)
{
T_AUDIO_FORMAT_INFO src_info = file_format->format_info;
T_AUDIO_FORMAT_INFO snk_info;
T_PLAY_ROUTE play_route = app_src_play_get_play_route();
if (play_route == PLAY_ROUTE_A2DP)
{
// TODO: Support A2DP TX
return;
}
else if (play_route == PLAY_ROUTE_HFP_AG)
{
// TODO: Support HFP TX
return;
}
#if (BAP_BROADCAST_SOURCE || BAP_UNICAST_CLIENT)
else if (play_route == PLAY_ROUTE_BIS || play_route == PLAY_ROUTE_CIS)
{
if (!app_lea_get_data_format(LEA_CODEC_DIR_ENCODE, &snk_info))
{
APP_PRINT_ERROR0("app_src_play_sd_pipe_start: lc3 format info does not exist");
return;
}
uint8_t chnl_cnt;
if (snk_info.attr.lc3.chann_location == AUDIO_LOCATION_MONO)
{
chnl_cnt = 1;
}
else
{
chnl_cnt = __builtin_popcount(snk_info.attr.lc3.chann_location);
}
lea_tx_mgr.pkt_len = snk_info.attr.lc3.frame_length * chnl_cnt;
lea_tx_mgr.p_lea_send_buf = calloc(1, lea_tx_mgr.pkt_len);
if (lea_tx_mgr.p_lea_send_buf == NULL)
{
APP_PRINT_ERROR0("app_src_play_sd_pipe_start: p_lea_send_buf malloc fail");
return;
}
lea_tx_mgr.target_threshold = 5; // frame_cnt
lea_tx_mgr.pre_fill_num = 4;
APP_PRINT_INFO2("app_src_play_sd_pipe_start: pkt_len %d, target_threshold %d",
lea_tx_mgr.pkt_len, lea_tx_mgr.target_threshold);
if (snk_info.attr.lc3.frame_duration == AUDIO_LC3_FRAME_DURATION_10_MS)
{
lea_tx_mgr.timer_duration = 10000;
}
else
{
lea_tx_mgr.timer_duration = 7500;
}
}
#endif
src_info.frame_num = 1;
snk_info.frame_num = 1;
if (sd.pipe_play.handle == NULL)
{
sd.pipe_play.handle = audio_pipe_create(AUDIO_STREAM_MODE_NORMAL,
src_info, snk_info,
sd.pipe_play.volume,
app_src_play_sd_pipe_cback);
}
sd.op_next_action = SD_STOPPED_IDLE_ACTION;
}
Audio track/pipe will be created after calling app_src_play_sd_local_start()
/app_src_play_sd_pipe_start()
, they will be released in the calling of app_src_play_sd_local_stop()
and app_src_play_sd_pipe_stop()
.
void app_src_play_sd_stop(uint8_t play_route)
{
if (play_route == PLAY_ROUTE_LOCAL)
{
app_src_play_sd_local_stop();
}
else if (play_route == PLAY_ROUTE_BIS ||
play_route == PLAY_ROUTE_CIS)
{
app_src_play_sd_pipe_stop();
}
}
static void app_src_play_sd_local_stop(void)
{
uint8_t res = PLAYBACK_SUCCESS;
audio_fs_decode_deinit();
app_stop_timer(&timer_idx_sd_local_put_data);
sd.local_play.play_state = SD_PLAY_STATE_IDLE;
if (sd.local_play.handle != NULL)
{
sd.local_play.play_monitor.local_track_state = PLAYBACK_TRACK_STATE_CLEAR;
audio_track_release(sd.local_play.handle);
}
if (sd.fs_handle != NULL)
{
if (0 != audio_fs_close(sd.fs_handle))
{
// return;
}
sd.fs_handle = NULL;
}
app_src_sd_card_dlps_enable(APP_SD_DLPS_ENTER_CHECK_PLAYING);
// TODO: FIX ME
// app_sd_card_power_down_enable(APP_SD_POWER_DOWN_ENTER_CHECK_PLAYBACK);
}
static void app_src_play_sd_pipe_stop(void)
{
audio_fs_decode_deinit();
if (sd.pipe_play.handle != NULL)
{
audio_pipe_release(sd.pipe_play.handle);
}
if (sd.fs_handle != NULL)
{
if (0 != audio_fs_close(sd.fs_handle))
{
// return;
}
sd.fs_handle = NULL;
}
app_src_sd_card_dlps_enable(APP_SD_DLPS_ENTER_CHECK_PLAYING);
}
When the end of the file is reached, the file system also releases the handle created to read audio file information.
Source Play Start/Stop
Source play start/stop can be divided into two parts, input route start/stop and output route start/stop.
When source play input route needs to be activated:
bool app_src_play_route_in_start(void)
{
bool result = false;
if (source_play.src_route == SOURCE_ROUTE_USB)
{
if (usb_ds_attr.active)
{
result = usb_encode_pipe_start();
}
if (usb_us_attr.active)
{
result = usb_decode_pipe_start();
}
}
#if F_APP_SD_CARD_PLAY
else if (source_play.src_route == SOURCE_ROUTE_SD_CARD)
{
result = app_src_play_sd_start(source_play.play_route);
}
#endif
#if F_APP_INTEGRATED_TRANSCEIVER
else if (source_play.src_route == SOURCE_ROUTE_A2DP)
{
result = app_src_play_pipe_start(source_play.play_route);
}
#endif
else
{
result = record_start();
}
return result;
}
When the source play input route needs to be stopped, it means releasing the started audio_track
and freeing the record handle:
void app_src_play_route_in_stop(void)
{
if (source_play.src_route == SOURCE_ROUTE_USB)
{
if (usb_ds_attr.active)
{
usb_encode_pipe_stop();
}
if (usb_us_attr.active)
{
usb_decode_pipe_stop();
}
}
#if F_APP_SD_CARD_PLAY
else if (source_play.src_route == SOURCE_ROUTE_SD_CARD)
{
app_src_play_sd_stop(source_play.play_route);
}
#endif
#if F_APP_INTEGRATED_TRANSCEIVER
else if (source_play.src_route == SOURCE_ROUTE_A2DP)
{
app_src_play_pipe_stop();
}
#endif
else
{
record_stop();
}
}
When source play output route needs to be activated, depending on the output format, specific processing is required:
bool app_src_play_a2dp_start_req(void)
{
APP_PRINT_INFO0("app_src_play_a2dp_start_req");
return bt_a2dp_stream_start_req(a2dp_play.sink_addr);
}
bool app_src_play_hfp_start_req(void)
{
APP_PRINT_INFO0("app_src_play_hfp_start_req");
return bt_hfp_ag_audio_connect_req(hfp_play.hf_addr);
}
bool app_lea_bsrc_start(void)
{
if (app_db.bsrc_db.source_handle == NULL)
{
APP_PRINT_ERROR0("app_lea_bsrc_start: init bis firstly!");
return false;
}
app_db.bsrc_db.prefer_state = BROADCAST_SOURCE_STATE_STREAMING;
app_lea_bsrc_target_state();
return true;
}
bool app_lea_ini_cis_media_start(uint8_t group_idx)
{
bool ret = false;
if (group_idx < app_db.group_handle_queue.count)
{
T_APP_LEA_GROUP_INFO *p_group = (T_APP_LEA_GROUP_INFO *)os_queue_peek(&app_db.group_handle_queue,
group_idx);
if (p_group)
{
ret = app_lea_ini_start_media(p_group->group_handle);
}
}
return ret;
}
//start in cases
bool app_src_play_route_out_start(void)
{
bool result = false;
switch (source_play.play_route)
{
case PLAY_ROUTE_A2DP:
{
result = app_src_play_a2dp_start_req();
}
break;
case PLAY_ROUTE_HFP_AG:
{
result = app_src_play_hfp_start_req();
}
break;
#if BAP_BROADCAST_SOURCE
case PLAY_ROUTE_BIS:
{
result = app_lea_bsrc_start();
}
break;
#endif
#if BAP_UNICAST_CLIENT
case PLAY_ROUTE_CIS:
{
result = app_lea_ini_cis_media_start(0);
}
#endif
case PLAY_ROUTE_LOCAL:
{
// DO Nothing
result = true;
}
case PLAY_ROUTE_MULTI_A2DP:
{
result = app_src_play_a2dp_start_req();
}
break;
default:
break;
}
return result;
}
When the source play output route needs to be stopped, depending on the output format, specific processing is required:
void app_src_play_a2dp_stop(void)
{
APP_PRINT_TRACE0("app_src_play_a2dp_stop");
a2dp_play.num_frame_buf = 0;
ring_buffer_clear(&a2dp_play.ring_buf);
if (a2dp_play.a2dp_state != A2DP_STATE_STREAM_STOP)
{
bt_a2dp_stream_suspend_req(a2dp_play.sink_addr);
}
app_dlps_enable(APP_DLPS_ENTER_CHECK_PLAYBACK);
}
void app_src_play_hfp_stop(void)
{
APP_PRINT_TRACE0("app_src_play_hfp_stop");
bt_hfp_ag_audio_disconnect_req(hfp_play.hf_addr);
}
bool app_lea_bsrc_stop(bool release)
{
if (app_db.bsrc_db.source_handle == NULL)
{
return false;
}
if (release)
{
app_db.bsrc_db.prefer_state = BROADCAST_SOURCE_STATE_IDLE;
}
else
{
if (app_db.bsrc_db.prefer_state != BROADCAST_SOURCE_STATE_IDLE)
{
app_db.bsrc_db.prefer_state = BROADCAST_SOURCE_STATE_CONFIGURED;
}
}
app_lea_bsrc_target_state();
return true;
}
bool app_lea_ini_cis_stream_stop(uint8_t group_idx, bool release)
{
bool ret = false;
if (group_idx < app_db.group_handle_queue.count)
{
T_APP_LEA_GROUP_INFO *p_group = (T_APP_LEA_GROUP_INFO *)os_queue_peek(&app_db.group_handle_queue,
group_idx);
if (p_group)
{
if (release)
{
ret = app_lea_ini_unicast_audio_release(p_group->group_handle);
}
else
{
ret = app_lea_ini_unicast_audio_stop(p_group->group_handle, 0);
}
}
}
return ret;
}
//stop in cases
void app_src_play_route_out_stop(void)
{
switch (source_play.play_route)
{
case PLAY_ROUTE_A2DP:
{
app_src_play_a2dp_stop();
}
break;
case PLAY_ROUTE_HFP_AG:
{
app_src_play_hfp_stop();
}
break;
#if BAP_BROADCAST_SOURCE
case PLAY_ROUTE_BIS:
{
app_lea_bsrc_stop(true);
}
break;
#endif
#if BAP_UNICAST_CLIENT
case PLAY_ROUTE_CIS:
{
app_lea_ini_cis_stream_stop(0, true);
}
#endif
case PLAY_ROUTE_MULTI_A2DP:
{
result = app_src_play_a2dp_stop();
}
break;
default:
break;
}
}
The APIs mentioned above are called in app_src_play_handle_cmd_set
,
User can fill in the corresponding cmd_id
in the ACI Host CLI Tool
according to the following case to perform operations:
void app_src_play_handle_cmd_set(uint8_t app_idx, uint8_t cmd_path, uint8_t *cmd_ptr,
uint16_t cmd_len, uint8_t *ack_pkt)
{
uint16_t cmd_id = (uint16_t)(cmd_ptr[0] | (cmd_ptr[1] << 8));
...
switch (cmd_id)
{
...
case CMD_SRC_PLAY_ROUTE_IN_START:
{
app_src_play_route_in_start();
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
case CMD_SRC_PLAY_ROUTE_IN_STOP:
{
app_src_play_route_in_stop();
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
case CMD_SRC_PLAY_ROUTE_OUT_START:
{
if (app_src_play_route_out_start())
{
ack_pkt[2] = CMD_SET_STATUS_COMPLETE;
}
else
{
ack_pkt[2] = CMD_SET_STATUS_SCENARIO_ERROR;
}
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
case CMD_SRC_PLAY_ROUTE_OUT_STOP:
{
app_src_play_route_out_stop();
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
default:
break;
}
}
LE Audio Initiator - BIS
Bluetooth Low Energy Audio CAP roles can be divided into Acceptor, Initiator, and Commander. In transmitter application, Initiator role is supported, which can transmit BIS or transmit and receive CIS.
In this chapter, the design SPEC for BIS will be presented.
Initialization
Initialization is performed through the function of app_lea_profile_init()
, including configuration
of LE Audio parameters, initialization of BAP and CAP, as well as the necessary data processing setup.
//app_lea_ini_profile.c
void app_lea_profile_init(void)
{
T_BLE_AUDIO_PARAMS ble_audio_param = {0};
ble_audio_param.evt_queue_handle = audio_evt_queue_handle;
ble_audio_param.io_queue_handle = audio_io_queue_handle;
ble_audio_param.bt_gatt_client_init = (GATT_CLIENT_DISCOV_MODE_REG_SVC_BIT |
GATT_CLIENT_DISCOV_MODE_CCCD_STORAGE_BIT |
GATT_CLIENT_DISCOV_MODE_USE_EXT_CLIENT);
ble_audio_param.acl_link_num = MAX_BLE_LINK_NUM;
ble_audio_param.io_event_type = IO_MSG_TYPE_LE_AUDIO;
ble_audio_init(&ble_audio_param);
app_lea_ini_bap_init();
app_lea_ini_cap_init();
app_lea_audio_data_init();
}
Configure BIS
Before broadcasting data through BIS, it is necessary to initialize the broadcast source parameters.
This can be achieved through the CMD_LEA_BSRC_INIT
command, specifying codec configuration, BIS number,
and ULL mode, among others. For detailed explanations for the command, please refer to ACI_CMD_LEA_BSRC_INIT.
void app_lea_ini_handle_cmd_set(uint8_t app_idx, uint8_t cmd_path, uint8_t *cmd_ptr,
uint16_t cmd_len, uint8_t *ack_pkt)
{
...
switch (cmd_id)
{
...
case CMD_LEA_BSRC_INIT:
{
struct
{
uint16_t cmd_id;
uint8_t codec_cfg;
uint8_t bis_num;
bool encryption;
bool ull_mode;
uint16_t pd;
} __attribute__((packed)) *bis_param = (typeof(bis_param))cmd_ptr;
T_CODEC_CFG_ITEM codec_cfg_type = (T_CODEC_CFG_ITEM)bis_param->codec_cfg;
uint8_t bis_num = bis_param->bis_num;
bool encryption = bis_param->encryption;
app_db.bis_ull_mode = bis_param->ull_mode;
uint16_t presentation_delay = bis_param->pd;
APP_PRINT_TRACE1("app_lea_ini_handle_cmd_set: bis ull mode %d", app_db.cis_ull_mode);
T_QOS_CFG_TYPE qos_type = QOS_CFG_BIS_HIG_RELIABILITY;
if (app_db.bis_ull_mode)
{
qos_type = QOS_CFG_BIS_LOW_LATENCY;
}
app_lea_bsrc_init(codec_cfg_type,
qos_type,
bis_num,
GAP_LOCAL_ADDR_LE_PUBLIC,
encryption,
presentation_delay);
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
...
}
}
Establish BIS
The broadcast source defines several states as below, among which STATE_CONFIGURED_STARTING
,
STATE_CONFIGURED_STOPPING
, STATE_STREAMING_STARTING
and STATE_STREAMING_STOPPING
are intermediate states, while STATE_IDLE
, STATE_CONFIGURED
and STATE_STREAMING
can serve as target states.
typedef enum
{
BROADCAST_SOURCE_STATE_IDLE = 0x00,
BROADCAST_SOURCE_STATE_CONFIGURED_STARTING = 0x01,
BROADCAST_SOURCE_STATE_CONFIGURED = 0x02,
BROADCAST_SOURCE_STATE_CONFIGURED_STOPPING = 0x03,
BROADCAST_SOURCE_STATE_STREAMING_STARTING = 0x04,
BROADCAST_SOURCE_STATE_STREAMING = 0x05,
BROADCAST_SOURCE_STATE_STREAMING_STOPPING = 0x06,
} T_BROADCAST_SOURCE_STATE;
By calling the app_lea_bsrc_start()
API, the broadcast will attempt to transition its state to BROADCAST_SOURCE_STATE_STREAMING
.
bool app_lea_bsrc_start(void)
{
if (app_db.bsrc_db.source_handle == NULL)
{
APP_PRINT_ERROR0("app_lea_bsrc_start: init bis firstly!");
return false;
}
app_db.bsrc_db.prefer_state = BROADCAST_SOURCE_STATE_STREAMING;
app_lea_bsrc_target_state();
return true;
}
Specifically, the module will configure and enable the Extended Advertisement and the Periodic
Advertisement through app_lea_bsrc_config()
, and create BIG through app_lea_bsrc_establish()
.
When the broadcast source successfully transitions to the BROADCAST_SOURCE_STATE_STREAMING
state
(the state changed event could be notified in app_lea_bsrc_sm_cb()
through with
MSG_BROADCAST_SOURCE_STATE_CHANGE
message), the data path will be established by calling
broadcast_source_setup_data_path()
.
void app_lea_bsrc_sm_cb(T_BROADCAST_SOURCE_HANDLE handle, uint8_t cb_type, void *p_cb_data)
{
...
switch (cb_type)
{
case MSG_BROADCAST_SOURCE_STATE_CHANGE:
{
APP_PRINT_INFO2("MSG_BROADCAST_SOURCE_STATE_CHANGE: state %d, cause 0x%x",
p_sm_data->p_state_change->state,
p_sm_data->p_state_change->cause);
app_db.bsrc_db.state = p_sm_data->p_state_change->state;
app_lea_bsrc_target_state();
if (p_sm_data->p_state_change->state == BROADCAST_SOURCE_STATE_STREAMING &&
p_sm_data->p_state_change->cause == GAP_SUCCESS)
{
uint8_t codec_id[5] = {LC3_CODEC_ID, 0, 0, 0, 0};
for (uint8_t i = 0; i < app_db.bsrc_db.group1_bis_num; i++)
{
broadcast_source_setup_data_path(app_db.bsrc_db.source_handle, i + 1,
codec_id, 0, 0, NULL);
}
}
}
break;
...
}
}
Once the data path is successfully established, notifications will also be received in
app_lea_bsrc_sm_cb()
with the message of MSG_BROADCAST_SOURCE_SETUP_DATA_PATH
. In the
app_lea_handle_bis_data_path_setup()
function, data path information is processed and stored in
the form of T_APP_LEA_ISO_CHANN
. Other modules, such as the source play module, can utilize
this information to specify the format for creating audio tracks. This enables data from sources
like MIC, line-in, or USB to be transmitted via BIS.
void app_lea_bsrc_sm_cb(T_BROADCAST_SOURCE_HANDLE handle, uint8_t cb_type, void *p_cb_data)
{
...
switch (cb_type)
{
case MSG_BROADCAST_SOURCE_SETUP_DATA_PATH:
{
APP_PRINT_INFO2("MSG_BROADCAST_SOURCE_SETUP_DATA_PATH: bis_idx %d, cause 0x%x",
p_sm_data->p_setup_data_path->bis_idx,
p_sm_data->p_setup_data_path->cause);
if (p_sm_data->p_setup_data_path->cause == GAP_SUCCESS)
{
T_LEA_SETUP_DATA_PATH data = {0};
data.iso_mode = BIG_ISO_MODE;
data.iso_conn_handle = p_sm_data->p_setup_data_path->bis_conn_handle;
data.path_direction = DATA_PATH_INPUT_FLAG;
data.presentation_delay = app_db.bsrc_db.prefer_qos.presentation_delay;
memcpy(&data.codec_parsed_data, &app_db.bsrc_db.codec_cfg, sizeof(T_CODEC_CFG));
if (app_db.bsrc_db.cfg_bis_num == 1)
{
data.codec_parsed_data.audio_channel_allocation = AUDIO_LOCATION_SIL | AUDIO_LOCATION_SIR;
}
else if (app_db.bsrc_db.cfg_bis_num == 2)
{
if (p_sm_data->p_setup_data_path->bis_idx == 1)
{
data.codec_parsed_data.audio_channel_allocation = AUDIO_LOCATION_SIL;
}
else if (p_sm_data->p_setup_data_path->bis_idx == 2)
{
data.codec_parsed_data.audio_channel_allocation = AUDIO_LOCATION_SIR;
}
}
app_lea_handle_bis_data_path_setup(&data);
}
}
break;
...
}
}
void app_lea_handle_bis_data_path_setup(T_LEA_SETUP_DATA_PATH *p_data)
{
T_APP_LEA_ISO_CHANN *p_iso_chann = app_lea_find_iso_chann(p_data->iso_conn_handle,
p_data->path_direction);
uint8_t chnl_cnt;
uint8_t blocks_num = 1;
if (p_iso_chann != NULL)
{
APP_PRINT_WARN0("app_lea_handle_bis_data_path_setup: iso channel already exist");
return;
}
else
{
p_iso_chann = app_lea_add_iso_chann(p_data->iso_conn_handle,
p_data->path_direction);
if (p_iso_chann == NULL)
{
return;
}
p_iso_chann->iso_mode = p_data->iso_mode;
}
p_iso_chann->codec_data = p_data->codec_parsed_data;
p_iso_chann->presentation_delay = p_data->presentation_delay;
p_iso_chann->time_stamp = 0;
p_iso_chann->pkt_seq_num = 0;
if (p_iso_chann->codec_data.audio_channel_allocation == AUDIO_LOCATION_MONO)
{
chnl_cnt = 1;
}
else
{
chnl_cnt = __builtin_popcount(p_iso_chann->codec_data.audio_channel_allocation);
}
if (p_iso_chann->codec_data.type_exist & CODEC_CFG_TYPE_BLOCKS_PER_SDU_EXIST)
{
blocks_num = p_iso_chann->codec_data.codec_frame_blocks_per_sdu;
}
p_iso_chann->frame_num = blocks_num * chnl_cnt;
APP_PRINT_INFO7("app_lea_handle_bis_data_path_setup: iso handle 0x%04x, frame_num %d, "
"dir %u, sample_frequency 0x%x, audio_channel_allocation 0x%08x, presentation_delay 0x%x, chnl_cnt %d",
p_iso_chann->iso_conn_handle, p_iso_chann->frame_num,
p_iso_chann->path_direction,
p_iso_chann->codec_data.sample_frequency,
p_iso_chann->codec_data.audio_channel_allocation,
p_iso_chann->presentation_delay,
chnl_cnt);
if (p_data->path_direction == DATA_PATH_INPUT_FLAG)
{
if (app_db.bsrc_db.cfg_bis_num == app_db.iso_input_queue.count)
{
app_lea_save_data_format(p_iso_chann);
#if F_APP_A2DP_XMIT_SRC_LEA_SUPPORT
app_a2dp_xmit_lea_pipe_rcfg();
#endif
}
}
}
Broadcast Data
Using the app_lea_iso_data_send()
API, data can be transmitted via BIS or CIS. The ext_flag
is used
to specify whether to include ts (timestamp) and seq (sequence) parameters. Typically, when the data
source is a MIC, line-in, or USB, the ts and seq values from the registered callback in the
audio track will be used.
void app_lea_iso_data_send(uint8_t *p_data, uint16_t len, bool ext_flag, uint32_t ts, uint16_t seq)
{
T_GAP_CAUSE cause = GAP_CAUSE_SUCCESS;
T_APP_LEA_ISO_CHANN *p_iso_chann = NULL;
uint8_t chnl_cnt = 0;
uint32_t time_stamp = 0;
uint16_t seq_num = 0;
uint32_t s = os_lock();
for (uint8_t i = 0; i < app_db.iso_input_queue.count; i++)
{
p_iso_chann = (T_APP_LEA_ISO_CHANN *)os_queue_peek(&app_db.iso_input_queue, i);
if (p_iso_chann->codec_data.audio_channel_allocation == AUDIO_LOCATION_MONO)
{
chnl_cnt = 1;
}
else
{
chnl_cnt = __builtin_popcount(p_iso_chann->codec_data.audio_channel_allocation);
}
if (ext_flag)
{
time_stamp = ts;
seq_num = seq;
}
else
{
time_stamp = (p_iso_chann->time_stamp + p_iso_chann->pkt_seq_num) *
(p_iso_chann->sdu_interval);
seq_num = p_iso_chann->pkt_seq_num;
}
if (chnl_cnt == 2)
{
cause = gap_iso_send_data(p_data,
p_iso_chann->iso_conn_handle,
len,
false,
time_stamp,
seq_num);
}
else if (chnl_cnt == 1)
{
if (p_iso_chann->codec_data.audio_channel_allocation & (AUDIO_LOCATION_FL |
AUDIO_LOCATION_SIL))
{
cause = gap_iso_send_data(p_data,
p_iso_chann->iso_conn_handle,
len / 2,
0,
time_stamp,
seq_num);
}
else
{
cause = gap_iso_send_data(p_data + (len / 2),
p_iso_chann->iso_conn_handle,
len / 2,
0,
time_stamp,
seq_num);
}
}
p_iso_chann->pkt_seq_num++;
if (cause != GAP_CAUSE_SUCCESS)
{
APP_PRINT_ERROR1("app_lea_iso_data_send: failed, cause 0x%x", cause);
}
}
os_unlock(s);
return;
}
LE Audio Initiator - CIS
Bluetooth Low Energy Audio CAP roles can be divided into Acceptor, Initiator, and Commander. In transmitter applications, Initiator role is supported, which can transmit BIS or transmit and receive CIS.
In this chapter, the design SPEC for CIS will be presented.
Initialization
Initialization is performed through the function of app_lea_profile_init()
, including configuration
of LE Audio parameters, initialization of BAP and CAP, as well as the necessary data processing setup.
//app_lea_ini_profile.c
void app_lea_profile_init(void)
{
T_BLE_AUDIO_PARAMS ble_audio_param = {0};
ble_audio_param.evt_queue_handle = audio_evt_queue_handle;
ble_audio_param.io_queue_handle = audio_io_queue_handle;
ble_audio_param.bt_gatt_client_init = (GATT_CLIENT_DISCOV_MODE_REG_SVC_BIT |
GATT_CLIENT_DISCOV_MODE_CCCD_STORAGE_BIT |
GATT_CLIENT_DISCOV_MODE_USE_EXT_CLIENT);
ble_audio_param.acl_link_num = MAX_BLE_LINK_NUM;
ble_audio_param.io_event_type = IO_MSG_TYPE_LE_AUDIO;
ble_audio_init(&ble_audio_param);
app_lea_ini_bap_init();
app_lea_ini_cap_init();
app_lea_audio_data_init();
}
Connect to LE Audio Device
The Initiator initiates scan by using app_lea_ini_scan_start()
to scan for nearby LE Audio devices
and reports them to the ACI Host.
// start scanning
void app_lea_ini_scan_start(void)
{
APP_PRINT_INFO0("app_ble_scan_start");
BLE_SCAN_PARAM param;
param.own_addr_type = GAP_LOCAL_ADDR_LE_PUBLIC;
param.phys = GAP_EXT_SCAN_PHYS_1M_BIT;
param.ext_filter_policy = GAP_SCAN_FILTER_ANY;
param.ext_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE;
param.scan_param_1m.scan_type = GAP_SCAN_MODE_PASSIVE;
param.scan_param_1m.scan_interval = 0x140;
param.scan_param_1m.scan_window = 0xD0;
param.scan_param_coded.scan_type = GAP_SCAN_MODE_PASSIVE;
param.scan_param_coded.scan_interval = 0x0050;
param.scan_param_coded.scan_window = 0x0025;
if (ble_scan_start(&app_lea_ini_scan_handle, app_lea_ini_scan_cb, ¶m, NULL))
{
app_lea_clear_scan_dev();
}
}
// report scanned devices to ACI Host
void app_lea_ini_scan_report(T_LE_EXT_ADV_REPORT_INFO *p_report)
{
T_APP_LEA_ADV_DATA lea_data = {0};
T_APP_LEA_SCAN_DEV *p_dev;
APP_PRINT_INFO3("app_lea_ini_scan_report: event_type 0x%x, bd_addr %s, addr_type %d",
p_report->event_type,
TRACE_BDADDR(p_report->bd_addr),
p_report->addr_type);
p_dev = app_lea_find_scan_dev(p_report->bd_addr, p_report->addr_type);
if (p_dev)
{
return;
}
app_lea_ini_scan_data_parse(p_report->data_len, p_report->p_data, &lea_data);
if (lea_data.adv_data_flags)
{
APP_PRINT_INFO5("app_lea_ini_scan_report: adv_data_flags 0x%x, ascs(type %d, sink 0x%x, source 0x%x), cap(type %d)",
lea_data.adv_data_flags,
lea_data.ascs_announcement_type,
lea_data.ascs_sink_available_contexts,
lea_data.ascs_source_available_contexts,
lea_data.cap_announcement_type);
app_lea_add_scan_dev(p_report->bd_addr, p_report->addr_type, &lea_data);
app_lea_ini_scan_report_result(p_report->event_type,
p_report->bd_addr,
p_report->addr_type,
&lea_data);
#if CSIP_SET_COORDINATOR
if (lea_data.adv_data_flags & APP_LEA_ADV_DATA_RSI_BIT)
{
set_coordinator_check_adv_rsi(p_report->data_len, p_report->p_data,
p_report->bd_addr, p_report->addr_type);
}
#endif
}
}
On the ACI Host side, initiate the establishment of an LE connection by invoking the app_lea_create_conn()
API using the CMD_LE_CREATE_CONN
command.
void app_cmd_ble_handle(uint8_t *cmd_ptr, uint16_t cmd_len, uint8_t cmd_path, uint8_t app_idx,
uint8_t *ack_pkt)
{
uint16_t cmd_id = (uint16_t)(cmd_ptr[0] | (cmd_ptr[1] << 8));
...
switch (cmd_id)
{
case CMD_LE_CREATE_CONN:
{
...
#if F_APP_LE_AUDIO_INITIATOR_SUPPORT
T_GAP_CAUSE gap_cause = app_lea_create_conn(CMD->remote_bd,
(T_GAP_REMOTE_ADDR_TYPE)CMD->remote_bd_type);
#else
T_GAP_CAUSE gap_cause = le_connect(CMD->init_phys, CMD->remote_bd,
(T_GAP_REMOTE_ADDR_TYPE)CMD->remote_bd_type,
(T_GAP_LOCAL_ADDR_TYPE)CMD->local_bd_type, CMD->scan_timeout);
APP_PRINT_TRACE5("app_cmd_ble_handle: init_phys %d, remote_bd_type %d, remote_bd %s, local_bd_type %d, scan_timeout %d",
CMD->init_phys, CMD->remote_bd_type, TRACE_BDADDR(CMD->remote_bd), CMD->local_bd_type,
CMD->scan_timeout);
#endif
((ACK_PKT)ack_pkt)->status = (uint16_t)gap_cause;
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
...
}
...
}
If the remote device supports coordinate set and belongs to a group of devices, the Initiator will
continue to scan for other devices in that group and automatically establish connections. The coordinated
set information is reported in LE_AUDIO_MSG_CSIS_CLIENT_READ_RESULT
message.
uint16_t app_lea_ini_csis_handle_msg(T_LE_AUDIO_MSG msg, void *buf)
{
uint16_t cb_result = BLE_AUDIO_CB_RESULT_SUCCESS;
switch (msg)
{
case LE_AUDIO_MSG_CSIS_CLIENT_READ_RESULT:
{
...
// check if there are more members in the group and start scanning again
if (p_read_result->mem_info.set_mem_size > 1 &&
app_link_get_le_link_num() < p_read_result->mem_info.set_mem_size)
{
app_lea_group_scan_start(group_handle);
}
}
break;
...
}
...
}
CIS Media
For a unicast stream, there are eight different streaming states defined as below.
typedef enum
{
AUDIO_STREAM_STATE_IDLE = 0x00, /**< Available API: bap_unicast_audio_cfg */
AUDIO_STREAM_STATE_IDLE_CONFIGURED = 0x01, /**< Available API: bap_unicast_audio_start, bap_unicast_audio_remove_cfg */
AUDIO_STREAM_STATE_CONFIGURED = 0x02, /**< Available API: bap_unicast_audio_start, bap_unicast_audio_release */
AUDIO_STREAM_STATE_STARTING = 0x03, /**< Available API: bap_unicast_audio_stop, bap_unicast_audio_release */
AUDIO_STREAM_STATE_STREAMING = 0x04, /**< Available API: bap_unicast_audio_stop, bap_unicast_audio_release,
bap_unicast_audio_update */
AUDIO_STREAM_STATE_PARTIAL_STREAMING = 0x05, /**< Available API: bap_unicast_audio_stop, bap_unicast_audio_release,
bap_unicast_audio_update */
AUDIO_STREAM_STATE_STOPPING = 0x06, /**< Available API: bap_unicast_audio_release */
AUDIO_STREAM_STATE_RELEASING = 0x07,
} T_AUDIO_STREAM_STATE;
The changes in the stream state will be notified through AUDIO_GROUP_MSG_BAP_STATE
message in
app_lea_ini_group_cb()
and relayed to ACI Host.
void app_lea_ini_group_cb(T_AUDIO_GROUP_MSG msg, T_BLE_AUDIO_GROUP_HANDLE handle,
void *buf)
{
T_APP_RESULT result = APP_RESULT_SUCCESS;
T_APP_LEA_GROUP_INFO *p_group = app_lea_find_group(handle);
switch (msg)
{
...
case AUDIO_GROUP_MSG_BAP_STATE:
{
T_AUDIO_GROUP_BAP_STATE *p_data = (T_AUDIO_GROUP_BAP_STATE *)buf;
APP_PRINT_INFO6("AUDIO_GROUP_MSG_BAP_STATE: group handle 0x%x, session handle 0x%x, curr_action %d, state %d, result %d, cause 0x%x",
handle, p_data->handle, p_data->curr_action,
p_data->state, p_data->result, p_data->cause);
struct
{
void *group_handle;
uint8_t state;
} __attribute__((packed)) rpt = {};
rpt.group_handle = handle;
rpt.state = p_data->state;
app_report_event(CMD_PATH_UART, EVENT_LE_AUDIO_BAP_STATE, 0, (uint8_t *)&rpt,
sizeof(rpt));
if (p_group != NULL && p_group->lea_unicast.session_handle == p_data->handle)
{
p_group->lea_unicast.bap_state = p_data->state;
if ((p_group->lea_unicast.bap_state == AUDIO_STREAM_STATE_IDLE ||
p_group->lea_unicast.bap_state == AUDIO_STREAM_STATE_IDLE_CONFIGURED) &&
p_group->lea_unicast.release_req == true)
{
bap_unicast_audio_remove_session(p_group->lea_unicast.session_handle);
}
}
}
break;
...
}
}
To transmit media via CIS, users can invoke app_lea_ini_cis_media_start()
to transition the stream
state to AUDIO_STREAM_STATE_STREAMING
.
bool app_lea_ini_cis_media_start(uint8_t group_idx)
{
bool ret = false;
if (group_idx < app_db.group_handle_queue.count)
{
T_APP_LEA_GROUP_INFO *p_group = (T_APP_LEA_GROUP_INFO *)os_queue_peek(&app_db.group_handle_queue,
group_idx);
if (p_group)
{
ret = app_lea_ini_start_media(p_group->group_handle);
}
}
return ret;
}
Specifically, the function will invoke:
app_lea_ini_select_media_prefer_codec()
API to choose the codec type.bap_unicast_audio_cfg()
API to set unicast audio configuration.app_lea_ini_config_codec()
API to configure ASE codec.bap_unicast_audio_start()
API to create CIS and set up data path.static bool app_lea_ini_start_media(T_BLE_AUDIO_GROUP_HANDLE group_handle) { T_APP_LEA_GROUP_INFO *p_group; uint8_t err_idx = 0; p_group = app_lea_find_group(group_handle); if (p_group) { if (app_lea_ini_ready_to_start(p_group, AUDIO_CONTEXT_MEDIA, 0)) { if (p_group->lea_unicast.session_handle == NULL) { p_group->lea_unicast.session_handle = audio_stream_session_allocate(p_group->group_handle); if (p_group->lea_unicast.session_handle == NULL) { err_idx = 1; goto failed; } p_group->lea_unicast.bap_state = AUDIO_STREAM_STATE_IDLE; p_group->lea_unicast.contexts_type = AUDIO_CONTEXT_MEDIA; p_group->lea_unicast.target_latency = ASE_TARGET_HIGHER_RELIABILITY; } if (p_group->lea_unicast.bap_state == AUDIO_STREAM_STATE_IDLE) { if (app_lea_ini_select_media_prefer_codec(p_group) == false) { err_idx = 2; goto failed; } if (bap_unicast_audio_cfg(p_group->lea_unicast.session_handle, p_group->lea_unicast.cfg_type, p_group->lea_unicast.dev_num, p_group->lea_unicast.dev_tbl) == false) { err_idx = 3; goto failed; } if (app_lea_ini_config_codec(p_group) == false) { err_idx = 4; goto failed; } if (bap_unicast_audio_start(p_group->lea_unicast.session_handle) == false) { err_idx = 5; goto failed; } } else if (p_group->lea_unicast.bap_state == AUDIO_STREAM_STATE_IDLE_CONFIGURED || p_group->lea_unicast.bap_state == AUDIO_STREAM_STATE_CONFIGURED) { if (p_group->lea_unicast.contexts_type != AUDIO_CONTEXT_MEDIA) { err_idx = 6; goto failed; } if (bap_unicast_audio_start(p_group->lea_unicast.session_handle) == false) { err_idx = 7; goto failed; } } else { err_idx = 8; goto failed; } } else { err_idx = 9; goto failed; } } else { err_idx = 10; goto failed; } return true; failed: APP_PRINT_ERROR2("app_lea_ini_start_media: failed, group_handle 0x%x, err_idx %d", group_handle, err_idx); return false; }
Once the data path is successfully established, notifications will also be received in
app_lea_ini_group_cb()
with the message of AUDIO_GROUP_MSG_BAP_SETUP_DATA_PATH
. In the
app_lea_handle_cis_data_path_setup()
function, data path information is processed and stored in
the form of T_APP_LEA_ISO_CHANN
. Other modules, such as the source play module, can utilize
this information to specify the format for creating an audio track. This enables data from sources
like MIC, line-in, or USB to be transmitted via CIS.
void app_lea_ini_group_cb(T_AUDIO_GROUP_MSG msg, T_BLE_AUDIO_GROUP_HANDLE handle,
void *buf)
{
T_APP_RESULT result = APP_RESULT_SUCCESS;
T_APP_LEA_GROUP_INFO *p_group = app_lea_find_group(handle);
switch (msg)
{
...
case AUDIO_GROUP_MSG_BAP_SETUP_DATA_PATH:
{
T_AUDIO_GROUP_MSG_BAP_SETUP_DATA_PATH *p_data = (T_AUDIO_GROUP_MSG_BAP_SETUP_DATA_PATH *)buf;
APP_PRINT_INFO6("AUDIO_GROUP_MSG_BAP_SETUP_DATA_PATH: group handle 0x%x, session handle 0x%x, dev_handle 0x%x, ase_id 0x%x, direction %d, cis_conn_handle 0x%x",
handle, p_data->handle,
p_data->dev_handle,
p_data->ase_id,
p_data->path_direction,
p_data->cis_conn_handle);
T_LEA_SETUP_DATA_PATH data = {0};
data.iso_mode = CIG_ISO_MODE;
data.iso_conn_handle = p_data->cis_conn_handle;
data.codec_parsed_data = p_data->codec_parsed_data;
data.path_direction = p_data->path_direction;
if (p_group != NULL && p_group->lea_unicast.session_handle == p_data->handle)
{
T_AUDIO_SESSION_QOS_CFG qos_cfg;
if (bap_unicast_audio_get_session_qos(p_group->lea_unicast.session_handle, &qos_cfg))
{
if (p_data->path_direction == DATA_PATH_INPUT_FLAG)
{
data.presentation_delay = qos_cfg.sink_presentation_delay;
}
else
{
data.presentation_delay = qos_cfg.source_presentation_delay;
}
}
}
app_lea_handle_cis_data_path_setup(&data);
}
break;
...
}
}
void app_lea_handle_cis_data_path_setup(T_LEA_SETUP_DATA_PATH *p_data)
{
T_APP_LEA_ISO_CHANN *p_iso_chann = app_lea_find_iso_chann(p_data->iso_conn_handle,
p_data->path_direction);
if (p_iso_chann != NULL)
{
APP_PRINT_WARN0("app_lea_handle_cis_data_path_setup: iso channel already exist");
return;
}
else
{
if (p_data->path_direction == DATA_PATH_INPUT_FLAG)
{
p_iso_chann = app_lea_add_iso_pending_chann(p_data->iso_conn_handle,
p_data->path_direction);
}
else
{
p_iso_chann = app_lea_add_iso_chann(p_data->iso_conn_handle,
p_data->path_direction);
}
if (p_iso_chann == NULL)
{
return;
}
p_iso_chann->iso_mode = p_data->iso_mode;
}
p_iso_chann->codec_data = p_data->codec_parsed_data;
p_iso_chann->presentation_delay = p_data->presentation_delay;
p_iso_chann->time_stamp = 0;
p_iso_chann->pkt_seq_num = 0;
p_iso_chann->frame_num = app_lea_get_frame_num(p_iso_chann);
//lea src
if (p_data->path_direction == DATA_PATH_INPUT_FLAG)
{
uint8_t current_iso_cnt = app_db.input_path_pending_q.count + app_db.iso_input_queue.count;
uint8_t link_num = app_link_get_le_link_num();
APP_PRINT_INFO3("app_lea_handle_cis_data_path_setup: current_iso_cnt %d conn_dev %d, link_num %d",
current_iso_cnt,
app_db.conn_dev_queue.count,
link_num);
if (current_iso_cnt >= link_num)
{
uint8_t i;
uint8_t n = app_db.input_path_pending_q.count;
APP_PRINT_INFO1("handle_cis_data_path_setup_cmplt_msg: pending num %u",
app_db.input_path_pending_q.count);
for (i = 0; i < n; i++)
{
p_iso_chann = (T_APP_LEA_ISO_CHANN *)os_queue_out(&app_db.input_path_pending_q);
APP_PRINT_INFO2("app_lea_handle_cis_data_path_setup: adding path handle %u curr_num %x",
p_iso_chann->iso_conn_handle,
app_db.iso_input_queue.count);
os_queue_in(&app_db.iso_input_queue, (void *)p_iso_chann);
}
app_lea_save_data_format(p_iso_chann);
}
}
APP_PRINT_INFO6("app_lea_handle_cis_data_path_setup: iso handle 0x%04x, frame_num %d, "
"dir %u, sample_frequency 0x%x, audio_channel_allocation 0x%08x, presentation_delay 0x%x",
p_iso_chann->iso_conn_handle, p_iso_chann->frame_num,
p_iso_chann->path_direction,
p_iso_chann->codec_data.sample_frequency,
p_iso_chann->codec_data.audio_channel_allocation,
p_iso_chann->presentation_delay);
}
CIS Conversation
Differing from CIS media, CIS Conversation both transmits and receives data streams. However, what is similar is that they share the stream state defined by unicast stream, which can be referenced in chapter CIS Media for an introduction to stream states.
To transmit and receive audio stream via CIS, users can invoke app_lea_ini_start_conversation()
to transition the stream state to AUDIO_STREAM_STATE_STREAMING
. Specifically, the function will invoke:
app_lea_ini_select_conversation_prefer_codec()
API to choose the codec type.bap_unicast_audio_cfg()
API to set unicast audio configuration.app_lea_ini_config_codec()
API to configure ASE codec.bap_unicast_audio_start()
API to create CIS and set up data path(s).bool app_lea_ini_start_conversation(T_BLE_AUDIO_GROUP_HANDLE group_handle) { T_APP_LEA_GROUP_INFO *p_group; uint8_t err_idx = 0; p_group = app_lea_find_group(group_handle); if (p_group) { if (app_lea_ini_ready_to_start(p_group, AUDIO_CONTEXT_CONVERSATIONAL, AUDIO_CONTEXT_CONVERSATIONAL)) { if (p_group->lea_unicast.session_handle == NULL) { p_group->lea_unicast.session_handle = audio_stream_session_allocate(p_group->group_handle); if (p_group->lea_unicast.session_handle == NULL) { err_idx = 1; goto failed; } p_group->lea_unicast.bap_state = AUDIO_STREAM_STATE_IDLE; p_group->lea_unicast.contexts_type = AUDIO_CONTEXT_CONVERSATIONAL; p_group->lea_unicast.target_latency = ASE_TARGET_LOWER_LATENCY; } if (p_group->lea_unicast.bap_state == AUDIO_STREAM_STATE_IDLE) { if (app_lea_ini_select_conversation_prefer_codec(p_group) == false) { err_idx = 2; goto failed; } if (bap_unicast_audio_cfg(p_group->lea_unicast.session_handle, p_group->lea_unicast.cfg_type, p_group->lea_unicast.dev_num, p_group->lea_unicast.dev_tbl) == false) { err_idx = 3; goto failed; } if (app_lea_ini_config_codec(p_group) == false) { err_idx = 4; goto failed; } if (bap_unicast_audio_start(p_group->lea_unicast.session_handle) == false) { err_idx = 5; goto failed; } } else if (p_group->lea_unicast.bap_state == AUDIO_STREAM_STATE_IDLE_CONFIGURED || p_group->lea_unicast.bap_state == AUDIO_STREAM_STATE_CONFIGURED) { if (p_group->lea_unicast.contexts_type != AUDIO_CONTEXT_CONVERSATIONAL) { err_idx = 6; goto failed; } if (bap_unicast_audio_start(p_group->lea_unicast.session_handle) == false) { err_idx = 7; goto failed; } } else { err_idx = 8; goto failed; } } else { err_idx = 9; goto failed; } } else { err_idx = 10; goto failed; } return true; failed: APP_PRINT_ERROR2("app_lea_ini_start_conversation: failed, group_handle 0x%x, err_idx %d", group_handle, err_idx); return false; }
Similar to CIS Media, once the data path is successfully established, notifications will also be received in app_lea_ini_group_cb()
with the message of AUDIO_GROUP_MSG_BAP_SETUP_DATA_PATH
. In the
app_lea_handle_cis_data_path_setup()
function, data path information is processed and stored in
the form of T_APP_LEA_ISO_CHANN
.
Unlike CIS Media, CIS Conversation establishes both an input-direction data path for sending data and an output-direction data path for receiving data (The direction is defined from the perspective of the lower stack).
Unicast Data
CIS, similar to BIS, utilize the API app_lea_iso_data_send()
to send data. Please refer to Broadcast Data for more details.
For CIS Conversation, data reception is also a part of its functionality. Data is reported through
the registered app_lea_data_direct_cb()
, allowing further data processing within this function.
void app_lea_data_direct_cb(uint8_t cb_type, void *p_cb_data)
{
T_BT_DIRECT_CB_DATA *p_data = (T_BT_DIRECT_CB_DATA *)p_cb_data;
switch (cb_type)
{
case BT_DIRECT_MSG_ISO_DATA_IND:
{
#if 0
APP_PRINT_TRACE5("app_lea_data_direct_cb: conn_handle 0x%x, iso_sdu_len %d, pkt_seq_num 0x%x, time_stamp 0x%x, pkt_status_flag 0x%x",
p_data->p_bt_direct_iso->conn_handle, p_data->p_bt_direct_iso->iso_sdu_len,
p_data->p_bt_direct_iso->pkt_seq_num, p_data->p_bt_direct_iso->time_stamp,
p_data->p_bt_direct_iso->pkt_status_flag);
#endif
#if 0
uint8_t *p_iso_data = p_data->p_bt_direct_iso->p_buf + p_data->p_bt_direct_iso->offset;
APP_PRINT_INFO5("app_lea_data_direct_cb: BT_DIRECT_MSG_ISO_DATA_IND, iso_sdu_len 0x%x, p_buf %p, offset %d, p_data %p, data %b",
p_data->p_bt_direct_iso->iso_sdu_len, p_data->p_bt_direct_iso->p_buf,
p_data->p_bt_direct_iso->offset, p_iso_data, TRACE_BINARY(p_data->p_bt_direct_iso->iso_sdu_len,
p_iso_data));
#endif
APP_PRINT_TRACE5("app_lea_data_direct_cb: conn_handle 0x%x, iso_sdu_len %d, pkt_seq_num 0x%x, time_stamp 0x%x, pkt_status_flag 0x%x",
p_data->p_bt_direct_iso->conn_handle, p_data->p_bt_direct_iso->iso_sdu_len,
p_data->p_bt_direct_iso->pkt_seq_num, p_data->p_bt_direct_iso->time_stamp,
p_data->p_bt_direct_iso->pkt_status_flag);
if (p_data->p_bt_direct_iso->pkt_status_flag != ISOCH_DATA_PKT_STATUS_VALID_DATA)
{
gap_iso_data_cfm(p_data->p_bt_direct_iso->p_buf);
break;
}
T_APP_LEA_ISO_CHANN *p_iso_chann = app_lea_find_iso_chann(p_data->p_bt_direct_iso->conn_handle,
DATA_PATH_OUTPUT_FLAG);
if (p_iso_chann != NULL)
{
#if 0
//Just for sample. Application can send the data to DSP.
uint16_t written_len;
T_AUDIO_STREAM_STATUS status;
if (p_data->p_bt_direct_iso->iso_sdu_len != 0)
{
status = AUDIO_STREAM_STATUS_CORRECT;
}
else
{
status = AUDIO_STREAM_STATUS_LOST;
}
audio_track_write(handle, p_data->p_bt_direct_iso->time_stamp,
p_data->p_bt_direct_iso->pkt_seq_num,
status,
p_iso_chann->frame_num,
p_data->p_bt_direct_iso->p_buf + p_data->p_bt_direct_iso->offset,
p_data->p_bt_direct_iso->iso_sdu_len,
&written_len);
#endif
}
gap_iso_data_cfm(p_data->p_bt_direct_iso->p_buf);
}
break;
default:
APP_PRINT_ERROR1("app_lea_data_direct_cb: unhandled cb_type 0x%x", cb_type);
break;
}
}
Bluetooth Audio Receiver
A2DP Sink
A2DP Profile Initialization
bt_a2dp_init()
is utilized in app_a2dp_init()
to initialize the A2DP profile and configure the maximum number of remote devices and A2DP latency.
A2DP latency is used to enable synchronization of audio and video playback by reporting SNK delay values caused by buffering,
decoding, and rendering.
bt_a2dp_role_set()
is utilized to set the Sink or Source of the A2DP role.
bt_a2dp_stream_endpoint_add()
is utilized to add an A2DP stream endpoint.
void app_a2dp_init(void)
{
if (app_cfg_const.supported_profile_mask & A2DP_PROFILE_MASK)
{
bt_a2dp_init(app_cfg_const.a2dp_link_number, A2DP_LATENCY_MS);
#if (F_APP_A2DP_SOURCE_SUPPORT || F_APP_A2DP_XMIT_SRC_SUPPORT || F_SOURCE_PLAY_SUPPORT)
bt_a2dp_role_set(BT_A2DP_ROLE_SRC);
#else
bt_a2dp_role_set(BT_A2DP_ROLE_SNK);
#endif
if (app_cfg_const.a2dp_codec_type_sbc)
{
T_BT_A2DP_STREAM_ENDPOINT sep;
sep.codec_type = BT_A2DP_CODEC_TYPE_SBC;
sep.u.codec_sbc.sampling_frequency_mask = app_cfg_const.sbc_sampling_frequency;
sep.u.codec_sbc.channel_mode_mask = app_cfg_const.sbc_channel_mode;
sep.u.codec_sbc.block_length_mask = app_cfg_const.sbc_block_length;
sep.u.codec_sbc.subbands_mask = app_cfg_const.sbc_subbands;
sep.u.codec_sbc.allocation_method_mask = app_cfg_const.sbc_allocation_method;
sep.u.codec_sbc.min_bitpool = app_cfg_const.sbc_min_bitpool;
sep.u.codec_sbc.max_bitpool = app_cfg_const.sbc_max_bitpool;
bt_a2dp_stream_endpoint_add(sep);
}
if (app_cfg_const.a2dp_codec_type_aac)
{
T_BT_A2DP_STREAM_ENDPOINT sep;
sep.codec_type = BT_A2DP_CODEC_TYPE_AAC;
sep.u.codec_aac.object_type_mask = app_cfg_const.aac_object_type;
sep.u.codec_aac.sampling_frequency_mask = app_cfg_const.aac_sampling_frequency;
sep.u.codec_aac.channel_number_mask = app_cfg_const.aac_channel_number;
sep.u.codec_aac.vbr_supported = app_cfg_const.aac_vbr_supported;
sep.u.codec_aac.bit_rate = app_cfg_const.aac_bit_rate;
bt_a2dp_stream_endpoint_add(sep);
}
#if F_APP_A2DP_CODEC_LDAC_SUPPORT
if (app_cfg_const.a2dp_codec_type_ldac)
{
T_BT_A2DP_STREAM_ENDPOINT sep;
sep.codec_type = BT_A2DP_CODEC_TYPE_LDAC;
sep.u.codec_ldac.sampling_frequency_mask = app_cfg_const.ldac_sampling_frequency;
sep.u.codec_ldac.channel_mode_mask = app_cfg_const.ldac_channel_mode;
bt_a2dp_stream_endpoint_add(sep);
}
#endif
bt_mgr_cback_register(app_a2dp_bt_cback);
}
A2DP Connect
In linkback_profile_search_start()
, the function gap_br_start_sdp_discov()
will first be called to discover A2DP SDP according to A2DP Sink’s UUID.
bool linkback_profile_search_start(uint8_t *bd_addr, uint32_t prof, bool is_special)
{
bool ret = true;
T_GAP_UUID_DATA uuid;
T_GAP_UUID_TYPE uuid_type = GAP_UUID16;
...
switch (prof)
{
...
case A2DP_SINK_PROFILE_MASK:
{
uuid.uuid_16 = UUID_AUDIO_SINK;
}
break;
...
if (ret)
{
if (gap_br_start_sdp_discov(bd_addr, uuid_type, uuid) != GAP_CAUSE_SUCCESS)
{
ret = false;
}
}
return ret;
}
Then, A2DP Sink will initiate profile connection by bt_a2dp_connect_req()
.
bool linkback_profile_connect_start(uint8_t *bd_addr, uint32_t prof, T_LINKBACK_CONN_PARAM *param)
{
bool ret = true;
...
switch (prof)
{
case A2DP_PROFILE_MASK:
ret = bt_a2dp_connect_req(bd_addr, param->protocol_version);
break;
...
return ret;
}
For A2DP Sink, app_a2dp_bt_cback()
function is used to handle Bluetooth Manager A2DP Sink-related events.
bt_a2dp_connect_cfm()
accepts or rejects the incoming connection from the remote device.
static void app_a2dp_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
T_BT_EVENT_PARAM *param = event_buf;
T_APP_BR_LINK *p_active_a2dp_link = &app_db.br_link[active_a2dp_idx];
bool handle = true;
T_APP_BR_LINK *p_link = NULL;
switch (event_type)
{
case BT_EVENT_A2DP_CONN_IND:
{
T_APP_BR_LINK *p_link = app_link_find_br_link(param->a2dp_conn_ind.bd_addr);
if (p_link != NULL)
{
bt_a2dp_connect_cfm(p_link->bd_addr, true);
}
}
break;
...
}
A2DP Streaming Control
For A2DP Sink, the app_a2dp_bt_cback()
function is used to handle Bluetooth Manager A2DP Streaming events.
app_judge_active_a2dp_idx_and_qos()
will be called to determine an A2DP link on one device as the active link, allowing AVRCP to control it.
static void app_a2dp_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
T_BT_EVENT_PARAM *param = event_buf;
T_APP_BR_LINK *p_active_a2dp_link = &app_db.br_link[active_a2dp_idx];
bool handle = true;
T_APP_BR_LINK *p_link = NULL;
switch (event_type)
{
...
case BT_EVENT_A2DP_STREAM_START_IND:
{
if ((p_active_a2dp_link->a2dp.is_streaming == false ||
p_active_a2dp_link->avrcp.play_status == BT_AVRCP_PLAY_STATUS_PAUSED) ||
(memcmp(p_active_a2dp_link->bd_addr,
param->a2dp_stream_start_ind.bd_addr, 6) == 0))
{
APP_PRINT_INFO3("app_a2dp_bt_cback: BT_EVENT_A2DP_STREAM_START_IND active_a2dp_idx %d, streaming_fg %d, avrcp_play_status %d",
active_a2dp_idx, p_active_a2dp_link->a2dp.is_streaming, p_active_a2dp_link->avrcp.play_status);
app_sniff_mode_b2s_disable_all(SNIFF_DISABLE_MASK_A2DP);
app_audio_set_bud_stream_state(BUD_STREAM_STATE_AUDIO);
bt_a2dp_stream_start_cfm(p_active_a2dp_link->bd_addr, true);
p_active_a2dp_link->a2dp.is_streaming = true;
app_judge_active_a2dp_idx_and_qos(p_active_a2dp_link->id, JUDGE_EVENT_A2DP_START);
}
}
break;
case BT_EVENT_A2DP_STREAM_START_RSP:
{
if (p_active_a2dp_link->a2dp.is_streaming == false ||
(memcmp(p_active_a2dp_link->bd_addr,
param->a2dp_stream_start_rsp.bd_addr, 6) == 0))
{
APP_PRINT_INFO2("app_a2dp_bt_cback: BT_EVENT_A2DP_STREAM_START_RSP active_a2dp_idx %d, streaming_fg %d",
active_a2dp_idx, p_active_a2dp_link->a2dp.is_streaming);
app_sniff_mode_b2s_disable_all(SNIFF_DISABLE_MASK_A2DP);
app_audio_set_bud_stream_state(BUD_STREAM_STATE_AUDIO);
p_link = app_link_find_br_link(param->a2dp_stream_start_rsp.bd_addr);
if (p_link != NULL)
{
p_link->a2dp.is_streaming = true;
app_judge_active_a2dp_idx_and_qos(p_link->id, JUDGE_EVENT_A2DP_START);
}
}
}
break;
case BT_EVENT_A2DP_STREAM_STOP:
{
if (memcmp(p_active_a2dp_link->bd_addr,
param->a2dp_stream_stop.bd_addr, 6) == 0)
{
if (app_link_get_a2dp_start_num() <= 1)
{
app_sniff_mode_b2s_enable_all(SNIFF_DISABLE_MASK_A2DP);
}
if (app_hfp_get_call_status() == APP_HFP_CALL_IDLE)
{
app_audio_set_bud_stream_state(BUD_STREAM_STATE_IDLE);
}
}
p_link = app_link_find_br_link(param->a2dp_stream_stop.bd_addr);
if (p_link != NULL)
{
p_link->a2dp.is_streaming = false;
app_judge_active_a2dp_idx_and_qos(p_link->id, JUDGE_EVENT_A2DP_STOP);
}
}
break;
case BT_EVENT_A2DP_STREAM_CLOSE:
{
if (memcmp(p_active_a2dp_link->bd_addr,
param->a2dp_stream_close.bd_addr, 6) == 0)
{
if (app_hfp_get_call_status() == APP_HFP_CALL_IDLE)
{
app_audio_set_bud_stream_state(BUD_STREAM_STATE_IDLE);
}
}
p_link = app_link_find_br_link(param->a2dp_stream_close.bd_addr);
if (p_link != NULL)
{
p_link->a2dp.is_streaming = false;
app_judge_active_a2dp_idx_and_qos(p_link->id, JUDGE_EVENT_A2DP_STOP);
}
}
break;
...
}
void app_judge_active_a2dp_idx_and_qos(uint8_t app_idx, T_APP_JUDGE_A2DP_EVENT event)
{
uint8_t active_a2dp_idx = app_a2dp_get_active_idx();
uint8_t active_hf_idx = app_hfp_get_active_idx();
APP_PRINT_TRACE6("app_judge_active_a2dp_idx_and_qos: 1 event %d, active_a2dp_idx %d, app_idx %d, "
"a2dp.wait_resume_link_id %d, streaming_fg %d, active_media_paused %d",
event, active_a2dp_idx, app_idx, a2dp.wait_resume_link_id,
app_db.br_link[active_a2dp_idx].a2dp.is_streaming, app_db.active_media_paused);
switch (event)
{
case JUDGE_EVENT_A2DP_CONNECTED:
{
uint8_t link_number = app_connected_profile_link_num(A2DP_PROFILE_MASK);
if (link_number <= 1)
{
set_active_a2dp_avrcp(app_db.br_link[app_idx].bd_addr);
app_bond_set_priority(app_db.br_link[app_idx].bd_addr);
if (link_number <= 0)
{
//exception
}
}
else
{
if ((app_db.br_link[active_a2dp_idx].a2dp.is_streaming == false) &&
(app_hfp_get_call_status() == APP_HFP_CALL_IDLE))
{
if (app_cfg_const.enable_multi_link)
{
app_bond_set_priority(app_db.br_link[app_idx].bd_addr);
app_bond_set_priority(app_db.br_link[find_other_link_by_bond_prio(app_idx)].bd_addr);
}
else
{
set_active_a2dp_avrcp(app_db.br_link[app_idx].bd_addr);
app_bond_set_priority(app_db.br_link[app_idx].bd_addr);
}
}
}
}
break;
case JUDGE_EVENT_A2DP_START:
{
APP_PRINT_TRACE3("JUDGE_EVENT_A2DP_START: active_a2dp_idx %d, avrcp %d, stream %d",
active_a2dp_idx,
app_db.br_link[active_a2dp_idx].avrcp.play_status,
app_db.br_link[active_a2dp_idx].a2dp.is_streaming);
if (app_cfg_const.enable_multi_sco_disc_resume)
{
app_pause_other_a2dp_avrcp(active_hf_idx, true);
}
else
{
app_pause_other_a2dp_avrcp(active_hf_idx, false);
}
app_bt_policy_qos_param_update(app_db.br_link[app_idx].bd_addr, BP_TPOLL_A2DP_PLAY_EVENT);
}
break;
case JUDGE_EVENT_A2DP_DISC:
{
if (active_a2dp_idx == app_idx)
{
//app_bt_sniffing_stop(app_db.br_link[app_idx].bd_addr, BT_SNIFFING_TYPE_A2DP);
if (app_connected_profile_link_num(A2DP_PROFILE_MASK))
{
set_active_a2dp_avrcp(app_db.br_link[find_other_link_by_bond_prio(
app_idx)].bd_addr);
app_bond_set_priority(app_db.br_link[find_other_link_by_bond_prio(app_idx)].bd_addr);
}
}
app_bt_policy_qos_param_update(app_db.br_link[app_idx].bd_addr, BP_TPOLL_A2DP_STOP_EVENT);
}
break;
case JUDGE_EVENT_A2DP_STOP:
{
app_db.br_link[app_idx].avrcp.play_status = BT_AVRCP_PLAY_STATUS_PAUSED;
#if F_APP_MUTILINK_VA_PREEMPTIVE
app_db.br_link[app_idx].a2dp.stream_only = false;
#endif
if ((active_a2dp_idx == app_idx) && (a2dp.wait_resume_link_id == MAX_BR_LINK_NUM))
{
uint8_t i;
for (i = 0; i < MAX_BR_LINK_NUM; i++)
{
uint8_t idx = find_other_link_by_bond_prio(active_a2dp_idx);
if (app_db.br_link[idx].connected_profile &
(A2DP_PROFILE_MASK | AVRCP_PROFILE_MASK))
{
if ((idx != active_a2dp_idx) &&
(app_db.br_link[idx].a2dp.is_streaming == true))
{
APP_PRINT_TRACE2("JUDGE_EVENT_A2DP_STOP: active_a2dp_idx %d, idx %d", active_a2dp_idx, idx);
set_active_a2dp_avrcp_with_prio(idx);
break;
}
}
}
}
app_bt_policy_qos_param_update(app_db.br_link[app_idx].bd_addr, BP_TPOLL_A2DP_STOP_EVENT);
}
break;
case JUDGE_EVENT_MEDIAPLAYER_PLAYING:
{
if (app_cfg_const.disable_multilink_preemptive)
{
}
else
{
APP_PRINT_TRACE3("JUDGE_EVENT_MEDIAPLAYER_PLAYING: preemptive active_a2dp_idx %d, app_idx %d, streaming_fg %d",
active_a2dp_idx, app_idx, app_db.br_link[app_idx].a2dp.is_streaming);
if (app_db.br_link[app_idx].a2dp.is_streaming == true)
{
if (app_hfp_get_call_status() != APP_HFP_CALL_IDLE)
{
if (app_cfg_const.enable_multi_sco_disc_resume)
{
app_pause_other_a2dp_avrcp(active_hf_idx, true);
}
else
{
app_pause_other_a2dp_avrcp(active_hf_idx, false);
}
}
else
{
set_active_a2dp_avrcp(app_db.br_link[app_idx].bd_addr);
app_pause_other_a2dp_avrcp(app_idx, false);
app_bond_set_priority(app_db.br_link[app_idx].bd_addr);
}
}
}
app_bt_policy_qos_param_update(app_db.br_link[app_idx].bd_addr, BP_TPOLL_A2DP_PLAY_EVENT);
}
break;
case JUDGE_EVENT_MEDIAPLAYER_PAUSED:
{
}
break;
case JUDGE_EVENT_SNIFFING_STOP:
{
}
break;
default:
break;
}
if (active_a2dp_idx == app_idx)
{
if (event == JUDGE_EVENT_A2DP_START)
{
app_audio_a2dp_play_status_update(APP_A2DP_STREAM_A2DP_START);
if (app_cfg_const.timer_auto_power_off_while_phone_connected_and_anc_apt_off)
{
app_auto_power_off_disable(AUTO_POWER_OFF_MASK_AUDIO);
}
}
else if (event == JUDGE_EVENT_A2DP_STOP)
{
app_audio_a2dp_play_status_update(APP_A2DP_STREAM_A2DP_STOP);
if (app_cfg_const.timer_auto_power_off_while_phone_connected_and_anc_apt_off)
{
app_auto_power_off_enable(AUTO_POWER_OFF_MASK_AUDIO,
app_cfg_const.timer_auto_power_off_while_phone_connected_and_anc_apt_off);
}
}
}
APP_PRINT_TRACE4("app_judge_active_a2dp_idx_and_qos: 2 event %d, active_a2dp_idx %d, app_idx %d, "
"a2dp.wait_resume_link_id %d",
event, active_a2dp_idx, app_idx, a2dp.wait_resume_link_id);
}
HFP HF
HFP roles can be divided into AG and HF:
Audio Gateway (AG) is the device that is the gateway of the audio, both for input and output. Typical devices acting as Audio Gateways are cellular phones.
Hands-Free unit (HF) is the device acting as the Audio Gateway’s remote audio input and output mechanism. It also provides some remote control means.
The code flow of HFP HF in the receiver role is introduced here.
HFP HF UUID
HFP HF’s UUID registration is referred to in hfp_sdp_record()
.
static const uint8_t hfp_sdp_record[] =
{
//total length
SDP_DATA_ELEM_SEQ_HDR,
0x4B,//0x37,//0x59,
//attribute SDP_ATTR_SRV_CLASS_ID_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_SRV_CLASS_ID_LIST >> 8),
(uint8_t)SDP_ATTR_SRV_CLASS_ID_LIST,
SDP_DATA_ELEM_SEQ_HDR, //0x35
0x06, //6bytes
SDP_UUID16_HDR, //0x19
(uint8_t)(UUID_HANDSFREE >> 8), //0x111E
(uint8_t)(UUID_HANDSFREE),
SDP_UUID16_HDR, //0x19
(uint8_t)(UUID_GENERIC_AUDIO >> 8), //0x1203
(uint8_t)(UUID_GENERIC_AUDIO),
//attribute SDP_ATTR_PROTO_DESC_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_PROTO_DESC_LIST >> 8),
(uint8_t)SDP_ATTR_PROTO_DESC_LIST,
SDP_DATA_ELEM_SEQ_HDR, //0x35
0x0C, //12bytes
SDP_DATA_ELEM_SEQ_HDR, //0x35
0x03, //3bytes
SDP_UUID16_HDR, //0x19
(uint8_t)(UUID_L2CAP >> 8), //0x0100
(uint8_t)(UUID_L2CAP),
SDP_DATA_ELEM_SEQ_HDR, //0x35
0x05, //5bytes
SDP_UUID16_HDR, //0x19
(uint8_t)(UUID_RFCOMM >> 8), //0x0003
(uint8_t)(UUID_RFCOMM),
SDP_UNSIGNED_ONE_BYTE, //0x08
RFC_HFP_CHANN_NUM, //0x02
//attribute SDP_ATTR_BROWSE_GROUP_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_BROWSE_GROUP_LIST >> 8),
(uint8_t)SDP_ATTR_BROWSE_GROUP_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x03,
SDP_UUID16_HDR,
(uint8_t)(UUID_PUBLIC_BROWSE_GROUP >> 8),
(uint8_t)UUID_PUBLIC_BROWSE_GROUP,
/*
//attribute SDP_ATTR_LANG_BASE_ATTR_ID_LIST...it is used for SDP_ATTR_SRV_NAME
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_LANG_BASE_ATTR_ID_LIST >> 8),
(uint8_t)SDP_ATTR_LANG_BASE_ATTR_ID_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x09,
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_LANG_ENGLISH >> 8),
(uint8_t)SDP_LANG_ENGLISH,
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_CHARACTER_UTF8 >> 8),
(uint8_t)SDP_CHARACTER_UTF8,
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_BASE_LANG_OFFSET >> 8),
(uint8_t)SDP_BASE_LANG_OFFSET,
//attribute SDP_ATTR_SRV_NAME
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)((SDP_ATTR_SRV_NAME + SDP_BASE_LANG_OFFSET) >> 8),
(uint8_t)(SDP_ATTR_SRV_NAME + SDP_BASE_LANG_OFFSET),
SDP_STRING_HDR, //0x25 text string
0x0F, //15 bytes
0x48, 0x61, 0x6e, 0x64, 0x73, 0x2d, 0x66, 0x72, 0x65, 0x65,
0x20, 0x75, 0x6e, 0x69, 0x74, //"Hands-free unit"
*/
//attribute SDP_ATTR_PROFILE_DESC_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_PROFILE_DESC_LIST >> 8),
(uint8_t)SDP_ATTR_PROFILE_DESC_LIST,
SDP_DATA_ELEM_SEQ_HDR, //0x35
0x08, //8 bytes
SDP_DATA_ELEM_SEQ_HDR, //0x35
0x06, //6 bytes
SDP_UUID16_HDR, //0x19
(uint8_t)(UUID_HANDSFREE >> 8), //0x111E
(uint8_t)(UUID_HANDSFREE),
SDP_UNSIGNED_TWO_BYTE, //0x09
(uint8_t)(0x0107 >> 8), //version number default hf1.7
(uint8_t)(0x0107),
//Attribute SDP_ATTR_SRV_NAME
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)((SDP_ATTR_SRV_NAME + SDP_BASE_LANG_OFFSET) >> 8),
(uint8_t)(SDP_ATTR_SRV_NAME + SDP_BASE_LANG_OFFSET),
SDP_STRING_HDR,
0x0F,
'H', 'a', 'n', 'd', 's', '-', 'F', 'r', 'e', 'e', ' ', 'u', 'n', 'i', 't',
//attribute SDP_ATTR_SUPPORTED_FEATURES
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)((SDP_ATTR_SUPPORTED_FEATURES) >> 8),
(uint8_t)(SDP_ATTR_SUPPORTED_FEATURES),
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(0x003F >> 8),
(uint8_t)(0x003F)
};
HFP Profile Initialization
bt_hfp_init()
is utilized in app_hfp_init()
to initialize HFP profile, and to configure the maximum link number of HFP links.
It sets the HFP RFCOMM channel number and configures the supported HFP features. HFP HF features are initialized in app_cfg_const.hfp_brsf_capability
.
void app_hfp_hf_init(void)
{
if (app_cfg_const.supported_profile_mask & (HFP_PROFILE_MASK | HSP_PROFILE_MASK))
{
bt_hfp_init(app_cfg_const.hfp_link_number, RFC_HFP_CHANN_NUM,
RFC_HSP_CHANN_NUM, app_cfg_const.hfp_hf_brsf_capability);
audio_mgr_cback_register(app_hfp_audio_cback);
bt_mgr_cback_register(app_hfp_bt_cback);
app_timer_reg_cb(app_hfp_timeout_cb, &hfp.tmr.id);
}
}
void app_hfp_init(void)
{
#if (F_APP_SCO_XMIT_AG_SUPPORT || F_SOURCE_PLAY_SUPPORT)
app_hfp_ag_init();
#else
app_hfp_hf_init();
#endif
}
HFP Profile Linkback
HFP HF will call gap_br_start_sdp_discov()
in linkback_profile_search_start()
to discover the HFP SDP record in AG.
bool linkback_profile_search_start(uint8_t *bd_addr, uint32_t prof, bool is_special)
{
bool ret = true;
T_GAP_UUID_DATA uuid;
T_GAP_UUID_TYPE uuid_type = GAP_UUID16;
...
switch (prof)
{
...
case HFP_HF_PROFILE_MASK:
{
uuid.uuid_16 = UUID_HANDSFREE;
}
break;
...
if (ret)
{
if (gap_br_start_sdp_discov(bd_addr, uuid_type, uuid) != GAP_CAUSE_SUCCESS)
{
ret = false;
}
}
return ret;
}
Then, HFP HF will initiate a profile connection to AG by bt_hfp_connect_req()
.
Note
If both devices initiate a connection at the same time, both channels shall be closed and each device shall wait a random time (not more than 1s and not less than 100ms) and then try to initiate the connection again. If it is known which device is the master, that device can retry at once.
bool linkback_profile_connect_start(uint8_t *bd_addr, uint32_t prof, T_LINKBACK_CONN_PARAM *param)
{
bool ret = true;
...
switch (prof)
{
case HFP_PROFILE_MASK:
#if (F_APP_SCO_XMIT_AG_SUPPORT || F_SOURCE_PLAY_SUPPORT)
ret = bt_hfp_ag_connect_req(bd_addr, param->server_channel, true);
#else
ret = bt_hfp_connect_req(bd_addr, param->server_channel, true);
#endif
break;
return ret;
}
HFP Profile Callback Handler
For HFP HF, app_hfp_bt_cback()
function is used to handle Bluetooth Manager HFP HF-related events:
HFP profile connection request should be confirmed when receiving
BT_EVENT_HFP_CONN_IND
.HFP profile connection is completed when receiving
BT_EVENT_HFP_CONN_CMPL
.HFP profile disconnection is indicated when receiving
BT_EVENT_HFP_DISCONN_CMPL
.
static void app_hfp_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
T_BT_EVENT_PARAM *param = event_buf;
bool handle = true;
switch (event_type)
{
case BT_EVENT_HFP_CONN_IND:
{
T_APP_BR_LINK *p_link;
p_link = app_link_find_br_link(param->hfp_conn_ind.bd_addr);
if (p_link == NULL)
{
APP_PRINT_ERROR0("app_hfp_bt_cback: no acl link found");
return;
}
bt_hfp_connect_cfm(p_link->bd_addr, true);
}
break;
case BT_EVENT_HFP_CONN_CMPL:
{
T_APP_BR_LINK *p_link;
p_link = app_link_find_br_link(param->hfp_conn_cmpl.bd_addr);
if (p_link != NULL)
{
uint8_t link_number;
uint8_t pair_idx_mapping;
p_link->hfp.call_id_type_chk = true;
p_link->hfp.call_id_type_num = false;
app_bond_get_pair_idx_mapping(p_link->bd_addr, &pair_idx_mapping);
bt_hfp_speaker_gain_level_report(p_link->bd_addr, app_cfg_nv.voice_gain_level[pair_idx_mapping]);
bt_hfp_microphone_gain_level_report(p_link->bd_addr, 0x0a);
app_hfp_batt_level_report(p_link->bd_addr);
link_number = app_connected_profile_link_num(HFP_PROFILE_MASK | HSP_PROFILE_MASK);
if (link_number == 1)
{
app_hfp_set_active_idx(p_link->bd_addr);
app_bond_set_priority(p_link->bd_addr);
}
if (app_db.br_link[app_db.first_hf_index].hfp.state == APP_HF_STATE_STANDBY)
{
app_db.first_hf_index = p_link->id;
}
else
{
app_db.last_hf_index = p_link->id;
}
p_link->hfp.state = APP_HF_STATE_CONNECTED;
}
}
break;
case BT_EVENT_HFP_VOICE_RECOGNITION_ACTIVATION:
{
T_APP_BR_LINK *p_link;
p_link = app_link_find_br_link(param->hfp_voice_recognition_activation.bd_addr);
if (p_link != NULL)
{
if (p_link->hfp.call_status == APP_HFP_CALL_IDLE)
{
p_link->hfp.call_status = APP_HFP_VOICE_ACTIVATION_ONGOING;
}
app_hfp_update_call_status();
if (p_link->remote_device_vendor_id == APP_REMOTE_DEVICE_IOS)
{
app_start_timer(&hfp.tmr.indices[TIMER_CANCEL_VOICE_DAIL], "cancel_iphone_voice_dail",
hfp.tmr.id, TIMER_CANCEL_VOICE_DAIL, false,
p_link->id, 1000);
}
}
}
break;
case BT_EVENT_HFP_VOICE_RECOGNITION_DEACTIVATION:
{
T_APP_BR_LINK *p_link;
p_link = app_link_find_br_link(param->hfp_voice_recognition_deactivation.bd_addr);
if (p_link != NULL)
{
if (p_link->hfp.call_status == APP_HFP_VOICE_ACTIVATION_ONGOING)
{
p_link->hfp.call_status = APP_HFP_CALL_IDLE;
}
app_hfp_update_call_status();
}
}
break;
case BT_EVENT_HFP_CALL_STATUS:
{
T_APP_BR_LINK *p_link;
#if C_APP_END_OUTGOING_CALL_PLAY_CALL_END_TONE == 0
uint8_t temp_idx = hfp.active_link_id;
#endif
p_link = app_link_find_br_link(param->hfp_call_status.bd_addr);
if (p_link != NULL)
{
switch (param->hfp_call_status.curr_status)
{
case BT_HFP_CALL_IDLE:
{
p_link->hfp.call_status = APP_HFP_CALL_IDLE;
}
break;
case BT_HFP_CALL_INCOMING:
{
p_link->hfp.call_status = APP_HFP_CALL_INCOMING;
}
break;
case BT_HFP_CALL_OUTGOING:
{
p_link->hfp.call_status = APP_HFP_CALL_OUTGOING;
}
break;
case BT_HFP_CALL_ACTIVE:
{
p_link->hfp.call_status = APP_HFP_CALL_ACTIVE;
}
break;
case BT_HFP_CALL_HELD:
{
//p_link->call_status = APP_HFP_CALL_HELD;
}
break;
case BT_HFP_CALL_ACTIVE_WITH_CALL_WAITING:
{
p_link->hfp.call_status = APP_HFP_CALL_ACTIVE_WITH_CALL_WAITING;
}
break;
case BT_HFP_CALL_ACTIVE_WITH_CALL_HELD:
{
p_link->hfp.call_status = APP_HFP_CALL_ACTIVE_WITH_CALL_HELD;
}
break;
default:
break;
}
if ((app_cfg_const.enable_auto_answer_incoming_call == 1) &&
(p_link->hfp.call_status == APP_HFP_CALL_INCOMING))
{
hfp.auto_answer_call_interval = app_cfg_const.timer_hfp_auto_answer_call * 1000;
app_start_timer(&hfp.tmr.indices[TIMER_AUTO_ANSWER_CALL], "auto_answer_call",
hfp.tmr.id, TIMER_AUTO_ANSWER_CALL, p_link->id, false,
hfp.auto_answer_call_interval);
}
if (p_link->hfp.call_status == APP_HFP_CALL_IDLE)
{
p_link->hfp.call_id_type_chk = true;
p_link->hfp.call_id_type_num = false;
}
app_hfp_update_call_status();
if ((p_link->hfp.call_status == APP_HFP_VOICE_ACTIVATION_ONGOING) &&
(p_link->remote_device_vendor_id == APP_REMOTE_DEVICE_IOS))
{
app_start_timer(&hfp.tmr.indices[TIMER_CANCEL_VOICE_DAIL], "cancel_iphone_voice_dail",
hfp.tmr.id, TIMER_CANCEL_VOICE_DAIL, p_link->id, false,
1000);
}
if (app_cfg_nv.bud_role != REMOTE_SESSION_ROLE_SECONDARY)
{
if (param->hfp_call_status.prev_status == BT_HFP_CALL_INCOMING &&
param->hfp_call_status.curr_status == BT_HFP_CALL_IDLE)
{
if (app_db.reject_call_by_key)
{
app_db.reject_call_by_key = false;
app_audio_tone_type_play(TONE_HF_CALL_REJECT, false, false);
}
}
if (p_link->id == temp_idx &&
param->hfp_call_status.prev_status == BT_HFP_CALL_ACTIVE &&
param->hfp_call_status.curr_status == BT_HFP_CALL_IDLE)
{
app_audio_tone_type_play(TONE_HF_CALL_END, false, false);
}
if (p_link->id == hfp.active_link_id &&
param->hfp_call_status.prev_status != BT_HFP_CALL_ACTIVE &&
param->hfp_call_status.curr_status == BT_HFP_CALL_ACTIVE)
{
app_audio_tone_type_play(TONE_HF_CALL_ACTIVE, false, false);
}
if (param->hfp_call_status.prev_status != BT_HFP_CALL_OUTGOING &&
param->hfp_call_status.curr_status == BT_HFP_CALL_OUTGOING)
{
app_audio_tone_type_play(TONE_HF_OUTGOING_CALL, false, false);
}
}
}
if (param->hfp_call_status.curr_status == BT_HFP_CALL_ACTIVE ||
param->hfp_call_status.curr_status == BT_HFP_CALL_INCOMING ||
param->hfp_call_status.curr_status == BT_HFP_CALL_OUTGOING)
{
if (app_cfg_const.timer_auto_power_off_while_phone_connected_and_anc_apt_off)
{
app_auto_power_off_disable(AUTO_POWER_OFF_MASK_VOICE);
}
app_audio_set_bud_stream_state(BUD_STREAM_STATE_VOICE);
}
else if (param->hfp_call_status.curr_status == BT_HFP_CALL_IDLE)
{
if (app_cfg_const.timer_auto_power_off_while_phone_connected_and_anc_apt_off)
{
app_auto_power_off_enable(AUTO_POWER_OFF_MASK_VOICE,
app_cfg_const.timer_auto_power_off_while_phone_connected_and_anc_apt_off);
}
app_audio_set_bud_stream_state(BUD_STREAM_STATE_IDLE);
}
}
break;
case BT_EVENT_HFP_SERVICE_STATUS:
{
T_APP_BR_LINK *p_link;
p_link = app_link_find_br_link(param->hfp_service_status.bd_addr);
if (p_link != NULL)
{
p_link->hfp.service_status = param->hfp_service_status.status;
app_hfp_check_service_status();
}
}
break;
case BT_EVENT_HFP_CALL_WAITING_IND:
case BT_EVENT_HFP_CALLER_ID_IND:
{
if (app_cfg_nv.bud_role != REMOTE_SESSION_ROLE_SECONDARY)
{
T_APP_BR_LINK *br_link;
T_APP_LE_LINK *le_link;
char *number;
uint16_t num_len;
if (event_type == BT_EVENT_HFP_CALLER_ID_IND)
{
br_link = app_link_find_br_link(param->hfp_caller_id_ind.bd_addr);
le_link = app_link_find_le_link_by_addr(param->hfp_caller_id_ind.bd_addr);
number = (char *)param->hfp_caller_id_ind.number;
num_len = strlen(param->hfp_caller_id_ind.number);
}
else
{
br_link = app_link_find_br_link(param->hfp_call_waiting_ind.bd_addr);
le_link = app_link_find_le_link_by_addr(param->hfp_call_waiting_ind.bd_addr);
number = (char *)param->hfp_call_waiting_ind.number;
num_len = strlen(param->hfp_call_waiting_ind.number);
}
if (br_link != NULL)
{
if (br_link->hfp.call_id_type_chk == true)
{
if (br_link->connected_profile & PBAP_PROFILE_MASK)
{
if (bt_pbap_vcard_listing_by_number_pull(br_link->bd_addr, number) == false)
{
br_link->hfp.call_id_type_chk = false;
br_link->hfp.call_id_type_num = true;
}
}
else
{
br_link->hfp.call_id_type_chk = false;
br_link->hfp.call_id_type_num = true;
}
}
if (br_link->hfp.call_id_type_chk == false)
{
if (br_link->hfp.call_id_type_num == true)
{
T_CMD_PATH cmd_path = CMD_PATH_UART;
uint8_t app_link_id = 0xff;
T_CALLER_ID_TYPE call_id_type = CALLER_ID_NUMBER;
if (br_link->connected_profile & SPP_PROFILE_MASK)
{
app_link_id = br_link->id;
cmd_path = CMD_PATH_SPP;
}
else if (br_link->connected_profile & IAP_PROFILE_MASK)
{
app_link_id = br_link->id;
cmd_path = CMD_PATH_IAP;
}
else if (le_link != NULL)
{
app_link_id = le_link->id;
cmd_path = CMD_PATH_LE;
}
app_hfp_call_id_rpt(cmd_path, app_link_id, call_id_type, num_len, (uint8_t *)number);
}
}
}
}
}
break;
case BT_EVENT_HFP_RING_ALERT:
{
T_APP_BR_LINK *p_link;
p_link = app_link_find_br_link(param->hfp_ring_alert.bd_addr);
if (p_link != NULL)
{
p_link->hfp.is_inband_ring = param->hfp_ring_alert.is_inband;
if ((app_cfg_const.always_play_hf_incoming_tone_when_incoming_call == false) &&
((p_link->hfp.is_inband_ring == false) ||
(p_link->id != hfp.active_link_id))) /* TODO check active sco link */
{
if (hfp.ring_active == false && p_link->hfp.call_status == APP_HFP_CALL_INCOMING)
{
hfp.ring_active = true;
app_hfp_ring_alert(p_link);
}
}
}
}
break;
case BT_EVENT_HFP_SPK_VOLUME_CHANGED:
{
T_APP_BR_LINK *p_link;
p_link = app_link_find_br_link(param->hfp_spk_volume_changed.bd_addr);
uint8_t temp_buff[7];
if (p_link != NULL)
{
if (app_db.remote_session_state == REMOTE_SESSION_STATE_DISCONNECTED)
{
uint8_t pair_idx_mapping;
app_bond_get_pair_idx_mapping(p_link->bd_addr, &pair_idx_mapping);
app_cfg_nv.voice_gain_level[pair_idx_mapping] = (param->hfp_spk_volume_changed.volume *
app_dsp_cfg_vol.voice_out_volume_max +
0x0f / 2) / 0x0f;
memcpy(&temp_buff[0], ¶m->hfp_spk_volume_changed.bd_addr, 6);
temp_buff[6] = app_cfg_nv.voice_gain_level[pair_idx_mapping];
app_report_event(CMD_PATH_UART, APP_EVENT_VOLUME_SYNC, 0, temp_buff, sizeof(temp_buff));
app_audio_vol_set(p_link->sco.track_handle, app_cfg_nv.voice_gain_level[pair_idx_mapping]);
app_audio_track_spk_unmute(AUDIO_STREAM_TYPE_VOICE);
}
else
{
}
}
}
break;
case BT_EVENT_HFP_MIC_VOLUME_CHANGED:
{
}
break;
case BT_EVENT_REMOTE_CONN_CMPL:
{
if (app_cfg_nv.bud_role == REMOTE_SESSION_ROLE_PRIMARY)
{
app_hfp_voice_nr_enable();
}
}
break;
case BT_EVENT_HFP_DISCONN_CMPL:
{
T_APP_BR_LINK *p_link;
p_link = app_link_find_br_link(param->hfp_disconn_cmpl.bd_addr);
if (p_link != NULL)
{
if (param->hfp_disconn_cmpl.cause == (HCI_ERR | HCI_ERR_CONN_ROLESWAP))
{
//do nothing
}
else
{
p_link->hfp.call_status = APP_HFP_CALL_IDLE;
p_link->hfp.state = APP_HF_STATE_STANDBY;
if (app_db.first_hf_index == p_link->id)
{
app_db.first_hf_index = app_db.last_hf_index;
}
for (uint8_t i = 0; i < MAX_BR_LINK_NUM; i++)
{
if (app_db.br_link[i].connected_profile & (HFP_PROFILE_MASK | HSP_PROFILE_MASK))
{
app_hfp_set_active_idx(app_db.br_link[i].bd_addr);
app_bond_set_priority(app_db.br_link[i].bd_addr);
break;
}
}
if (app_hfp_get_call_status() != APP_HFP_CALL_IDLE)
{
app_hfp_update_call_status();
}
}
if ((param->hfp_disconn_cmpl.cause & ~HCI_ERR) != HCI_ERR_CONN_ROLESWAP)
{
app_hfp_check_service_status();
}
}
}
break;
default:
handle = false;
break;
}
if (handle == true)
{
APP_PRINT_INFO1("app_hfp_bt_cback: event_type 0x%04x", event_type);
}
}
Send HFP Vendor AT Command
bt_hfp_send_vnd_at_cmd_req()
is utilized in br_cmd_handle()
to send HFP vendor AT command.
void br_cmd_handle(uint8_t *cmd_ptr, uint16_t cmd_len, uint8_t cmd_path, uint8_t app_idx,
uint8_t *ack_pkt)
{
uint16_t cmd_id = (uint16_t)(cmd_ptr[0] | (cmd_ptr[1] << 8));
APP_PRINT_TRACE1("app_cmd br_cmd_handle: cmd_id 0x%04x", cmd_id);
typedef struct
{
uint16_t cmd_id;
uint8_t status;
} __attribute__((packed)) *ACK_PKT;
switch (cmd_id)
{
case CMD_BT_SEND_AT_CMD:
{
uint8_t app_index = cmd_ptr[2];
if (bt_hfp_send_vnd_at_cmd_req(app_db.br_link[app_index].bd_addr, (char *)&cmd_ptr[3]) == false)
{
ack_pkt[2] = CMD_SET_STATUS_DISALLOW;
}
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
}
}
HFP Call Status
HFP HF’s call status T_BT_HFP_CALL_STATUS
is updated with event BT_EVENT_HFP_CALL_STATUS
when HF receives related AG indicators or HF takes action to change them.
typedef enum t_bt_hfp_call_status
{
BT_HFP_CALL_IDLE = 0x00,
BT_HFP_CALL_INCOMING = 0x01,
BT_HFP_CALL_OUTGOING = 0x02,
BT_HFP_CALL_ACTIVE = 0x03,
BT_HFP_CALL_HELD = 0x04,
BT_HFP_CALL_ACTIVE_WITH_CALL_WAITING = 0x05,
BT_HFP_CALL_ACTIVE_WITH_CALL_HELD = 0x06,
} T_BT_HFP_CALL_STATUS;
HFP HF application could control the audio module and handle answer/reject action according to the call status,
which are processed in app_mmi_handle_action()
.
void app_mmi_hf_reject_call(void)
{
T_APP_BR_LINK *p_link;
T_APP_AUDIO_TONE_TYPE tone_type = TONE_TYPE_INVALID;
uint8_t active_hf_idx = app_hfp_get_active_idx();
p_link = &(app_db.br_link[active_hf_idx]);
if (app_cfg_nv.bud_role == REMOTE_SESSION_ROLE_SECONDARY)
{
return;
}
if (p_link != NULL)
{
app_hfp_stop_ring_alert_timer();
tone_type = (T_APP_AUDIO_TONE_TYPE)app_hfp_get_call_in_tone_type(p_link);
app_audio_tone_type_cancel(tone_type, false);
if (bt_hfp_call_terminate_req(p_link->bd_addr))
{
app_db.reject_call_by_key = true;
}
}
}
void app_mmi_hf_end_active_call(void)
{
uint8_t active_hf_idx = app_hfp_get_active_idx();
if (app_cfg_nv.bud_role == REMOTE_SESSION_ROLE_SECONDARY)
{
return;
}
if (app_db.br_link[app_hfp_get_active_idx()].hfp.call_status > APP_HFP_CALL_ACTIVE)
{
bt_hfp_release_active_call_accept_held_or_waiting_call_req(app_db.br_link[active_hf_idx].bd_addr);
}
else
{
bt_hfp_call_terminate_req(app_db.br_link[active_hf_idx].bd_addr);
}
}
void app_mmi_hf_end_outgoing_call(void)
{
uint8_t active_hf_idx = app_hfp_get_active_idx();
if (app_cfg_nv.bud_role == REMOTE_SESSION_ROLE_SECONDARY)
{
return;
}
bt_hfp_call_terminate_req(app_db.br_link[active_hf_idx].bd_addr);
}
void app_mmi_handle_action(uint8_t action)
{
uint8_t active_hf_idx = app_hfp_get_active_idx();
switch (action)
{
...
case MMI_HF_ANSWER_CALL:
{
T_APP_BR_LINK *p_link;
T_APP_AUDIO_TONE_TYPE tone_type = TONE_TYPE_INVALID;
p_link = &(app_db.br_link[active_hf_idx]);
if (app_cfg_nv.bud_role == REMOTE_SESSION_ROLE_SECONDARY)
{
return;
}
if (p_link != NULL)
{
app_hfp_stop_ring_alert_timer();
tone_type = (T_APP_AUDIO_TONE_TYPE)app_hfp_get_call_in_tone_type(p_link);
app_audio_tone_type_cancel(tone_type, false);
bt_hfp_call_answer_req(p_link->bd_addr);
}
}
break;
case MMI_HF_REJECT_CALL:
{
app_mmi_hf_reject_call();
}
break;
case MMI_HF_END_ACTIVE_CALL:
{
app_mmi_hf_end_active_call();
}
break;
case MMI_HF_END_OUTGOING_CALL:
{
app_mmi_hf_end_outgoing_call();
}
break;
...
}
}
MAP MCE
MAP roles can be divided into MSE and MCE:
Message Server Equipment (MSE) is the device that provides the message repository engine (i.e., has the ability to provide a client unit with messages that are stored in this device and notifications of changes in its message repository).
Message Client Equipment (MCE) is the device that uses the message repository engine of the MSE for browsing and displaying existing messages and to upload messages created on the MCE to the MSE.
The code flow of MAP MCE is introduced here.
MAP Initialization
Main function is invoked when the application is powered on or the chip is reset, MAP initialization function is included in app_test_init()
.
void app_test_init(void)
{
bt_map_init(1, RFC_MAP_MNS_CHANN_NUM, L2CAP_MAP_MNS_PSM, 0x0000024F);
...
os_task_create(&app_task_handle, "app_task", app_task, NULL, stack_size, 2);
...
os_sched_start();
return 0;
}
int main(void)
{
...
#if F_APP_TEST_SUPPORT
app_test_init();
#endif
...
}
SDP Record for MNS on MCE Device
There shall be one service record for the MCE device (Message Notification Service, server role).
#define RFC_MAP_MNS_CHANN_NUM 20 //user defined
#define L2CAP_MAP_MNS_PSM 0x1001 //user defined
#if F_APP_BT_PROFILE_MAP_MCE_SUPPORT
const uint8_t map_mce_sdp_record[] =
{
SDP_DATA_ELEM_SEQ_HDR,
0x49,
//attribute SDP_ATTR_SRV_CLASS_ID_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_SRV_CLASS_ID_LIST >> 8),
(uint8_t)SDP_ATTR_SRV_CLASS_ID_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x03,
SDP_UUID16_HDR,
(uint8_t)(UUID_MSG_NOTIFICATION_SERVER >> 8),
(uint8_t)(UUID_MSG_NOTIFICATION_SERVER),
//attribute SDP_ATTR_PROTO_DESC_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_PROTO_DESC_LIST >> 8),
(uint8_t)SDP_ATTR_PROTO_DESC_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x11,
SDP_DATA_ELEM_SEQ_HDR,
0x03,
SDP_UUID16_HDR,
(uint8_t)(UUID_L2CAP >> 8),
(uint8_t)(UUID_L2CAP),
SDP_DATA_ELEM_SEQ_HDR,
0x05,
SDP_UUID16_HDR,
(uint8_t)(UUID_RFCOMM >> 8),
(uint8_t)(UUID_RFCOMM),
SDP_UNSIGNED_ONE_BYTE,
RFC_MAP_MNS_CHANN_NUM, //channel number
SDP_DATA_ELEM_SEQ_HDR,
0x03,
SDP_UUID16_HDR,
(uint8_t)(UUID_OBEX >> 8),
(uint8_t)(UUID_OBEX),
//Attribute SDP_ATTR_SRV_NAME
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)((SDP_ATTR_SRV_NAME + SDP_BASE_LANG_OFFSET) >> 8),
(uint8_t)(SDP_ATTR_SRV_NAME + SDP_BASE_LANG_OFFSET),
SDP_STRING_HDR,
0x0B,
'R', 'e', 'a', 'l', 't', 'e', 'k', '-', 'M', 'N', 'S',
//attribute SDP_ATTR_PROFILE_DESC_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_PROFILE_DESC_LIST >> 8),
(uint8_t)SDP_ATTR_PROFILE_DESC_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x08,
SDP_DATA_ELEM_SEQ_HDR,
0x06,
SDP_UUID16_HDR,
(uint8_t)(UUID_MSG_ACCESS_PROFILE >> 8),
(uint8_t)UUID_MSG_ACCESS_PROFILE,
SDP_UNSIGNED_TWO_BYTE,
0x01,
0x04, //version 1.4
//attribute SDP_ATTR_L2C_PSM
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)((SDP_ATTR_L2C_PSM) >> 8),
(uint8_t)(SDP_ATTR_L2C_PSM),
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(L2CAP_MAP_MNS_PSM >> 8),
(uint8_t)(L2CAP_MAP_MNS_PSM),
//attribute SDP_ATTR_MAP_SUPPERTED_FEATS
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)((SDP_ATTR_MAP_SUPPERTED_FEATS) >> 8),
(uint8_t)(SDP_ATTR_MAP_SUPPERTED_FEATS),
SDP_UNSIGNED_FOUR_BYTE,
(uint8_t)(0x0000024F >> 24),
(uint8_t)(0x0000024F >> 16),
(uint8_t)(0x0000024F >> 8),
(uint8_t)(0x0000024F)
};
#endif
MAP Connect
OBEX connections in MAP shall always be initiated by the MCE device. The establishment of a Message Notification Service connection is done with the MCE as OBEX Server and the MSE as OBEX Client. The establishment of a Message Notification connection requires the previous establishment of a Message Access Service connection.
The MAP connection is realized by CMD, gap_br_start_sdp_discov()
is invoked to establish MAS through SDP using UUID in app_map_handle_cmd()
,
UUID needs to be set as UUID_MSG_ACCESS_SERVER
.
void app_map_handle_cmd(uint8_t app_idx, T_CMD_PATH cmd_path, uint8_t *cmd_ptr,
uint16_t cmd_len, uint8_t *ack_pkt)
{
uint16_t cmd_id = (uint16_t)(cmd_ptr[0] | (cmd_ptr[1] << 8));
...
switch (cmd_id)
{
case CMD_MAP_CONNECT:
{
T_GAP_UUID_DATA uuid_data;
uuid_data.uuid_16 = UUID_MSG_ACCESS_SERVER;
gap_br_start_sdp_discov(app_db.br_link[app_idx].bd_addr, GAP_UUID16, uuid_data);
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
}
}
void app_handle_cmd_set(uint8_t *cmd_ptr, uint16_t cmd_len, uint8_t cmd_path, uint8_t rx_seqn,
uint8_t app_idx)
{
uint16_t cmd_id;
uint8_t ack_pkt[3];
cmd_id = (uint16_t)(cmd_ptr[0] | (cmd_ptr[1] << 8));
ack_pkt[0] = cmd_ptr[0];
ack_pkt[1] = cmd_ptr[1];
ack_pkt[2] = CMD_SET_STATUS_COMPLETE;
...
switch (cmd_id)
{
case CMD_MAP_SDP_REQUEST...CMD_MAP_PUSH_MESSAGE:
app_map_handle_cmd(app_idx, (T_CMD_PATH)cmd_path, cmd_ptr, cmd_len, ack_pkt);
break;
}
}
bt_map_mas_msg_notification_set()
is used to register for being notified of the arrival of new messages in app_handle_cmd_set()
.
After this API is called, the MSE device will establish an OBEX connection for the message notification service.
void app_handle_cmd_set(uint8_t *cmd_ptr, uint16_t cmd_len, uint8_t cmd_path, uint8_t rx_seqn,
uint8_t app_idx)
{
...
case CMD_MAP_REG_MSG_NOTIFICATION:
{
struct
{
uint16_t cmd_id;
uint8_t enable;
} __attribute__((packed)) *params = (typeof(params)) cmd_ptr;
bt_map_mas_msg_notification_set(app_db.br_link[app_idx].bd_addr, params->enable);
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
...
}
bt_map_mns_connect_cfm()
accepts or rejects the incoming MNS Connection when receiving BT_EVENT_MAP_MNS_CONN_IND
.
static void app_test_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
T_BT_EVENT_PARAM *param = event_buf;
bool handle = true;
...
switch (event_type)
{
...
case BT_EVENT_MAP_MNS_CONN_IND:
{
bt_map_mns_connect_cfm(param->map_mns_conn_ind.bd_addr, true);
}
break;
}
}
MAP Get Message
When getting a message, bt_map_mas_folder_set()
is used to navigate the folders of the MSE.
bt_map_mas_folder_listing_get()
is used to retrieve the Folder-Listing object from the current folder of the MSE.
The Folder-Listing object is an XML object and shall be encoded in UTF-8.
In the context of the MAP profile, the Folder-Listing object shall not contain message entries.
It shall only contain folder entries located in the current folder level.
bt_map_mas_msg_listing_get()
is used to retrieve Messages-Listing objects from the MSE.
The Messages-Listing object is an XML object and shall be encoded in UTF-8.
bt_map_mas_msg_get()
is used to retrieve a specific message from the MSE, and the corresponding event is BT_EVENT_MAP_GET_MSG_CMPL
.
void app_handle_cmd_set(uint8_t *cmd_ptr, uint16_t cmd_len, uint8_t cmd_path, uint8_t rx_seqn,
uint8_t app_idx)
{
...
case CMD_MAP_SET_FOLDER:
{
struct
{
uint16_t cmd_id;
uint8_t folder;
} __attribute__((packed)) *params;
params = (typeof(params)) cmd_ptr;
bt_map_mas_folder_set(app_db.br_link[app_idx].bd_addr, (T_BT_MAP_FOLDER)params->folder);
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
case CMD_MAP_GET_FOLDER_LISTING:
{
struct
{
uint16_t cmd_id;
uint8_t max_list_count;
uint8_t start_offset;
} __attribute__((packed)) *params = (typeof(params)) cmd_ptr;
bt_map_mas_folder_listing_get(app_db.br_link[app_idx].bd_addr, params->max_list_count,
params->start_offset);
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
//inbox name is fixed here
case CMD_MAP_GET_MESSAGE_LISTING:
{
struct
{
uint16_t cmd_id;
uint8_t max_list_count;
uint8_t start_offset;
} __attribute__((packed)) *params = (typeof(params)) cmd_ptr;
uint8_t map_path_inbox[12] =
{
0x00, 0x69, 0x00, 0x6e, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x78, 0x00, 0x00
};
bt_map_mas_msg_listing_get(app_db.br_link[app_idx].bd_addr, map_path_inbox, sizeof(map_path_inbox),
params->max_list_count, params->start_offset);
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
case CMD_MAP_GET_MESSAGE:
{
struct
{
uint16_t cmd_id;
uint8_t handle_len;
uint8_t msg_handle[];
} __attribute__((packed)) *params = (typeof(params)) cmd_ptr;
bt_map_mas_msg_get(app_db.br_link[app_idx].bd_addr, params->msg_handle, params->handle_len, false);
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
...
}
MAP Push Message
bt_map_mas_msg_push()
is used to push a message to a folder of the MSE. In the case of sending messages through the MSE, the messages shall be uploaded into the ‘Outbox’ folder of the MSE.
In the case of uploading messages to the MSE, the messages shall not be uploaded into the ‘Outbox’ folder of the MSE,
but any other folder is permitted. In the case of sending messages through the MSE,
the MCE shall get a notification when the messages have been sent to the network and thus have been shifted by the MSE from the ‘Outbox’ to the ‘Sent’ folder.
case CMD_MAP_PUSH_MESSAGE:
{
struct
{
uint16_t cmd_id;
uint16_t msg_len;
uint8_t msg[];
} __attribute__((packed)) *params = (typeof(params)) cmd_ptr;
uint8_t map_path_outbox[14] =
{
0x00, 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x62,
0x00, 0x6f, 0x00, 0x78, 0x00, 0x00
};
bt_map_mas_msg_push(app_db.br_link[app_idx].bd_addr, map_path_outbox, sizeof(map_path_outbox),
false, false, params->msg, params->msg_len);
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
MAP Disconnect
bt_map_mas_disconnect_req()
is used to disconnect Message Access Service.
case CMD_MAP_DISCONNECT:
{
bt_map_mas_disconnect_req(app_db.br_link[app_idx].bd_addr);
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
PBAP PCE
PBAP roles can be divided into PSE and PCE:
Phone Book Server Equipment (PSE) is the device that contains the source phone book objects.
Phone Book Client Equipment (PCE) is the device that retrieves phone book objects from the Server Equipment.
The code flow of PBAP PCE is introduced here.
PBAP Initialization
bt_pbap_init()
is invoked in app_pbap_init()
when the application is powered on or the chip is reset.
void app_pbap_init(void)
{
if (app_cfg_const.supported_profile_mask & PBAP_PROFILE_MASK)
{
bt_pbap_init(app_cfg_const.pbap_link_number);
bt_mgr_cback_register(app_pbap_bt_cback);
app_timer_reg_cb(app_pbap_timeout_cb, &app_pbap_timer_id);
}
}
int main(void)
{
...
#if F_APP_BT_PROFILE_PBAP_PCE_SUPPORT
app_pbap_init();
#endif
...
}
PBAP Connect
We always use UUID_PBAP_PSE
to do service discovery. OBEX connections in PBAP shall always be initiated by the PCE device using bt_pbap_connect_req()
.
CMD_PBAP_CONNECT
is utilized to initiate SDP in app_pbap_cmd_handle()
, and bt_pbap_connect_req
will be called after receiving BT_EVENT_SDP_ATTR_INFO
.
void app_pbap_cmd_handle(uint8_t *cmd_ptr, uint16_t cmd_len, uint8_t cmd_path, uint8_t app_idx,
uint8_t *ack_pkt)
{
uint16_t cmd_id = (uint16_t)(cmd_ptr[0] | (cmd_ptr[1] << 8));
uint8_t active_hf_idx = app_hfp_get_active_idx();
switch (cmd_id)
{
case CMD_PBAP_CONNECT:
{
T_GAP_UUID_DATA uuid_data;
uuid_data.uuid_16 = UUID_PBAP_PSE;
gap_br_start_sdp_discov(app_db.br_link[app_idx].bd_addr, GAP_UUID16, uuid_data);
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
...
}
}
void app_handle_cmd_set(uint8_t *cmd_ptr, uint16_t cmd_len, uint8_t cmd_path, uint8_t rx_seqn,
uint8_t app_idx)
{
uint16_t cmd_id;
uint8_t ack_pkt[3];
cmd_id = (uint16_t)(cmd_ptr[0] | (cmd_ptr[1] << 8));
...
switch (cmd_id)
{
#if F_APP_PBAP_CMD_SUPPORT
case CMD_PBAP_DOWNLOAD...CMD_PBAP_DISCONNECT:
{
app_pbap_cmd_handle(cmd_ptr, cmd_len, cmd_path, app_idx, ack_pkt);
}
break;
#endif
...
}
}
static void app_test_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
T_BT_EVENT_PARAM *param = event_buf;
bool handle = true;
...
switch (event_type)
{
...
case BT_EVENT_SDP_ATTR_INFO:
{
T_BT_SDP_ATTR_INFO *sdp_info = ¶m->sdp_attr_info.info;
if (sdp_info->srv_class_uuid_data.uuid_16 == UUID_MSG_ACCESS_SERVER)
{
bt_map_mas_connect_over_rfc_req(param->sdp_attr_info.bd_addr, sdp_info->server_channel);
}
else if (sdp_info->srv_class_uuid_data.uuid_16 == UUID_PBAP_PSE)
{
bt_pbap_connect_req(param->sdp_attr_info.bd_addr, sdp_info->server_channel,
sdp_info->supported_feat);
}
}
break;
...
}
}
Note
It takes time to complete the authorization which involves user participation. So DO NOT initiate a PBAP connection immediately after pairing with phone. It is recommended to establish a PBAP connection when actually needed.
PBAP Pull
CMD_PBAP_DOWNLOAD
is utilized to download the phonebook of interest in app_pbap_cmd_handle()
,
users can choose the content to be pulled according to different cases such as current call history (cch), phonebook, all records, etc.
case CMD_PBAP_DOWNLOAD:
{
app_pbap_download_info_set_default();
switch (cmd_ptr[2])
{
...
case PBAP_DOWNLOAD_METHOD_ALL:
{
pbap_download_info.download_flag |= (PBAP_DOWNLOAD_ME_PB_MASK | PBAP_DOWNLOAD_SM_PB_MASK |
PBAP_DOWNLOAD_CCH_MASK);
}
break;
case PBAP_DOWNLOAD_METHOD_ALL_PB:
{
pbap_download_info.download_flag |= (PBAP_DOWNLOAD_ME_PB_MASK | PBAP_DOWNLOAD_SM_PB_MASK);
}
break;
case PBAP_DOWNLOAD_METHOD_CCH:
{
pbap_download_info.storage = BT_PBAP_PHONE_BOOK_CCH;
pbap_download_info.phone_book = BT_PBAP_PHONE_BOOK_CCH;
}
break;
default:
ack_pkt[2] = CMD_SET_STATUS_PARAMETER_ERROR;
break;
}
if (ack_pkt[2] == CMD_SET_STATUS_COMPLETE)
{
pbap_download_info.method = cmd_ptr[2];
pbap_download_info.filter = (uint64_t)(cmd_ptr[3] | (cmd_ptr[4] << 8) | (cmd_ptr[5] << 16) |
(cmd_ptr[6] << 24));
if (bt_pbap_phone_book_size_get(app_db.br_link[active_hf_idx].bd_addr,
(T_BT_PBAP_REPOSITORY)pbap_download_info.repos,
(T_BT_PBAP_PHONE_BOOK)pbap_download_info.phone_book) == false)
{
ack_pkt[2] = CMD_SET_STATUS_PROCESS_FAIL;
}
}
app_report_event(cmd_path, APP_EVENT_ACK, app_idx, ack_pkt, 3);
}
break;
...
Users can also control PBAP pause/continue/abort to pull information through CMD_PBAP_DOWNLOAD_CONTROL
,
where bt_pbap_pull_abort()
, bt_pbap_pull_continue()
are called:
case CMD_PBAP_DOWNLOAD_CONTROL:
{
switch (cmd_ptr[2])
{
case PBAP_DOWNLOAD_CONTROL_ABORT:
{
if (bt_pbap_pull_abort(app_db.br_link[active_hf_idx].bd_addr) == false)
{
ack_pkt[2] = CMD_SET_STATUS_PROCESS_FAIL;
}
else
{
app_stop_timer(&timer_idx_pbap_pull_continue);
}
}
break;
case PBAP_DOWNLOAD_CONTROL_SUSPEND:
{
enable_auto_pbap_download_continue_flag = false;
}
break;
case PBAP_DOWNLOAD_CONTROL_CONTINUE:
{
if (bt_pbap_pull_continue(app_db.br_link[active_hf_idx].bd_addr))
{
enable_auto_pbap_download_continue_flag = true;
}
else
{
ack_pkt[2] = CMD_SET_STATUS_PROCESS_FAIL;
}
}
break;
default:
ack_pkt[2] = CMD_SET_STATUS_PARAMETER_ERROR;
break;
}
app_report_event(cmd_path, APP_EVENT_ACK, app_idx, ack_pkt, 3);
if (ack_pkt[2] == CMD_SET_STATUS_COMPLETE)
{
uint8_t temp_buff[1];
temp_buff[0] = cmd_ptr[2];
app_report_event(cmd_path, APP_EVENT_PBAP_REPORT_SESSION_STATUS, app_idx, temp_buff,
sizeof(temp_buff));
}
}
break;
PBAP Disconnect
When the PBAP connection is no longer needed, call bt_pbap_disconnect_req()
in CMD_PBAP_DISCONNECT
to terminate the PBAP connection.
case CMD_PBAP_DISCONNECT:
{
bt_pbap_disconnect_req(app_db.br_link[app_idx].bd_addr);
app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt);
}
break;
CIS Acceptor
Bluetooth Low Energy Audio CAP roles can be divided into Acceptor, Initiator, and Commander. The Acceptor role can enable Bluetooth Low Energy Audio advertising and be connected by a remote device, control the music player and telephone call by MCP and CCP profile.
CIS Initialization
app_lea_acc_profile_init()
includes the initialization flow for ASCS, VCS, CSIS, MCP, CCP, and other modules.
void app_lea_acc_profile_init(void)
{
T_CAP_INIT_PARAMS cap_init_param = {0};
#if (F_APP_TMAP_CT_SUPPORT || F_APP_TMAP_UMR_SUPPORT)
app_lea_ascs_init();
#endif
#if F_APP_MCP_SUPPORT
app_lea_mcp_init();
#endif
#if F_APP_CCP_SUPPORT
app_lea_ccp_init();
#endif
app_lea_pacs_init();
#if F_APP_VCS_SUPPORT
app_lea_vcs_init();
#endif
#if F_APP_TAMP_BMR_SUPPORT
app_lea_bca_init();
#endif
app_lea_profile_bap_init();
#if F_APP_CSIS_SUPPORT
app_lea_csis_init(&cap_init_param);
#endif
app_lea_profile_cap_init(&cap_init_param);
#if F_APP_TMAS_SUPPORT
app_lea_profile_tmas_init();
#endif
#if (F_APP_TMAP_CT_SUPPORT || F_APP_TMAP_UMR_SUPPORT)
app_lea_uca_init();
#endif
}
CIS Connect
Firstly, the Acceptor needs to enable Bluetooth Low Energy Audio advertising, and then the remote device can scan and create a Bluetooth Low Energy Audio link to it.
The adv_interval_min
and adv_interval_max
parameters can be modified by the user to change the Bluetooth Low Energy Audio advertising interval.
Actually, the user can enable or disable the F_APP_LE_AUDIO_CIS_RND_ADDR
macro to use public or static random address for advertisement.
static void app_lea_adv_set(uint16_t audio_adv_flag, uint8_t service_num)
{
uint16_t audio_adv_len = 0;
T_LE_EXT_ADV_EXTENDED_ADV_PROPERTY adv_event_prop = LE_EXT_ADV_EXTENDED_ADV_CONN_UNDIRECTED;
uint16_t adv_interval_min = 0x40;
uint16_t adv_interval_max = 0x50;
#if F_APP_LE_AUDIO_CIS_RND_ADDR
T_GAP_LOCAL_ADDR_TYPE own_address_type = GAP_LOCAL_ADDR_LE_RANDOM;
#else
T_GAP_LOCAL_ADDR_TYPE own_address_type = GAP_LOCAL_ADDR_LE_PUBLIC;
#endif
T_GAP_REMOTE_ADDR_TYPE peer_address_type = GAP_REMOTE_ADDR_LE_PUBLIC;
uint8_t peer_address[6] = {0, 0, 0, 0, 0, 0};
T_GAP_ADV_FILTER_POLICY filter_policy = GAP_ADV_FILTER_ANY;
#if F_APP_LE_AUDIO_CIS_RND_ADDR
//the type of static random address is 0xC0
if ((app_cfg_nv.lea_static_random_addr[5] & 0xC0) != 0xC0)
{
le_gen_rand_addr(GAP_RAND_ADDR_STATIC, app_cfg_nv.lea_static_random_addr);
app_cfg_store(app_cfg_nv.lea_static_random_addr, 6);
APP_PRINT_TRACE1("app_lea_adv_set: cis_static_random_addr %s",
TRACE_BDADDR(app_cfg_nv.lea_static_random_addr));
}
#endif
audio_adv_len = app_lea_adv_ext_data(audio_adv_flag, service_num);
ble_ext_adv_mgr_init_adv_params(&app_lea_adv_handle, adv_event_prop, adv_interval_min,
adv_interval_max, own_address_type, peer_address_type, peer_address,
filter_policy, audio_adv_len, app_lea_adv_data,
sizeof(app_lea_adv_scan_rsp_data), app_lea_adv_scan_rsp_data, NULL);
ble_ext_adv_mgr_change_adv_phy(app_lea_adv_handle, GAP_PHYS_PRIM_ADV_1M, GAP_PHYS_2M);
ble_ext_adv_mgr_register_callback(app_lea_adv_cback, app_lea_adv_handle);
}
app_lea_adv_start()
enables Bluetooth Low Energy Audio advertising, and app_lea_adv_stop()
disables Bluetooth Low Energy Audio advertising.
void app_lea_adv_start(uint8_t mode)
{
uint8_t public_addr_lsb[6];
uint8_t len = 0;
gap_get_param(GAP_PARAM_BD_ADDR, public_addr_lsb);
APP_PRINT_INFO2("app_lea_adv_start: public addr %s mode %d",
TRACE_BDADDR(public_addr_lsb), mode);
if ((mode == LEA_ADV_MODE_PAIRING) && (app_link_get_le_link_num() > 2))
{
return;
}
if (app_lea_adv_state == BLE_EXT_ADV_MGR_ADV_DISABLED)
{
#if F_APP_LE_AUDIO_CIS_RND_ADDR
ble_ext_adv_mgr_set_random(app_lea_adv_handle, app_cfg_nv.lea_static_random_addr);
#endif
if (ble_ext_adv_mgr_enable(app_lea_adv_handle, 0) == GAP_CAUSE_SUCCESS)
{
if ((T_LEA_ADV_MODE)mode == LEA_ADV_MODE_LINK_LOSS_LINK_BACK)
{
app_start_timer(&timer_idx_lea_adv, "lea_adv_linkloss", app_lea_adv_timer_id,
APP_LEA_TMR_LINKLOSS, 0, false, LEA_ADV_TMR_LINK_LOST * 1000);
}
else if ((T_LEA_ADV_MODE)mode == LEA_ADV_MODE_PAIRING)
{
app_start_timer(&timer_idx_lea_adv, "lea_adv_pairing", app_lea_adv_timer_id,
APP_LEA_TMR_PAIRING, 0, false, LEA_ADV_TMR_PAIRING * 1000);
}
}
}
return;
}
void app_lea_adv_stop()
{
app_stop_timer(&timer_idx_lea_adv);
ble_ext_adv_mgr_disable(app_lea_adv_handle, 0);
}
For the Acceptor, the app_lea_uca_link_sm()
function is used to handle Bluetooth Low Energy Audio and Legacy events. It has three states: LEA_LINK_IDLE
, LEA_LINK_CONNECTED
, and LEA_LINK_STREAMING
to handle different events.
Based on some specific events, the state machine can switch its state with the app_lea_uca_link_state_change()
API.
void app_lea_uca_link_sm(uint16_t conn_handle, uint8_t event, void *p_data)
{
T_APP_LE_LINK *p_link;
p_link = app_link_find_le_link_by_conn_handle(conn_handle);
if (p_link == NULL)
{
return;
}
APP_PRINT_INFO3("app_lea_uca_link_sm: conn_handle 0x%x, event %x, %d", conn_handle, event,
p_link->lea_link_state);
switch (p_link->lea_link_state)
{
case LEA_LINK_IDLE:
app_lea_uca_link_idle(p_link, event, p_data);
break;
case LEA_LINK_CONNECTED:
app_lea_uca_link_connected(p_link, event, p_data);
break;
case LEA_LINK_STREAMING:
app_lea_uca_link_streaming(p_link, event, p_data);
break;
default:
break;
}
app_lea_uca_dump_ase_info(p_link);
app_lea_uca_dump_call_info(p_link);
}
static void app_lea_uca_link_state_change(T_APP_LE_LINK *p_link, T_LEA_LINK_STATE state)
{
APP_PRINT_INFO2("app_lea_uca_link_state_change: change from %d to %d", p_link->lea_link_state,
state);
p_link->lea_link_state = state;
}
For example, unicast audio state machine idle state app_lea_uca_link_idle()
handles LEA_CONNECT
event, and the state will change to LEA_LINK_CONNECTED
from LEA_LINK_IDLE
.
static void app_lea_uca_link_idle(T_APP_LE_LINK *p_link, uint8_t event, void *p_data)
{
APP_PRINT_INFO2("app_lea_uca_link_idle: event %x, state %x", event, p_link->lea_link_state);
switch (event)
{
case LEA_CONNECT:
{
// TODO: to avoid service discovery taking long time, change to 7.5ms
//ble_set_prefer_conn_param(p_link->conn_id, 0x06, 0x06, 0, 500);
app_lea_uca_link_state_change(p_link, LEA_LINK_CONNECTED);
app_bond_le_set_bond_flag((void *)p_link, BOND_FLAG_LEA);
app_sniff_mode_b2s_enable_all(SNIFF_DISABLE_MASK_LEA);
}
break;
default:
break;
}
}
CIS Media
For CIS Acceptor down-link audio path, app_lea_uca_handle_iso_data()
sends ISO data to DSP, which can decode LC3 audio data to PCM, and output audio by codec.
void app_lea_uca_handle_iso_data(T_BT_DIRECT_CB_DATA *p_data)
{
T_LEA_ASE_ENTRY *p_ase_entry;
p_ase_entry = app_lea_ascs_find_ase_entry_non_conn(LEA_ASE_DOWN_DIRECT,
(void *)&p_data->p_bt_direct_iso->conn_handle,
NULL);
if (p_ase_entry != NULL)
{
uint16_t written_len;
T_AUDIO_STREAM_STATUS status;
if (p_data->p_bt_direct_iso->iso_sdu_len != 0)
{
status = AUDIO_STREAM_STATUS_CORRECT;
}
else
{
status = AUDIO_STREAM_STATUS_LOST;
}
audio_track_write(p_ase_entry->track_handle, p_data->p_bt_direct_iso->time_stamp,
p_data->p_bt_direct_iso->pkt_seq_num,
status,
p_ase_entry->frame_num,
p_data->p_bt_direct_iso->p_buf + p_data->p_bt_direct_iso->offset,
p_data->p_bt_direct_iso->iso_sdu_len,
&written_len);
}
}
The Acceptor can control the remote connected device’s music player by mcp_client_write_media_cp()
to fill the specific parameter.
For example, the Acceptor can pause the music player.
T_MCP_CLIENT_WRITE_MEDIA_CP_PARAM param;
param.opcode = MCS_MEDIA_CONTROL_POINT_CHAR_OPCODE_PAUSE;
mcp_client_write_media_cp(p_link->conn_handle, 0, p_link->gmcs, ¶m, true);
CIS Conversation
For the conversation scenario, the acceptor also needs to handle the up-link audio path. app_lea_uca_audio_cback()
receives ISO data from the DSP which can encode PCM to LC3 audio data and send it to the remote device.
static void app_lea_uca_audio_cback(T_AUDIO_EVENT event_type, void *event_buf, uint16_t buf_len)
{
T_AUDIO_EVENT_PARAM *param = event_buf;
switch (event_type)
{
...
case AUDIO_EVENT_TRACK_DATA_IND:
{
uint32_t timestamp;
uint16_t seq_num;
uint8_t frame_num;
uint16_t read_len;
uint8_t *buf;
T_AUDIO_STREAM_STATUS status;
if (param->track_data_ind.len == 0)
{
return;
}
buf = malloc(param->track_data_ind.len);
if (buf == NULL)
{
return;
}
if (audio_track_read(param->track_data_ind.handle,
×tamp,
&seq_num,
&status,
&frame_num,
buf,
param->track_data_ind.len,
&read_len) == true)
{
uint16_t conn_handle = 0;
#if F_APP_CCP_SUPPORT
conn_handle = app_lea_ccp_get_active_conn_handle();
#endif
T_LEA_ASE_ENTRY *p_ase_entry = app_lea_ascs_find_ase_entry(LEA_ASE_TRACK, conn_handle,
param->track_data_ind.handle);
if (p_ase_entry != NULL)
{
if (app_lea_uca_mic_ignore_cnt == 0)
{
gap_iso_send_data((uint8_t *)buf, p_ase_entry->cis_conn_handle, param->track_data_ind.len, true,
timestamp,
seq_num);
}
if (app_lea_uca_mic_ignore_cnt > 0)
{
app_lea_uca_mic_ignore_cnt--;
}
}
}
free(buf);
}
break;
}
}
Actually, the acceptor can control the remote connected device’s telephone call by ccp_client_write_call_cp()
filling the specific parameter.
For example, the acceptor can accept the incoming call.
T_CCP_CLIENT_WRITE_CALL_CP_PARAM write_call_cp_param = {0};
write_call_cp_param.opcode = TBS_CALL_CONTROL_POINT_CHAR_OPCODE_ACCEPT;
write_call_cp_param.param.accept_opcode_call_index = p_call_entry->call_index;
ccp_client_write_call_cp(p_link->conn_handle, 0, p_link->gtbs, false, &write_call_cp_param);
CIS VCS
For LE Audio volume control, the Acceptor also needs to save the volume value and SPK mute state to FTL from the volume controller.
The function app_lea_vol_update_track_volume()
will configure the current audio track volume using the VCS value to accurately reflect the audio output.
static uint16_t app_lea_vcs_handle_vcs_msg(T_LE_AUDIO_MSG msg, void *buf)
{
...
switch (msg)
{
case LE_AUDIO_MSG_VCS_VOLUME_CP_IND:
{
T_APP_LE_LINK *p_link;
T_VCS_VOLUME_CP_IND *p_vcs_vol_state = (T_VCS_VOLUME_CP_IND *)buf;
p_link = app_link_find_le_link_by_conn_handle(p_vcs_vol_state->conn_handle);
if (p_link != NULL)
{
app_cfg_nv.lea_vol_setting = p_vcs_vol_state->volume_setting;
app_cfg_nv.lea_vol_out_mute = p_vcs_vol_state->mute;
APP_PRINT_TRACE3("app_lea_vcs_handle_vcs_msg: LE_AUDIO_MSG_VCS_VOLUME_CP_IND \
conn_handle 0x%02X, volume_setting 0x%02X, mute %d",
p_vcs_vol_state->conn_handle,
p_vcs_vol_state->volume_setting,
p_vcs_vol_state->mute);
}
}
break;
default:
break;
}
return cb_result;
}
static uint16_t app_lea_vol_ble_audio_cback(T_LE_AUDIO_MSG msg, void *buf)
{
...
switch (msg)
{
case LE_AUDIO_MSG_VCS_VOLUME_CP_IND:
{
T_APP_LE_LINK *p_link;
T_VCS_VOLUME_CP_IND *p_vcs_vol_state = (T_VCS_VOLUME_CP_IND *)buf;
p_link = app_link_find_le_link_by_conn_handle(p_vcs_vol_state->conn_handle);
if ((p_link != NULL))
{
app_lea_vol_update_track_volume();
}
}
break;
default:
break;
}
return cb_result;
}
The acceptor can change the local device’s audio volume, such as volume up/down, and SPK mute/unmute.
It will always notify the new volume state by calling vcs_set_param(&vcs_param)
to the remotely connected device.
T_VCS_PARAM vcs_param;
vcs_get_param(&vcs_param);
...
vcs_param.volume_setting = volume;
vcs_param.mute = mute;
vcs_param.volume_flags = VCS_USER_SET_VOLUME_SETTING;
vcs_param.change_counter++;
vcs_set_param(&vcs_param);
BIS Acceptor
BIS Acceptor Initialization
app_lea_acc_profile_init()
is utilized to initialize BIS Acceptor-related services and profiles.
app_lea_pacs_init()
is utilized to initialize PACS. app_lea_vcs_init()
is utilized to initialize VCS. app_lea_bca_init()
is utilized to initialize broadcast audio-related functions. app_lea_profile_bap_init()
is utilized to initialize BAP role and ISO capabilities. app_lea_csis_init()
is utilized to initialize CSIS.
app_lea_profile_cap_init()
is utilized to initialize CAS. app_lea_profile_tmas_init()
is utilized to initialize TMAS.
void app_lea_acc_profile_init(void)
{
T_CAP_INIT_PARAMS cap_init_param = {0};
app_lea_pacs_init();
#if F_APP_VCS_SUPPORT
app_lea_vcs_init();
#endif
#if F_APP_TAMP_BMR_SUPPORT
app_lea_bca_init();
#endif
app_lea_profile_bap_init();
#if F_APP_CSIS_SUPPORT
app_lea_csis_init(&cap_init_param);
#endif
app_lea_profile_cap_init(&cap_init_param);
#if F_APP_TMAS_SUPPORT
app_lea_profile_tmas_init();
#endif
}
BIS Acceptor Connect
The Acceptor must establish a connection with the Commander if it wants to be controlled by a remote Commander. To accomplish this, the Acceptor shall enable LE advertising before the Initiator scanning and creating a connection. The Acceptor could stop the advertising by calling app_lea_adv_stop()
if it wants to stop advertising or timeout.
void app_lea_adv_start(uint8_t mode)
{
uint8_t public_addr_lsb[6];
uint8_t len = 0;
gap_get_param(GAP_PARAM_BD_ADDR, public_addr_lsb);
APP_PRINT_INFO2("app_lea_adv_start: public addr %s mode %d",
TRACE_BDADDR(public_addr_lsb), mode);
if ((mode == LEA_ADV_MODE_PAIRING) && (app_link_get_le_link_num() > 2))
{
return;
}
if (app_lea_adv_state == BLE_EXT_ADV_MGR_ADV_DISABLED)
{
#if F_APP_LE_AUDIO_CIS_RND_ADDR
ble_ext_adv_mgr_set_random(app_lea_adv_handle, app_cfg_nv.lea_static_random_addr);
#endif
if (ble_ext_adv_mgr_enable(app_lea_adv_handle, 0) == GAP_CAUSE_SUCCESS)
{
if ((T_LEA_ADV_MODE)mode == LEA_ADV_MODE_LINK_LOSS_LINK_BACK)
{
app_start_timer(&timer_idx_lea_adv, "lea_adv_linkloss", app_lea_adv_timer_id,
APP_LEA_TMR_LINKLOSS, 0, false, LEA_ADV_TMR_LINK_LOST * 1000);
}
else if ((T_LEA_ADV_MODE)mode == LEA_ADV_MODE_PAIRING)
{
app_start_timer(&timer_idx_lea_adv, "lea_adv_pairing", app_lea_adv_timer_id,
APP_LEA_TMR_PAIRING, 0, false, LEA_ADV_TMR_PAIRING * 1000);
}
}
}
return;
}
void app_lea_adv_stop()
{
app_stop_timer(&timer_idx_lea_adv);
ble_ext_adv_mgr_disable(app_lea_adv_handle, 0);
}
app_lea_bca_sm()
function is used to handle Bluetooth Low Energy Audio events based on the corresponding state.
bool app_lea_bca_sm(uint8_t event, void *p_data)
{
APP_PRINT_INFO2("app_lea_bca_sm: event 0x%x, state 0x%x", event,
app_lea_bca_state_machine);
bool accept = true;
switch (app_lea_bca_state_machine)
{
case LEA_BCA_STATE_IDLE:
{
accept = app_lea_bca_state_idle(event, p_data);
}
break;
case LEA_BCA_STATE_PRE_SCAN:
case LEA_BCA_STATE_PRE_ADV:
accept = app_lea_bca_state_starting(event, p_data);
break;
case LEA_BCA_STATE_CONN_SCAN:
case LEA_BCA_STATE_CONN:
accept = app_lea_bca_state_conn(event, p_data);
break;
case LEA_BCA_STATE_SCAN:
accept = app_lea_bca_state_scan(event, p_data);
break;
case LEA_BCA_STATE_STREAMING:
accept = app_lea_bca_state_streaming(event, p_data);
break;
default:
accept = false;
break;
}
return accept;
}
BIS Acceptor Synchronize
If the Acceptor wants to synchronize a source autonomously without an assistant, it must scan the extended advertising and periodic advertising nearby, and create the Periodic Advertising (PA) and Broadcast Isochronous Stream (BIS) synchronization.
In order to receive the broadcast sync state and event, and to initiate state changes and further operations at a higher layer, the following broadcast audio sync callback function needs to be registered.
void app_lea_bca_sync_cb(T_BLE_AUDIO_SYNC_HANDLE handle, uint8_t cb_type, void *p_cb_data)
{
T_BLE_AUDIO_SYNC_CB_DATA *p_sync_cb = (T_BLE_AUDIO_SYNC_CB_DATA *)p_cb_data;
T_APP_LEA_BCA_DB *p_bc_source = app_lea_bca_find_device_by_bs_handle(handle);
if (p_bc_source == NULL)
{
return;
}
APP_PRINT_INFO1("app_lea_bca_sync_cb: cb_type %d", cb_type);
switch (cb_type)
{
...
case MSG_BLE_AUDIO_PA_SYNC_STATE:
{
APP_PRINT_INFO3("MSG_BLE_AUDIO_PA_SYNC_STATE: sync_state %d, action %d, cause 0x%x\r\n",
p_sync_cb->p_pa_sync_state->sync_state,
p_sync_cb->p_pa_sync_state->action,
p_sync_cb->p_pa_sync_state->cause);
T_APP_LEA_BCA_SYNC_CHECK para;
para.type = BS_TYPE_PA;
para.p_sync_cb = p_sync_cb;
para.p_bc_source = p_bc_source;
para.handle = handle;
//PA sync lost
if (((p_sync_cb->p_pa_sync_state->action == BLE_AUDIO_PA_LOST) ||
(p_sync_cb->p_pa_sync_state->action == BLE_AUDIO_PA_SYNC)) &&
(p_sync_cb->p_pa_sync_state->sync_state == GAP_PA_SYNC_STATE_TERMINATED) &&
(p_sync_cb->p_pa_sync_state->cause == 0x13e))
{
if (app_lea_bca_release_all(para))
{
app_lea_bca_tgt_active(false, (APP_BIS_BIS_CTRL_RESET_ACTIVE & APP_BIS_BIS_CTRL_RESET_SD_ACTIVE));
app_lea_mgr_tri_mmi_handle_action(MMI_BIG_START, true);
}
}
else if ((p_sync_cb->p_pa_sync_state->sync_state == GAP_PA_SYNC_STATE_SYNCHRONIZING_WAIT_SCANNING)
&&
!p_bc_source->is_past)
{
p_bc_source->is_past = 1;
app_lea_acc_scan_start();
}
else if (((p_sync_cb->p_pa_sync_state->action == BLE_AUDIO_PA_TERMINATE) &&
(p_sync_cb->p_pa_sync_state->cause == 0x144) &&
(p_sync_cb->p_pa_sync_state->sync_state == GAP_PA_SYNC_STATE_TERMINATED)))
{
if (app_lea_bca_release_all(para))
{
app_lea_bca_tgt_active(false, (APP_BIS_BIS_CTRL_RESET_ACTIVE & APP_BIS_BIS_CTRL_RESET_SD_ACTIVE));
}
}
else if (((p_sync_cb->p_pa_sync_state->action == BLE_AUDIO_PA_TERMINATE) &&
(p_sync_cb->p_pa_sync_state->cause == 0x116) &&
(p_sync_cb->p_pa_sync_state->sync_state == GAP_PA_SYNC_STATE_TERMINATED)))
{
if (app_lea_bca_state() == LEA_BCA_STATE_WAIT_TERM ||
app_lea_bca_state() == LEA_BCA_STATE_WAIT_RETRY)
{
if (app_lea_bca_release_all(para))
{
app_lea_bca_tgt_active(false, (APP_BIS_BIS_CTRL_RESET_ACTIVE & APP_BIS_BIS_CTRL_RESET_SD_ACTIVE));
}
}
}
p_bc_source->sync_state = p_sync_cb->p_pa_sync_state->sync_state;
}
break;
case MSG_BLE_AUDIO_BASE_DATA_MODIFY_INFO:
{
APP_PRINT_TRACE3("MSG_BLE_AUDIO_BASE_DATA_MODIFY_INFO: p_base_mapping %p, used %d, sd_source %d\r\n",
p_sync_cb->p_base_data_modify_info->p_base_mapping, p_bc_source->used, app_lea_bca_get_sd_source());
if (p_sync_cb->p_base_data_modify_info->p_base_mapping)
{
T_BASE_DATA_MAPPING *p_mapping = p_sync_cb->p_base_data_modify_info->p_base_mapping;
app_lea_bca_remap_bis(p_mapping, handle);
p_bc_source->used |= APP_LEA_BCA_BASE_DATA;
if (p_bc_source->used & APP_LEA_BCA_BIG_INFO &&
((app_lea_bca_bs_tgt.ctrl & APP_BIS_BIS_CTRL_SD_ACTIVE) == 0))
{
if (app_lea_bca_get_sd_source() != 0xff && p_bc_source->is_encryp)
{
bass_send_broadcast_code_required(p_bc_source->source_id);
}
else
{
app_lea_bca_big_establish(handle, p_bc_source->is_encryp);
}
}
}
}
break;
case MSG_BLE_AUDIO_PA_REPORT_INFO:
{
if (p_bc_source->big_state == BIG_SYNC_RECEIVER_SYNC_STATE_SYNCHRONIZED)
{
ble_audio_pa_terminate(p_bc_source->sync_handle);
}
}
break;
case MSG_BLE_AUDIO_PA_BIGINFO:
{
T_LE_BIGINFO_ADV_REPORT_INFO *p_adv_report_info = p_sync_cb->p_le_biginfo_adv_report_info;
APP_PRINT_INFO7("MSG_BLE_AUDIO_PA_BIGINFO: num_bis %d, %d, %d, %d, 0x%x ,%d, %d",
p_adv_report_info->num_bis,
p_adv_report_info->encryption,
app_lea_bca_state_machine,
p_bc_source->used,
app_lea_bca_get_sd_source(),
p_bc_source->is_encryp,
p_adv_report_info->encryption);
if (app_lea_bca_state_machine == LEA_BCA_STATE_WAIT_TERM)
{
break;
}
p_bc_source->used |= APP_LEA_BCA_BIG_INFO;
p_bc_source->is_encryp = p_adv_report_info->encryption;
if ((p_bc_source->used & APP_LEA_BCA_BASE_DATA) == 0)
{
break;
}
if (app_lea_bca_bs_tgt.ctrl & APP_BIS_BIS_CTRL_SD_ACTIVE)
{
T_BIG_MGR_SYNC_RECEIVER_BIG_CREATE_SYNC_PARAM sync_param;
app_lea_bca_apply_sync_pera(&sync_param, handle, p_adv_report_info->encryption);
}
else
{
if (app_lea_bca_get_sd_source() != 0xff &&
!p_bc_source->is_encryp && p_adv_report_info->encryption)
{
bass_send_broadcast_code_required(p_bc_source->source_id);
}
else
{
app_lea_bca_big_establish(handle, p_adv_report_info->encryption);
}
}
}
break;
case MSG_BLE_AUDIO_BIG_SYNC_STATE:
{
T_APP_LEA_BCA_SYNC_CHECK para;
para.type = BS_TYPE_BIG;
para.p_sync_cb = p_sync_cb;
para.p_bc_source = p_bc_source;
para.handle = handle;
APP_PRINT_INFO4("MSG_BLE_AUDIO_BIG_SYNC_STATE: sync_state %d, action %d,action role %d, cause 0x%x\r\n",
p_sync_cb->p_big_sync_state->sync_state,
p_sync_cb->p_big_sync_state->action,
p_sync_cb->p_big_sync_state->action_role,
p_sync_cb->p_big_sync_state->cause);
if ((p_sync_cb->p_big_sync_state->sync_state == BIG_SYNC_RECEIVER_SYNC_STATE_TERMINATED) &&
(p_sync_cb->p_big_sync_state->action == BLE_AUDIO_BIG_TERMINATE ||
p_sync_cb->p_big_sync_state->action == BLE_AUDIO_BIG_IDLE) &&
(p_sync_cb->p_big_sync_state->cause == 0))
{
uint8_t dev_info = 0;
APP_PRINT_INFO1("app_lea_bca_sync_cb: BIG_SYNC_RECEIVER_SYNC_STATE_TERMINATED, sync_handle: 0x%x",
p_bc_source->sync_handle);
if (app_lea_bca_release_all(para))
{
app_lea_bca_tgt_active(false, (APP_BIS_BIS_CTRL_RESET_ACTIVE & APP_BIS_BIS_CTRL_RESET_SD_ACTIVE));
}
}
else if ((p_sync_cb->p_big_sync_state->sync_state == BIG_SYNC_RECEIVER_SYNC_STATE_TERMINATED) &&
((p_sync_cb->p_big_sync_state->action == BLE_AUDIO_BIG_SYNC) ||
(p_sync_cb->p_big_sync_state->action == BLE_AUDIO_BIG_IDLE)) &&
((p_sync_cb->p_big_sync_state->cause == 0x113) || (p_sync_cb->p_big_sync_state->cause == 0x108) ||
(p_sync_cb->p_big_sync_state->cause == 0x13e)))
{
uint8_t dev_info = 0;
if (!app_lea_bca_release_all(para))
{
app_lea_bca_state_change(LEA_BCA_STATE_WAIT_RETRY);
}
else
{
app_lea_bca_tgt_active(false, (APP_BIS_BIS_CTRL_RESET_ACTIVE & APP_BIS_BIS_CTRL_RESET_SD_ACTIVE));
}
if (p_bc_source->big_state == BIG_SYNC_RECEIVER_SYNC_STATE_SYNCHRONIZED)
{
app_audio_tone_type_play(TONE_BIS_LOSST, false, false);
}
app_lea_mgr_tri_mmi_handle_action(MMI_BIG_START, true);
}
else if (p_sync_cb->p_big_sync_state->sync_state == BIG_SYNC_RECEIVER_SYNC_STATE_SYNCHRONIZED)
{
if (p_sync_cb->p_big_sync_state->action == BLE_AUDIO_BIG_SYNC)
{
T_BLE_AUDIO_BIS_INFO bis_sync_info;
bool result = ble_audio_get_bis_sync_info(p_bc_source->sync_handle,
&bis_sync_info);
if (result == false)
{
// goto failed;
}
APP_PRINT_ERROR4("BIG_SYNC_RECEIVER_SYNC_STATE_SYNCHRONIZED%d,%d,%d, source_id=%d: ", result,
bis_sync_info.bis_num, bis_sync_info.bis_info[0].bis_idx, p_bc_source->source_id);
uint8_t codec_id[5] = {1, 0, 0, 0, 0};
uint32_t controller_delay = 0x1122;
codec_id[0] = LC3_CODEC_ID;
APP_PRINT_INFO1("app_lea_bca_sync_cb: MSG_BLE_AUDIO_BIG_SYNC_STATE: bis_idx: %d",
p_bc_source->bis_idx);
ble_audio_bis_setup_data_path(handle, p_bc_source->bis_idx, codec_id, controller_delay, 0, NULL);
app_lea_acc_scan_stop();
}
}
if (p_sync_cb->p_big_sync_state->sync_state == BIG_SYNC_RECEIVER_SYNC_STATE_TERMINATED ||
p_sync_cb->p_big_sync_state->sync_state == BIG_SYNC_RECEIVER_SYNC_STATE_TERMINATING)
{
p_bc_source->used &= (APP_LEA_BCA_BASE_DATA_RESET & APP_LEA_BCA_BIG_INFO_RESET);
}
p_bc_source->big_state = p_sync_cb->p_big_sync_state->sync_state;
}
break;
...
default:
break;
}
return;
}
Bluetooth Audio Transceiver
A2DP Transparent Transmission
SPI and A2DP Transmit Manager
In the A2DP Transparent Transmission scenario, Device 1 is connected to the phone to receive A2DP data, which is then transmitted to Device 2 through SPI. Device 2 converts the received data into SBC or LC3 format and forwards it to the headphones through A2DP or BIS.
Initiate SPI.
For Device 1, its SPI role is set as a master, and the relevant functionality is enabled by activating the
F_APP_SPI_ROLE_MASTER
flag. The initialization function to achieve this isapp_spi_master_init()
.For Device 2, its SPI role is set as a slave, and the relevant functionality is enabled by activating the
F_APP_SPI_ROLE_SLAVE
flag. The initialization function isapp_spi_slave_init()
.A2DP Format Transmission.
Device 2 utilizes the Audio Pipe to convert data format, thus requiring knowledge of the specific input data format. When Device 1 receives the
BT_EVENT_A2DP_STREAM_START_IND
, it will obtain the negotiated data format and utilize theCMD_A2DP_XMIT_CONFIG
command to forward this information to Device 2 through SPI.//Device 1 sends data format information app_audio_bt_cback() |---app_audio_a2dp_stream_start_handle() |---app_a2dp_xmit_mgr_report_a2dp_param() void app_a2dp_xmit_mgr_report_a2dp_param(uint8_t *a2dp_param, uint16_t len) { app_report_event(CMD_PATH_SPI, CMD_A2DP_XMIT_CONFIG, 0, a2dp_param, len); }
Device 2 processes the received commands within the
app_a2dp_xmit_mgr_handle_cmd_set()
function. When it receives theA2DP FORMAT
command, the corresponding content is stored in thea2dp_xmit_mgr.a2dp_in_format
variable, which will be utilized by the Audio Pipe operations. Additionally, thea2dp_xmit_mgr.a2dp_in_format_ready
is set to true, effectively remembering the current state.//Device 2 receives data format information void app_a2dp_xmit_mgr_handle_cmd_set(uint8_t app_idx, uint8_t cmd_path, uint8_t *cmd_ptr, uint16_t cmd_len, uint8_t *ack_pkt) { ... switch (cmd_id) { ... case CMD_A2DP_XMIT_CONFIG: { uint8_t *p_param = &cmd_ptr[2]; uint16_t param_len = cmd_len - 2; app_a2dp_xmit_mgr_save_a2dp_in_format(p_param, param_len); } break; ... } }
void app_a2dp_xmit_mgr_save_a2dp_in_format(uint8_t *format_info, uint16_t param_len) { if (!a2dp_xmit_mgr.a2dp_in_format_ready) { memcpy(&a2dp_xmit_mgr.a2dp_in_format, format_info, param_len); a2dp_xmit_mgr.a2dp_in_format_ready = true; } app_a2dp_xmit_mgr_print_format("app_a2dp_xmit_mgr_save_a2dp_in_format: ", a2dp_xmit_mgr.a2dp_in_format); }
A2DP Data Transmission.
In the A2DP Transparent Transmission scenario, once Device 1 receives audio data from the mobile, it immediately forwards it to Device 2 without local playback. The audio data is transmitted via SPI together with the
CMD_A2DP_XMIT_AUDIO
command:static void app_audio_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len) { switch (event_type) { case BT_EVENT_A2DP_STREAM_DATA_IND: { ... #if (F_APP_A2DP_XMIT_SNK_SUPPORT || F_APP_A2DP_XMIT_SNK_LEA_SUPPORT) app_a2dp_xmit_mgr_report_a2dp_data(param->a2dp_stream_data_ind.payload, param->a2dp_stream_data_ind.len); #endif ... } } void app_a2dp_xmit_mgr_report_a2dp_data(uint8_t *p_data, uint16_t len) { app_report_event(CMD_PATH_SPI, CMD_A2DP_XMIT_AUDIO, 0, p_data, len); }
For Device 2, it cannot directly send the received audio data to the headphones because the format negotiated between Device 2 and the headphones is typically different from the format used for transmission between Device 1 and the mobile phone. Therefore, format conversion is required on the Device 2 side using the Audio Pipe. However, before proceeding with the conversion, it is important to note that upon receiving audio data, Device 2 will first store it in a pre-allocated ring buffer. This buffer serves as a temporary storage, making the data available for the subsequent Audio Pipe processing.
Currently, Device 2 supports two different output methods for audio transmission to the headphones: A2DP and BIS. To modularly build these two different output options, we have implemented the relevant functionalities for A2DP output in the
app_a2dp_xmit_src.c
file and for BIS output in theapp_a2dp_xmit_lea.c
file. The data processing functions for these outputs areapp_a2dp_xmit_src_handle_a2dp_data_ind()
andapp_a2dp_xmit_lea_handle_a2dp_data_ind()
respectively.void app_a2dp_xmit_mgr_handle_a2dp_data_in(uint8_t *p_audio, uint16_t audio_len) { switch (a2dp_xmit_mgr.xmit_play_route) { #if F_APP_A2DP_XMIT_SRC_SUPPORT case XMIT_PLAY_ROUTE_A2DP_SRC: { app_a2dp_xmit_src_handle_a2dp_data_ind(p_audio, audio_len); } break; #endif #if F_APP_A2DP_XMIT_SRC_LEA_SUPPORT case XMIT_PLAY_ROUTE_BIS: { app_a2dp_xmit_lea_handle_a2dp_data_ind(p_audio, audio_len); } break; #endif default: APP_PRINT_ERROR1("app_a2dp_xmit_mgr_handle_a2dp_data_in: invalid route path %d", a2dp_xmit_mgr.xmit_play_route); break; } }
It may have been noticed that when receiving data, the processing is determined based on the variable
a2dp_xmit_mgr.xmit_play_route
which distinguishes whether it should be handled by theapp_a2dp_xmit_src_handle_a2dp_data_ind()
function or theapp_a2dp_xmit_lea_handle_a2dp_data_ind()
function. The value of this variable determines the appropriate function to select for processing the received audio data. From the user’s perspective, a prior selection between A2DP or BIS output must be made by issuing the commandCMD_A2DP_XMIT_ROUTE_OUT_CTRL
through ACI Host. The Bluetooth Audio Transceiver APP will then store this choice in the variablea2dp_xmit_mgr.xmit_play_route
to perform audio data demultiplexing based on the selected output.void app_a2dp_xmit_mgr_handle_cmd_set(uint8_t app_idx, uint8_t cmd_path, uint8_t *cmd_ptr, uint16_t cmd_len, uint8_t *ack_pkt) { ... switch (cmd_id) { ... case CMD_A2DP_XMIT_SET_ROUTE_OUT: { a2dp_xmit_mgr.xmit_play_route = (T_A2DP_XMIT_PLAY_ROUTE)cmd_ptr[2]; app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt); } break; ... } }
A2DP Output
Request Starting Streaming.
For Device 2’s output, the initiation or termination is controlled by the
CMD_A2DP_XMIT_ROUTE_OUT_CTRL
command. For A2DP output, upon receiving theXMIT_PLAY_STATE_START
parameter, theapp_a2dp_xmit_src_stream_start_req()
function initiates anAVDTP_START
request to the mobile phone.void app_a2dp_xmit_mgr_handle_cmd_set(uint8_t app_idx, uint8_t cmd_path, uint8_t *cmd_ptr, uint16_t cmd_len, uint8_t *ack_pkt) { ... switch (cmd_id) { ... case CMD_A2DP_XMIT_ROUTE_OUT_CTRL: { T_A2DP_XMIT_PLAY_STATE type = (T_A2DP_XMIT_PLAY_STATE)cmd_ptr[2]; app_a2dp_xmit_mgr_route_out_start_stop(type); app_cmd_set_event_ack(cmd_path, app_idx, ack_pkt); } break; ... } } app_a2dp_xmit_mgr_route_out_start_stop() |---app_a2dp_xmit_src_start_stop() |---app_a2dp_xmit_src_stream_start_req() |---bt_a2dp_stream_start_req() static void app_a2dp_xmit_src_stream_start_req(void) { bt_a2dp_stream_start_req(a2d_src_ctrl.sink_addr); }
Subsequently, the phone establishes an A2DP connection and negotiates the audio format. The APP retrieves the negotiation result through
BT_EVENT_A2DP_CONFIG_CMPL
and stores the format in thea2d_src_ctrl.format_info_out
variable.app_audio_bt_cback() //BT_EVENT_A2DP_CONFIG_CMPL |---app_a2dp_xmit_src_save_a2dp_out_param() void app_a2dp_xmit_src_save_a2dp_out_param(uint8_t *format_info) { if (!a2d_src_ctrl.data_route_out_ready) { memcpy(&a2d_src_ctrl.format_info_out, format_info, sizeof(T_AUDIO_FORMAT_INFO)); a2d_src_ctrl.data_route_out_ready = true; } app_a2dp_xmit_mgr_print_format("app_a2dp_xmit_src_save_a2dp_out_param: ", a2d_src_ctrl.format_info_out); }
Create Audio Pipe.
Once the mobile phone accepts Device 2’s stream start request, the APP receives the
BT_EVENT_A2DP_STREAM_START_RSP
event. At this point, both the audio input format transmitted from Device 1 and the output format negotiated with the phone are available. Consequently, the APP can create the Audio Pipe for further processing.app_a2dp_xmit_src_bt_cback() //BT_EVENT_A2DP_STREAM_START_RSP |---app_a2dp_xmit_src_start_rsp_handler() |---app_a2dp_xmit_src_param_rcfg() static uint8_t app_a2dp_xmit_src_param_rcfg(void) { uint8_t res = A2DP_XMIT_MGR_SUCCESS; if (audio_pipe_handle != NULL) { res = A2DP_XMIT_MGR_PIPE_CREATE_ERROR; return res; } if (!app_a2dp_xmit_mgr_get_a2dp_in_format((uint8_t *)&a2d_src_ctrl.format_info_in)) { APP_PRINT_ERROR0("app_a2dp_xmit_lea_pipe_rcfg: a2dp format info does not exist"); res = A2DP_XMIT_MGR_SYS_ERROR; return res; } if (a2d_src_ctrl.data_route_out_ready) { T_AUDIO_FORMAT_INFO format_info_in = a2d_src_ctrl.format_info_in; T_AUDIO_FORMAT_INFO format_info_out = a2d_src_ctrl.format_info_out; if (audio_pipe_handle == NULL) { audio_pipe_handle = audio_pipe_create(format_info_in, format_info_out, a2dp_gain_table[app_cfg_nv.audio_gain_level[cur_pair_idx]], audio_pipe_callback); } } else { res = A2DP_XMIT_MGR_SYS_ERROR; } return res; }
Fill Data to Audio Pipe.
When creating the Audio Pipe, the
audio_pipe_callback()
function is registered. Upon receiving theAUDIO_PIPE_EVENT_STARTED
, it indicates that the Audio Pipe is ready to operate. In this event, theapp_a2dp_xmit_src_fill_pipe()
function is used to fill the first packet of data to the Audio Pipe. After completing the filling, anAUDIO_PIPE_EVENT_DATA_FILLED
event is received, allowing for the continued filling of data.When there is no data available in the ring buffer for filling, the
flag_pipe_get_data_empty
is set.audio_pipe_callback() //AUDIO_PIPE_EVENT_STARTED |---app_a2dp_xmit_src_fill_pipe() static uint16_t app_a2dp_xmit_src_fill_pipe(void) { uint16_t res = A2DP_XMIT_MGR_SUCCESS; uint8_t frame_info[2]; res = app_a2dp_xmit_mgr_a2dp_raw_data_read(frame_info, 2); if (res == A2DP_XMIT_MGR_SUCCESS) { uint16_t audio_len = (uint16_t)(frame_info[0] | (frame_info[1] << 8)); uint8_t *p_read_data_buf = malloc(audio_len); if (p_read_data_buf) { res = app_a2dp_xmit_mgr_a2dp_raw_data_read(p_read_data_buf, audio_len); if (res == A2DP_XMIT_MGR_SUCCESS) { flag_pipe_get_data_empty = false; APP_PRINT_INFO2("app_a2dp_xmit_src_fill_pipe: seq_num %d, audio_len %d", seq_num, audio_len); if (!audio_pipe_fill(audio_pipe_handle, 0, seq_num, AUDIO_STREAM_STATUS_CORRECT, 0, (void *)p_read_data_buf, audio_len)) { res = A2DP_XMIT_MGR_PIPE_FILL_ERROR; } else { seq_num++; } } else { flag_pipe_get_data_empty = true; } free(p_read_data_buf); } else { res = A2DP_XMIT_MGR_MEM_ERROR; } } else { flag_pipe_get_data_empty = true; } return res; }
If data is received from Device 1 and
flag_pipe_get_data_empty
is set, the data is directly taken and filled into the pipe for processing.app_a2dp_xmit_mgr_handle_a2dp_data_in() |---app_a2dp_xmit_src_handle_a2dp_data_ind() void app_a2dp_xmit_src_handle_a2dp_data_ind(uint8_t *data, uint16_t len) { if (a2d_src_ctrl.play_state != XMIT_PLAY_STATE_START) { APP_PRINT_ERROR1("app_a2dp_xmit_src_handle_a2dp_data_ind: play_state %d err", a2d_src_ctrl.play_state); return; } if (app_a2dp_xmit_mgr_a2dp_raw_data_write(data, len) == A2DP_XMIT_MGR_SUCCESS) { if (flag_pipe_get_data_empty) { app_a2dp_xmit_src_fill_pipe(); } } }
Send Generated Data to Earphones.
After converting the data format using the Audio Pipe, the APP will receive an
AUDIO_PIPE_EVENT_DATA_IND
event inaudio_pipe_cllback()
. Upon receiving this event, the transformed audio data can be obtained using theaudio pipe drain()
function and subsequently sent to the headphones with thebt_a2dp_stream_data_send()
function.audio_pipe_callback() //AUDIO_PIPE_EVENT_DATA_IND |---app_a2dp_xmit_src_pipe_data_ind() static uint16_t app_a2dp_xmit_src_pipe_data_ind(void) { uint16_t res = A2DP_XMIT_MGR_SUCCESS; uint16_t data_len = 0; uint16_t frame_number = 0; audio_pipe_drain(audio_pipe_handle, p_drain_data_buf, &data_len, &frame_number); if (data_len == 0) { res = A2DP_XMIT_MGR_PIPE_DRAIN_ERROR; } else { if (src_a2dp_credits) { if (bt_a2dp_stream_data_send(a2d_src_ctrl.sink_addr, a2dp_seq_num, (uint8_t)frame_number, p_drain_data_buf, data_len)) { a2dp_seq_num++; src_a2dp_credits--; } else { res = A2DP_XMIT_MGR_DATA_SEND_ERROR; } } else { APP_PRINT_WARN0("app_a2dp_xmit_src_pipe_data_ind: no reason need to send"); } } APP_PRINT_INFO1("app_a2dp_xmit_src_pipe_data_ind: res 0x%x", res); return res; }
Request Stopping Streaming.
To stop the audio conversion and data transmission on Device 2, similar to the initialization process, use the
CMD_A2DP_XMIT_ROUTE_OUT_CTRL
command with theXMIT_PLAY_STATE_IDLE
parameter. This action will initiate anAVDTP_SUSPEND
request, release the Audio Pipe, and clear any residual audio data from Device 1.app_a2dp_xmit_mgr_route_out_start_stop() |---app_a2dp_xmit_src_start_stop() |---app_a2dp_xmit_src_stream_stop() static void app_a2dp_xmit_src_stream_stop(void) { if (a2d_src_ctrl.bt_strm_state != A2DP_XMIT_SRC_STREAM_STOP) { bt_a2dp_stream_suspend_req(a2d_src_ctrl.sink_addr); } if (a2d_src_ctrl.play_state == XMIT_PLAY_STATE_START) { a2d_src_ctrl.play_state = XMIT_PLAY_STATE_IDLE; } if (audio_pipe_handle != NULL) { audio_pipe_release(audio_pipe_handle); audio_pipe_handle = NULL; } app_a2dp_xmit_mgr_a2dp_raw_data_clear(); app_dlps_enable(APP_DLPS_ENTER_CHECK_PLAYBACK); }
BIS Output
Initiate BIS and Start Streaming.
To utilize the BIS for audio output, first initialize it. By using the
CMD_LEA_BSRC_START
command, options for a single BIS output (stereo) or dual BIS outputs (Left and Right). Subsequently, use theCMD_A2DP_XMIT_ROUTE_OUT_CTRL
command with theXMIT_PLAY_STATE_START
parameter to establish one or two datapaths for BIS, making it into a streaming state.app_a2dp_xmit_mgr_handle_cmd_set() //CMD_A2DP_XMIT_ROUTE_OUT_CTRL |---app_a2dp_xmit_mgr_route_out_start_stop() |---app_a2dp_xmit_lea_src_start_stop() |---app_lea_bsrc_start() void app_a2dp_xmit_lea_src_start_stop(T_A2DP_XMIT_PLAY_STATE type) { APP_PRINT_INFO1("app_a2dp_xmit_lea_src_start_stop: %d", type); if (type == XMIT_PLAY_STATE_START) { app_lea_bsrc_start(); } else if (type == XMIT_PLAY_STATE_IDLE) { app_lea_bsrc_stop(true); } }
Create Audio Pipe.
Upon successful creation of the datapath, the output format will be saved, and an Audio Pipe will be generated in the
app_a2dp_xmit_lea_pipe_rcfg()
function.void app_lea_handle_bis_data_path_setup(T_LEA_SETUP_DATA_PATH *p_data) { ... if (p_data->path_direction == DATA_PATH_INPUT_FLAG) { if (app_db.bsrc_db.cfg_bis_num == app_db.iso_input_queue.count) { app_lea_save_data_format(p_iso_chann); #if F_APP_A2DP_XMIT_SRC_LEA_SUPPORT app_a2dp_xmit_lea_pipe_rcfg(); // TODO: put to BROADCAST_SOURCE_STATE_CONFIGURED? #endif } } }
void app_a2dp_xmit_lea_pipe_rcfg(void) { if (!app_a2dp_xmit_mgr_get_a2dp_in_format((uint8_t *)&a2dp_xmit_lea_ctrl.format_in)) { APP_PRINT_ERROR0("app_a2dp_xmit_lea_pipe_rcfg: a2dp format info does not exist"); return; } if (!app_lea_get_data_format((uint8_t *)&a2dp_xmit_lea_ctrl.format_out)) { APP_PRINT_ERROR0("app_a2dp_xmit_lea_pipe_rcfg: lc3 format info does not exist"); return; } app_a2dp_xmit_mgr_print_format("app_a2dp_xmit_lea_pipe_rcfg: ", a2dp_xmit_lea_ctrl.format_in); app_a2dp_xmit_mgr_print_format("app_a2dp_xmit_lea_pipe_rcfg: ", a2dp_xmit_lea_ctrl.format_out); if (a2dp_xmit_lea_ctrl.format_out.attr.lc3.chann_location == AUDIO_LOCATION_MONO) { a2dp_xmit_lea_ctrl.chnl_cnt = 1; } else { a2dp_xmit_lea_ctrl.chnl_cnt = __builtin_popcount( a2dp_xmit_lea_ctrl.format_out.attr.lc3.chann_location); } uint16_t len = a2dp_xmit_lea_ctrl.format_out.attr.lc3.frame_length * a2dp_xmit_lea_ctrl.chnl_cnt; a2dp_xmit_lea_ctrl.p_lea_send_buf = calloc(1, len); APP_PRINT_INFO1("app_a2dp_xmit_lea_pipe_rcfg: p_lea_send_buf len %d", len); if (a2dp_xmit_lea_ctrl.p_lea_send_buf == NULL) { APP_PRINT_ERROR0("app_a2dp_xmit_lea_pipe_rcfg: p_lea_send_buf malloc fail"); return; } if (audio_pipe_handle == NULL) { audio_pipe_handle = audio_pipe_create(a2dp_xmit_lea_ctrl.format_in, a2dp_xmit_lea_ctrl.format_out, app_dsp_cfg_vol.playback_volume_default, app_a2dp_xmit_lea_pipe_callback); } uint32_t sync_timer_period = 0; if (a2dp_xmit_lea_ctrl.format_out.attr.lc3.frame_duration == AUDIO_LC3_FRAME_DURATION_10_MS) { app_a2dp_xmit_lea_sync_timer_init(10000); } else { app_a2dp_xmit_lea_sync_timer_init(7500); } }
Fill Data to Audio Pipe.
When creating the Audio Pipe, the
app_a2dp_xmit_lea_pipe_callback()
function is registered. Upon receiving theAUDIO_PIPE_EVENT_STARTED
, it indicates that the Audio Pipe is ready to operate. In this event, theapp_a2dp_xmit_lea_fill_pipe()
function is used to fill the first packet of data to Audio Pipe. After completing the filling, anAUDIO_PIPE_EVENT_DATA_FILLED
event is received, allowing the continued filling of data.When there is no data available in the ring buffer for filling, the
flag_pipe_get_data_empty
is set.app_a2dp_xmit_lea_pipe_callback() //AUDIO_PIPE_EVENT_STARTED |---app_a2dp_xmit_lea_fill_pipe() static uint16_t app_a2dp_xmit_lea_fill_pipe(void) { uint16_t res = A2DP_XMIT_MGR_SUCCESS; uint8_t frame_info[2]; res = app_a2dp_xmit_mgr_a2dp_raw_data_read(frame_info, 2); if (res == A2DP_XMIT_MGR_SUCCESS) { uint16_t audio_len = (uint16_t)(frame_info[0] | (frame_info[1] << 8)); uint8_t *p_read_data_buf = malloc(audio_len); if (p_read_data_buf) { res = app_a2dp_xmit_mgr_a2dp_raw_data_read(p_read_data_buf, audio_len); if (res == A2DP_XMIT_MGR_SUCCESS) { flag_pipe_get_data_empty = false; APP_PRINT_INFO2("app_a2dp_xmit_lea_fill_pipe: pipe_fill_seq %d, audio_len %d", a2dp_xmit_lea_ctrl.pipe_fill_seq, audio_len); if (!audio_pipe_fill(audio_pipe_handle, 0, a2dp_xmit_lea_ctrl.pipe_fill_seq, AUDIO_STREAM_STATUS_CORRECT, 0, (void *)p_read_data_buf, audio_len)) { res = A2DP_XMIT_MGR_PIPE_FILL_ERROR; } else { a2dp_xmit_lea_ctrl.pipe_fill_seq++; } } else { flag_pipe_get_data_empty = true; } free(p_read_data_buf); } else { res = A2DP_XMIT_MGR_MEM_ERROR; } } else { flag_pipe_get_data_empty = true; } return res; }
If data is received from Device 1 and
flag_pipe_get_data_empty
is set, the data is directly taken and filled into the pipe for processing.app_a2dp_xmit_mgr_handle_a2dp_data_in() |---app_a2dp_xmit_lea_handle_a2dp_data_ind() void app_a2dp_xmit_lea_handle_a2dp_data_ind(uint8_t *p_audio, uint16_t audio_len) { if (a2dp_xmit_lea_ctrl.play_state == XMIT_PLAY_STATE_IDLE) { APP_PRINT_ERROR0("app_a2dp_xmit_lea_handle_a2dp_data_ind: brsc not started"); return; } if (app_a2dp_xmit_mgr_a2dp_raw_data_write(p_audio, audio_len) == A2DP_XMIT_MGR_SUCCESS) { if (flag_pipe_get_data_empty) { app_a2dp_xmit_lea_fill_pipe(); } } }
Send Generated Data to Earphones.
After converting the data format using the Audio Pipe, the APP will receive a
AUDIO_PIPE_EVENT_DATA_IND
event inapp_a2dp_xmit_lea_pipe_callback()
. Due to the fixed interval required for BIS packet transmission, the converted data cannot be directly sent out, instead, it needs to be stored in the ring buffer ofa2dp_xmit_lea_ctrl.ring_buf
using the function ofapp_a2dp_xmit_lea_iso_data_storage()
.app_a2dp_xmit_lea_pipe_callback //AUDIO_PIPE_EVENT_DATA_IND |---app_a2dp_xmit_lea_pipe_data_ind_handler static uint16_t app_a2dp_xmit_lea_pipe_data_ind_handler(void) { uint16_t res = A2DP_XMIT_MGR_SUCCESS; uint16_t data_len = 0; uint16_t frame_number = 0; audio_pipe_drain(audio_pipe_handle, p_drain_data_buf, &data_len, &frame_number); if (data_len == 0) { res = A2DP_XMIT_MGR_PIPE_DRAIN_ERROR; } else { res = app_a2dp_xmit_lea_iso_data_storage(p_drain_data_buf, data_len); } APP_PRINT_INFO3("app_a2dp_xmit_lea_pipe_data_ind_handler: data_len %d, frame_number %d, res %d", data_len, frame_number, res); return res; }
The packet transmission is controlled by a hardware timer. To ensure a continuous data flow for transmission, the hardware timer initiates its operation only after receiving three sets of converted data.
static bool app_a2dp_xmit_lea_pipe_callback(T_AUDIO_PIPE_HANDLE handle, T_AUDIO_PIPE_EVENT event, uint32_t param) { ... switch (event) { ... case AUDIO_PIPE_EVENT_DATA_IND: { if (app_a2dp_xmit_lea_pipe_data_ind_handler() == A2DP_XMIT_MGR_SUCCESS) { a2dp_xmit_lea_ctrl.pipe_ind_seq++; } if (!a2dp_xmit_lea_ctrl.timer_started && a2dp_xmit_lea_ctrl.pipe_ind_seq > 2) { app_a2dp_xmit_lea_sync_timer_start(); } } break; ... } ... }
When the set interval time elapses, the
app_a2dp_xmit_lea_iso_data_read()
function is utilized to retrieve the stored converted data from the ring buffer. Subsequently, the data in the transformed format is sent out using theapp_lea_iso_data_send()
function.app_a2dp_xmit_lea_sync_timer_handler() |---app_a2dp_xmit_lea_msg_send() |---app_a2dp_xmit_lea_msg_handle() |---app_a2dp_xmit_lea_send_iso_data() static void app_a2dp_xmit_lea_send_iso_data(void) { uint16_t res = A2DP_XMIT_MGR_SUCCESS; uint16_t len = a2dp_xmit_lea_ctrl.format_out.attr.lc3.frame_length * a2dp_xmit_lea_ctrl.chnl_cnt; uint8_t read_ret = app_a2dp_xmit_lea_iso_data_read(a2dp_xmit_lea_ctrl.p_lea_send_buf, len); if (read_ret != A2DP_XMIT_MGR_SUCCESS) { memset(a2dp_xmit_lea_ctrl.p_lea_send_buf, 0, len); } app_lea_iso_data_send(a2dp_xmit_lea_ctrl.p_lea_send_buf, len, false, 0, 0); }
Request Stopping Streaming.
To stop the audio conversion and data transmission on Device 2, similar to the initialization process, you need to use the
CMD_A2DP_XMIT_ROUTE_OUT_CTRL
command with theXMIT_PLAY_STATE_IDLE
parameter. This action will remove the established datapaths.app_a2dp_xmit_mgr_route_out_start_stop() |---app_a2dp_xmit_lea_src_start_stop() |---app_lea_bsrc_stop() void app_a2dp_xmit_lea_src_start_stop(T_A2DP_XMIT_PLAY_STATE type) { APP_PRINT_INFO1("app_a2dp_xmit_lea_src_start_stop: %d", type); if (type == XMIT_PLAY_STATE_START) { app_lea_bsrc_start(); } else if (type == XMIT_PLAY_STATE_IDLE) { app_lea_bsrc_stop(true); } }
Once the datapaths are removed, the Audio Pipe will be released, any residual audio data from Device 1 and generated by the Audio Pipe will be cleared in
app_a2dp_xmit_lea_handle_chann_remove()
.app_lea_handle_bis_data_path_remove() |---app_lea_remove_iso_chann() |---app_a2dp_xmit_lea_handle_chann_remove void app_a2dp_xmit_lea_handle_chann_remove(void) { APP_PRINT_INFO1("app_a2dp_xmit_lea_handle_chann_remove: iso_input_queue %d", app_db.iso_input_queue.count); if (app_db.iso_input_queue.count == 0) { if (a2dp_xmit_lea_ctrl.timer_started) { app_a2dp_xmit_lea_sync_timer_stop(); } a2dp_xmit_lea_ctrl.play_state = XMIT_PLAY_STATE_IDLE; if (audio_pipe_handle != NULL) { audio_pipe_release(audio_pipe_handle); audio_pipe_handle = NULL; } } if (a2dp_xmit_lea_ctrl.p_lea_send_buf != NULL) { free(a2dp_xmit_lea_ctrl.p_lea_send_buf); a2dp_xmit_lea_ctrl.p_lea_send_buf = NULL; } ring_buffer_clear(&a2dp_xmit_lea_ctrl.ring_buf); app_a2dp_xmit_mgr_a2dp_raw_data_clear(); }
HFP Transparent Transmission
SPI and HFP Transmit Manager
In the HFP Transparent Transmission scenario, Device 1 is connected to the phone to receive HFP data, which is then transmitted to Device 2 through SPI. Device 2 forwards it to the headphones after SCO is connected.
For Device 1, its SPI role is set as master, and the relevant functionality is enabled by activating the F_APP_SPI_ROLE_MASTER
flag.
For Device 2, its SPI role is configured as slave,
and the relevant functionality is enabled by activating the F_APP_SPI_ROLE_SLAVE
flag.
When Device 1 receives the BT_EVENT_SCO_CONN_CMPL
, it will obtain the negotiated data format and utilize the CMD_SCO_XMIT_CONFIG
command in app_audio_sco_conn_cmpl_handle()
to forward this information to Device 2 through SPI.
static void app_audio_sco_conn_cmpl_handle(uint8_t *bd_addr, uint8_t air_mode, uint8_t rx_pkt_len)
{
uint8_t pair_idx_mapping;
T_AUDIO_FORMAT_INFO format_info = {};
p_link = app_link_find_br_link(bd_addr);
...
#if (F_APP_SCO_XMIT_AG_SUPPORT || F_APP_SCO_XMIT_HF_SUPPORT)
app_report_event(CMD_PATH_SPI, CMD_SCO_XMIT_CONFIG, 0, (uint8_t *)&format_info,
sizeof(T_AUDIO_FORMAT_INFO));
...
#endif
...
}
static void app_audio_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
T_BT_EVENT_PARAM *param = event_buf;
bool handle = true;
uint8_t active_hf_idx = app_hfp_get_active_idx();
switch (event_type)
{
case BT_EVENT_SCO_CONN_CMPL:
{
...
if (param->sco_conn_cmpl.cause != 0)
{
break;
}
app_audio_sco_conn_cmpl_handle(param->sco_conn_cmpl.bd_addr, param->sco_conn_cmpl.air_mode,
param->sco_conn_cmpl.rx_pkt_len);
...
}
break;
...
}
Device 1 and Device 2 will respectively utilize app_sco_xmit_handle_sco_param()
and
app_sco_xmit_save_output_param()
to save the negotiated data format. After this,
both input and output channels can be marked as Ready by setting sco_ctrl.in_route_ready
.
static void app_sco_xmit_handle_sco_param(uint8_t *param, uint16_t param_len)
{
if (!sco_ctrl.in_route_ready)
{
memcpy(&sco_ctrl.format_info_in, param, param_len);
if (sco_ctrl.format_info_in.type == AUDIO_FORMAT_TYPE_MSBC)
{
APP_PRINT_INFO7("app_sco_xmit_handle_sco_param: type %d, "
"sample_rate %d, allocation_method %d, bitpool %d, block_length %d, chann_mode %d, subband_num %d",
sco_ctrl.format_info_in.type,
sco_ctrl.format_info_in.attr.msbc.sample_rate,
sco_ctrl.format_info_in.attr.msbc.allocation_method,
sco_ctrl.format_info_in.attr.msbc.bitpool,
sco_ctrl.format_info_in.attr.msbc.block_length,
sco_ctrl.format_info_in.attr.msbc.chann_mode,
sco_ctrl.format_info_in.attr.msbc.subband_num);
}
else if (sco_ctrl.format_info_in.type == AUDIO_FORMAT_TYPE_CVSD)
{
APP_PRINT_INFO4("app_sco_xmit_handle_sco_param: type %d, "
"sample_rate %d, chann_num %d, frame_duration %d",
sco_ctrl.format_info_in.type,
sco_ctrl.format_info_in.attr.cvsd.sample_rate,
sco_ctrl.format_info_in.attr.cvsd.chann_num,
sco_ctrl.format_info_in.attr.cvsd.frame_duration);
}
sco_ctrl.in_route_ready = true;
}
#if F_APP_SCO_XMIT_HF_SUPPORT
app_sco_xmit_param_recfg();
#endif
}
void app_sco_xmit_save_output_param(T_AUDIO_FORMAT_INFO *format_info)
{
if (!sco_ctrl.out_route_ready)
{
memcpy(&sco_ctrl.format_info_out, format_info, sizeof(T_AUDIO_FORMAT_INFO));
if (sco_ctrl.format_info_out.type == AUDIO_FORMAT_TYPE_MSBC)
{
APP_PRINT_INFO7("app_sco_xmit_save_output_param: type %d, "
"sample_rate %d, allocation_method %d, bitpool %d, block_length %d, chann_mode %d, subband_num %d",
sco_ctrl.format_info_out.type,
sco_ctrl.format_info_out.attr.msbc.sample_rate,
sco_ctrl.format_info_out.attr.msbc.allocation_method,
sco_ctrl.format_info_out.attr.msbc.bitpool,
sco_ctrl.format_info_out.attr.msbc.block_length,
sco_ctrl.format_info_out.attr.msbc.chann_mode,
sco_ctrl.format_info_out.attr.msbc.subband_num);
}
else if (sco_ctrl.format_info_out.type == AUDIO_FORMAT_TYPE_CVSD)
{
APP_PRINT_INFO4("app_sco_xmit_save_output_param: type %d, "
"sample_rate %d, chann_num %d, frame_duration %d",
sco_ctrl.format_info_out.type,
sco_ctrl.format_info_out.attr.cvsd.sample_rate,
sco_ctrl.format_info_out.attr.cvsd.chann_num,
sco_ctrl.format_info_out.attr.cvsd.frame_duration);
}
}
sco_ctrl.out_route_ready = true;
}
HFP Transmit Data
In the HFP Transparent Transmission scenario, once Device 1 receives SCO data from the mobile
while the reference event is BT_EVENT_SCO_DATA_IND
in app_audio_bt_cback()
,
it immediately forwards it to Device 2 without creating local track handle.
The SCO data is transmitted via SPI together with the CMD_SCO_XMIT_AUDIO
command.
CMD_SCO_XMIT_AUDIO
will be called in app_sco_xmit_handle_cmd_set()
, SCO data will be sent to
headphones via app_sco_xmit_send_sco()
.
static void app_audio_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
T_BT_EVENT_PARAM *param = event_buf;
bool handle = true;
uint8_t active_hf_idx = app_hfp_get_active_idx();
switch (event_type)
{
case BT_EVENT_SCO_DATA_IND:
{
...
p_link = app_link_find_br_link(param->sco_data_ind.bd_addr);
if (p_link == NULL)
{
break;
}
p_link->sco.seq_num++;
#if (F_APP_SCO_XMIT_HF_SUPPORT || F_APP_SCO_XMIT_AG_SUPPORT)
app_report_event(CMD_PATH_SPI, CMD_SCO_XMIT_AUDIO, 0, param->sco_data_ind.p_data,
param->sco_data_ind.length);
...
}
static void app_sco_xmit_send_sco(uint8_t *data, uint16_t len)
{
uint8_t active_hf_idx = app_hfp_get_active_idx();
T_APP_BR_LINK *p_link;
p_link = app_link_find_br_link(app_db.br_link[active_hf_idx].bd_addr);
if (p_link == NULL)
{
APP_PRINT_ERROR0("app_sco_xmit_send_sco: no br link found");
}
sco_seq_num++;
if (p_link->sco.duplicate_fst_data)
{
p_link->sco.duplicate_fst_data = false;
bt_sco_data_send(p_link->bd_addr, sco_seq_num - 1, data, len);
}
bt_sco_data_send(p_link->bd_addr, sco_seq_num, data, len);
}
void app_sco_xmit_handle_cmd_set(uint8_t app_idx, uint8_t cmd_path, uint8_t *cmd_ptr,
uint16_t cmd_len, uint8_t *ack_pkt)
{
uint16_t cmd_id = (uint16_t)(cmd_ptr[0] | (cmd_ptr[1] << 8));
...
switch (cmd_id)
{
...
case CMD_SCO_XMIT_AUDIO:
{
uint8_t *p_audio = &cmd_ptr[2];
uint16_t audio_len = cmd_len - 2;
if (flag_direct_send)
{
app_sco_xmit_send_sco(p_audio, audio_len);
}
...
}
break;
...
}
}
The specific operation process can refer to ACI Host CLI Test (HFP Transfer).
Bluetooth Audio Transmitter MP3
The path of the playback code is src\sample\bt_audio_trx\music_playback
. The specific operation process can refer to ACI Host CLI Test.
Local Playback
The code of the local playback part is in playback_stream_ctrl.c
.
The music start process is as follows.
Receive Data
Device will enter MUSIC_FLOW_JUMP_HEAD
state after receiving the music data transmitted by host in the idle state.
//music flow state
typedef enum
{
MUSIC_FLOW_IDLE = 0x00,
MUSIC_FLOW_JUMP_HEAD = 0x01,
MUSIC_FLOW_CREAT_TRACK = 0x02,
MUSIC_FLOW_START = 0x03,
MUSIC_FLOW_STARTED = 0x04
} T_MUSIC_FLOW_STATE;
static struct
{
T_MUSIC_MODE play_mode;
T_MUSIC_STATE play_state;
uint8_t play_flow;
uint8_t preq_pkts;
uint16_t frame_size;
uint32_t header_len;
bool seamless_start;
bool en_report_play_time;
bool is_short_audio;
} music_info;
uint8_t app_music_start(void)
{
uint8_t res = MUSIC_STATE_ERROR;
APP_PRINT_INFO1("app_music_start: play_flow:%d", music_info.play_flow);
if (music_info.play_flow == MUSIC_FLOW_IDLE)
{
music_info.play_flow = MUSIC_FLOW_JUMP_HEAD;
}
if ((music_info.play_flow == MUSIC_FLOW_JUMP_HEAD) &&
(stream_get_data_size() > STREAM_BUF_CHECK_LEVEL ||
PLAYBACK_AUDIO_FILE_STOPPING == playback_audio_file_get_state()))
{
if (app_music_enter_state(MUSIC_FLOW_JUMP_HEAD))
{
music_info.play_flow = MUSIC_FLOW_CREAT_TRACK;
res = MUSIC_NEXT_STATE_ERROR;
}
}
...
}
Estimate Ring Buffer Water Level
When the file header transmission is completed in app_music_jump_file_header()
,
APP will estimate the water level of play ring buffer according to the current data in app_music_play_get_threshold()
.
After estimating the water level, play_flow
will enter MUSIC_FLOW_CREAT_TRACK
state.
static bool app_music_jump_file_header(void)
{
bool head_jump_ok = false;
uint8_t head_type = 0xFF;
uint32_t read_len = 0;
uint32_t ring_buf_size = stream_get_data_size();
APP_PRINT_WARN2("app_watch_music_judge_file_header, header len: 0x%x, ring_buf_size: 0x%x",
music_info.header_len, ring_buf_size);
if (ring_buf_size <= 0)
{
return false;
}
if (music_info.header_len == 0)
{
head_type = playback_audio_file_get_header(&music_info.header_len);
switch (head_type)
{
case PLAYBACK_AF_ERR_HEADER:
case PLAYBACK_AF_NOT_HEADER:
ring_buf_size = stream_get_data_size();
stream_remove_data(ring_buf_size, &read_len);
music_info.header_len -= read_len;
head_jump_ok = false;
break;
case PLAYBACK_AF_IS_HEADER:
if (stream_get_data_size() > music_info.header_len)
{
stream_remove_data(music_info.header_len, &read_len);
music_info.header_len -= read_len;
head_jump_ok = true;
}
else if (music_info.header_len > STREAM_BUF_HIGH_LEVEL)
{
ring_buf_size = stream_get_data_size();
stream_remove_data(ring_buf_size, &read_len);
music_info.header_len -= read_len;
head_jump_ok = false;
}
break;
case PLAYBACK_AF_DATA_FRAME:
head_jump_ok = true;
break;
default:
break;
}
}
else
{
ring_buf_size = stream_get_data_size();
if (ring_buf_size >= music_info.header_len)
{
stream_remove_data(music_info.header_len, &read_len);
music_info.header_len -= read_len;
}
else
{
stream_remove_data(ring_buf_size, &read_len);
music_info.header_len -= read_len;
}
if (music_info.header_len == 0)
{
head_jump_ok = true;
}
}
return head_jump_ok;
}
static bool app_music_enter_state(uint8_t state)
{
bool ret_state = false;
switch (state)
{
case MUSIC_FLOW_IDLE:
{
ret_state = true;
}
break;
case MUSIC_FLOW_JUMP_HEAD:
{
ret_state = app_music_jump_file_header();
}
break;
...
}
static uint32_t app_music_play_get_threshold(void)
{
uint32_t start_level = 0;
if (music_info.is_short_audio)
{
start_level = (music_info.preq_pkts) * music_info.frame_size;
}
else
{
uint8_t frame_num_max = STREAM_BUF_HIGH_LEVEL / music_info.frame_size;
if (music_info.frame_size > 2048)
{
start_level = STREAM_BUF_HIGH_LEVEL;
}
else if (music_info.frame_size > 1024)
{
if (frame_num_max > 10)
{
start_level = 10 * music_info.frame_size;
}
else
{
start_level = STREAM_BUF_HIGH_LEVEL;
}
}
else
{
start_level = (music_info.preq_pkts + 8) * music_info.frame_size;
}
}
APP_PRINT_INFO2("app_music_play_get_threshold: 0x%x, is_short_audio: %d", start_level,
music_info.is_short_audio);
return start_level;
}
Start Play Audio Track
After the data is filled in (referring to playback_audio_file_is_end()
) and reaches the preset water level, create and start the audio track playback.
uint8_t app_music_start(void)
{
...
if ((music_info.play_flow == MUSIC_FLOW_CREAT_TRACK) &&
(stream_get_data_size() > STREAM_BUF_CHECK_LEVEL ||
PLAYBACK_AUDIO_FILE_STOPPING == playback_audio_file_get_state()))
{
if (app_music_enter_state(MUSIC_FLOW_CREAT_TRACK))
{
music_info.play_flow = MUSIC_FLOW_START;
res = MUSIC_NEXT_STATE_ERROR;
}
}
if (music_info.play_flow == MUSIC_FLOW_START)
{
if (stream_get_data_size() > app_music_play_get_threshold())
{
if (app_music_enter_state(MUSIC_FLOW_START))
{
res = MUSIC_SUCCESS;
music_info.play_flow = MUSIC_FLOW_STARTED;
app_music_send_player_status(MUSIC_PLAYER_PLAYING);
}
}
}
...
}
static bool app_music_enter_state(uint8_t state)
{
bool ret_state = false;
switch (state)
{
case MUSIC_FLOW_CREAT_TRACK:
{
uint16_t u16_res = 0;
T_PLAYBACK_AF_FORMAT_INFO get_fmt_info;
T_PLAY_SET_INFO set_play_info;
music_info.header_len = 0;
u16_res = audio_fs_decode_before_get_frame(NULL);
if (u16_res != 0)
{
ret_state = false;
break;
}
u16_res = playback_audio_file_get_audio_info(&get_fmt_info);
if (u16_res != 0)
{
ret_state = false;
break;
}
else
{
music_info.frame_size = get_fmt_info.frame_size;
playback_stream_get_music_info(get_fmt_info, &set_play_info);
music_info.preq_pkts = set_play_info.preq_pkts;
ret_state = true;
}
}
break;
case MUSIC_FLOW_START:
{
if (music_info.play_mode == MUSIC_LOCAL_PLAY)
{
playback_stream_ctrl_start();
}
ret_state = true;
}
break;
...
}
music_info.play_flow
will enter MUSIC_FLOW_START
, the API playback_stream_ctrl_start()
in
playback_stream_ctrl.c
will be called, which controls the play flow of playback.
As a protection, the track that may exist already will be released before the audio track creation.
When the data is lower than the preset water level, continue to request data playback from the host in playback_stream_put_data()
.
uint8_t playback_stream_ctrl_start(void)
{
uint8_t res = PLAYBACK_SUCCESS;
uint32_t sampling_frequency = 0;
APP_PRINT_TRACE0("playback_stream_ctrl_start ++");
app_dlps_disable(APP_DLPS_ENTER_CHECK_PLAYBACK);
if (playback_track_handle)
{
audio_track_release(playback_track_handle);
playback_track_handle = NULL;
}
if (playback.eq_instance != NULL)
{
eq_release(playback.eq_instance);
playback.eq_instance = NULL;
}
if ((res = playback_stream_parameter_recfg()) != 0)
{
return res;
}
playback.buffer_state = PLAYBACK_BUF_NORMAL;
playback.play_state = PLAYBACK_STATE_PLAY;
playback_stream_volume_set(playback.volume);
if (playback_track_handle != NULL)
{
playback_stream_get_sample_rate(&sampling_frequency);
if ((sampling_frequency == SAMPLE_RATE_44K) || (sampling_frequency == SAMPLE_RATE_48K))
{
app_eq_idx_check_accord_mode();
playback.eq_instance = app_eq_create(EQ_CONTENT_TYPE_AUDIO, EQ_STREAM_TYPE_AUDIO, SPK_SW_EQ,
app_db.spk_eq_mode, app_cfg_nv.eq_idx);
if (playback.eq_instance != NULL)
{
eq_enable(playback.eq_instance);
audio_track_effect_attach(playback_track_handle, playback.eq_instance);
}
}
else
{
APP_PRINT_WARN1("EQ don't support this sample rate: %d", sampling_frequency);
}
audio_track_start(playback_track_handle);
}
return res;
}
//need put data
void playback_stream_put_data(uint8_t pkt_num)
{
uint16_t res = 0;
uint8_t frame_cnt = 0;
uint16_t time_ms = playback.put_data_time_ms;
T_PLAYBACK_FRAME_PKT playback_frame;
static uint16_t s_seq_num = 0;
APP_PRINT_INFO1("playback_stream_put_data pkt_num: %d", pkt_num);
while (frame_cnt < pkt_num)
{
// This maybe AUDIO_EVENT_TRACK_BUFFER_HIGH event
if (playback.buffer_state == PLAYBACK_BUF_HIGH)
{
time_ms = playback.put_data_time_ms * 2;
break;
}
res = playback_audio_file_get_frame(&playback_frame);
if (res != 0)
{
APP_PRINT_ERROR1("playback_stream_put_data ERROR,RES:0x%x", res);
break;
}
uint16_t written_len;
s_seq_num++;
if (audio_track_write(playback_track_handle,
0,// timestamp,
s_seq_num,
AUDIO_STREAM_STATUS_CORRECT,
playback_frame.frame_num,// frame_num,
playback_frame.buf,
playback_frame.length,
&written_len) == false)
{
res = PLAYBACK_AF_WRITE_ERROR;
break;
}
frame_cnt++;
}
stream_check_and_request_data(); // request data from host
playback.buffer_state = PLAYBACK_BUF_NORMAL;
if (res == PLAYBACK_AF_END_ERROR)
{
app_stop_timer(&timer_idx_playback_put_data);
if (frame_cnt == 0)
{
APP_PRINT_WARN0("playback_stream_put_data,file end, and paly next song!!!");
playback_stream_ctrl_stop();
app_music_send_player_status(MUSIC_PLAYER_STOPPED);
}
}
else //if (playback_db.sd_play_state == APP_AUDIO_FS_STATE_PLAY)
{
playback_stream_put_data_start_timer(time_ms);
}
}
A2DP Source Playback
The process of A2DP Source playback is similar to that of local playback.
APP will call the a2dp_src_stream_ctrl_start()
when music_info.play_flow
enters the MUSIC_FLOW_START
state.
static struct
{
T_A2DP_SRC_PLAY_STATE play_state;
T_APP_A2DP_SRC_STATE bt_strm_state;
T_A2DP_SRC_BUF_STATE buffer_state;
uint8_t sink_addr[6];
uint8_t frm_num; // check level
} a2d_src_ctrl;
void a2dp_src_stream_ctrl_start(void)
{
APP_PRINT_INFO1("a2dp_src_stream_ctrl_start: bt stream state: %d", a2d_src_ctrl.bt_strm_state);
a2d_src_ctrl.buffer_state = A2DP_SRC_BUF_LOW;
#if A2DP_SRC_STREAM_DBG == 0
if (a2d_src_ctrl.bt_strm_state != APP_A2DP_SRC_STREAM_START)
{
bt_a2dp_stream_start_req(a2d_src_ctrl.sink_addr);
}
else
#endif
{
a2dp_src_stream_param_recfg();
a2d_src_ctrl.play_state = A2DP_SRC_PLAY_STATE_PLAY;
app_dlps_disable(APP_DLPS_ENTER_CHECK_PLAYBACK);
}
}
When sending data to the headset, format conversion is required on the device side. The Audio Pipe will be created in the a2dp_src_stream_param_recfg()
function.
uint8_t a2dp_src_stream_param_recfg(void)
{
uint8_t res = A2DP_SRC_SUCCESS;
uint16_t u16_res = 0;
uint32_t sample_rate = 0;
// uint16_t sample_counts = 1024; /* default */
// uint16_t frame_duration = 20; /* default */
uint16_t frame_size = 512;
uint8_t channel_mode = 0;
// uint32_t bit_rate = 0;
T_PLAYBACK_AF_FORMAT_INFO get_fmt_info;
if (audio_pipe_handle != NULL)
{
res = A2DP_SRC_PIPE_CREATE_ERROR;
return res;
}
u16_res = playback_audio_file_get_audio_info(&get_fmt_info);
if (u16_res == 0)
{
T_AUDIO_FORMAT_INFO format_info;
uint32_t device = AUDIO_DEVICE_OUT_SPK;
format_info = get_fmt_info.format_info;
frame_size = get_fmt_info.frame_size;
a2d_src_ctrl.frm_num = 4;
if (frame_size > 2048)
{
frame_size = 1024;
}
uint8_t frm_num = STREAM_BUF_SIZE / 2 / frame_size;
a2d_src_ctrl.frm_num = (frm_num > 8) ? 7 : 4;
if (format_info.type == AUDIO_FORMAT_TYPE_AAC)
{
APP_PRINT_INFO4("a2dp_src_stream_param_recfg: AAC, "
" transport_format:0x%x, sample_rate:%d, channel_mode:%d, bitrate:%d",
format_info.attr.aac.transport_format,
format_info.attr.aac.sample_rate,
format_info.attr.aac.chann_num,
format_info.attr.aac.bitrate);
}
else if (format_info.type == AUDIO_FORMAT_TYPE_MP3)
{
APP_PRINT_INFO3("a2dp_src_stream_param_recfg: MP3, sample_rate:%d, channel_mode:%d, frm_num:%d",
format_info.attr.mp3.sample_rate,
format_info.attr.mp3.chann_mode,
a2d_src_ctrl.frm_num);
}
T_AUDIO_FORMAT_INFO snk_info;
snk_info.type = AUDIO_FORMAT_TYPE_SBC;
snk_info.attr.sbc.subband_num = 8;
snk_info.attr.sbc.bitpool = a2dp_src_bitpool; //change to be same with min bitpool
snk_info.attr.sbc.sample_rate = 48000;
snk_info.attr.sbc.block_length = 16;
snk_info.attr.sbc.chann_mode = AUDIO_SBC_CHANNEL_MODE_JOINT_STEREO;
snk_info.attr.sbc.allocation_method = 0;
float sbc_block = snk_info.attr.sbc.block_length;
float sbc_subband = snk_info.attr.sbc.subband_num;
a2dp_sbc_time = (sbc_block * sbc_subband) / 48;
if (audio_pipe_handle == NULL)
{
audio_pipe_handle = audio_pipe_create(format_info, snk_info,
a2dp_gain_table[app_cfg_nv.audio_gain_level[cur_pair_idx]],
audio_codec_callback);
}
}
else
{
res = A2DP_SRC_SYS_ERROR;
}
return res;
}
The action of Audio Pipe will be processed mainly in a2dp_src_stream_handle_msg()
:
If the function receives
AUDIO_PIPE_EVENT_CREATED
,audio_pipe_start()
will be called.If the function receives
AUDIO_PIPE_EVENT_STARTED
,a2dp_src_stream_get_data_from_fs()
will be called, and data will be sent to DSP.If the function receives
AUDIO_PIPE_EVENT_DATA_IND
,a2dp_src_stream_data_ind()
will be called.If the function receives
AUDIO_PIPE_EVENT_DATA_FILLED
,a2dp_src_stream_fill_data()
andstream_check_and_request_data()
will be called, which means DSP buffer level low, need more data.If the function receives
AUDIO_PIPE_EVENT_RELEASED
, Audio Pipe will be stopped and ring buffer will be released.If the function receives
AUDIO_A2DP_SRC_EVENT_DATA_SEND
,a2dp_src_stream_send_data()
will be called.
void a2dp_src_stream_handle_msg(T_IO_MSG msg)
{
uint16_t subtype = msg.subtype;
APP_PRINT_INFO1("a2dp_src_stream_handle_msg: subtype: (0x%x)", subtype);
switch (subtype)
{
case AUDIO_PIPE_EVENT_CREATED:
{
uint32_t snk_buf_size = msg.u.param;
APP_PRINT_TRACE1("AUDIO_PIPE_EVENT_CREATED snk_buf_size:0x%x", snk_buf_size);
audio_pipe_start(audio_pipe_handle);
p_snk_data_buf = os_mem_alloc(RAM_TYPE_DSPSHARE, snk_buf_size);
a2d_src_ctrl.play_state = A2DP_SRC_PLAY_STATE_PLAY;
}
break;
case AUDIO_PIPE_EVENT_STARTED: // send first pkt data to dsp
{
uint16_t res_tmp = 0;
res_tmp = a2dp_src_stream_get_data_from_fs();
APP_PRINT_TRACE1("AUDIO_PIPE_EVENT_STARTED res_tmp 0x%x", res_tmp) ;
}
break;
case AUDIO_PIPE_EVENT_DATA_IND: // get encode data to buf_pool
{
if (a2d_src_ctrl.play_state == A2DP_SRC_PLAY_STATE_PLAY)
{
a2dp_src_stream_data_ind();
}
}
break;
case AUDIO_PIPE_EVENT_DATA_FILLED: // dsp buf low, need put data to share memory
{
if (a2d_src_ctrl.play_state == A2DP_SRC_PLAY_STATE_PLAY)
{
a2dp_src_stream_fill_data();
static uint8_t s_check_cnt = 0;
s_check_cnt++;
if (s_check_cnt > 4)
{
s_check_cnt = 0;
stream_check_and_request_data();
}
}
}
break;
case AUDIO_PIPE_EVENT_RELEASED:
{
if (p_snk_data_buf != NULL)
{
free(p_snk_data_buf);
p_snk_data_buf = NULL;
}
if (a2dp_src_stream_ctrl_stop_complete_hook)
{
a2dp_src_stream_ctrl_stop_complete_hook();
}
}
break;
case AUDIO_A2DP_SRC_EVENT_DATA_SEND: // timer msg peek data from buf_pool and send data
{
a2dp_src_stream_send_data();
}
break;
default:
break;
}
}
Bluetooth Audio Intergrated Transceiver
A2DP Intergrated Transceiver Transmission
In the A2DP Intergrated Transceiver Transmission scenario, ACI Device is connected to the Phone to receive A2DP data, which is transmitted to Headset simultaneously. The path of the main code is sdk\src\sample\bt_audio_trx\source_play\app_src_play_a2dp.c
.
Acquisition of A2DP Format
In this scenario, you need to get the specific A2DP formats supported by the Phone and Headset respectively. Define the following structure to store the obtained formats:
typedef struct
{
T_AUDIO_FORMAT_INFO src_a2dp_format;
bool src_a2dp_format_ready;
T_AUDIO_FORMAT_INFO sink_a2dp_format[MAX_BR_LINK_NUM];
bool sink_a2dp_format_ready[MAX_BR_LINK_NUM];
T_SRC_PLAY_A2DP_STATE sink_a2dp_state[MAX_BR_LINK_NUM];
T_MULTI_A2DP_PARAM sink_a2dp_param[MAX_BR_LINK_NUM];
uint8_t num_frame_buf;
uint8_t *p_buf;
T_RING_BUFFER ring_buf;
uint8_t sink_addr[MAX_BR_LINK_NUM][6];
uint8_t src_addr[6];
} T_SRC_PLAY_A2DP;
The A2DP data format of the connected device can be retrieved using the following function. This function is invoked within the app_audio_bt_cback()
after each A2DP connection is established and successfully configured. If the obtained A2DP role (representing the Device’s role) is BT_A2DP_ROLE_SRC
, then store the format in a2dp_play.sink_a2dp_format
. If the role is BT_A2DP_ROLE_SNK
, store the format in a2dp_play.src_a2dp_format
.
void app_src_play_save_a2dp_format(T_AUDIO_FORMAT_INFO *format_info, uint8_t *bd_addr, uint8_t role)
{
uint8_t link_idx;
link_idx = app_src_play_a2dp_get_connected_idx(bd_addr);
if (role == BT_A2DP_ROLE_SRC)
{
if (!a2dp_play.sink_a2dp_format_ready[link_idx])
{
memcpy(&a2dp_play.sink_a2dp_format[link_idx], format_info, sizeof(T_AUDIO_FORMAT_INFO));
if (a2dp_play.sink_a2dp_format[link_idx].attr.sbc.bitpool == 0)
{
a2dp_play.sink_a2dp_format[link_idx].attr.sbc.bitpool = 0x22;
}
a2dp_play.sink_a2dp_format_ready[link_idx] = true;
}
app_src_play_print_a2dp_format("app_src_play_save_a2dp_snk_format: ",
&a2dp_play.sink_a2dp_format[link_idx]);
}
else if (role == BT_A2DP_ROLE_SNK)
{
if (!a2dp_play.src_a2dp_format_ready)
{
memcpy(&a2dp_play.src_a2dp_format, format_info, sizeof(T_AUDIO_FORMAT_INFO));
if (a2dp_play.src_a2dp_format.attr.sbc.bitpool == 0)
{
a2dp_play.src_a2dp_format.attr.sbc.bitpool = 0x22;
}
a2dp_play.src_a2dp_format_ready = true;
}
app_src_play_print_a2dp_format("app_src_play_save_a2dp_src_format: ",
&a2dp_play.src_a2dp_format);
}
}
static void app_audio_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
T_BT_EVENT_PARAM *param = event_buf;
bool handle = true;
uint8_t active_a2dp_idx = app_a2dp_get_active_idx();
uint8_t active_hf_idx = app_hfp_get_active_idx();
switch (event_type)
{
case BT_EVENT_A2DP_CONFIG_CMPL:
{
T_AUDIO_FORMAT_INFO format_info = {};
app_audio_save_a2dp_config((uint8_t *)¶m->a2dp_config_cmpl, &format_info);
#if F_SOURCE_PLAY_SUPPORT
app_src_play_save_a2dp_format(&format_info, param->a2dp_config_cmpl.bd_addr,
param->a2dp_config_cmpl.role);
#endif
}
break;
}
}
Transmission of A2DP Data
The start/stop of data transmission is also controlled by the source play commands, which can be referred to Source Play Start/Stop. After output route is started and Phone start to play music, A2DP data can be obtained in BT_EVENT_A2DP_STREAM_DATA_IND
, so the A2DP stream data can also be processed in function app_src_play_pipe_handle_stream_data_in()
invoked in app_audio_bt_cback()
.
bool app_src_play_pipe_handle_stream_data_in(uint8_t *p_data, uint16_t data_len,
uint8_t frame_number)
{
if (flag_direct_send)
{
app_src_play_a2dp_handle_data(p_data, data_len, frame_number);
}
if (a2dp_snk_pipe_play.handle)
{
if (frame_number > 1)
{
a2dp_snk_pipe_play.p_fill_buf = malloc(data_len);
a2dp_snk_pipe_play.fill_len = data_len;
memcpy(a2dp_snk_pipe_play.p_fill_buf, p_data, a2dp_snk_pipe_play.fill_len);
APP_PRINT_TRACE3("app_src_play_pipe_handle_stream_data_in: data_len %d, fill len %d, fill_buf %b",
data_len, a2dp_snk_pipe_play.fill_len,
TRACE_BINARY(data_len, a2dp_snk_pipe_play.p_fill_buf));
if (a2dp_snk_pipe_play.p_fill_buf == NULL)
{
APP_PRINT_ERROR0("app_src_play_pipe_handle_stream_data_in: mem error!!");
return false;
}
if (flag_pipe_get_data_empty)
{
app_src_play_pipe_fill_data();
}
}
else
{
//TODO: ring buffer
}
}
return true;
}
static void app_audio_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
switch (event_type)
{
case BT_EVENT_A2DP_STREAM_DATA_IND:
{
T_APP_BR_LINK *p_link;
p_link = app_link_find_br_link(param->a2dp_stream_data_ind.bd_addr);
if (p_link == NULL)
{
break;
}
#if F_APP_INTEGRATED_TRANSCEIVER
app_src_play_pipe_handle_stream_data_in(param->a2dp_stream_data_ind.payload,
param->a2dp_stream_data_ind.len, param->a2dp_stream_data_ind.frame_num);
#endif
}
break;
}
}
To improve A2DP transmit quality, function gap_br_vendor_data_rate_set()
in app_bt_policy.c
can be invoked before sending A2DP data to Headset.
static void set_bd_addr(void)
{
...
#if F_APP_INTEGRATED_TRANSCEIVER
gap_br_vendor_data_rate_set(0);
#else
gap_br_vendor_data_rate_set(1);
#endif
...
}
If a2dp_play.src_a2dp_format
and a2dp_play.sink_a2dp_format
is the same, then the flag_direct_send
will be set to 1 and the application will go directly to function app_src_play_a2dp_handle_data()
.
uint16_t app_src_play_a2dp_handle_data(uint8_t *p_data, uint16_t data_len, uint8_t frame_number)
{
uint16_t res = SRC_PLAY_A2DP_SUCCESS;
if (frame_number > 1)
{
res = app_src_play_a2dp_send_data(p_data, data_len, frame_number);
return res;
}
if (ring_buffer_write(&a2dp_play.ring_buf, p_data, data_len))
{
a2dp_play.num_frame_buf += frame_number;
}
else
{
res = SRC_PLAY_A2DP_ERR_RINGBUF;
APP_PRINT_ERROR0("app_src_play_a2dp_handle_data: a2dp_play.ring_buf is full, drop pkt");
}
if (a2dp_play.num_frame_buf == A2DP_PACKET_FRAME_NUM)
{
a2dp_play.num_frame_buf -= A2DP_PACKET_FRAME_NUM;
uint16_t data_len_to_send = data_len * A2DP_PACKET_FRAME_NUM;
uint8_t *p_data_to_send = malloc(data_len_to_send);
if (p_data_to_send)
{
uint32_t actual_len = ring_buffer_read(&a2dp_play.ring_buf, data_len_to_send, p_data_to_send);
APP_PRINT_INFO1("app_src_play_a2dp_handle_data: actual_len %d sent", actual_len);
res = app_src_play_a2dp_send_data(p_data_to_send, data_len_to_send, A2DP_PACKET_FRAME_NUM);
#if F_APP_ATTACH_LOCAL_PLAY_SUPPORT
if (app_src_play_is_local_play_attached())
{
app_src_play_attach_local_play_handle_data(p_data_to_send,
data_len_to_send,
a2dp_seq_num,
A2DP_PACKET_FRAME_NUM,
0);
}
#endif
free(p_data_to_send);
}
else
{
res = SRC_PLAY_A2DP_ERR_RAM;
}
}
return res;
}
HFP Intergrated Transceiver Transmission
In the HFP Intergrated Transceiver Transmission scenario, ACI Device is connected to the Phone to receive SCO data, which is transmitted to Headset simultaneously. The path of the main code is sdk\src\sample\bt_audio_trx\source_play\app_src_play_hfp.c
.
Acquisition of HFP Format
Similar to Acquisition of A2DP Format, the HFP HF and AG formats supported by Phone and Headset can also be obtained after the SCO connection is successfully established, which is also handled in the app_audio_sco_conn_cmpl_handle()
. The format structure is defined as follow.
static struct
{
T_AUDIO_FORMAT_INFO hfp_hf_format;
bool hfp_hf_format_ready;
uint8_t hf_addr[6];
T_AUDIO_FORMAT_INFO hfp_ag_format;
bool hfp_ag_format_ready;
uint8_t ag_addr[6];
} hfp_play;
After the HFP connection is established, the Device will first save the address of the linked device as hfp_play.hf_addr
and hfp_play.ag_addr
according to the role event BT_EVENT_HFP_AG_CONN_CMPL
and BT_EVENT_HFP_CONN_CMPL
of the connection in app_src_play_hfp_bt_cback()
. The processing function is as follows:
static void app_src_play_hfp_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
T_BT_EVENT_PARAM *param = event_buf;
T_APP_BR_LINK *p_link;
bool handle = true;
switch (event_type)
{
case BT_EVENT_HFP_AG_CONN_CMPL:
{
hfp_play.hfp_hf_format_ready = false;
memcpy(hfp_play.hf_addr, param->hfp_ag_conn_cmpl.bd_addr, 6);
}
break;
#if F_APP_INTEGRATED_TRANSCEIVER
case BT_EVENT_HFP_CONN_CMPL:
{
hfp_play.hfp_ag_format_ready = false;
memcpy(hfp_play.ag_addr, param->hfp_conn_cmpl.bd_addr, 6);
}
break;
}
}
The function to get the HFP data format is app_src_play_save_hfp_format
, which will be invoked in app_audio_sco_conn_cmpl_handle()
in the callback function case of BT_EVENT_SCO_CONN_CMPL
, once the SCO connection is established.
void app_src_play_save_hfp_format(T_AUDIO_FORMAT_INFO *format_info, uint8_t *bd_addr)
{
if ((!hfp_play.hfp_hf_format_ready) && (!memcmp(hfp_play.hf_addr, bd_addr, 6)))
{
memcpy(&hfp_play.hfp_hf_format, format_info, sizeof(T_AUDIO_FORMAT_INFO));
hfp_play.hfp_hf_format_ready = true;
app_src_play_print_hfp_format("app_src_play_save_hfp_hf_format: ",
&hfp_play.hfp_hf_format);
}
#if F_APP_INTEGRATED_TRANSCEIVER
else if ((!hfp_play.hfp_ag_format_ready) && (!memcmp(hfp_play.ag_addr, bd_addr, 6)))
{
memcpy(&hfp_play.hfp_ag_format, format_info, sizeof(T_AUDIO_FORMAT_INFO));
hfp_play.hfp_ag_format_ready = true;
app_src_play_print_hfp_format("app_src_play_save_hfp_ag_format: ",
&hfp_play.hfp_ag_format);
}
#endif
}
static void app_audio_sco_conn_cmpl_handle(uint8_t *bd_addr, uint8_t air_mode, uint8_t rx_pkt_len)
{
uint8_t pair_idx_mapping;
T_AUDIO_FORMAT_INFO format_info = {};
T_APP_BR_LINK *p_link;
p_link = app_link_find_br_link(bd_addr);
if (p_link == NULL)
{
return;
}
#if F_SOURCE_PLAY_SUPPORT
app_src_play_save_hfp_format(&format_info, bd_addr);
#endif
}
static void app_audio_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
...
switch (event_type)
{
case BT_EVENT_SCO_CONN_CMPL:
{
...
app_audio_sco_conn_cmpl_handle(param->sco_conn_cmpl.bd_addr, param->sco_conn_cmpl.air_mode,
param->sco_conn_cmpl.rx_pkt_len);
}
break;
}
}
Transmission of SCO Data
To improve call quality, function bt_sco_link_retrans_window_set
can be invoked in BT_EVENT_SCO_CONN_CMPL
in the app_src_play_hfp_bt_cback()
to set the transmit window of lowerstack after the SCO connection is established.
static void app_src_play_hfp_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
...
case BT_EVENT_SCO_CONN_CMPL:
{
if (!memcmp(hfp_play.ag_addr, param->sco_conn_cmpl.bd_addr, 6))
{
bt_sco_link_retrans_window_set(hfp_play.ag_addr, 1);
}
else if (!memcmp(hfp_play.hf_addr, param->sco_conn_cmpl.bd_addr, 6))
{
bt_sco_link_retrans_window_set(hfp_play.hf_addr, 1);
}
}
break;
...
}
When Phone is called, SCO data will be generated simultaneously, and Device can process the data. By invoking app_src_play_hfp_send_sco()
, SCO data will be sent to Phone and Headset respectively, which is a two-way communication.
void app_src_play_hfp_send_sco(uint8_t *p_data, uint16_t len, uint8_t bd_addr[6])
{
uint8_t active_hf_idx = app_hfp_get_active_idx();
uint16_t hfp_seq_num;
T_APP_BR_LINK *p_link;
bool sco_tx_result = false;
#if F_APP_INTEGRATED_TRANSCEIVER
p_link = app_link_find_br_link(bd_addr);
#else
p_link = app_link_find_br_link(app_db.br_link[active_hf_idx].bd_addr);
#endif
if (p_link == NULL)
{
APP_PRINT_ERROR0("app_src_play_hfp_send_sco: no br link found");
return;
}
#if F_APP_INTEGRATED_TRANSCEIVER
if (!memcmp(hfp_play.ag_addr, bd_addr, 6))
{
hfp_ag_seq_num++;
hfp_seq_num = hfp_ag_seq_num;
memcpy(bd_addr, hfp_play.hf_addr, 6);
}
else
{
hfp_hf_seq_num++;
hfp_seq_num = hfp_hf_seq_num;
memcpy(bd_addr, hfp_play.ag_addr, 6);
}
#else
hfp_hf_seq_num++;
hfp_seq_num = hfp_hf_seq_num;
memcpy(bd_addr, p_link->bd_addr, 6);
#endif
if (p_link->sco.duplicate_fst_data)
{
p_link->sco.duplicate_fst_data = false;
bt_sco_data_send(bd_addr, hfp_seq_num - 1, p_data, len);
#if CONFIG_REALTEK_APP_BT_AUDIO_TRI_DONGLE
APP_PRINT_ERROR0("app_src_play_hfp_send_sco: duplicate_fst_data");
#endif
}
sco_tx_result = bt_sco_data_send(bd_addr, hfp_seq_num, p_data, len);
if (sco_tx_result == false)
{
APP_PRINT_ERROR0("app_src_play_hfp_send_sco: bt_sco_data_send fail");
}
}
static void app_src_play_hfp_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
...
case BT_EVENT_SCO_DATA_IND:
{
#if F_APP_INTEGRATED_TRANSCEIVER
if (param->sco_data_ind.status == 0)
{
app_src_play_hfp_send_sco(param->sco_data_ind.p_data, param->sco_data_ind.length,
param->sco_data_ind.bd_addr);
}
}
#endif
...
}
UART DFU
In addition to the OTA Module OTA, the Bluetooth Audio Transceiver application also provides UART DFU functionality for device upgrades. This feature allows external MCU to transfer upgrade packages to the device via UART, without needing to be aware of the format of the upgrade package. It only needs to adhere to the specified interaction commands.
Currently, ACI Host can be used to simulate an external MCU device for implementing UART DFU upgrades.
Code Flow on Device Side
The UART DFU feature is disabled by default. To enable the feature, set
F_APP_UART_DFU
to 1 in the app_flags.h
file:
// app_flags.h
#define F_APP_UART_DFU 0
The ACI Host commands are implemented through CMD_UART_DFU
. Different functionalities are achieved
by carrying different opcodes in the CMD_UART_DFU
command, including requesting to start DFU
(UART_DFU_START_REQ
), transferring data (UART_DFU_DATA_IND
), rebooting the device
(UART_DFU_REBOOT
), and interrupting DFU (UART_DFU_ABORT
).
void app_uart_dfu_process(uint8_t cmd_path, uint16_t opcode, uint8_t *p_data, uint16_t len)
{
switch (opcode)
{
case UART_DFU_TEST_EN:
uart_dfu_handle_test_en();
break;
case UART_DFU_START_REQ:
uart_dfu_handle_start_req(cmd_path, p_data, len);
break;
case UART_DFU_DATA_IND:
uart_dfu_handle_data_ind(cmd_path, p_data, len);
break;
case UART_DFU_REBOOT:
uart_dfu_handle_reboot_req();
break;
case UART_DFU_ABORT:
uart_dfu_handle_abort_req();
break;
case UART_DFU_GET_VER:
uart_dfu_handle_get_ver(cmd_path);
break;
default:
break;
}
}
The device communicates its status to ACI Host by sending different events, including whether DFU is
permitted (EVENT_DFU_START_RSP
), requesting data (EVENT_DFU_DATA_REQ
), reporting local version
(EVENT_DFU_LOCAL_VERSION
), and notifying DFU results (EVENT_DFU_RESULT
).
typedef enum
{
...
EVENT_DFU_START_RSP = 0x3160,
EVENT_DFU_DATA_REQ = 0x3161,
EVENT_DFU_RESULT = 0x3162,
EVENT_DFU_LOCAL_VERSION = 0x3163,
...
} T_EVENT_ID;
When ACI Host sends UART_DFU_START_REQ
opcode, it carries the version number of the upgrade
package. The device checks whether its local version is lower than the provided one to determine
whether to accept the upgrade. It then informs ACI Host through the EVENT_DFU_START_RSP
event and
requests the first set of data through the EVENT_DFU_DATA_REQ
event.
static void uart_dfu_handle_start_req(uint8_t cmd_path, uint8_t *data, uint16_t len)
{
uint32_t dfu_version, local_version;
uint32_t next_block_offset;
uint16_t next_block_length;
uint8_t ret = 0;
T_UART_DFU_START_RSP rsp_state = UART_DFU_REJECT;
LE_STREAM_TO_UINT32(dfu_version, data);
local_version = uart_dfu_get_ota_header_ver();
APP_PRINT_INFO3("uart_dfu_handle_start_req: force_update %d, version local 0x%08x, dfu 0x%08x",
force_update, local_version, dfu_version);
if (!force_update && local_version > dfu_version)
{
ret = 1;
goto ERR;
}
if (dfu_mgr.state != UART_DFU_STATE_IDLE)
{
ret = 2;
goto ERR;
}
ota_write_buf = malloc(OTA_WRITE_BUFFER_SIZE);
if (ota_write_buf == NULL)
{
ret = 3;
goto ERR;
}
app_dlps_disable(APP_DLPS_ENTER_CHECK_OTA_TOOLING_PARK);
dfu_mgr.state = UART_DFU_STATE_MERGED_HEADER;
rsp_state = UART_DFU_ACCEPT;
app_report_event(cmd_path, EVENT_DFU_START_RSP, 0, (uint8_t *)&rsp_state, sizeof(rsp_state));
next_block_offset = 0;
next_block_length = OTA_MERGED_FILE_HEAD_SIZE;
uart_dfu_req_data(cmd_path, next_block_offset, next_block_length);
return;
ERR:
APP_PRINT_INFO1("uart_dfu_handle_start_req: failed %d", -ret);
app_report_event(cmd_path, EVENT_DFU_START_RSP, 0, (uint8_t *)&rsp_state, sizeof(rsp_state));
}
ACI Host retrieves the corresponding data from the file based on the offset and length received in
the EVENT_DFU_DATA_REQ
event, and sends it to the device through the UART_DFU_DATA_IND
opcode.
Subsequent data transfers are facilitated through EVENT_DFU_DATA_REQ
event and UART_DFU_DATA_IND
opcode until the device receives all the data. This process is handled in the
uart_dfu_handle_data_ind()
function. The device then informs ACI Host of the DFU result through
the EVENT_DFU_RESULT
event. ACI Host sends the UART_DFU_REBOOT
opcode to the device to complete
the entire UART DFU process.
static void uart_dfu_handle_data_ind(uint8_t cmd_path, uint8_t *data, uint16_t len)
{
uint32_t next_block_offset = 0;
uint16_t next_block_length = 0;
if (dfu_mgr.cur_expect_block_len != len)
{
...
}
if (dfu_mgr.state == UART_DFU_STATE_MERGED_HEADER) //handle merged header
{
...
uart_dfu_req_data(cmd_path, next_block_offset, next_block_length);
dfu_mgr.state = UART_DFU_STATE_SUB_FILE_HEADER;
}
else if (dfu_mgr.state == UART_DFU_STATE_SUB_FILE_HEADER) //handle sub_file headers
{
...
uart_dfu_req_data(cmd_path, next_block_offset, next_block_length);
dfu_mgr.state = UART_DFU_STATE_CONTROL_HEADER;
}
else if (dfu_mgr.state == UART_DFU_STATE_CONTROL_HEADER) // READ handle control header
{
...
uart_dfu_req_data(cmd_path, next_block_offset, next_block_length);
dfu_mgr.state = UART_DFU_STATE_IMAGE_PAYLOAD;
}
else if (dfu_mgr.state == UART_DFU_STATE_IMAGE_PAYLOAD)
{
...
if ((dfu_mgr.buf_index == OTA_WRITE_BUFFER_SIZE) || // Every 4k write once
(dfu_mgr.cur_sub_image_relative_offset ==
dfu_mgr.sub_bin.sub_image_header[dfu_mgr.cur_sub_image_index].size)) // Or last packet
{
...
//last pkt of one sub image, check image
if (dfu_mgr.cur_sub_image_relative_offset
==
dfu_mgr.sub_bin.sub_image_header[dfu_mgr.cur_sub_image_index].size)
{
...
if (check_image)
{
//update cur_sub_image_relative_offset
dfu_mgr.cur_sub_image_relative_offset = 0;
dfu_mgr.cur_sub_image_index++;
//if it is last sub image, complete check
if (dfu_mgr.cur_sub_image_index == dfu_mgr.end_sub_image_index)
{
//OTA complete
...
uart_dfu_update_complete_check();
T_UART_DFU_RESULT duf_result = UART_DFU_SUCCESS;
app_report_event(CMD_PATH_UART, EVENT_DFU_RESULT, 0, (uint8_t *)&duf_result, sizeof(duf_result));
return;
}
else
{
//request Nth sub image
...
uart_dfu_req_data(cmd_path, next_block_offset, next_block_length);
return;
}
}
else
{
...
}
}
}
//prepare next block
...
dfu_mgr.state = UART_DFU_STATE_IMAGE_PAYLOAD;
uart_dfu_req_data(cmd_path, next_block_offset, next_block_length);
APP_PRINT_INFO1("uart_dfu_handle: cur relative offset 0x%x", dfu_mgr.cur_sub_image_relative_offset);
}
}
During the UART DFU process, ACI Host can send the UART_DFU_ABORT
opcode to abort the DFU process.
If certain anomalies occur at the device, it will inform ACI Host through the EVENT_DFU_RESULT
event, carrying the UART_DFU_FAIL
status, and subsequently exit the DFU process.
static void uart_dfu_restore(void)
{
memset(&dfu_mgr, 0, sizeof(T_UART_DFU_MGR));
if (ota_write_buf != NULL)
{
free(ota_write_buf);
ota_write_buf = NULL;
}
app_dlps_enable(APP_DLPS_ENTER_CHECK_OTA_TOOLING_PARK);
}
Integration for External MCU
Command Format
UART DFU is based on Command/Event interface ACI Data Formats. The External MCU sends commands to the device, and the device sends events to the MCU, reporting its status or requesting data.
The UART packet format is illustrated in the figure below. This chapter focuses on the specific
format of UART DFU Command
and UART DFU Event
. Please refer to ACI Data Formats
for an explanation of the packet header and packet tail.
External MCU should send the command Opcode CMD_UART_DFU (0x3270)
with Sub-Opcode to achieve
specific functions, including requesting to start DFU, sending DFU data, aborting DFU, and rebooting
the device:
Opcode: CMD_UART_DFU (0x3270)
Sub-Opcode:
UART_DFU_START_REQ = 0x0000,
UART_DFU_DATA_IND = 0x0001,
UART_DFU_ABORT = 0x0002,
UART_DFU_REBOOT = 0x0003,
UART_DFU_TEST_EN = 0x0004,
UART_DFU_GET_VER = 0x0005,
The device supports the following events to report its own status or request data.
EVENT_DFU_START_RSP = 0x3160,
EVENT_DFU_DATA_REQ = 0x3161,
EVENT_DFU_RESULT = 0x3162,
EVENT_DFU_LOCAL_VERSION = 0x3163,
Sub-Opcode:
UART_DFU_START_REQ
.Direction: External MCU -> Device
Function: Request to start UART DFU.
Format:
Byte 0~1
Byte 2~3
Byte 4~7
0x3270
0x0000
dfu_version
Byte 4~7: Version the upgrade package, for example, 1.2.3.4 would be represented as 0x01020304.
Sub-Opcode:
UART_DFU_DATA_IND
.Direction: External MCU -> Device
Function: Send DFU data to device.
Format:
Byte 0~1
Byte 2~3
Byte 4~N
0x3270
0x0001
data
Byte 4~N: When a
EVENT_DFU_DATA_REQ
event is received from the device, carryingoffset
andlength
parameters, the External MCU extracts data of the specified length from the upgrade file, starting at the specified offset, and fills the data to this field.Sub-Opcode:
UART_DFU_ABORT
.Direction: External MCU -> Device
Function: The External MCU terminates the DFU process.
Format:
Byte 0~1
Byte 2~3
0x3270
0x0002
Sub-Opcode:
UART_DFU_REBOOT
.Direction: External MCU -> Device
Function: The External MCU needs to instruct the device to reboot after a successful upgrade.
Format:
Byte 0~1
Byte 2~3
0x3270
0x0003
Sub-Opcode:
UART_DFU_TEST_EN
.Direction: External MCU -> Device
Function: If the External MCU wants to downgrade the device, it should send this command before
UART_DFU_START_REQ
to enable test mode.Format:
Byte 0~1
Byte 2~3
0x3270
0x0004
Sub-Opcode:
UART_DFU_GET_VER
.Direction: External MCU -> Device
Function: Obtain the version number of the OTA header image of the device. This is commonly utilized to allow the external MCU to request the device’s version, enabling the MCU to decide whether to initiate an upgrade request.
Format:
Byte 0~1
Byte 2~3
0x3270
0x0005
Event:
EVENT_DFU_START_RSP
.Direction: Device -> External MCU
Function: When the device receives the
UART_DFU_START_REQ
command, it compares the current device version with the upgrade package version. Only if the upgrade package version is higher than the device version will it allow the upgrade, responding withUART_DFU_ACCEPT (0x01)
; otherwise, it replies withUART_DFU_REJECT (0x00)
.Format:
Byte 0~1
Byte 2
0x3160
Response state
Byte 2:
UART_DFU_ACCEPT (0x01)
orUART_DFU_REJECT (0x00)
Event:
EVENT_DFU_DATA_REQ
.Direction: Device -> External MCU
Function: Used when the device accepts the upgrade and actively requests subsequent data packets.
Format:
Byte 0~1
Byte 2~5
Byte 6~7
0x3161
Offset
Length
Byte 2~5: Data offset in the upgrade file. Byte 6~7: Data length.
Event:
EVENT_DFU_RESULT
.Direction: Device -> External MCU
Function: The device reports the upgrade result. In case of errors during the upgrade process, the device reports the
UART_DFU_FAIL
status. If the upgrade is completed successfully, the device reports theUART_DFU_SUCCESS
status.Format:
Byte 0~1
Byte 2
0x3162
status
Byte 2:
UART_DFU_SUCCESS (0x01)
orUART_DFU_FAIL (0x00)
Event:
EVENT_DFU_LOCAL_VERSION
.Direction: Device -> External MCU
Function: Report device’s local version if
UART_DFU_GET_VER
received.Format:
Byte 0~1
Byte 2~5
0x3163
Version
Byte 2~5: Device’s local version, represented as 0x01020304.
Interaction Flow
Interaction Flow
This figure depicts the interaction flow between the External MCU and the Device during a successful
UART DFU process. Normal Mode DFU is employed for device upgrades, while Test Mode DFU is utilized
for device downgrades, typically during the development and debugging phases. In Test Mode, the
External MCU is required to send the UART_DFU_TEST_EN
command before sending the UART_DFU_START_REQ
.
This ensures that upon receiving the UART_DFU_START_REQ
command, the device skips version comparison
and starts up from a lower version bank after the DFU process is complete.
Exception Handling
DFU Fail
On the device side, if any exception occurs, it will report EVENT_DFU_RESULT
event with parameter
UART_DFU_FAIL (0x00)
, and autonomously recover its state. In this case, the External MCU needs to
restore its own state to ensure it can restart the DFU process successfully next time.
Unexpected Offset and Length
Upon receiving the EVENT_DFU_DATA_REQ
event, the External MCU needs to check whether it can
retrieve the corresponding data from the file based on the offset and length. If the offset and
length exceed the file size, the External MCU should send the UART_DFU_ABORT
command to terminate
the DFU process.
Acoustics MP
Acoustics MP of Bluetooth Audio Transceiver application mainly includes HW EQ Fitting. This feature is used for Audio Component calibration, including SPK and MIC device. It also supports calibration via various scenarios, such as playback for SPK response, voice and record for MIC gain.
Flow on Device Side
The Acoustics MP feature is enabled by default. Two flags are used
in the app_flags.h
file: F_APP_SAIYAN_EQ_FITTING
and F_APP_SUPPORT_CAPTURE_ACOUSTICS_MP
:
F_APP_SAIYAN_EQ_FITTING
enables HW EQ Fitting via playback and voice.F_APP_SUPPORT_CAPTURE_ACOUSTICS_MP
enables HW EQ Fitting via record (SPP Capture).
#define F_APP_SAIYAN_EQ_FITTING 1
#define F_APP_SUPPORT_CAPTURE_ACOUSTICS_MP 1
Before calibration, SPP connection should be established for interaction between the device and MP Tool.
The specific commands sent by MP Tool will be processed in app_eq_fitting_cmd_handle()
or app_data_capture_cmd_handle()
on the device’s side.
// HW EQ command
case CMD_HW_EQ_TEST_MODE: // 0x1200
case CMD_HW_EQ_START_SET: // 0x1201
case CMD_HW_EQ_CONTINUE_SET: // 0x1202
case CMD_HW_EQ_CLEAR_CALIBRATE_FLAG: // 0x1204
case CMD_HW_EQ_SET_TEST_MODE_TMP_EQ: // 0x1205
case CMD_HW_EQ_SET_TEST_MODE_TMP_EQ_ADVANCED: // 0x1206
{
app_eq_fitting_cmd_handle(cmd_ptr, cmd_len, cmd_path, app_idx, ack_pkt);
}
break;
// SPP Capture command
case CMD_DSP_CAPTURE_V2_START_STOP: // 0x0220
{
app_data_capture_cmd_handle(cmd_ptr, cmd_len, cmd_path, app_idx, ack_pkt);
}
break;
And after processing the command, the device will reply with the EVENT_ACK
and the other corresponding event to the tool by app_report_event()
:
// EVENT_ACK
EVENT_ACK = 0x0000,
// HW EQ event
EVENT_HW_EQ_TEST_MODE = 0x1200,
EVENT_HW_EQ_START_SET = 0x1201,
EVENT_HW_EQ_CONTINUE_SET = 0x1202,
EVENT_HW_EQ_CLEAR_CALIBRATE_FLAG = 0x1204,
EVENT_HW_EQ_SET_TEST_MODE_TMP_EQ = 0x1205,
EVENT_HW_EQ_SET_TEST_MODE_TMP_EQ_ADVANCED = 0x1206,
// SPP Capture event
EVENT_DSP_CAPTURE_V2_START_STOP_RESULT = 0x0220,
EVENT_DSP_CAPTURE_V2_DATA = 0x0221,
Note
It should be noted that EVENT_DSP_CAPTURE_V2_DATA
does not actually have a corresponding command. It is actually capture data.
A complete Acoustics MP flow should include the following steps:
Enter HW EQ Test Mode.
Measure and calculate.
Apply temp EQ.
Download to flash.
Exit HW EQ Test Mode.
Check after download.
It can also be referred to the figure below, and among these steps, the more important are: Apply temp EQ, Download to flash, and Check after download.
Enter or Exit HW EQ Test Mode
The device uses CMD_HW_EQ_TEST_MODE (0x1200)
to enter or exit HW EQ Test Mode, which can be distinguished by different parameters in the command. When entering HW EQ Test Mode, the is_test_mode
flag will be set to true. Otherwise, this flag will be set to false.
case CMD_HW_EQ_TEST_MODE:
{
uint8_t test_mode_status = cmd_ptr[2];
if (test_mode_status == HW_EQ_ENTER_TEST_MODE) // Enter HW EQ Test Mode
{
is_test_mode = true;
...
}
else if (test_mode_status == HW_EQ_EXIT_TEST_MODE) // Exit HW EQ Test Mode
{
is_test_mode = false;
...
}
else
{
ack_pkt[2] = CMD_SET_STATUS_PARAMETER_ERROR;
}
app_report_event(cmd_path, EVENT_ACK, app_idx, ack_pkt, 3);
if (ack_pkt[2] == CMD_SET_STATUS_COMPLETE)
{
app_report_event(cmd_path, EVENT_HW_EQ_TEST_MODE, app_idx, &ack_pkt[2], sizeof(uint8_t));
}
}
break;
Measure and Calculate
Through measurement, the compensation value can be calculated by fitting algorithm for the subsequent apply process. Different sample rates have different parameters. For example, when using 48k sampling rate to measure the SPK response, three sets of EQ filter parameters with different sample rates will be generated.
Apply Temp EQ
Then the device can use CMD_HW_EQ_SET_TEST_MODE_TMP_EQ_ADVANCED (0x1206)
to apply temp EQ parameters. This command is used to assist Acoustics MP and verify calibration effect.
When the device is in HW EQ Test Mode, the tool can send temporary HW EQ parameters to the device. The device opens memory to temporarily store this parameter. Once an audio_track
that meets the conditions (device, sample rate) is established, the device applies the HW EQ parameters, otherwise it will take a long time to test if each sample rate per scenario follows.
When the device exits HW EQ Test Mode, the device will release the temp EQ parameters.
The device uses app_eq_fitting_set_test_mode_tmp_eq_advanced
to handle the details. There will be 2 situations. One is to take effect in real time. That is, when receiving the temp EQ parameters, audio_track
is already in the STARTED
state by app_eq_fitting_is_streaming
.
app_eq_fitting_cmd_handle()
|---app_eq_fitting_set_test_mode_tmp_eq_advanced()
static void app_eq_fitting_set_test_mode_tmp_eq_advanced(void)
{
if (test_mode_tmp_eq_advanced)
{
...
if (eq_para->device_type == HW_EQ_DEVICE_PRIMARY_SPEAKER) //pri spk
{
eq_type = CODEC_EQ_CONFIG_PATH_DAC;
eq_channel = 0; // DAC0
}
else if (eq_para->device_type == HW_EQ_DEVICE_PRIMARY_MIC) // pri mic
{
eq_type = CODEC_EQ_CONFIG_PATH_ADC;
eq_channel = 0; // ADC0
}
else if (eq_para->device_type == HW_EQ_DEVICE_SECONDARY_MIC) // sec mic
{
eq_type = CODEC_EQ_CONFIG_PATH_ADC;
eq_channel = 1; // ADC1
}
if (app_eq_fitting_is_streaming(AUDIO_STREAM_TYPE_PLAYBACK)) // playback scenario
{
sample_rate = app_eq_fitting_get_sample_rate(AUDIO_CATEGORY_AUDIO); // 44.1k or 48k
if (sample_rate == eq_para->sample_rate) // sample rate match
{
audio_probe_codec_hw_eq_set(eq_type, eq_channel, eq_para->para, para_len); // HW EQ set
}
}
else if (app_eq_fitting_is_streaming(AUDIO_STREAM_TYPE_VOICE)) // voice scenario
{
sample_rate = app_eq_fitting_get_sample_rate(AUDIO_CATEGORY_VOICE); // 16k
if (sample_rate == eq_para->sample_rate) // sample rate match
{
audio_probe_codec_hw_eq_set(eq_type, eq_channel, eq_para->para, para_len); // HW EQ set
}
}
else if (app_eq_fitting_is_streaming(AUDIO_STREAM_TYPE_RECORD)) // record scenario
{
sample_rate = app_eq_fitting_get_sample_rate(AUDIO_CATEGORY_RECORD); // 48k
if (sample_rate == eq_para->sample_rate) // sample rate match
{
audio_probe_codec_hw_eq_set(eq_type, eq_channel, eq_para->para, para_len); // HW EQ set
}
}
}
}
The other situation is that the EQ parameters will be temporarily stored and then applied when audio_track
is established.
static void app_eq_fitting_cback(T_AUDIO_EVENT event_type, void *event_buf, uint16_t buf_len)
{
...
switch (event_type)
{
case AUDIO_EVENT_TRACK_STATE_CHANGED:
{
...
if (is_test_mode) // in HW EQ Test Mode
{
...
app_eq_fitting_set_test_mode_tmp_eq_advanced();
}
...
}
}
...
}
Playback or voice scenario
If we want to apply EQ parameters during playback or voice scenario, we can trigger A2DP or HFP play to create the related audio_track
.
Record scenario
If we want to apply EQ parameters in a record scenario, we can trigger Capture start to create the record track. The device uses CMD_DSP_CAPTURE_V2_START_STOP (0x0220)
to start and stop capture.
// start capture
app_data_capture_cmd_handle()
|---app_data_capture_recorder_create()
|---audio_track_create()
// stop capture
app_data_capture_cmd_handle()
|---app_data_capture_stop_process
|---audio_track_release()
// capture data
app_data_capture_cmd_handle()
|---app_data_capture_register()
|---audio_probe_dsp_evt_cback_register(app_data_capture_dsp_event_cback);
void app_data_capture_dsp_event_cback(uint32_t event, void *msg)
{
switch (event)
{
case AUDIO_PROBE_DSP_EVT_MAILBOX_DSP_DATA:
{
...
app_report_event(dsp_capture_data_path, EVENT_DSP_CAPTURE_V2_DATA, dsp_capture_data_app_idx,
p_info->p_data, p_info->data_len); // EVENT_DSP_CAPTURE_V2_DATA
}
break;
...
}
}
Download to Flash
After the apply process is verified, the device can download “MP EQ Information” to flash by using CMD_HW_EQ_START_SET (0x1201)
and CMD_HW_EQ_CONTINUE_SET (0x1202)
. The first 1KB of Flash is used to store HW EQ Fitting data currently.
app_eq_fitting_cmd_handle()
|---app_eq_fitting_write_hw_eq()
static uint8_t app_eq_fitting_write_hw_eq(uint8_t *data, uint32_t len)
{
uint8_t failed_cause = HW_EQ_WRITE_SUCCESS;
bool resume_bp_lv = false;
uint8_t old_bp_lv;
uint8_t *flash_tem_buf = NULL;
is_disallow_playback = true;
if (!app_eq_fitting_is_media_buffer_idle())
{
failed_cause = HW_EQ_WRITE_WRONG_TRACK_STATE;
goto exit;
}
/* need 4K for temporary storage, take it from heap */
flash_tem_buf = (uint8_t *)malloc(FLASH_NOR_SECTOR_SIZE); // 0x1000
if (!flash_tem_buf)
{
failed_cause = HW_EQ_WRITE_MALLOC_FAIL;
goto exit;
}
if (!fmc_flash_nor_get_bp_lv(EQ_FITTING_ADDR, &old_bp_lv))
{
failed_cause = HW_EQ_WRITE_GET_BP_LV_FAIL;
goto exit;
}
if (fmc_flash_nor_set_bp_lv(EQ_FITTING_ADDR, 0))
{
resume_bp_lv = true;
}
else
{
failed_cause = HW_EQ_WRITE_SET_BP_LV_FAIL;
goto exit;
}
if (fmc_flash_nor_read(EQ_FITTING_ADDR, flash_tem_buf, FLASH_NOR_SECTOR_SIZE))
{
if (len <= EQ_FITTING_SIZE)
{
memcpy(flash_tem_buf, data, len);
}
else
{
failed_cause = HW_EQ_WRITE_WRONG_LEN;
goto exit;
}
}
else
{
failed_cause = HW_EQ_WRITE_READ_FAIL;
goto exit;
}
if (!fmc_flash_nor_erase(EQ_FITTING_ADDR, FMC_FLASH_NOR_ERASE_SECTOR))
{
failed_cause = HW_EQ_WRITE_ERASE_FAIL;
goto exit;
}
if (!fmc_flash_nor_write(EQ_FITTING_ADDR, flash_tem_buf, FLASH_NOR_SECTOR_SIZE))
{
failed_cause = HW_EQ_WRITE_FAIL;
goto exit;
}
exit:
if (resume_bp_lv)
{
fmc_flash_nor_set_bp_lv(EQ_FITTING_ADDR, old_bp_lv);
}
if (flash_tem_buf)
{
free(flash_tem_buf);
}
if (failed_cause != HW_EQ_WRITE_WRONG_TRACK_STATE)
{
is_disallow_playback = false;
}
APP_PRINT_ERROR1("app_eq_fitting_write_hw_eq: cause %d", failed_cause);
return failed_cause;
}
// flash_map.h
#define EQ_FITTING_ADDR 0x02000000
#define EQ_FITTING_SIZE 0x00000400 //1K Bytes
Check after Downloading
Finally, the device exits the MP test mode and returns to user mode. It is possible to trigger A2DP Play, HFP Play, or Capture Start again to check the parameters downloaded to flash before. It is expected to use the one downloaded to flash before.
static void app_eq_fitting_cback(T_AUDIO_EVENT event_type, void *event_buf, uint16_t buf_len)
{
...
switch (event_type)
{
case AUDIO_EVENT_TRACK_STATE_CHANGED:
{
...
if (stream_type == AUDIO_STREAM_TYPE_PLAYBACK)
{
app_eq_fitting_send_hw_eq(AUDIO_CATEGORY_AUDIO);
}
else if (stream_type == AUDIO_STREAM_TYPE_VOICE)
{
app_eq_fitting_send_hw_eq(AUDIO_CATEGORY_VOICE);
}
else if (stream_type == AUDIO_STREAM_TYPE_RECORD)
{
app_eq_fitting_send_hw_eq(AUDIO_CATEGORY_RECORD);
}
...
}
}
...
}
static bool app_eq_fitting_send_hw_eq(T_AUDIO_CATEGORY category)
{
...
for (i = 0; i < pysical_path_group.physical_path_num; i++)
{
...
if (eq_config_path != CODEC_EQ_CONFIG_PATH_MAX &&
(io_idx < sizeof(hw_eq_info) / sizeof(T_HW_EQ_INFO *)))
{
T_HW_EQ_INFO *tmp = hw_eq_info[io_idx];
while (tmp)
{
if (tmp->sample_rate == sample_rate) // sample rate match
{
T_HW_EQ_PARA *buf = malloc(tmp->len);
if (buf)
{
if (app_eq_fitting_read_hw_eq(sizeof(T_HW_EQ_DATA) + tmp->offset, (uint8_t *)buf, tmp->len)) // read HW EQ from flash
{
audio_probe_codec_hw_eq_set(eq_config_path, channel, (uint8_t *)buf->para,
buf->stage_number * EQ_STAGE_LEN); // HW EQ set
}
free(buf);
}
break;
}
tmp = tmp->next;
}
}
}
...
return true;
}
Command and Event
Enter or Exit MP EQ Test Mode
CMD_HW_EQ_TEST_MODE
Direction: Tool -> Device
Function: Request to enter or exit HW EQ Test Mode.
Format:
Byte 0~1
Byte 2
0x1200
test mode status
Byte 2:
HW_EQ_EXIT_TEST_MODE (0x00)
orHW_EQ_ENTER_TEST_MODE (0x01)
.EVENT_HW_EQ_TEST_MODE
Direction: Device -> Tool
Function: The device reports the CMD process result to the tool.
Format:
Byte 0~1
Byte 2
0x1200
status
Byte 2: Status.
0x00
means success, and0x03
means parameter error.
Start Set MP EQ Info
CMD_HW_EQ_START_SET
Direction: Tool -> Device
Function: Request to start set MP EQ info.
Format:
Byte 0~1
Byte 2~3
Byte 4~5
0x1201
EQ_totallen
Byte 2~3: Total length of all EQ parameters.
Byte 4~5: CRC16 of all EQ parameters. The device does check after receiving the complete EQ parameters.EVENT_HW_EQ_START_SET
Direction: Device -> Tool
Function: The device reports the CMD process result and Max_packet_size to the tool.
Format:
Byte 0~1
Byte 2
Byte 3~4
0x1201
status
Max_packet_size
Byte 2: Status.
0x00
means success, and0x05
means process fail.
Byte 3~4:Max_packet_size
. The current setting is 500 bytes, which isMAX_EQ_TOOL_CMD_LENGTH
in macro definition.
Continue Set MP EQ Info
CMD_HW_EQ_CONTINUE_SET
Direction: Tool -> Device
Function: Request to continue set MP EQ info.
Format:
Byte 0~1
Byte 2
Byte 3
Byte 4~N
0x1202
num_of_total_packet
index_packet
data[]
Byte 2: Total packet number.
Byte 3: Current package index. Valid index should be 0, 1, …,number_of_total_packet
- 1.
Byte 4~N:HW_EQ_DATA
. That is, the followingT_HW_EQ_DATA
.typedef struct __attribute__((__packed__)) t_hw_eq_para { uint8_t device_type; uint8_t rsv; uint32_t sample_rate; uint8_t stage_number; uint8_t para[0]; /* para len is stage_number * 20 bytes */ } T_HW_EQ_PARA; typedef struct __attribute__((__packed__)) t_hw_eq_data { uint32_t magic_word; uint8_t calibrated; uint16_t total_len; /* total len of all groups of */ uint16_t crc16; /* CRC calc range: all groups of eq para */ T_HW_EQ_PARA eq_para[0]; // sereral Groups of T_HW_EQ_PARA } T_HW_EQ_DATA;
EVENT_HW_EQ_CONTINUE_SET
Direction: Device -> Tool
Function: The device reports the CMD process result to the tool.
Format:
Byte 0~1
Byte 2
0x1202
status
Byte 2: status.
0x00
means success,0x03
means parameter error and0x05
means process fail.
Set Test Mode Temp EQ Advanced
CMD_HW_EQ_SET_TEST_MODE_TMP_EQ_ADVANCED
Direction: Tool -> Device
Function: Request to set temp MP EQ info.
Format:
Byte 0~1
Byte 2
Byte 3~N
0x1206
eq_num
data[]
Byte 2: Number of EQ.
0x00
indicates clear temp EQ parameter,0x01
~0x03
are all valid number of EQ parameters and Others are RFU.
Byte 3~N:T_HW_EQ_DATA
.EVENT_HW_EQ_SET_TEST_MODE_TMP_EQ_ADVANCED
Direction: Device -> Tool
Function: The device reports the CMD process result to the tool.
Format:
Byte 0~1
Byte 2
0x1206
status
Byte 2: Status.
0x00
means success and0x05
means process fail.
Find My
Find My is an application technology released by Apple. The magic of this technology is that the peripheral products that support this technology (such as AirTag) can use the Apple devices around it (iPhone, iPad, AirPods, AirTag, etc.) to help it locate even if it do not have a GPS module. For more detailed information, please refer to the official Apple website at https://www.apple.com/icloud/find-my/. The document outlines how to enable the Find My feature, provides a software overview of all Find My features, and guides users on getting started with running the Find My application.
Realtek Find My
Realtek Find My SDK is based on Find My Network ADK v1.0 and is compatible with the latest version of the Find My Network Accessory Specification.
Find My APP
To use Find My features, please use Find My APP on iOS devices. The Find My APP is where Apple devices are located, location is shared with friends and family, and Find My Network-enabled accessories are located. The APP displays the location of findable items and includes additional features to protect devices, such as playing sound and using Lost Mode.
Transport
The Find My Network accessory protocol uses Bluetooth LE as the primary transport to interact with Apple devices.
Roles
It includes the following four roles: Owner device, Accessory, Find My Network and Apple server.
The relationship between the four roles is shown in the following figure:
Owner device
When an accessory is paired with an Apple device through the Find My APP, the accessory is associated with the Apple ID on that device. This device and all other Apple devices signed in with the same Apple ID are treated as owner devices.
Accessory
An accessory is a device that implements the Find My Network accessory protocol and can be located using the Apple Find My Network and servers. In the following, the accessory refers to the Realtek Bluetooth LE SoC that supports the Find My feature.
Find My Network
The Find My Network provides a mechanism to locate accessories by using the vast network of Apple devices that have Find My enabled.
Apple server
The Apple server receives encrypted location data from Finder devices and temporarily stores it.
Feature Enable
Our SDK supports Find My. To enable Find My, simply follow the steps below.
Add Find My File
Copy Find My source folder to the path of src\sample\bt_audio_trx
.
Copy the crypto source folder to the path of src\sample\common\findmy
.
Find My Macro Configuration
Enable the F_APP_FINDMY_FEATURE_SUPPORT
macro for Find My in the app_flags.h
file.
#define F_APP_FINDMY_FEATURE_SUPPORT 1
Global Size Configuration
Because Find My occupies more Global RAM size, please modify the value of APP_GLOBAL_SIZE
in the mem_config.h
file to match the actual RAM_GLOBAL
size.
#define APP_GLOBAL_SIZE (24*1024)
Configuration of MCUConfig Tool
Since Elliptic Curve Cryptography takes more than 4 seconds, the idle task cannot be executed, thus triggering a watchdog reset. Therefore, the watchdog timeout is recommended to be configured to 8 seconds.
Software Authentication Token
Licensees must download a provisioned software authentication token and UUID into Realtek nonvolatile memory (Flash) so that the Find My Network server can validate the pairing. Per the FMNA specification, the software authentication token is only valid per pairing session. It is necessary to write the initial software authentication token into the accessory Flash. Subsequent tokens will be updated in Flash whenever new tokens are received from iOS during pairing sessions. These updated tokens will remain in the Flash memory even after the system reboots. For more detailed information, please refer to Software Token Authentication Server Specification.
Apple token address is defined in flash_map.h
.
#define BKP_DATA2_ADDR 0x023FE000
#define BKP_DATA2_SIZE 0x00002000 //8K Bytes
Note
When reprogramming the Find My images after pairing, ensure that the Erase All for Download and User Data
option is not selected. Choosing this option will result in the latest token being erased or overwritten, preventing successful pairing in the future.
Download the token:
To generate the
token.bin
for downloading, openTOKEN_DECODE.exe
in thesdk\tool\token_decode
path. Then input the base64 encoded token string and the corresponding UUID released by Apple.Copy
token.bin
andmp_bkupdata2.ini
files to the path ofsdk\tool\Gadgets
.Open a command window, input:
prepend_header.exe /backup_data2 token.bin /mp_ini mp_bkupdata2.ini /ic_type 87x3e md5.exe token_MP.bin
Using the MPPG Tool, download the
token_MP-XX.bin
file, and the written address is defined in the flash map. Please refer to the following figure.
Bluetooth Requirements
Bluetooth Low Energy is used as the wireless transport for all communication between Apple products and accessories.
Bluetooth Connection
The accessory must support at least two simultaneous connections in a peripheral role.
#define APP_FINDMY_MAX_LINKS 2 /** FIND MY LE link number */
Accessory Information Service
The Accessory information service UUID is:
#define AIS_SERVICE_BASE_UUID {0x8B, 0x47, 0x38, 0xDC, 0xB9, 0x11, 0xA9, 0xA1, 0xB1, 0x43, 0x51, 0x3C, 0x02, 0x01, 0x29, 0x87}
The UUID for Accessory information service characteristics is 6AA5XXXX-6352-4D57-A7B4-003A416FBB0B
, where XXXX
is unique for each characteristic.
#define GATT_UUID128_PROD_DATA 0x0B, 0xBB, 0x6F, 0x41, 0x3A, 0x00, 0xB4, 0xA7, 0x57, 0x4D, 0x52, 0x63, 0x01, 0x00, 0xA5, 0x6A
#define GATT_UUID128_MANU_NAME 0x0B, 0xBB, 0x6F, 0x41, 0x3A, 0x00, 0xB4, 0xA7, 0x57, 0x4D, 0x52, 0x63, 0x02, 0x00, 0xA5, 0x6A
#define GATT_UUID128_MODEL_NAME 0x0B, 0xBB, 0x6F, 0x41, 0x3A, 0x00, 0xB4, 0xA7, 0x57, 0x4D, 0x52, 0x63, 0x03, 0x00, 0xA5, 0x6A
#define GATT_UUID128_RESERVED 0x0B, 0xBB, 0x6F, 0x41, 0x3A, 0x00, 0xB4, 0xA7, 0x57, 0x4D, 0x52, 0x63, 0x04, 0x00, 0xA5, 0x6A
#define GATT_UUID128_ACC_CATEGORY 0x0B, 0xBB, 0x6F, 0x41, 0x3A, 0x00, 0xB4, 0xA7, 0x57, 0x4D, 0x52, 0x63, 0x05, 0x00, 0xA5, 0x6A
#define GATT_UUID128_ACC_CAP 0x0B, 0xBB, 0x6F, 0x41, 0x3A, 0x00, 0xB4, 0xA7, 0x57, 0x4D, 0x52, 0x63, 0x06, 0x00, 0xA5, 0x6A
#define GATT_UUID128_FW_VERS 0x0B, 0xBB, 0x6F, 0x41, 0x3A, 0x00, 0xB4, 0xA7, 0x57, 0x4D, 0x52, 0x63, 0x07, 0x00, 0xA5, 0x6A
#define GATT_UUID128_FINDMY_VERS 0x0B, 0xBB, 0x6F, 0x41, 0x3A, 0x00, 0xB4, 0xA7, 0x57, 0x4D, 0x52, 0x63, 0x08, 0x00, 0xA5, 0x6A
#define GATT_UUID128_BATT_TYPE 0x0B, 0xBB, 0x6F, 0x41, 0x3A, 0x00, 0xB4, 0xA7, 0x57, 0x4D, 0x52, 0x63, 0x09, 0x00, 0xA5, 0x6A
#define GATT_UUID128_BATT_LVL 0x0B, 0xBB, 0x6F, 0x41, 0x3A, 0x00, 0xB4, 0xA7, 0x57, 0x4D, 0x52, 0x63, 0x0A, 0x00, 0xA5, 0x6A
The characteristic data can be received in ais_attr_read_cb()
.
T_APP_RESULT ais_attr_read_cb(uint8_t conn_id, T_SERVER_ID service_id,
uint16_t attrib_index, uint16_t offset, uint16_t *p_length, uint8_t **pp_value)
Find My Network Service
The Find My Network service UUID is:
#define FINDMY_UUID_SERVICE 0xFD44
The UUID for Find My Network service characteristics is 4F86XXXX-943B-49EF-BED4-2F730304427A
,
where XXXX
is unique for each characteristic.
#define GATT_UUID128_PAIR_CTRL_POINT 0x7A, 0x42, 0x04, 0x03, 0x73, 0x2F, 0xD4, 0xBE, 0xEF, 0x49, 0x3B, 0x94, 0x01, 0x00, 0x86, 0x4F
#define GATT_UUID128_CONF_CTRL_POINT 0x7A, 0x42, 0x04, 0x03, 0x73, 0x2F, 0xD4, 0xBE, 0xEF, 0x49, 0x3B, 0x94, 0x02, 0x00, 0x86, 0x4F
#define GATT_UUID128_NON_OWNER_CTRL_POINT 0x7A, 0x42, 0x04, 0x03, 0x73, 0x2F, 0xD4, 0xBE, 0xEF, 0x49, 0x3B, 0x94, 0x03, 0x00, 0x86, 0x4F
#define GATT_UUID128_PAIRED_OWNER_INFO_CTRL_POINT 0x7A, 0x42, 0x04, 0x03, 0x73, 0x2F, 0xD4, 0xBE, 0xEF, 0x49, 0x3B, 0x94, 0x04, 0x00, 0x86, 0x4F
#define GATT_UUID128_DEBUG_CTRL_POINT 0x7A, 0x42, 0x04, 0x03, 0x73, 0x2F, 0xD4, 0xBE, 0xEF, 0x49, 0x3B, 0x94, 0x05, 0x00, 0x86, 0x4F
Set and update characteristic data through the following interface:
T_APP_RESULT fns_attr_write_cb(uint8_t conn_id, T_SERVER_ID service_id,
uint16_t attrib_index, T_WRITE_TYPE write_type, uint16_t length, uint8_t *p_value,
P_FUN_WRITE_IND_POST_PROC *p_write_ind_post_proc)
void fns_cccd_update_cb(uint8_t conn_id, T_SERVER_ID service_id, uint16_t index,
uint16_t cccbits)
Bluetooth LE Advertising
The chapter will cover the various states and operations related to Bluetooth Low Energy advertising for accessories within the Find My Network.
Find My State
The accessory operations can be described using a state machine with the states listed in this chapter and transition between them based on interactions with an owner device.
Unpaired
The accessory must be in an unpaired state on first startup or before the accessory setup is completed.
Connected
The accessory must enter the connected state after the Find My Network pairing successfully completes with the owner device.
Nearby
The accessory must enter the nearby state immediately after it disconnects from an owner device. The accessory shall remain in the nearby state for nearby time.
Separated
The accessory must enter the separated state under these conditions:
The accessory is paired and starts up from a reset, power cycle, or other reinitialization procedure.
The accessory is in the nearby state and the nearby time has expired.
Payload for Pairing
The accessory that is not Find My Network paired shall advertise the Find My Network service as a primary service when the user puts the accessory in pairing mode. The Bluetooth LE payload for pairing is:
static uint8_t pairing_adv_data[29] =
{
/* Flags */
0x18, /* length */
GAP_ADTYPE_SERVICE_DATA, /* type="Flags" */
LO_WORD(FINDMY_UUID_SERVICE),
HI_WORD(FINDMY_UUID_SERVICE),
};
The fmna_adv_init_pairing()
is used to initialize pairing data.
void fmna_adv_init_pairing(void)
{
fmna_pairing_adv_service_data_init();
fmna_adv_platform_init_pairing((uint8_t *)&m_fmna_pairing_adv_payload,
sizeof(m_fmna_pairing_adv_payload));
}
Payload for Nearby State
The accessory must enter the connected state after the Find My Network pairing successfully completes with the owner device. Then, the accessory shall advertise the Find My Network Bluetooth LE payload for nearby state. Payload for nearby state defined in:
static uint8_t nearby_adv_data[31] =
{
0x03,
0xFF,
0x4C, 0x00,
};
The fmna_adv_init_nearby()
is used to initialize nearby data.
void fmna_adv_init_nearby(uint8_t pubkey[FMNA_PUBKEY_BLEN])
{
// Initialize Nearby manufacturing data with the public key
fmna_nearby_adv_manuf_data_init(pubkey);
fmna_adv_platform_init_nearby((uint8_t *)&m_fmna_nearby_adv_packet,
sizeof(m_fmna_nearby_adv_packet));
}
Payload for Separated State
When the accessory is in the separated state, the accessory shall advertise the Find My Network LE payload.
static uint8_t separate_adv_data[31] =
{
0x03,
0xFF,
0x4C, 0x00,
};
The fmna_adv_platform_init_separated()
is used to initialize separated data.
void fmna_adv_platform_init_separated(uint8_t *separated_adv_manuf_data,
size_t separated_adv_manuf_data_size)
{
fmna_fast_adv_interval = fmna_separated_adv_fast_intv;
fmna_slow_adv_interval = fmna_separated_adv_slow_intv;
memcpy(separate_adv_data + MANU_DATA_OFFSET, separated_adv_manuf_data,
separated_adv_manuf_data_size);
separate_adv_data[0] = 3 + separated_adv_manuf_data_size;
ble_ext_adv_mgr_set_adv_data(app_findmy_adv_get_adv_handle(), 3 + separated_adv_manuf_data_size + 1,
(uint8_t *)separate_adv_data);
FMNA_LOG_INFO("ADV Separate len %d", 3 + separated_adv_manuf_data_size + 1);
FMNA_LOG_HEXDUMP_INFO(separate_adv_data, 31);
}
Find My Pairing
The accessory must be paired with an owner device before it can be located. The owner device initiates the standard Bluetooth LE encryption before accessing the Find My Network services.
Find My Pairing Mode
The accessory automatically enters pairing mode after power on. The app_findmy_enter_pair_mode()
is used to enter pairing mode.
The accessory automatically enters pairing mode after power on. The app_findmy_enter_pair_mode()
is used to enter pairing mode.
void app_findmy_enter_pair_mode(void)
{
APP_PRINT_INFO0("app_findmy_enter_pair_mode");
if (app_cfg_nv.bud_role != REMOTE_SESSION_ROLE_SECONDARY)
{
start_pair_adv();
}
}
Generate Pairing Data
The accessory must respond to a pairing session request using the Send_pairing_data
opcode. The response from the accessory must be sent within 60 seconds.
typedef struct
{
uint8_t c1[C1_BLEN];
uint8_t e2[E2_BLEN];
} __attribute__((packed)) fmna_send_pairing_data_t;
The fm_crypto_ckg_gen_c1()
is used to generate C1.
int fm_crypto_ckg_gen_c1(fm_crypto_ckg_context_t ctx, byte out[32])
The populate_e2_generation_encryption_msg()
is used to generate E2.
static void populate_e2_generation_encryption_msg(void)
Send Pairing Data
The accessory must send the encrypted payload generated using Apple server encryption key (Q_E
).
fmna_ret_code_t fmna_crypto_generate_send_pairing_data_params(void)
Finalize Pairing
The owner device initiates the finalize pairing process to complete pairing.
fmna_ret_code_t fmna_crypto_finalize_pairing(void)
Sound
Play sound requirements apply exclusively to accessories that are equipped with a sound maker.
typedef enum
{
FMNA_SERVICE_OPCODE_SOUND_START = 0x0200,
FMNA_SERVICE_OPCODE_SOUND_STOP = 0x0201,
FMNA_SERVICE_OPCODE_SOUND_COMPLETED = 0x020D,
} FMNA_Service_Opcode_t;
Start Sound
Click the Play Sound
button after the accessory is connected.
Click the Play Sound
button after the accessory is connected.
The Sound_Start
opcode is used to play the TONE_FINDMY_SOUND
tone on the sound maker of the accessory.
The Sound_Start
opcode is used to play the TONE_FINDMY_SOUND
tone on the sound maker of the accessory.
case FMNA_SERVICE_OPCODE_SOUND_START:
{
...
{
fmna_connection_update_connection_info(conn_handle, FMNA_MULTI_STATUS_PLAYING_SOUND, true);
response_status = RESPONSE_STATUS_SUCCESS;
fmna_state_machine_dispatch_event(FMNA_SM_EVENT_SOUND_START);
}
} break;
If no operation is performed, the sound will stop after ten seconds.
void fmna_sound_platform_start(void)
{
APP_PRINT_INFO0("fmna_sound_platform_start: Sound starting...");
app_audio_tone_type_play(TONE_FINDMY_SOUND, false, false);//play sound
findmy_sound_state = FMNA_SOUND_PLAY;
app_start_timer(&timer_idx_findmy_sound_stop, "findmy_stop",
findmy_timer_id, APP_TIMER_FINDMY_SOUND_STOP, 0, false,
10 * 1000);
}
Due to the lack of Find My sound sources, modifying the tone type is necessary.
typedef enum
{
TONE_POWER_ON, //0x00
TONE_POWER_OFF, //0x01
...
#if F_APP_FINDMY_FEATURE_SUPPORT
TONE_FINDMY_SOUND = 0x61, //resue of TONE_APT_EQ_0
#endif
} T_APP_AUDIO_TONE_TYPE;
Stop Sound
Click the Stop Sound
button when playing the sound.
The Sound_Stop
opcode is used to stop an ongoing sound request.
case FMNA_SERVICE_OPCODE_SOUND_STOP:
{
if (!fmna_connection_is_status_bit_enabled(CONN_HANDLE_ALL, FMNA_MULTI_STATUS_PLAYING_SOUND))
{
response_status = RESPONSE_STATUS_INVALID_STATE;
}
else
{
fmna_state_machine_dispatch_event(FMNA_SM_EVENT_SOUND_STOP);
}
} break;
Then the accessory will be in the FMNA_SM_EVENT_SOUND_COMPLETE
state.
void fmna_sound_platform_stop(void)
{
ret_code_t ret_code = app_timer_stop(m_fmna_sound_timeout_timer_id);
APP_ERROR_CHECK(ret_code);
fmna_state_machine_dispatch_event(FMNA_SM_EVENT_SOUND_COMPLETE);
}
Sound Completed
The accessory will confirm the completion of the stop sound procedure by sending the Sound_Completed
message.
uint32_t fmna_generic_evt_sound_complete_handler(FMNA_SM_Event_t fmna_evt, void *p_context)
{
uint16_t sound_conn_handle = fmna_connection_get_conn_handle_with_multi_status_enabled(
FMNA_MULTI_STATUS_PLAYING_SOUND);
if (sound_conn_handle == CONN_HANDLE_INVALID)
{
return FMNA_SM_STATUS_SUCCESS;
}
if (fmna_connection_is_status_bit_enabled(sound_conn_handle, FMNA_MULTI_STATUS_ENCRYPTED))
{
fmna_gatt_send_indication(sound_conn_handle, FMNA_SERVICE_OPCODE_SOUND_COMPLETED, NULL, 0);
}
else
{
fmna_gatt_send_indication(sound_conn_handle, FMNA_SERVICE_NON_OWNER_OPCODE_SOUND_COMPLETED, NULL, 0);
}
fmna_connection_update_connection_info_all(FMNA_MULTI_STATUS_PLAYING_SOUND, false);
return FMNA_SM_STATUS_SUCCESS;
}
SDK Usage with iOS Find My APP
The chapter will guide users through the process of testing and using the Find My function on iOS devices.
Command Operation
To enter the Find My Network pairing mode and start pairing advertising when the accessory is in the unpaired state, send the command
findmy enter_pairing
. The default timeout for this process is 10 minutes.2023-07-28 16:19:59,073 INFO: input command: findmy enter_pairing 2023-07-28 16:19:59,073 INFO: Parser cmdParser: cmd opcode: 2300 param: [00] name: CMD_FINDMY_FEATURE 2023-07-28 16:19:59,073 INFO: Packet sendPacket: <<<send packet: AA 05 03 00 00 23 00 D5 2023-07-28 16:19:59,088 INFO: AciHostCLI continuously_read: >>>receive packet: AA 02 05 00 00 00 00 23 00 D6 2023-07-28 16:19:59,088 INFO: Parser eventParser: syncWord: AA,seqn: 02,len: 5,opcode: 0000,params: [00 23 00], check_sum: D6 2023-07-28 16:19:59,088 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-28 16:19:59,088 INFO: Parser eventParser: event_id: [00 23] 2023-07-28 16:19:59,088 INFO: Parser eventParser: status: [00]
After the accessory is paired, send the command
mmi freset
to reset it to the default factory settings and clear all bonding information.2023-07-28 16:19:33,066 INFO: input command: mmi freset 2023-07-28 16:19:33,066 INFO: Parser cmdParser: cmd opcode: 0004 param: [00 58] name: APP_CMD_MMI 2023-07-28 16:19:33,066 INFO: Packet sendPacket: <<<send packet: AA 02 04 00 04 00 00 58 9E 2023-07-28 16:19:33,082 INFO: AciHostCLI continuously_read: >>>receive packet: AA 02 05 00 00 00 04 00 00 F5 2023-07-28 16:19:33,082 INFO: Parser eventParser: syncWord: AA,seqn: 02,len: 5,opcode: 0000,params: [04 00 00], check_sum: F5 2023-07-28 16:19:33,082 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-28 16:19:33,082 INFO: Parser eventParser: event_id: [04 00] 2023-07-28 16:19:33,082 INFO: Parser eventParser: status: [00] 2023-07-28 16:19:33,598 INFO: AciHostCLI continuously_read: >>>receive packet: AA 03 03 00 07 00 00 F3 2023-07-28 16:19:33,598 INFO: Parser eventParser: syncWord: AA,seqn: 03,len: 3,opcode: 0007,params: [00], check_sum: F3 2023-07-28 16:19:33,598 INFO: Parser eventParser: event name: EVENT_DEVICE_STATE 2023-07-28 16:19:33,598 INFO: Parser eventParser: device_state: [00] 2023-07-28 16:19:33,598 INFO: Packet sendPacket: <<<send packet: AA 03 05 00 00 00 07 00 00 F1 2023-07-28 16:19:35,186 ERROR: gap in packets, between 3 and 1 packet before: [170, 3, 3, 0, 7, 0, 0, 243] packet after: [170, 1, 8, 0, 35, 0, 19, 34, 119, 86, 34, 3, 173] 2023-07-28 16:19:35,186 INFO: AciHostCLI continuously_read: >>>receive packet: AA 01 08 00 23 00 13 22 77 56 22 03 AD 2023-07-28 16:19:35,186 INFO: Parser eventParser: syncWord: AA,seqn: 01,len: 8,opcode: 0023,params: [13 22 77 56 22 03], check_sum: AD 2023-07-28 16:19:35,186 INFO: Parser eventParser: event name: EVENT_BT_READY 2023-07-28 16:19:35,186 INFO: Parser eventParser: factory_addr: [13 22 77 56 22 03] 2023-07-28 16:19:35,186 INFO: Packet sendPacket: <<<send packet: AA 04 05 00 00 00 23 00 00 D4
After the accessory is separated, send the
findmy put_serial_number
command to initiate the serial number read state.2023-07-28 16:24:35,541 INFO: input command: findmy put_serial_number 2023-07-28 16:24:35,541 INFO: Parser cmdParser: cmd opcode: 2300 param: [01] name: CMD_FINDMY_FEATURE 2023-07-28 16:24:35,541 INFO: Packet sendPacket: <<<send packet: AA 22 03 00 00 23 01 B7 2023-07-28 16:24:35,558 INFO: AciHostCLI continuously_read: >>>receive packet: AA 1F 05 00 00 00 00 23 00 B9 2023-07-28 16:24:35,558 INFO: Parser eventParser: syncWord: AA,seqn: 1F,len: 5,opcode: 0000,params: [00 23 00], check_sum: B9 2023-07-28 16:24:35,568 INFO: Parser eventParser: event name: APP_EVENT_ACK 2023-07-28 16:24:35,568 INFO: Parser eventParser: event_id: [00 23] 2023-07-28 16:24:35,568 INFO: Parser eventParser: status: [00]
Run the First Test
To test the Find My function, please launch the Find My APP on an iOS device and follow the steps below:
Press the
Add New Item
button to enroll a new Tag device.Press the
Other Supported Items
button to start scanning for the pairing advertising sent by the accessory.Send the
findmy enter pairing
command to trigger pairing advertising. When the mobile application scans the pairing advertising, the following window will appear. Press theConnect
button within the application.Press the
Continue
button, enter the name, and set the icon to complete the pairing session.
Users should be able to pair their Find My Network-enabled accessory and test the following features using the Find My APP:
GFPS Finder
The GFPS Finder, a novel protocol launched by Google, delineates an end-to-end encryption method specifically for tracking beaconing Bluetooth LE devices. It represents an expansion of the existing GFPS specification.
This extension should be implemented by vendors who are keen to activate location tracking for their devices, ensuring compatibility with Eddystone-E2EE-EID.
This document is partitioned into the following sections for a comprehensive introduction:
Enable GFPS Finder Feature presents the method for activating the GFPS Finder function.
GFPS Finder Features provides an overview of the capabilities supported by GFPS Finder.
Test With Find My Device APP introduces the procedure for testing using the Find My Device APP.
Enable GFPS Finder Feature
To enable GFPS, users need to make the appropriate configurations in app_gfps_cfg.c
and the project.
Parameters Configuration
GFPS Finder parameters can be configured in app_gfps_cfg.c
:
void app_gfps_cfg_init(void)
{
app_gfps_cfg.gfps_model_id[0] = 0;
app_gfps_cfg.gfps_model_id[1] = 0;
app_gfps_cfg.gfps_model_id[2] = 0;
app_gfps_cfg.gfps_support = 1;
app_gfps_cfg.gfps_finder_support = 1;
app_gfps_cfg.gfps_le_device_support = 1;
app_gfps_cfg.gfps_enable_tx_power = 1;
app_gfps_cfg.gfps_tx_power = -6;
app_gfps_cfg.tone_gfps_findme = 0x9C;//power_on.wav
app_gfps_cfg.gfps_account_key_num = 5;
app_gfps_cfg.gfps_discov_adv_interval = 32;
app_gfps_cfg.gfps_not_discov_adv_interval = 100;
app_gfps_cfg.gfps_battery_info_enable = 0;
app_gfps_cfg.gfps_le_disconn_force_enter_pairing_mode = 0;
app_gfps_cfg.gfps_le_device_mode = GFPS_LE_DEVICE_MODE_LE_MODE_WITHOUT_CSIP;
uint8_t gfps_public_key[64] = {0};
uint8_t gfps_private_key[32] = {0};
memcpy(app_gfps_cfg.gfps_public_key, gfps_public_key, 64);
memcpy(app_gfps_cfg.gfps_private_key, gfps_private_key, 32);
app_gfps_cfg.tone_gfps_dult = 0x9C;//power_on.wav
uint8_t device_name[64] = {0};
uint8_t company_name[64] = {0};
memcpy(app_gfps_cfg.gfps_company_name, company_name, sizeof(company_name));
memcpy(app_gfps_cfg.gfps_device_name, device_name, sizeof(device_name));
app_gfps_cfg.gfps_device_type = GFPS_LOCATOR_TRACKER;
}
Transport
app_gfps_cfg.gfps_support
must be set to 1. Otherwise, the GFPS advertising will not be advertised, and there will be no GFPS function, which is equivalent to enabling/disabling the GFPS function.
Module ID/Anti-spoofing public key/Anti-spoofing private key (Hex):
app_gfps_cfg.gfps_model_id
: Model ID information.app_gfps_cfg.gfps_public_key
: Public key information.app_gfps_cfg.gfps_private_key
: Private key information.
The registered Model ID, public key, and private key must be filled in. These parameters shall not all be zero. Users need to register these parameters by themselves. The registration address is Nearby.
Enable TX power data in ADV:
app_gfps_cfg.gfps_tx_power
: The mobile phone utilizes this TX power data to estimate the distance between itself and the device. If the distance surpasses a certain limit, the GFPS notification window will not appear. This value must invariably be provided. However, if the TX power data has already been specified while registering the Model ID on the Google Nearby Device console page, this value will be disregarded by the mobile phone. Consequently, abstaining from setting the TX power during the registration of the Model ID is recommended.
Discoverable/Not Discoverable advertising interval (0.625 ms/per unit):
GFPS advertising interval setting must be filled in.
app_gfps_cfg.gfps_discov_adv_interval
: Discoverable advertising interval. The default value is 32. If this value is set too large, it may affect the efficiency of the initial pairing.app_gfps_cfg.gfps_not_discov_adv_interval
: Not Discoverable advertising interval. The default value is 100. If wanting to minimize the power consumption in device idle, the maximum value can be set to 400. However, it may affect the efficiency of the subsequent pairing.
Account Key number:
app_gfps_cfg.gfps_account_key_num
: The maximum number of GFPS account keys the device could store in the FTL, which must be filled in.
Enable Finder:
app_gfps_cfg.gfps_finder_support
: Enable or disable the GFPS Finder feature.
Configure DULT informations:
app_gfps_cfg.gfps_company_name
: The company name of the device series registered in the Nearby Console.app_gfps_cfg.gfps_device_name
: The device name of the device series registered in the Nearby Console.app_gfps_cfg.gfps_device_type
: Device type, which can be referred toT_GFPS_DEVICE_TYPE
:typedef enum { GFPS_LOCATOR_TRACKER = 1, GFPS_WATCH = 146, GFPS_HEADPHONES = 149, GFPS_EARPHONES = 150, } T_GFPS_DEVICE_TYPE;
Add GFPS Finder Files
Copy the GFPS related files provided in 3rd_service_gfps
to sdk
.
Set up GFPS Finder Environment
Enable GFPS related flags in app_flags.h
:
#undef CONFIG_REALTEK_GFPS_FEATURE_SUPPORT
#define CONFIG_REALTEK_GFPS_FEATURE_SUPPORT 1
#undef CONFIG_REALTEK_GFPS_FINDER_SUPPORT
#define CONFIG_REALTEK_GFPS_FINDER_SUPPORT (1 && CONFIG_REALTEK_GFPS_FEATURE_SUPPORT)
#undef CONFIG_REALTEK_GFPS_LE_DEVICE_SUPPORT
#define CONFIG_REALTEK_GFPS_LE_DEVICE_SUPPORT (1 && CONFIG_REALTEK_GFPS_FEATURE_SUPPORT)
Enable build gfps_lib
in Keil project:
Find gfps_lib
in Keil project –> Right click –> Options for File gfps_lib
–> Tick in front of Include in Target Build
.
Enable build gfps
in Keil project:
Find the folder gfps
in Keil project –> Right click –> Options for Group gfps
–> Tick in front of Include in Target Build
.
GFPS Finder Features
This chapter introduces GFPS Finder support features:
GFPS Finder Provisioning will be introduced in chapter GFPS Finder Provisioning.
GFPS Finder Ring will be introduced in chapter GFPS Finder Ring.
GFPS Finder Set UTP Mode will be introduced in chapter GFPS Finder Set UTP Mode.
GFPS Finder Unprovision will be introduced in chapter GFPS Finder Unprovision.
GFPS Finder Provisioning
Provisioning refers to the process from not supporting finder to supporting finder. For users intent on utilizing the GFPS Finder feature, commencement of the provisioning process is necessary.
T_GFPS_FINDER_CAUSE app_gfps_finder_cb(T_GFPS_FINDER_CB_DATA *p_data)
{
T_GFPS_FINDER_CAUSE cause = GFPS_FINDER_CAUSE_SUCCESS;
T_GFPS_FINDER_CB_DATA data;
memcpy(&data, p_data, sizeof(T_GFPS_FINDER_CB_DATA));
uint8_t evt = data.evt;
uint8_t ret_err = 0;
APP_PRINT_INFO1("app_gfps_finder_cb: evt %d", evt);
switch (evt)
{
case GFPS_FINDER_EVT_SET_EIK:
{
memcpy(&p_app_gfps_finder->p_finder->eik, &data.msg_data.eik, sizeof(T_GFPS_EIK));
int8_t save_ret = ftl_save_to_storage(&p_app_gfps_finder->p_finder->eik,
GFPS_FINDER_EIK_FLASH_OFFSET,
sizeof(T_GFPS_EIK));
if (save_ret)
{
ret_err = 1;
goto err;
}
T_BLE_EXT_ADV_MGR_STATE adv_state = gfps_finder_adv_get_adv_state();
if (adv_state == BLE_EXT_ADV_MGR_ADV_DISABLED)
{
uint8_t hash;
uint32_t counter = (p_app_gfps_finder->p_finder->clock_value / 1024) * 1024;
app_gfps_finder_generate_adv_ei_and_hash(p_app_gfps_finder->p_finder->adv_ei,
p_app_gfps_finder->p_finder->eik.key, counter, &hash);
gfps_finder_adv_update_adv_ei_hash(p_app_gfps_finder->p_finder->adv_ei, hash);
gfps_finder_adv_start(0);
app_gfps_finder_start_update_adv_ei_timer();
}
T_GFPS_FINDER test;
memset(&test, 0, sizeof(T_GFPS_FINDER));
int8_t load_ret = ftl_load_from_storage(&test.eik, GFPS_FINDER_EIK_FLASH_OFFSET,
sizeof(T_GFPS_EIK));
if (load_ret)
{
APP_PRINT_ERROR1("app_gfps_finder_cb: load eik from ftl fail %d", load_ret);
}
APP_PRINT_INFO2("app_gfps_finder_cb: load eik %b, valid %d",
TRACE_BINARY(32, test.eik.key), test.eik.valid);
}
break;
......
default:
{
}
break;
}
return cause;
err:
cause = GFPS_FINDER_CAUSE_INVALID_VALUE;
APP_PRINT_ERROR1("app_gfps_finder_cb: err %d", ret_err);
return cause;
}
GFPS Finder Ring
GFPS Finder supports the function of making the device ring. If users want to use this function, please refer to the following flow chart:
T_GFPS_FINDER_CAUSE app_gfps_finder_cb(T_GFPS_FINDER_CB_DATA *p_data)
{
T_GFPS_FINDER_CAUSE cause = GFPS_FINDER_CAUSE_SUCCESS;
T_GFPS_FINDER_CB_DATA data;
memcpy(&data, p_data, sizeof(T_GFPS_FINDER_CB_DATA));
uint8_t evt = data.evt;
uint8_t ret_err = 0;
APP_PRINT_INFO1("app_gfps_finder_cb: evt %d", evt);
switch (evt)
{
......
case GFPS_FINDER_EVT_RING:
{
p_app_gfps_finder->gfps_finder_conn_id = data.msg_data.ring.conn_id;
p_app_gfps_finder->gfps_finder_service_id = data.msg_data.ring.service_id;
uint8_t ring_type = data.msg_data.ring.ring_type;
uint16_t ring_time = data.msg_data.ring.ring_time;
uint8_t ring_volume_level = data.msg_data.ring.ring_volume_level;
/*the first byte may hold a special value of 0xFF to ring all components that can ring.*/
if (ring_type == 0xFF)
{
ring_type = GFPS_ALL_RING;
}
app_gfps_msg_set_ring_timeout(ring_time);
app_gfps_msg_handle_ring_event(ring_type);
if ((ring_volume_level != GFPS_FINDER_RING_VOLUME_DEFAULT) &&
(p_app_gfps_finder->p_finder->ring_volume_modify == GFPS_FINDER_RING_VOLUME_ENABLE))
{
p_app_gfps_finder->gfps_finder_ring_volume_level = ring_volume_level;
}
/*A byte indicating the new ringing state*/
uint8_t ring_state;
if (ring_type == GFPS_ALL_STOP)
{
ring_state = GFPS_FINDER_RING_GATT_STOP;
}
else
{
ring_state = GFPS_FINDER_RING_STARTED;
}
gfps_finder_rsp_ring_request(p_app_gfps_finder->gfps_finder_conn_id,
p_app_gfps_finder->gfps_finder_service_id,
ring_state, ring_type, ring_time);
}
break;
......
default:
{
}
break;
}
return cause;
err:
cause = GFPS_FINDER_CAUSE_INVALID_VALUE;
APP_PRINT_ERROR1("app_gfps_finder_cb: err %d", ret_err);
return cause;
}
GFPS Finder Set UTP Mode
Unwanted Tracking Protection mode is intended to allow any client to identify abusive devices with no server communication. By default, the provider should rotate all identifiers as described in the ID Rotation chapter below. The server can decide to relay an Unwanted Tracking Protection mode activation request through a sighter of the provider. By doing so, it causes the provider to temporarily use a fixed MAC address, allowing clients to detect it and warn the user of possible unwanted tracking.
To activate or deactivate the unwanted tracking protection mode of the beacon, the seeker should perform a write operation to the characteristic.
T_GFPS_FINDER_CAUSE app_gfps_finder_cb(T_GFPS_FINDER_CB_DATA *p_data)
{
T_GFPS_FINDER_CAUSE cause = GFPS_FINDER_CAUSE_SUCCESS;
T_GFPS_FINDER_CB_DATA data;
memcpy(&data, p_data, sizeof(T_GFPS_FINDER_CB_DATA));
uint8_t evt = data.evt;
uint8_t ret_err = 0;
APP_PRINT_INFO1("app_gfps_finder_cb: evt %d", evt);
switch (evt)
{
......
case GFPS_FINDER_EVT_UTP_ACTIVE:
{
gfps_finder_adv_update_frame_type(0x41);
app_gfps_finder_upt_enable_start_update_rpa_timer();
}
break;
case GFPS_FINDER_EVT_UTP_DEACTIVE:
{
gfps_finder_adv_update_frame_type(0x40);
app_gfps_finder_upt_enable_stop_rpa_timer();
}
break;
......
default:
{
}
break;
}
return cause;
err:
cause = GFPS_FINDER_CAUSE_INVALID_VALUE;
APP_PRINT_ERROR1("app_gfps_finder_cb: err %d", ret_err);
return cause;
}
GFPS Finder Unprovision
GFPS Finder Unprovision refers to the process of transitioning from supporting the Finder to not supporting it.
T_GFPS_FINDER_CAUSE app_gfps_finder_cb(T_GFPS_FINDER_CB_DATA *p_data)
{
T_GFPS_FINDER_CAUSE cause = GFPS_FINDER_CAUSE_SUCCESS;
T_GFPS_FINDER_CB_DATA data;
memcpy(&data, p_data, sizeof(T_GFPS_FINDER_CB_DATA));
uint8_t evt = data.evt;
uint8_t ret_err = 0;
APP_PRINT_INFO1("app_gfps_finder_cb: evt %d", evt);
switch (evt)
{
......
case GFPS_FINDER_EVT_CLEAR_EIK:
{
memset(&p_app_gfps_finder->p_finder->eik, 0, sizeof(T_GFPS_EIK));
uint8_t ret = ftl_save_to_storage(&p_app_gfps_finder->p_finder->eik, GFPS_FINDER_EIK_FLASH_OFFSET,
sizeof(T_GFPS_EIK));
if (ret)
{
ret_err = 2;
goto err;
}
T_BLE_EXT_ADV_MGR_STATE adv_state = gfps_finder_adv_get_adv_state();
if (adv_state == BLE_EXT_ADV_MGR_ADV_ENABLED)
{
gfps_finder_adv_stop(APP_STOP_ADV_CAUSE_GFPS_FINDER);
app_gfps_finder_stop_update_adv_ei_timer();
app_gfps_finder_stop_update_random_window_timer();
}
}
break;
......
default:
{
}
break;
}
return cause;
err:
cause = GFPS_FINDER_CAUSE_INVALID_VALUE;
APP_PRINT_ERROR1("app_gfps_finder_cb: err %d", ret_err);
return cause;
}
Test With Find My Device APP
Factory reset and power on the device.
Factory reset: Input
mmi freset
in ACI Host CLI Tool to do factory reset.Power on: Input
mmi pwron
in ACI Host CLI Tool to power on.
Click
connect
button on the popup window to connect.Agree to user responsibility and enter screen lock.
Add the device to the Find My Device APP.
One Wire UART
The purpose of this document is to give an overview of one wire UART function. This document will be divided into the following parts to introduce:
How to enable one wire UART will be introduced in chapter Configuration.
Source code of one wire UART will be introduced in chapter Code Overview.
Configuration
This chapter introduces how to enable one wire UART:
How to configure peripheral will be introduced in chapter Peripheral Configuration.
How to configure one wire UART macro will be introduced in chapter Macro Configuration.
Peripheral Configuration
Firstly, the parameter app_cfg_const.one_wire_uart_support
should be set to enable one wire UART.
app_cfg_const.one_wire_uart_support = 1;
Secondly, PINMUX should be configured as UART. If users want to enable two or more UARTs, the corresponding number of pins should be configured.
Currently, only UART0
and UART2
are available. The macro ONE_WIRE_UART0_PINMUX
is configured as UART0
and ONE_WIRE_UART2_PINMUX
is configured as UART2
.
#define ONE_WIRE_UART0_PINMUX P3_0
#define ONE_WIRE_UART2_PINMUX P3_1
Thirdly, baud rate should be configured the same as the other side. Currently, baud rate is configured as 115200 through parameter
app_transfer_cfg.data_uart_baud_rate
.
app_transfer_cfg.data_uart_baud_rate = BAUD_RATE_115200;
Macro Configuration
Set macro F_APP_ENABLE_TWO_ONE_WIRE_UART
in app_flags.h
:
#define F_APP_ENABLE_TWO_ONE_WIRE_UART 1
Code Overview
This chapter introduces one wire UART Source code:
One wire UART Init will be introduced in chapter One Wire UART Init.
One wire UART Data Send will be introduced in chapter One Wire UART Data Send.
One wire UART Data Receive will be introduced in chapter One Wire UART Data Receive.
One Wire UART Init
Initialization of one wire UART includes initialization of app_uart
and setting of UART. Initializing flow is as below:
The function app_console_uart_init()
is used for the APP to set parameters to UART.
static void app_console_uart_init(void)
{
...
T_CONSOLE_UART_CONFIG console_uart_config;
...
console_uart_config.one_wire_uart_support = app_cfg_const.one_wire_uart_support;
console_uart_config.data_uart_baud_rate = app_transfer_cfg.data_uart_baud_rate;
console_uart_config.callback = app_console_handle_wake_up;
console_uart_config.uart_rx_dma_enable = false;
console_uart_config.uart_tx_dma_enable = false;
...
console_uart_config_init(&console_uart_config);
}
The function app_uart_buffer_alloc()
is used to initialize the APP database and configure one wire UART by calling function UART_OneWireConfig
and register callback to UART to receive data.
void app_uart_init(void)
{
app_uart_buffer_alloc(0);
app_uart_buffer_alloc(2);
console_uart_init(app_uart_callback);
}
When the app_task
is created, the function app_one_wire_uart_open()
is called to configure PINMUX mode and pad and initialize the UART driver by calling function app_console_uart_driver_init()
.
void app_one_wire_uart_open(uint8_t index)
{
switch (index)
{
case T_IDX_UART0:
{
...
Pinmux_Deinit(ONE_WIRE_UART0_PINMUX);
Pinmux_Config(ONE_WIRE_UART0_PINMUX, UART0_TX);
Pad_Config(ONE_WIRE_UART0_PINMUX, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE,
PAD_OUT_LOW);
Pad_PullConfigValue(ONE_WIRE_UART0_PINMUX, PAD_STRONG_PULL);
app_console_uart_driver_init(0);
UART_ClearRxFifo(UART0);
UART_INTConfig(UART0, UART_INT_RD_AVA | UART_INT_IDLE,
ENABLE);//for normal pin, line status intr unnecessary
...
}
break;
case T_IDX_UART2:
{
...
}
break;
default:
break;
}
}
One Wire UART Data Send
UART will automatically transition to TX mode before sending any data. Following data transmission, UART will enter RX mode.
If users want to send data by 2 one wire UARTs at the same time, these three functions shall be called in different conditions:
If the command format is the same as current in the code, users can call
app_report_uart_event()
directly. The parameter index represents UART index:static void app_report_uart_event(uint16_t event_id, uint8_t *data, uint16_t len, uint8_t index) { if (app_cfg_const.enable_data_uart || app_cfg_const.one_wire_uart_support) { uint16_t total_len; uint8_t check_sum; typedef struct { uint8_t sync_byte; uint8_t seq; uint16_t pkt_len; uint16_t event_id; uint8_t data[0]; } __attribute__((packed)) T_SEND_BUF; ... send_buf->sync_byte = CMD_SYNC_BYTE; send_buf->seq = uart_tx_seqn[index]; send_buf->pkt_len = len + sizeof(send_buf->event_id); send_buf->event_id = event_id; if (len) { memcpy(send_buf->data, data, len); } check_sum = app_util_calc_checksum((uint8_t *)&send_buf->seq, total_len - 2); send_buf->data[len] = check_sum; if (app_push_data_transfer_queue(CMD_PATH_UART, (uint8_t *)send_buf, total_len, index) == false) { free(send_buf); } } }
If the command format is different from current in the code, users can fix the command format in
app_report_uart_event()
or callapp_push_data_transfer_queue()
. The parameter index represents UART index. The function includes flow control in the APP.If users don’t need any flow control in the APP, the function
console_uart_write()
can be called. The parameter index represents UART index.
One Wire UART Data Receive
Data received from UART is sent to the callback app_uart_callback()
and received data will be sent to the app_task
:
RAM_TEXT_SECTION void app_uart_callback(T_CONSOLE_UART_EVENT evt, void *buf, uint16_t len, uint8_t index)
{
APP_PRINT_INFO4("app_uart_callback len %x, index %x, evt %x, data %b", len, index, evt, TRACE_BINARY(len, buf));
uint32_t s;
switch (evt)
{
case CONSOLE_UART_EVENT_DATA_IND:
{
T_IO_MSG msg;
if (index == cmd_block[index].id)
{
...
msg.type = IO_MSG_TYPE_UART;
msg.subtype = 0;
msg.u.param = index;
app_io_msg_send(&msg);
}
}
break;
default:
break;
}
}
Data can be parsed in the function app_uart_parser()
and specific commands shall be handled in app_handle_cmd_set()
after parsing.
USB Mass Storage
This application note describes the functional implementation method and the employed USB Mass Storage descriptors.
This USB Mass Storage addresses Bulk-Only transport, or in other words, transport of command, data, and status
occurring solely via bulk endpoints (not via interrupt or control endpoints). This specification only uses the
default pipe to clear a STALL
condition on the bulk endpoints and to issue class-specific requests as defined
below. This specification does not require the use of an interrupt endpoint.
Requirements
The device descriptors and related descriptors for USB Mass Storage are mostly introduced in this paragraph.
USB Device Configure Descriptor
Device descriptor describes general information about USB Device.
USB Mass Storage Configure Descriptor
This application exposes the following features:
USB Mass Storage interface descriptor.
Need to configure the mass storage class specification.
Endpoint Descriptor.
Configure endpoint packet size.
Source Code Overview
The following sections describe important parts of this application.
Initialization
The USB main function is invoked when the application is in the USB init flow, and it performs the following initialization functions.
void app_usb_init(void)
{
memset(&app_usb_db, 0, sizeof(T_APP_USB_DB));
usb_dm_cb_register(app_usb_dm_cb);
adp_register_state_change_cb(ADP_DETECT_5V, (P_ADP_PLUG_CBACK)app_usb_adp_state_change_cb, NULL);
usb_dev_init();
T_USB_CORE_CONFIG config = {.speed = USB_SPEED_FULL, .class_set = {.hid_enable = 0, .uac_enable = 0}};
config.speed = USB_SPEED_HIGH;
usb_dm_core_init(config);
#if F_APP_USB_MSC_SUPPORT
sd_config_init((T_SD_CONFIG *)&sd_card_cfg);
sd_board_init();
sd_card_init();
extern int usb_ms_scsi_init(void);
usb_ms_scsi_init();
extern int usb_ms_disk_init(void);
usb_ms_disk_init();
usb_msc_init();
#endif
}
USB Device Configure
The USB device application can configure the descriptor.
USB Mass Storage Configure Descriptor
In analogy to the device descriptor, a mass storage configuration descriptor is applicable only in the case of MassStorage-only devices.
static T_USB_INTERFACE_DESC usb_msc_if_desc =
{
.bLength = sizeof(T_USB_INTERFACE_DESC),
.bDescriptorType = USB_DESC_TYPE_INTERFACE,
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_MSC,
.bInterfaceSubClass = 0x06, //SCSI
.bInterfaceProtocol = 0x50, //BBB
.iInterface = 4
};
static const T_USB_ENDPOINT_DESC usb_ms_bi_ep_desc_hs =
{
.bLength = sizeof(T_USB_ENDPOINT_DESC),
.bDescriptorType = USB_DESC_TYPE_ENDPOINT,
.bEndpointAddress = MSC_BULK_IN_EP,
.bmAttributes = USB_EP_TYPE_BULK,
.wMaxPacketSize = 512,
.bInterval = 4,
};
static const T_USB_ENDPOINT_DESC usb_ms_bo_ep_desc_hs =
{
.bLength = sizeof(T_USB_ENDPOINT_DESC),
.bDescriptorType = USB_DESC_TYPE_ENDPOINT,
.bEndpointAddress = MSC_BULK_OUT_EP,
.bmAttributes = USB_EP_TYPE_BULK,
.wMaxPacketSize = 512,
.bInterval = 4,
};
static const T_USB_ENDPOINT_DESC usb_ms_bi_ep_desc_fs =
{
.bLength = sizeof(T_USB_ENDPOINT_DESC),
.bDescriptorType = USB_DESC_TYPE_ENDPOINT,
.bEndpointAddress = 0x82,
.bmAttributes = USB_EP_TYPE_BULK,
.wMaxPacketSize = 64,
.bInterval = 1,
};
static const T_USB_ENDPOINT_DESC usb_ms_bo_ep_desc_fs =
{
.bLength = sizeof(T_USB_ENDPOINT_DESC),
.bDescriptorType = USB_DESC_TYPE_ENDPOINT,
.bEndpointAddress = 0x02,
.bmAttributes = USB_EP_TYPE_BULK,
.wMaxPacketSize = 64,
.bInterval = 1,
};
void usb_msc_init(void)
{
usb_ms_driver_if_desc_register((T_USB_DESC_HDR **)usb_ms_if_descs_fs,
(T_USB_DESC_HDR **)usb_ms_if_descs_hs);
usb_ms_driver_init();
}
USB Ctrl
USB will boot up and successfully list all of its features when this API is run.
void app_usb_start(void)
{
if (app_cfg_const.bud_role != REMOTE_SESSION_ROLE_SECONDARY)
{
app_usb_set_hp_mode();
app_auto_power_off_disable(AUTO_POWER_OFF_MASK_USB_AUDIO_MODE);
app_dlps_disable(APP_DLPS_ENTER_CHECK_USB);
#if (TARGET_RTL8773DO == 1)
pmu_vcore3_pon_domain_enable(PMU_USB);
usb_dm_start(false);
#else
usb_dm_start(false);
#endif
app_ipc_publish(USB_IPC_TOPIC, USB_IPC_EVT_PLUG, NULL);
}
}
APP Configurable Functions
APP configurable functions are defined in app_flags.h
.
F_APP_USB_MSC_SUPPORT
can enable the USB Mass Storage function in app_flags.h
.
Test Procedure
Make sure that the USB Mass Storage functionality is implemented on the EVB and the system is properly configured. This may require software development and configuration on the EVB. Connect the EVB to the host using a USB cable. Ensure that the USB cable can transfer data correctly and that the EVB is recognized by the host.
Set up Test Environment
To set up a USB Mass Storage testing environment, the following components are needed: USB Mass Storage EVB, and the SD card connects with Evolution Board via SDIO. This is a hardware device that supports USB Mass Storage and is typically used to simulate a storage device.
USB Cable: This is used to connect the USB Mass Storage EVB to a USB port on a computer.
Computer: This is used to run the test code and communicate with the USB Mass Storage EVB.
Test USB Mass Storage
Open Device Manager (Windows) on the host to check if the connected USB device is enumerated correctly.
Files can be copied, erased, and other operations performed in the mass storage.
LE HID Host
The purpose of this document is to provide an overview of the Bluetooth LE HID host application based on HOGP. HOGP defines the procedures and features that are utilized by Bluetooth LE HID devices through GATT, as well as Bluetooth HID hosts through GATT. This profile shall operate over an LE transport only.
HID Roles
HOGP defines three roles: HID Device, Boot Host, and Report Host.
The HID Device shall be a GATT server.
The Boot Host shall be a GATT client.
The Report Host shall be a GATT client.
Use of the term HID Host refers to both host roles: Boot Host, and Report Host. A Report Host is required to support a HID Parser and be able to handle arbitrary formats for data transfers (known as reports) whereas a Boot Host is not required to support a HID Parser as all data transfers (reports) for Boot Protocol mode are of predefined length and format.
Roles/Service Relationships
The relationship between services and the profile roles is shown below:
![../../_images/Boot_Host_HID_Device_Relationship.png](../../_images/Boot_Host_HID_Device_Relationship.png)
![../../_images/Report_Host_HID_Device_Relationships.png](../../_images/Report_Host_HID_Device_Relationships.png)
Note
Profile roles are represented by yellow boxes and services are represented by orange boxes.
The Report Host supports the Scan Client role of the Scan Parameters Profile. The Boot Host shall not support the Scan Client role of the Scan Parameters Profile.
LE HID Host Configuration
This chapter provides an introduction on how to enable the LE HID host feature.
Set macro BLE_HID_CLIENT_SUPPORT
and F_APP_BLE_HID_HOST_SUPPORT
in app_flags.h
.
#define BLE_HID_CLIENT_SUPPORT 1
#define F_APP_BLE_HID_HOST_SUPPORT 1
API Introduction
This chapter defines the APIs for the LE HID host.
HID Interaction
Below is a flow chart depicting the interaction between an HID host and an HID device based on Low Energy connections.
![../../_images/hid_host_hid_device_Interaction.png](../../_images/hid_host_hid_device_Interaction.png)
HID Client Init
To initialize the HID client and configure the maximum number of HID links, the following interface can be used:
bool hids_add_client(P_FUN_HIDS_CLIENT_APP_CB app_cb, uint8_t link_num)
{
T_ATTR_UUID srv_uuid = {0};
srv_uuid.is_uuid16 = true;
srv_uuid.p.uuid16 = GATT_UUID_HIDS;
if (gatt_client_spec_register(&srv_uuid, hids_client_cbs) == GAP_CAUSE_SUCCESS)
{
/* register callback for profile to inform application that some events happened. */
hids_client_cb = app_cb;
hids_client_link_num = link_num;
hids_table = calloc(1, link_num * sizeof(T_HIDS_LINK));
return true;
}
return false;
}
HID Read Report Map
After the HID discovery is completed, the report map can be read using the characteristic UUID
.
T_APP_RESULT app_ble_hid_service_cback(uint16_t conn_handle, uint8_t type,
void *p_data)
{
T_APP_RESULT app_result = APP_RESULT_SUCCESS;
if (type == GATT_MSG_HIDS_CLIENT_DIS_DONE)
{
T_HIDS_CLIENT_DIS_DONE *p_dis_done = (T_HIDS_CLIENT_DIS_DONE *)p_data;
APP_PRINT_TRACE1("app_ble_hid_service_cback: discover state %d",
p_dis_done->is_found);
if (p_dis_done->is_found)
{
hid_conn_handle = conn_handle;
for (uint8_t i = 0; i < p_dis_done->srv_instance_num; i++)
{
hids_client_read_report_map_value(conn_handle, i);
}
}
}
else if (type == GATT_MSG_HIDS_CLIENT_READ_RESULT)
{
T_HIDS_CLIENT_READ_RESULT *p_read_result = (T_HIDS_CLIENT_READ_RESULT *)p_data;
APP_PRINT_TRACE1("app_ble_hid_service_cback: char_uuid 0x%x",
p_read_result->char_uuid);
if (p_read_result->char_uuid == GATT_UUID_CHAR_REPORT_MAP)
{
app_ble_hid_host_read_report_map_handle(conn_handle,
p_read_result->data.hids_report_map.p_hids_report_map,
p_read_result->data.hids_report_map.hids_report_map_len);
}
}
return app_result;
}
Send the report map of the HID device to the ACI
host via UART
path.
void app_ble_hid_host_read_report_map_handle(uint16_t conn_handle, uint8_t *report_buf,
uint16_t report_len)
{
T_APP_LE_LINK *p_link;
p_link = app_link_find_le_link_by_conn_handle(conn_handle);
if (p_link != NULL)
{
APP_PRINT_INFO3("app_ble_hid_host_read_report_map_handle: le_addr %s, conn_handle 0x%x, len %d",
TRACE_BDADDR(p_link->bd_addr), conn_handle, report_len);
if ((report_buf == NULL) || (report_len == 0))
{
return;
}
struct
{
uint16_t conn_handle;
uint16_t pkt_len;
uint8_t payload[];
} __attribute__((packed)) *rpt = NULL;
rpt = calloc(1, report_len + sizeof(*rpt));
rpt->conn_handle = conn_handle;
rpt->pkt_len = report_len;
memcpy(&rpt->payload, report_buf, report_len);
app_report_event(CMD_PATH_UART, EVENT_BLE_HID_READ_REPORT_MAP, 0, (uint8_t *)rpt,
report_len + sizeof(*rpt));
free(rpt);
}
}
HID Read Report
After the HID discovery is complete, users can read the HID report by using the characteristic UUID.
T_APP_RESULT app_ble_hid_service_cback(uint16_t conn_handle, uint8_t type,
void *p_data)
{
if (type == GATT_MSG_HIDS_CLIENT_READ_RESULT)
{
T_HIDS_CLIENT_READ_RESULT *p_read_result = (T_HIDS_CLIENT_READ_RESULT *)p_data;
APP_PRINT_TRACE1("app_ble_hid_service_cback: char_uuid 0x%x",
p_read_result->char_uuid);
if (p_read_result->char_uuid == GATT_UUID_CHAR_REPORT)
{
app_ble_hid_host_read_feature_report_handle(conn_handle,
p_read_result->data.hids_report.p_hids_report_value,
p_read_result->data.hids_report.hids_report_value_len,
p_read_result->data.hids_report.report_id);
}
}
}
To send the HID device report to the ACI Host via UART path.
void app_ble_hid_host_read_feature_report_handle(uint16_t conn_handle, uint8_t *p_value,
uint16_t length, uint8_t report_id)
{
T_APP_LE_LINK *p_link;
p_link = app_link_find_le_link_by_conn_handle(conn_handle);
if (p_link != NULL)
{
APP_PRINT_INFO3("app_ble_hid_host_read_feature_report_handle: le_addr %s, conn_handle 0x%x, len %d",
TRACE_BDADDR(p_link->bd_addr), conn_handle, length);
struct
{
uint16_t conn_handle;
uint8_t report_id;
uint16_t pkt_len;
uint8_t payload[];
} __attribute__((packed)) *rpt = NULL;
rpt = calloc(1, length + sizeof(*rpt));
rpt->conn_handle = conn_handle;
rpt->report_id = report_id;
rpt->pkt_len = length;
memcpy(&rpt->payload, p_value, length);
app_report_event(CMD_PATH_UART, EVENT_BLE_HID_READ_REPORT, 0, (uint8_t *)rpt,
length + sizeof(*rpt));
free(rpt);
}
}
HID Input Report
After the HID device sends the report data, the HID host will receive the input reports.
T_APP_RESULT app_ble_hid_service_cback(uint16_t conn_handle, uint8_t type,
void *p_data)
{
if (type == GATT_MSG_HIDS_CLIENT_NOTIFY_IND)
{
T_HIDS_CLIENT_NOTIFY_DATA *p_notify_data = (T_HIDS_CLIENT_NOTIFY_DATA *)p_data;
APP_PRINT_TRACE3("app_ble_hid_service_cback: report id 0x%x, data length %d, data %b",
p_notify_data->report_id, p_notify_data->data_len,
TRACE_BINARY(p_notify_data->data_len, p_notify_data->p_data));
app_ble_hid_host_inreport_handle(conn_handle, p_notify_data->p_data,
p_notify_data->data_len, p_notify_data->report_id);
}
}
To send the HID input report data to the ACI Host via UART path.
void app_ble_hid_host_inreport_handle(uint16_t conn_handle, uint8_t *p_value,
uint16_t length, uint8_t report_id)
{
T_APP_LE_LINK *p_link;
p_link = app_link_find_le_link_by_conn_handle(conn_handle);
if (p_link != NULL)
{
APP_PRINT_INFO3("app_ble_hid_host_inreport_handle: le_addr %s, conn_handle 0x%x, len %d",
TRACE_BDADDR(p_link->bd_addr), conn_handle, length);
struct
{
uint16_t conn_handle;
uint8_t report_id;
uint16_t pkt_len;
uint8_t payload[];
} __attribute__((packed)) *rpt = NULL;
rpt = calloc(1, length + sizeof(*rpt));
rpt->conn_handle = conn_handle;
rpt->report_id = report_id;
rpt->pkt_len = length;
memcpy(&rpt->payload, p_value, length);
app_report_event(CMD_PATH_UART, EVENT_BLE_HID_IN_REPORT, 0, (uint8_t *)rpt,
length + sizeof(*rpt));
free(rpt);
}
}
Application Controller Interface Commands and Events
This chapter introduces the functional specifications for the Application Controller interface (ACI), which provides a uniform command method for the Host to access Device capabilities and control connections with other Devices. The commands (Host -> Device) and events (Device -> Host) are sent between the Host and the Device.
Retransmission
To enhance the reliability of packet transmission and reception, a retransmission mechanism has been
implemented on the Device side. When the Device sends an event (excluding ACI_EVENT_ACK) to
the Host, the Host shall respond with an ACI_CMD_ACK; failure to do so will trigger retransmission,
with the number of retries determined by the DT_RESEND_NUM
parameter. This feature is enabled by
default in sdk\src\mcu\module\data_transfer\data_transfer.c
.
#define DT_RESEND_NUM 20
Similarly, when the Host sends a command (excluding ACI_CMD_ACK) to the Device, the Device responds with an ACI_EVENT_ACK. If the ACI_EVENT_ACK is not received, the decision to trigger retransmission and the number of retransmissions are determined by the Host.
ACI Data Formats
The ACI Command packet is used to send commands to the Device from the Host. The ACI Event packet is used to send events to the Host from the Device. The format of the ACI Command and Event packet is shown below, and the definition of each field is explained below.
SyncWord:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xAA |
Sync word. |
SeqN:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Sequence number (range: 1~255). |
Length:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXX |
The total length of the Opcode field and the Parameter field in octets (range: 1~255). |
Opcode:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXX |
Opcode of ACI Command and Events. |
Parameter 0 - N:
Size: Parameter_Total_Length
Value |
Parameter Description |
---|---|
0xXX |
Each command or event has a specific number of parameters associated with it. These parameters and the size of each of the parameters are defined for each command or event. Each parameter is an integer number of octets in size. |
CheckSum:
Size: 1
Value |
Parameter Description |
---|---|
0xXX |
The CheckSum is obtained by calculating through |
Note
In this packet model, it is recommended that the length of the Parameter does not exceed 1024 bytes.
uint8_t app_util_calc_checksum(uint8_t *dataPtr, uint16_t len)
{
uint8_t check_sum;
check_sum = 0;
while (len)
{
check_sum += *dataPtr;
dataPtr++;
len--;
}
return (0xff - check_sum + 1); //((~check_sum)+1);
}
Example: ACI_CMD_MMI
ACI Command data packet:
AA 04 04 00 04 00 00 54 A0
ACI Commands and Events
ACI Commands
Summary of ACI Commands
Opcode |
Command |
Available |
---|---|---|
0x0000 |
Y |
|
0x0002 |
Y |
|
0x0003 |
Y |
|
0x0004 |
Y |
|
0x0005 |
Y |
|
0x0006 |
Y |
|
0x0009 |
Y |
|
0x0012 |
Y |
|
0x0017 |
Y |
|
0x0018 |
Y |
|
0x001B |
Y |
|
0x001C |
Y |
|
0x001E |
Y |
|
0x001F |
Y |
|
0x0020 |
Y |
|
0x0022 |
Y |
|
0x0030 |
Y |
|
0x0040 |
Y |
|
0x0102 |
Y |
|
0x0103 |
Y |
|
0x0104 |
Y |
|
0x0109 |
Y |
|
0x010E |
Y |
|
0x0111 |
Y |
|
0x0112 |
Y |
|
0x0113 |
Y |
|
0x0115 |
Y |
|
0x0116 |
Y |
|
0x0161 |
Y |
|
0x0162 |
Y |
|
0x0163 |
Y |
|
0x0164 |
Y |
|
0x020A |
Y |
|
0x0308 |
Y |
|
0x0309 |
Y |
|
0x030F |
Y |
|
0x0310 |
Y |
|
0x0400 |
Y |
|
0x0403 |
Y |
|
0x0404 |
Y |
|
0x0480 |
Y |
|
0x0481 |
Y |
|
0x0482 |
Y |
|
0x0483 |
Y |
|
0x0484 |
Y |
|
0x0488 |
Y |
|
0x0489 |
Y |
|
0x0420 |
Y |
|
0x0423 |
Y |
|
0x0426 |
Y |
|
0x0A0E |
Y |
|
0x2300 |
Y |
|
0x2400 |
Y |
|
0x3200 |
Y |
|
0x3201 |
Y |
|
0x3220 |
Y |
|
0x3223 |
Y |
|
0x3020 |
Y |
|
0x3021 |
Y |
|
0x3022 |
Y |
|
0x3023 |
Y |
|
0x3024 |
Y |
|
0x3025 |
Y |
|
0x3026 |
Y |
|
0x3027 |
Y |
|
0x3028 |
Y |
|
0x3029 |
Y |
|
0x302A |
Y |
|
0x302B |
Y |
|
0x302C |
Y |
|
0x302D |
Y |
|
0x302E |
Y |
|
0x302F |
Y |
|
0x3030 |
Y |
|
0x3031 |
Y |
|
0x3032 |
Y |
|
0x3033 |
Y |
|
0x3034 |
Y |
|
0x3250 |
Y |
|
0x3251 |
Y |
|
0x3252 |
Y |
|
0x3253 |
Y |
|
0x3254 |
Y |
|
0x3255 |
Y |
|
0x3256 |
Y |
|
0x3270 |
Y |
|
0x3300 |
Y |
|
0x3301 |
Y |
|
0x3302 |
Y |
|
0x3303 |
Y |
|
0x3304 |
Y |
|
0x3305 |
Y |
|
0x3306 |
Y |
|
0x3307 |
Y |
|
0x3801 |
Y |
|
0x3802 |
Y |
|
0x3803 |
Y |
|
0x3805 |
Y |
|
0x3809 |
Y |
|
0x380A |
Y |
|
0x3810 |
Y |
|
0x5008 |
N |
|
0x5009 |
N |
|
0x8000 |
Y |
|
0x8001 |
Y |
|
0x8004 |
Y |
|
0x8005 |
Y |
|
0x8006 |
Y |
|
0x8007 |
Y |
|
0x8009 |
Y |
|
0x80C3 |
Y |
|
0x8013 |
Y |
|
0x8040 |
Y |
|
0x8041 |
Y |
|
0x8042 |
Y |
|
0x8043 |
Y |
|
0x8044 |
Y |
|
0x8045 |
Y |
|
0x8046 |
Y |
|
0x8047 |
Y |
|
0x8048 |
Y |
|
0x8049 |
Y |
|
0x804A |
Y |
|
0x804B |
Y |
|
0x804C |
Y |
|
0x8080 |
Y |
|
0x8081 |
Y |
|
0x8082 |
Y |
|
0x8083 |
Y |
|
0x8084 |
Y |
|
0x8085 |
Y |
|
0x8086 |
Y |
|
0x8088 |
Y |
|
0x8089 |
Y |
|
0x808A |
Y |
|
0x80C0 |
Y |
|
0x8100 |
Y |
ACI_CMD_ACK
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_ACK |
0x0000 |
event_id, status |
None |
Description
This command is used for the Host to acknowledge the received event.
Command Parameters
event_id:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXX |
The acknowledged event_id. |
status:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Command complete: MCU can handle this command. |
0x01 |
Command disallow: MCU cannot handle this command. |
0x02 |
Unknown CMD. |
0x03 |
Parameters error . |
0x04 |
Busy. |
0x05 |
Process fail. |
0x06 |
One wire extend. |
0x08 |
Music req. |
ACI_CMD_BT_CREATE_CONNECTION
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_BT_CREATE_CONNECTION |
0x0002 |
profile, bd_addr |
Description
This command is used to trigger the linkback behavior for specific profiles.
Command Parameters
profile:
Size: 4 octets
Value | Parameter Description |
---|---|
0xXXXXXXXX | Bit mask (only used for Bluetooth Audio Transceiver function). 0x00000001: A2DP_SINK. 0x00000002: AVRCP_CONTROLLER. 0x00000004: HFP_HF. 0x00000080: HSP_AG. 0x00000200: MAP_MSE. 0x00000400: A2DP_SRC. 0x00000800: AVRCP_TARGET. 0x00001000: HFP_AG. 0x00002000: PBAP_PSE. 0x00004000: HSP_HF. |
bd_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
MAC address (Little-Endian) of the dedicated device. |
ACI_CMD_BT_DISCONNECT
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_BT_DISCONNECT |
0x0003 |
profile, bd_addr |
Description
This command is used to cancel the ongoing linkback procedure or disconnect the linked profiles. BTM will disconnect the ACL link if all of the profiles are disconnected.
Command Parameters
profile:
Size: 4 octets
Value | Parameter Description |
---|---|
0xXXXXXXXX | Bit mask (only used for Bluetooth Audio Transceiver function). 0x00000001: A2DP_SINK. 0x00000002: AVRCP_CONTROLLER. 0x00000004: HFP_HF. 0x00000080: HSP_AG. 0x00000200: MAP_MSE. 0x00000400: A2DP_SRC. 0x00000800: AVRCP_TARGET. 0x00001000: HFP_AG. 0x00002000: PBAP_PSE. 0x00004000: HSP_HF. 0xffffffff: All profile. |
bd_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXX |
MAC address (Little-Endian) of the target device. |
ACI_CMD_MMI
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_MMI |
0x0004 |
reserved, action |
None |
Description
MMI action, the user can add the corresponding MMI action according to specific needs based on sdk\src\sample\bt_audio_trx\app\app_mmi.h
.
Command Parameters
reserved:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Reserved. |
action:
Size: 1 octet
Value |
Parameter Description |
Return Event |
---|---|---|
0x02 |
MMI_FORCE_END_OUTGOING_CALL |
|
0x03 |
MMI_ANSWER_CALL |
|
0x04 |
MMI_REJECT_CALL |
|
0x05 |
MMI_END_ACTIVE_CALL |
None |
0x0E |
MMI_QUERY_CURRENT_CALL_LIST |
None |
0x32 |
MMI_AV_PLAY_PAUSE |
None |
0x54 |
MMI_DEV_POWER_ON |
|
0x56 |
MMI_DEV_POWER_OFF |
|
0x58 |
MMI_DEV_FACTORY_RESET_TO_DEFAULT |
|
0xA1 |
MMI_DUT_TEST_MODE |
None |
0xBB |
MMI_DULT_ENTER_ID_READ_STATE |
None |
Command Detail:
MMI_FORCE_END_OUTGOING_CALL
: End call without checking SCO status.MMI_ANSWER_CALL
: Answer an incoming call.MMI_REJECT_CALL
: Reject an incoming call.MMI_END_ACTIVE_CALL
: Add SCO if SCO doesn’t exist, otherwise end the call.MMI_QUERY_CURRENT_CALL_LIST
: Query call list.MMI_AV_PLAY_PAUSE
: Play or pause the audio stream.MMI_DEV_POWER_ON
: Change the device to power on state.MMI_DEV_POWER_OFF
: Change the device to power off state.MMI_DEV_FACTORY_RESET_TO_DEFAULT
: Reset the device to factory settings.MMI_DUT_TEST_MODE
: Enter device test mode.MMI_DULT_ENTER_ID_READ_STATE
: Make the device enter ID read state.
ACI_CMD_LEGACY_DATA_TRANSFER
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEGACY_DATA_TRANSFER |
0x0005 |
link_id, |
None |
Description
This command is used to send to SPP.
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Link index, which will be informed when the link is established (event: ACI_EVENT_PROFILE_CONN_STATUS). |
type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Single packet. |
0x01 |
Fragmented start packet. |
0x02 |
Fragmented continue packet. |
0x03 |
Fragmented end packet. |
total_length:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Total payload length. |
payload_length:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Payload length in this packet. |
payload:
Size: N octets
Value |
Parameter Description |
---|---|
payload |
N octets of the payload in this packet. |
ACI_CMD_ASSIGN_BUFFER_SIZE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_ASSIGN_BUFFER_SIZE |
0x0006 |
rx_buffer_size |
None |
Description
Host indicates to the Device about the max UART RX buffer size. The default value is 256 Bytes.
Command Parameters
rx_buffer_size:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXX |
The max UART RX buffer size of Host MCU. |
ACI_CMD_BT_GET_REMOTE_NAME
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_BT_GET_REMOTE_NAME |
0x0435 |
bd_addr |
None |
Description
Get the remote device name.
Command Parameters
bd_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXX |
The remote device Bluetooth address. |
ACI_CMD_SET_CFG
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SET_CFG |
0x0012 |
cfg_type, cfg_data |
None |
Description
Set device’s LE/legacy name.
Command Parameters
cfg_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Set the LE display name. |
0x01 |
Set the BR/EDR display name. |
cfg_data:
Size: N octets
Value |
Parameter Description |
---|---|
Name_length |
Must be less than 39. |
Name |
Name with length. |
ACI_CMD_GET_CFG_SETTING
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_GET_CFG_SETTING |
0x0017 |
get_type |
Description
Get config setting of device’s LE/legacy name.
Command Parameters
get_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
GET_CFG_LE_NAME |
0x01 |
GET_CFG_LEGACY_NAME |
ACI_CMD_GET_STATUS
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_GET_STATUS |
0x0018 |
status_index |
Description
Report some status information.
Command Parameters
status_index:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x02 |
Report device battery. |
0x04 |
Report application state. |
0x0F |
Report factory reset status. |
0x10 |
Report reject connect request status. |
0x11 |
Report radio mode. |
0x12 |
Report SCO status. |
0x13 |
Report MIC mute status. |
0xA1 |
Report device volume. |
ACI_CMD_BT_HFP_DIAL_WITH_NUMBER
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_BT_HFP_DIAL_WITH_NUMBER |
0x001B |
dial_num_payload |
None |
Description
Dial out with number to outgoing call.
Command Parameters
dial_num_payload:
Size: 25 octets
Parameter Description |
---|
The number is ASCII format. |
ACI_CMD_GET_BD_ADDR
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_GET_BD_ADDR |
0x001C |
None |
Description
Get Bluetooth device address.
Command Parameters
None.
ACI_CMD_STRING_MODE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_STRING_MODE |
0x001E |
None |
None |
Description
This command is used to set string mode.
Command Parameters
None.
ACI_CMD_SET_VP_VOLUME
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SET_VP_VOLUME |
0x001F |
VP volume |
None |
Description
This command is used to set voice prompt volume.
Command Parameters
VP volume:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 ~ 0x0F |
VP volume level. |
ACI_CMD_SET_AND_READ_DLPS
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SET_AND_READ_DLPS |
0x0020 |
action |
Description
Enable/disable device auto-enter DLPS.
Command Parameters
action:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Disable auto enter DLPS. |
0x01 |
Enable auto enter DLPS. |
ACI_CMD_XM_SET_MODE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_SET_MODE |
0x0030 |
mode |
None |
Description
Set device mode.
Command Parameters
mode:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Disable page scan and inquiry scan. |
0x01 |
Enable inquiry scan. |
0x02 |
Enable page scan. |
0x03 |
Enable page scan and inquiry scan. |
ACI_CMD_BT_HFP_SCO_MAG
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_BT_HFP_SCO_MAG |
0x0040 |
link_id, cfm |
None |
Description
SCO connection management.
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Link index, this index will be informed when the link established (event: ACI_EVENT_PROFILE_CONN_STATUS). |
cfm:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Reject the SCO connection indication. |
0x01 |
Accept the SCO connection indication. |
0x02 |
Send a request to disconnect the SCO connection. |
ACI_CMD_LE_DATA_TRANSFER
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LE_DATA_TRANSFER |
0x0102 |
link_id, type, total_length, payload_length, payload |
None |
Description
This command is used to send the data to remote devices via the LE link.
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for LE link. |
type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Single packet. |
0x01 |
Fragmented start packet. |
0x02 |
Fragmented continue packet. |
0x03 |
Fragmented end packet. |
total_length:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Total payload length. |
payload_length:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Payload length in this packet. |
payload:
Size: N octets
Parameter Description |
---|
N octets of the payload in this packet. |
ACI_CMD_LE_START_SCAN
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LE_START_SCAN |
0x0103 |
local_addr_type, |
None |
Description
Start LE scan.
Command Parameters
local_addr_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
GAP_LOCAL_ADDR_LE_PUBLIC |
0x01 |
GAP_LOCAL_ADDR_LE_RANDOM |
0x02 |
GAP_LOCAL_ADDR_LE_RPA_OR_PUBLIC |
0x03 |
GAP_LOCAL_ADDR_LE_RPA_OR_RAND |
phys:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x01 |
GAP_EXT_SCAN_PHYS_1M_BIT |
0x04 |
GAP_EXT_SCAN_PHYS_CODED_BIT |
0x05 |
GAP_EXT_SCAN_PHYS_ALL |
filter_policy:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
GAP_SCAN_FILTER_ANY |
0x01 |
GAP_SCAN_FILTER_WHITE_LIST |
0x02 |
GAP_SCAN_FILTER_ANY_RPA |
0x03 |
GAP_SCAN_FILTER_WHITE_LIST_RPA |
ext_filter_duplicate:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
GAP_SCAN_FILTER_DUPLICATE_DISABLE |
0x01 |
GAP_SCAN_FILTER_DUPLICATE_ENABLE |
0x02 |
GAP_SCAN_FILTER_DUPLICATE_ENABLED_RESET_FOR_EACH_PERIOD |
scan_type of 1M PHY:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
GAP_SCAN_MODE_PASSIVE |
0x01 |
GAP_SCAN_MODE_ACTIVE |
scan_interval of 1M PHY:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
In units of 0.625ms, range: 0x0004 to 0xFFFF. |
scan_window of 1M PHY:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
In units of 0.625ms, range: 0x0004 to 0xFFFF. |
scan_type of Coded PHY:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
GAP_SCAN_MODE_PASSIVE |
0x01 |
GAP_SCAN_MODE_ACTIVE |
scan_interval of Coded PHY:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
In units of 0.625ms, range: 0x0004 to 0xFFFF. |
scan_window of Coded PHY:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
In units of 0.625ms, range: 0x0004 to 0xFFFF. |
ACI_CMD_LE_STOP_SCAN
Command |
Opcode |
Command Parameter |
Return Event |
---|---|---|---|
ACI_CMD_LE_STOP_SCAN |
0x0104 |
None |
None |
Description
Stop LE scan.
Command Parameters
None.
ACI_CMD_LE_START_PAIR
Command |
Opcode |
Command Parameter |
Return Event |
---|---|---|---|
ACI_CMD_LE_START_PAIR |
0x0109 |
link_id |
None |
Description
This command is used to pair a connected device.
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for LE link. |
ACI_CMD_LE_CREATE_CONN
Command |
Opcode |
Command Parameter |
Return Event |
---|---|---|---|
ACI_CMD_LE_CREATE_CONN |
0x010E |
init_phys, |
None |
Description
This command is used to initiate connection to a specific device.
Command Parameters
init_phys:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Bit0: 1M PHY. |
remote_bd_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
GAP_REMOTE_ADDR_LE_PUBLIC |
0x01 |
GAP_REMOTE_ADDR_LE_RANDOM |
0x02 |
GAP_REMOTE_ADDR_LE_PUBLIC_IDENTITY |
0x03 |
GAP_REMOTE_ADDR_LE_RANDOM_IDENTITY |
0x10 |
GAP_REMOTE_ADDR_CLASSIC |
0xff |
GAP_REMOTE_ADDR_LE_ANONYMOUS |
remote_bd:
Size: 6 octet
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
The address of device intended to connect. |
local_bd_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
GAP_LOCAL_ADDR_LE_PUBLIC |
0x01 |
GAP_LOCAL_ADDR_LE_RANDOM |
0x02 |
GAP_LOCAL_ADDR_LE_RAP_OR_PUBLIC |
0x03 |
GAP_LOCAL_ADDR_LE_RAP_OR_RAND |
scan_timeout:
Size: 2 octet
Value |
Parameter Description |
---|---|
0xXXXX |
Scan timer in units of 10ms. |
ACI_CMD_ANCS_GET_NOTIFICATION_ATTR
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_ANCS_GET_NOTIFICATION_ATTR |
0x0111 |
link_id, notification_uid, |
Description
This command is used to get the notification attribute.
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for LE link. |
notification_uid:
Size: 4 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXX |
notification_uid |
attribute_ids_len:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
attribute_ids_len |
attribute_ids:
Size: attribute_ids_len octets
Value |
Parameter Description |
---|---|
0xXX, … |
attribute_ids |
ACI_CMD_ANCS_GET_APP_ATTR
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_ANCS_GET_APP_ATTR |
0x0112 |
link_id, |
Description
This command is used to get the APP attribute.
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for LE link. |
app_identifier_len:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
app_identifier_len |
app_identifier:
Size: N octets
Parameter Description |
---|
N octets of app_identifier. |
attribute_ids_len:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
attribute_ids_len |
attribute_ids:
Size: N octets
Parameter Description |
---|
N octets of attribute_ids. |
ACI_CMD_ANCS_PERFORM_NOTIFICATION_ACTION
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_ANCS_PERFORM_NOTIFICATION_ACTION |
0x011 |
link_id, |
Description
This command is used to perform the notification action.
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for LE link. |
notification_uid:
Size: 4 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXX |
notification_uid |
action_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
action_id |
ACI_CMD_AMS_WRITE_REMOTE_CMD
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_AMS_WRITE_REMOTE_CMD |
0x0115 |
link_id, cmd_id |
None |
Description
This command is used to send remote CMD to iOS media APP.
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for LE link. |
cmd_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
RemoteCommandIDPlay |
0x01 |
RemoteCommandIDPause |
0x02 |
RemoteCommandIDTogglePlayPause |
0x03 |
RemoteCommandIDNextTrack |
0x04 |
RemoteCommandIDPreviousTrack |
0x05 |
RemoteCommandIDVolumeUp |
0x06 |
RemoteCommandIDVolumeDown |
0x07 |
RemoteCommandIDAdvanceRepeatMode |
0x08 |
RemoteCommandIDAdvanceShuffleMode |
0x09 |
RemoteCommandIDSkipForward |
0x0A |
RemoteCommandIDSkipBackward |
0x0B |
RemoteCommandIDLikeTrack |
0x0C |
RemoteCommandIDDislikeTrack |
0x0D |
RemoteCommandIDBookmarkTrack |
Others |
Reserved. |
ACI_CMD_AMS_WRITE_ENTITY_UPD_CMD
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_AMS_WRITE_ENTITY_UPD_CMD |
0x0116 |
link_id, value_len, value |
None |
Description
This command is used to send entity update CMD to iOS media APP.
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for LE link. |
value_len:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Value_len |
value:
Size: value_len octets
Value |
Parameter Description |
---|---|
0xXX, … |
Value. |
ACI_CMD_LE_MODIFY_WHITELIST
Command |
Opcode |
Command Parameter |
Return Event |
---|---|---|---|
ACI_CMD_LE_MODIFY_WHITELIST |
0x0161 |
operation, address, address_type |
None |
Description
This command is used to modify the white list.
Command Parameters
operation:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Clear white list. |
0x01 |
Add a device to the white list. |
0x02 |
Remove a device from the white list. |
address (Needless for clear white list):
Size: 6 octet
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
Address. |
remote_bd_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
GAP_REMOTE_ADDR_LE_PUBLIC |
0x01 |
GAP_REMOTE_ADDR_LE_RANDOM |
0x02 |
GAP_REMOTE_ADDR_LE_PUBLIC_IDENTITY |
0x03 |
GAP_REMOTE_ADDR_LE_RANDOM_IDENTITY |
0x10 |
GAP_REMOTE_ADDR_CLASSIC |
0xff |
GAP_REMOTE_ADDR_LE_ANONYMOUS |
ACI_CMD_LE_MODIFY_WHITELIST_BY_IDX
Command |
Opcode |
Command Parameter |
Return Event |
---|---|---|---|
ACI_CMD_LE_MODIFY_WHITELIST_BY_IDX |
0x0162 |
operation, bond_idx |
None |
Description
This command is used to modify white list by bond index.
Command Parameters
operation:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Clear white list. |
0x01 |
Add a device to white list. |
0x02 |
Remove a device from white list. |
bond_idx (Needless for clear white list):
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Operate target device in the bond list by priority. |
ACI_CMD_LE_MODIFY_RESOLVELIST_BY_IDX
Command |
Opcode |
Command Parameter |
Return Event |
---|---|---|---|
ACI_CMD_LE_MODIFY_RESOLVELIST_BY_IDX |
0x0163 |
operation, bond_idx |
None |
Description
This command is used to modify the resolving list by bond index.
Command Parameters
operation:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Clear resolving list. |
0x01 |
Add a device to the resolving list. |
0x02 |
Remove a device from the resolving list. |
bond_idx (Needless for clear resolving list):
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Operate target device in the bond list by priority. |
ACI_CMD_LE_SET_RESOLUTION
Command |
Opcode |
Command Parameter |
Return Event |
---|---|---|---|
ACI_CMD_LE_SET_RESOLUTION |
0x0164 |
target_state |
None |
Description
This command is used to enable/disable resolution.
Command Parameters
target_state:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Disable resolution. |
0x01 |
Enable resolution. |
ACI_CMD_SET_VOLUME
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SET_VOLUME |
0x020A |
volume level |
Description
Set playback or voice volume depending on the scenario.
Command Parameters
volume level:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
0~maximum (volume level). |
ACI_CMD_GET_FW_VERSION
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_GET_FW_VERSION |
0x0308 |
type |
Description
Get the firmware version.
Command Parameters
type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Get FW version. |
ACI_CMD_BT_BOND_INFO_CLEAR
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_BT_BOND_INFO_CLEAR |
0x0309 |
link_type, bd_addr |
Description
Clear the device’s link key of the target remote connection according to bd_addr.
Command Parameters
link_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Clear BR/EDR bond info. |
Others |
Reserved. |
bd_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
MAC address of target device. |
ACI_CMD_GET_PACKAGE_ID
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_GET_PACKAGE_ID |
0x030F |
None |
Description
Get chip ID and package ID.
Command Parameters
None.
ACI_CMD_SWITCH_TO_HCI_DOWNLOAD_MODE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SWITCH_TO_HCI_DOWNLOAD_MODE |
0x0310 |
None |
None |
Description
This command is used to enter HCI download mode and then reset.
Command Parameters
None.
ACI_CMD_INQUIRY
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_INQUIRY |
0x0321 |
action, timeout |
Description
This request searches the neighbor’s Bluetooth devices.
Command Parameters
action:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Start inquiry. |
0x01 |
Stop inquiry. |
timeout:
Size: 1 octet
Value | Parameter Description |
---|---|
0x01 ~ 0x30 |
The maximum amount of time before the inquiry is halted. Time = N * 1.28 sec. Range: 1.28 - 61.44 sec. |
ACI_CMD_SEND_DTMF
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SEND_DTMF(abandon) |
0x0400 |
number |
None |
Description
Send DTMF.
Command Parameters
number:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
The DTMF character must be one from the set 0-9, #, *, A-D. For example, if the character is 3, the parameter number should be set to 0x33. |
ACI_CMD_SEND_VGM
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SEND_VGM |
0x0403 |
level |
None |
Description
Send VGM.
Command Parameters
level:
Size: 1 octet
Value | Parameter Description |
---|---|
0xXX |
VGM value. Range: 0 ~ 15. |
ACI_CMD_SEND_VGS
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SEND_VGS |
0x0404 |
level |
None |
Description
Send VGS.
Command Parameters
level:
Size: 1 octet
Value | Parameter Description |
---|---|
0xXX | VGS value, range: 0 ~ 15. |
ACI_CMD_HFP_AG_CONNECT_SCO
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_HFP_AG_CONNECT_SCO |
0x0480 |
link_id |
None |
Description
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Link ID. |
ACI_CMD_HFP_AG_DISCONNECT_SCO
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_HFP_AG_DISCONNECT_SCO |
0x0481 |
link_id |
None |
Description
HFP AG disconnects SCO.
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Link ID. |
ACI_CMD_HFP_AG_CALL_INCOMING
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_HFP_AG_CALL_INCOMING |
0x0482 |
link_id |
None |
Description
Notify the incoming call.
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Link ID. |
ACI_CMD_HFP_AG_CALL_ANSWER
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_HFP_AG_CALL_ANSWER |
0x0483 |
link_id |
None |
Description
Answer the incoming call.
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Link ID. |
ACI_CMD_HFP_AG_CALL_TERMINATE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_HFP_AG_CALL_TERMINATE |
0x0484 |
link_id |
None |
Description
Terminate the call.
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Link ID. |
ACI_CMD_HFP_AG_MIC_GAIN_LEVEL_SET
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_HFP_AG_MIC_GAIN_LEVEL_SET |
0x0488 |
link_id, action |
None |
Description
Mute or unmute the MIC.
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Link ID. |
action:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
MIC_MUTE |
0x0A |
MIC_UNMUTE |
ACI_CMD_HFP_AG_SPEAKER_GAIN_LEVEL_SET
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_HFP_AG_SPEAKER_GAIN_LEVEL_SET |
0x0489 |
link_id, action |
None |
Description
Turn the SPK volume up or down.
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Link ID. |
action:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
SPK_VOL_UP |
0x00 |
SPK_VOL_DOWN |
ACI_CMD_PBAP_DOWNLOAD
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_PBAP_DOWNLOAD |
0x0420 |
method |
None |
Description
PBAP download.
Command Parameters
method:
Size: 1 octet
Value | Parameter Description |
---|---|
0x03 ~ 0x05 |
PBAP download method. Range: 0x03: PBAP_DOWNLOAD_METHOD_ALL, download the phonebook of ME/SM and CCH. 0x04: PBAP_DOWNLOAD_METHOD_ALL_PB, download the phonebook of ME/SM. 0x05: PBAP_DOWNLOAD_METHOD_CCH, the Combined Calls History contains incoming/outgoing/missed call history. |
ACI_CMD_PBAP_CONNECT
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_PBAP_CONNECT |
0x0423 |
None |
None |
Description
PBAP connect.
Command Parameters
None.
ACI_CMD_PBAP_DISCONNECT
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_PBAP_DISCONNECT |
0x0426 |
None |
None |
Description
PBAP disconnect.
Command Parameters
None.
ACI_CMD_TRI_DONGLE_CMD
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_TRI_DONGLE_CMD |
0x0A0E |
sub_command_id, sub_command_parameters |
Description
Command Tri dongle legacy & LE operation.
Command Parameters
sub_command_id:
Size: 1 octet
Value |
Parameter Description |
Return Event |
---|---|---|
0x00 |
Command Tri dongle start LE scan. |
|
0x01 |
Command Tri dongle stop LE scan. |
None |
0x02 |
Command Tri dongle start BR inquiry scan. |
|
0x03 |
Command Tri dongle stop BR inquiry scan. |
None |
0x04 |
Command Tri dongle connect to target LE device. |
None |
0x05 |
Command Tri dongle disconnect to target LE device. |
None |
0x06 |
Command Tri dongle connect to target BR device. |
None |
0x07 |
Command Tri dongle disconnect to target BR device. |
None |
0x08 |
Command Tri dongle report connected LE device info. |
|
0x09 |
Command Tri dongle report connected BR device info. |
|
0x0A |
Command Tri dongle clear all bond info. |
None |
0x0B |
Command Tri dongle clear to target LE device. |
None |
0x0C |
Command Tri dongle clear to target BR device. |
None |
0x0D |
Command Tri dongle get passkey support info. |
None |
0x0E |
Command Tri dongle BAS request to target LE device. |
None |
0x0F |
Command Tri dongle DIS one UUID request to targe LE device. |
None |
0x10 |
Command Tri dongle LE RSSI to target LE device. |
None |
0x11 |
Command Tri dongle BR RSSI to target LE device. |
None |
0x12 |
Command Tri dongle LE scan status. |
None |
0x13 |
Command Tri dongle BR inquiry scan status. |
None |
0x14 |
Command Tri dongle LE bondlist info. |
None |
0x15 |
Command Tri dongle DIS all UUID request to target LE device. |
None |
0x16 |
Command Tri dongle BR bondlist info. |
None |
Only the following sub command ID are required to fill sub command parameters:
0x02 (Command Tri dongle start BR inquiry scan).
0x04 (Command Tri dongle connect to target LE device).
0x05 (Command Tri dongle disconnect to target LE device).
0x06 (Command Tri dongle connect to target BR device).
0x07 (Command Tri dongle disconnect to target BR device).
0x0B (Command Tri dongle clear to target LE device).
0x0C (Command Tri dongle clear to target BR device).
0x0E (Command Tri dongle BAS request to target LE device).
0x0F (Command Tri dongle DIS one UUID request to target LE device).
0x10 (Command Tri dongle LE RSSI to target LE device).
0x11 (Command Tri dongle BR RSSI to target LE device).
0x15 (Command Tri dongle DIS all UUID request to target LE device).
sub_command_parameters:
Size: 49 octets
Sub Command ID |
Required Sub Command Parameter |
---|---|
0x02 |
continuous (1 octet, 0 = Disable, 1 = Enable) |
0x04 |
bd_addr (6 octets, Little-Endian), |
0x05 |
bd_addr (6 octets, Little-Endian) |
0x06 |
bd_addr (6 octets, Little-Endian) |
0x07 |
bd_addr (6 octets, Little-Endian) |
0x0B |
bd_addr (6 octets, Little-Endian) |
0x0C |
bd_addr (6 octets, Little-Endian) |
0x0E |
bd_addr (6 octets, Little-Endian) |
0x0F |
UUID (2 octets, Little-Endian), |
0x10 |
bd_addr (6 octets, Little-Endian) |
0x11 |
bd_addr (6 octets, Little-Endian) |
0x15 |
bd_addr (6 octets, Little-Endian) |
ACI_CMD_FINDMY_FEATURE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_FINDMY_FEATURE |
0x2300 |
action |
None |
Description
Find My action.
Command Parameters
action:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
ENTER_PAIRING |
0x01 |
MMI_PUT_SERIAL_NUMBER |
Command Detail:
ENTER_PAIRING
: Enter Find My pairing mode.MMI_PUT_SERIAL_NUMBER
: Put the state of the serial number.
ACI_CMD_GFPS_FINDER_FEATURE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_GFPS_FINDER_FEATURE |
0x2400 |
action |
None |
Description
GFPS finder action.
Command Parameters
action:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
GFPS_FINDER_INVALID_ACTION |
0x01 |
GFPS_FINDER_STOP_RING |
Command Detail
GFPS_FINDER_STOP_RING
: Stop ring.
ACI_CMD_SPI_INIT
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SPI_INIT |
0x3200 |
role |
None |
Description
SPI role init.
Command Parameters
None.
role:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
SPI_ROLE_MASTER |
0x01 |
SPI_ROLE_SLAVE |
ACI_CMD_SPI_SLAVE_TRIGGER
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SPI_SLAVE_TRIGGER |
0x3201 |
None |
None |
Description
Trigger SPI transmission by the slave. This command is for the test.
Command Parameters
None.
ACI_CMD_A2DP_XMIT_SET_ROUTE_OUT
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
CMD_A2DP_XMIT_SET_ROUTE_OUT |
0x3223 |
route_path |
None |
Description
Set transparent transmission music (from SPI) output route.
Command Parameters
type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
XMIT_PLAY_ROUTE_A2DP_SRC |
0x01 |
XMIT_PLAY_ROUTE_BIS |
ACI_CMD_A2DP_XMIT_ROUTE_OUT_CTRL
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_A2DP_XMIT_ROUTE_OUT_CTRL |
0x3220 |
type |
None |
Description
Enable playing transparent transmission music by A2DP source or BIS music (from SPI).
Command Parameters
type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
XMIT_PLAY_STATE_START |
0x01 |
XMIT_PLAY_STATE_IDLE |
ACI_CMD_LEA_BSRC_INIT
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_BSRC_INIT |
0x3020 |
codec_type, bis_num, |
None |
Description
Broadcast init.
Command Parameters
codec_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x0D |
CODEC_CFG_ITEM_48_4 |
0x03 |
CODEC_CFG_ITEM_16_2 |
bis_num:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x01 |
bis_num = 1. |
0x02 |
bis_num = 2. |
encryption:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
False. |
0x01 |
True. |
ull_mode:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
False. |
0x01 |
True. |
pd:
Size: 2 octet
Value |
Parameter Description |
---|---|
0xXXXX |
Presentation delay (Effective when ull_mode is enabled). |
ACI_CMD_LEA_BSRC_START
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_BSRC_START |
0x3021 |
None |
None |
Description
Start broadcasting.
Command Parameters
None.
ACI_CMD_LEA_BSRC_STOP
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_BSRC_STOP |
0x3022 |
stop_option |
None |
Description
Stop broadcasting.
Command Parameters
release:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Do not delete BIS configuration. |
0x01 |
Delete BIS configuration. |
ACI_CMD_LEA_SCAN
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_SCAN |
0x3023 |
action |
None |
Description
Start or stop scanning devices supporting LE Audio.
Command Parameters
action:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Start scanning. |
0x01 |
Stop scanning. |
ACI_CMD_LEA_CIS_START_MEDIA
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_CIS_START_MEDIA |
0x3024 |
group_idx |
None |
Description
Start CIS music.
Command Parameters
group_idx:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
start_group_idx_0: start CIS media on group 0. |
0x01 |
start_group_idx_1: start CIS media on group 1. |
ACI_CMD_LEA_CIS_STOP_STREAM
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_CIS_STOP_STREAM |
0x3025 |
group_idx and action |
None |
Description
Stop CIS streaming.
Command Parameters
group_idx and action:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
stop_group_idx_0: stop CIS media on group 0. |
0x01 |
release_group_idx_0: Stop CIS media on group 0 and release CIS. |
0x02 |
stop_group_idx_1: Stop CIS media on group 1. |
0x03 |
release_group_idx_1: Stop CIS media on group 1 and release CIS. |
ACI_CMD_LEA_CIS_ULL_MODE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_CIS_ULL_MODE |
0x3026 |
action |
None |
Description
Enable/Disable CIS media Ultra Low Latency mode. Please use this command before starting CIS media.
Command Parameters
action:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Disable CIS ULL. |
0x01 |
Enable CIS ULL. |
ACI_CMD_LEA_CSIS_MEMBER_SCAN
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_CSIS_MEMBER_SCAN |
0x3027 |
group_idx |
None |
Description
Scan devices belonging to the same group.
Command Parameters
group_idx:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
group_idx_0 |
0x01 |
group_idx_1 |
ACI_CMD_LEA_CSIS_GROUP_SCAN_STOP
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_CSIS_GROUP_SCAN_STOP |
0x3028 |
None |
None |
Description
Stop scanning devices that belong to the same group.
Command Parameters
None.
ACI_CMD_LEA_BST_START
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_BST_START |
0x3029 |
action |
None |
Description
Broadcast audio reception start procedure.
Command Parameters
action:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
group_0_sync_0: Start broadcast on group 0 and sync 0. |
0x01 |
group_0_sync_1: Start broadcast on group 0 and sync 1. |
0x02 |
group_1_sync_0: Start broadcast on group 1 and sync 0. |
0x03 |
group_1_sync_1: Start broadcast on group 1 and sync 1. |
ACI_CMD_LEA_BST_STOP
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_BST_STOP |
0x302A |
action |
None |
Description
Broadcast audio reception stop procedure.
Command Parameters
action:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
group_0_sync_0: Stop broadcast on group 0 and sync 0. |
0x01 |
group_0_sync_1: Stop broadcast on group 0 and sync 1. |
0x02 |
group_1_sync_0: Stop broadcast on group 1 and sync 0. |
0x03 |
group_1_sync_1: Stop broadcast on group 1 and sync 1. |
ACI_CMD_LEA_BST_REMOVE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_BST_REMOVE |
0x302B |
action |
None |
Description
Broadcast audio reception removal procedure.
Command Parameters
action:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
group_0_sync_0: Remove broadcast on group 0 and sync 0. |
0x01 |
group_0_sync_1: Remove broadcast on group 0 and sync 1. |
0x02 |
group_1_sync_0: Remove broadcast on group 1 and sync 0. |
0x03 |
group_1_sync_1: Remove broadcast on group 1 and sync 1. |
ACI_CMD_LEA_GVCS_VOLUME
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_GVCS_VOLUME |
0x302C |
group_idx, volume |
None |
Description
Set VCS volume.
Command Parameters
group_idx:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Group handle index. |
volume:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Set VCS volume to 0xXX. |
ACI_CMD_LEA_GVCS_MUTE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_GVCS_MUTE |
0x302D |
group_idx, mute_state |
None |
Description
Set VCP mute state.
Command Parameters
group_idx:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Group handle index. |
mute_state:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Set unmute. |
0x01 |
Set mute. |
ACI_CMD_LEA_GMIC_MUTE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_GMIC_MUTE |
0x302E |
group_idx, mute_state |
None |
Description
Set GMIC MIC mute state.
Command Parameters
group_idx:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Group handle index. |
mute_state:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Set MIC unmute. |
0x01 |
Set MIC mute. |
ACI_CMD_LEA_BAAS_SCAN
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_BAAS_SCAN |
0x302F |
None |
None |
Description
Start extended scan for BAAS.
Command Parameters
None.
ACI_CMD_LEA_PA_SYNC_DEV
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_PA_SYNC_DEV |
0x3030 |
dev_idx |
None |
Description
PA sync by device index.
Command Parameters
dev_idx:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Dev0: PA sync with device 0. |
0x01 |
Dev1: PA sync with device 1. |
0x02 |
Dev2: PA sync with device 2. |
ACI_CMD_LEA_CIS_START_CONVERSATION
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_CIS_START_CONVERSATION |
0x3031 |
group_idx |
None |
Description
Start CIS conversation.
Command Parameters
group_idx:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Start CIS media on group 0. |
0x01 |
Start CIS media on group 1. |
ACI_CMD_LEA_CCP_ACTION
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_CCP_ACTION |
0x3032 |
call_action, call_index |
None |
Description
CCP control action.
Command Parameters
call_action:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x05 |
Incoming call action. |
0x12 |
Local terminate. |
0x14 |
Local accept. |
call_index:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Call index. |
ACI_CMD_LEA_MCP_STATE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_MCP_STATE |
0x3033 |
media_state |
None |
Description
Update MCP state.
Command Parameters
media_state:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x01 |
The media player starts playing the current track. |
0x02 |
The media player paused the current track. |
ACI_CMD_LEA_MCP_NOTIFY
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_MCP_NOTIFY |
0x3034 |
mcs_uuid, param |
None |
Description
Set MCP Notification.
Command Parameters
mcs_uuid:
Size: 2 octets
Value |
Parameter Description |
---|---|
0x2B96 |
MCS_UUID_CHAR_TRACK_CHANGED |
0x2B98 |
MCS_UUID_CHAR_TRACK_DURATION |
0x2B99 |
MCS_UUID_CHAR_TRACK_POSITION |
param:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x10 |
Track position. |
0x60 |
Track duration. |
ACI_CMD_LEA_ADV_START
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_ADV_START |
0x3250 |
None |
None |
Description
Start LE Audio advertising, allowing the device to be scanned and connected by remote device.
Command Parameters
None.
ACI_CMD_LEA_ADV_STOP
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_ADV_STOP |
0x3251 |
None |
None |
Description
Stop LE Audio advertising, preventing it from being scanned by remote device.
Command Parameters
None.
ACI_CMD_LEA_CCP_CALL_CP
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_CCP_CALL_CP |
0x3252 |
conn_id, call_cp |
Description
Control the phone call of the connected remote device.
Command Parameters
conn_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Connection identity for connected remote device. |
call_cp:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Answer incoming call. |
0x01 |
Terminate call. |
0x02 |
Move call to local hold. |
0x03 |
Move local hold call to active call. |
0x04 |
Originate call. |
0x05 |
Join calls. |
ACI_CMD_LEA_MCP_MEDIA_CP
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_MCP_MEDIA_CP |
0x3253 |
conn_id, media_cp |
Description
Control the active music player of connected remote device.
Command Parameters
conn_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Connection identity for connected remote device. |
media_cp:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x01 |
Play current track. |
0x02 |
Pause current track. |
0x03 |
Fast rewind. |
0x04 |
Fast forward. |
0x05 |
Stop current track. |
0x30 |
Move to previous track. |
0x31 |
Move to next track. |
ACI_CMD_LEA_SYNC_INIT
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_SYNC_INIT |
0x3254 |
bis_mode, bis_policy, addr |
None |
Description
Initialize the BIS parameters, including BIS role and BIS policy. The address field is only used when BIS policy is set to LEA_BIS_POLICY_SPECIFIC
.
Command Parameters
bis_mode:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x01 |
LEA_BROADCAST_DELEGATOR |
0x02 |
LEA_BROADCAST_SINK |
bis_policy:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
LEA_BIS_POLICY_RANDOM |
0x01 |
LEA_BIS_POLICY_SPECIFIC |
addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXX,0xXX,0xXX,0xXX,0xXX,0xXX |
The source address that wants to sync. |
ACI_CMD_LEA_SYNC
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_SYNC |
0x3255 |
sync |
None |
Description
Start/stop syncing the broadcast audio stream.
Command Parameters
opcode:
Size: 2 octets
Value |
Parameter Description |
---|---|
0x00 |
Sync = true. |
0x01 |
Sync = false. |
ACI_CMD_LEA_VCS_SET
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_LEA_VCS_SET |
0x3256 |
conn_id, vol_type |
None |
Description
Change the volume of the local device’s audio and notify VCS audio volume state to the remote device.
Command Parameters
conn_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Connection identity for connected remote device. |
vol_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Volume up. |
0x01 |
Volume down. |
0x02 |
SPK mute. |
0x03 |
SPK unmute. |
ACI_CMD_UART_DFU
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_UART_DFU |
0x3270 |
opcode |
None |
Description
Start/abort UART DFU, transmit DFU Data, enable test mode, get device’s version, and reboot the device.
Command Parameters
opcode:
Size: 2 octets
Value |
Parameter Description |
---|---|
0x0000 |
UART_DFU_START_REQ, request to start DFU. |
0x0001 |
UART_DFU_DATA_IND, send data packet. |
0x0002 |
UART_DFU_ABORT, abort DFU. |
0x0003 |
UART_DFU_REBOOT, reboot device. |
0x0004 |
UART_DFU_TEST_EN, enable test mode. |
0x0005 |
UART_DFU_GET_VER, get version of device. |
ACI_CMD_SRC_PLAY_SET_SRC_ROUTE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SRC_PLAY_SET_SRC_ROUTE |
0x3300 |
src_route |
None |
Description
Set source route.
Command Parameters
src_route:
Size: 2 octets
Value |
Parameter Description |
---|---|
0x01, 0x00 |
mic |
0x02, 0x00 |
line-in |
0x03, 0x01 |
usb_ds |
0x03, 0x02 |
usb_us |
0x03, 0x03 |
usb_ds_us |
0x04, 0x00 |
sd_card |
0x05, 0x00 |
spdif |
0x06, 0x00 |
I2S |
ACI_CMD_SRC_PLAY_GET_SRC_ROUTE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SRC_PLAY_GET_SRC_ROUTE |
0x3301 |
None |
None |
Description
Get source route.
Command Parameters
None.
ACI_CMD_SRC_PLAY_SET_PLAY_ROUTE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SRC_PLAY_SET_PLAY_ROUTE |
0x3302 |
play_route |
None |
Description
Set play route.
Command Parameters
play_route:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x01 |
a2dp |
0x02 |
hfp_ag |
0x03 |
bis |
0x04 |
cis |
0x05 |
local |
0x06 |
multi_a2dp |
ACI_CMD_SRC_PLAY_GET_PLAY_ROUTE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SRC_PLAY_GET_PLAY_ROUTE |
0x3303 |
None |
None |
Description
Get play route.
Command Parameters
None.
ACI_CMD_SRC_PLAY_ROUTE_IN_START
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SRC_PLAY_ROUTE_IN_START |
0x3304 |
None |
None |
Description
Start route in the record.
Command Parameters
None.
ACI_CMD_SRC_PLAY_ROUTE_IN_STOP
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SRC_PLAY_ROUTE_IN_STOP |
0x3305 |
None |
None |
Description
Stop route in the record.
Command Parameters
None.
ACI_CMD_SRC_PLAY_ROUTE_OUT_START
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SRC_PLAY_ROUTE_OUT_START |
0x3306 |
None |
None |
Description
Start to route out play.
Command Parameters
None.
ACI_CMD_SRC_PLAY_ROUTE_OUT_STOP
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SRC_PLAY_ROUTE_OUT_STOP |
0x3307 |
None |
None |
Description
Stop route out play.
Command Parameters
None.
ACI_CMD_MAP_CONNECT
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_MAP_CONNECT |
0x3801 |
None |
None |
Description
Set up MAP connection.
Command Parameters
None.
ACI_CMD_MAP_GET_FOLDER_LISTING
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_MAP_GET_FOLDER_LISTING |
0x3802 |
max_list_count, start_offset |
None |
Description
Get folder list through MAP.
Command Parameters
max_list_count:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x0A |
Max list count. |
start_offset:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Start offset. |
ACI_CMD_MAP_DISCONNECT
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_MAP_DISCONNECT |
0x3803 |
None |
None |
Description
Disconnect MAP connection.
Command Parameters
None.
ACI_CMD_MAP_GET_MESSAGE_LISTING
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_MAP_GET_MESSAGE_LISTING |
0x3805 |
max_list_count, start_offset |
None |
Description
Get message list through MAP.
Command Parameters
max_list_count:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x0A |
Max list count. |
start_offset:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Start offset. |
ACI_CMD_MAP_REG_MSG_NOTIFICATION
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_MAP_REG_MSG_NOTIFICATION |
0x3809 |
enable |
None |
Description
Register message notification through MAP.
Command Parameters
enable:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x01 |
Enable. |
ACI_CMD_MAP_GET_MESSAGE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_MAP_GET_MESSAGE |
0x380A |
handle_len, msg_handle[] |
None |
Description
Get a message through MAP.
Command Parameters
handle_len:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x20 |
Length of message. |
msg_handle:
Size
Value | Parameter Description |
---|---|
msg_handle[] | Array of message handles. |
ACI_CMD_MAP_PUSH_MESSAGE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_MAP_PUSH_MESSAGE |
0x3810 |
msg_len, msg[] |
None |
Description
Push message through MAP.
Command Parameters
msg_len
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Length of a specific message to be pushed. |
msg
Size
Value |
Parameter Description |
---|---|
msg[] |
Array of messages. |
ACI_CMD_SET_FRAME_INFO
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SET_FRAME_INFO (abandon) |
0x5008 |
format, |
Description
Set MP3 information and trigger media playing.
Command Parameters
format:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x30 |
MP3. |
channel:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Stereo. |
0x01 |
Joint stereo. |
0x02 |
Dual. |
0x03 |
Mono. |
sample_counts:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
The frame size is the number of samples per frame, representing the number of samples in a frame of data. |
sampling_freq:
Size: 4 octets
Value | Parameter Description |
---|---|
48000, 44100, 32000, 24000, 22050, 16000, 11025, 12000, 8000 |
The sample rate for encoding or decoding. The supported values are 32000, 44100, and 48000 in HZ for MPEG-1 Layer 3. Additional 16000, 22050, and 24000 in HZ for MPEG-2 Layer 3, and additional 8000, 11025, and 12000 in HZ for MPEG-2.5 Layer 3. |
bitrate:
Size: 4 octets
Value |
Parameter Description |
---|---|
8000 ~ 320000 bit/s |
Bitrate for decoding. |
version:
Size: 1 octet
Value |
Parameter Description |
---|---|
0 |
MPEG Version 2.5 (unofficial). |
1 |
Reserved. |
2 |
MPEG Version 2 (ISO/IEC 13818-3). |
3 |
MPEG Version 1 (ISO/IEC 11172-3). |
layer:
Size: 1 octet
Value |
Parameter Description |
---|---|
0 |
Reserved. |
1 |
Layer 3. |
2 |
Layer 2. |
3 |
Layer 1. |
ACI_CMD_SET_FRAME_CONTENT
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_SET_FRAME_CONTENT(abandon) |
0x5009 |
frame_content |
Description
Set MP3 frames to play.
Command Parameters
frame_content:
Size: N octets
Parameter Description |
---|
N octets of each MP3 frame in the file. |
ACI_CMD_XM_ENTER_HCI_MODE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_ENTER_HCI_MODE |
0x8000 |
None |
None |
Description
Set the device into the HCI mode.
Command Parameters
None.
ACI_CMD_XM_DEVICE_REBOOT
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_DEVICE_REBOOT |
0x8001 |
None |
Description
SW reboots after 1 sec.
Command Parameters
None.
ACI_CMD_XM_MMI
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_MMI |
0x8004 |
action |
None |
Description
Makes MMI actions.
Command Parameters
action:
Size: 1 octet
Value |
Parameter Description |
Return Event |
---|---|---|
0x01 |
XM_MMI_MODE_LOCAL_PLAY |
None |
0x02 |
XM_MMI_MODE_A2DP_SOURCE |
None |
0x03 |
XM_MMI_BT_BOND_CLEAR_ALL |
None |
Command Detail:
XM_MMI_MODE_LOCAL_PLAY
: Switch music mode to local playback.XM_MMI_MODE_A2DP_SOURCE
: Switch music mode to A2DP Source mode.XM_MMI_BT_BOND_CLEAR_ALL
: Delete all bond information in bond storage.
ACI_CMD_XM_BT_SET_ADDR
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_BT_SET_ADDR |
0x8005 |
bt_addr |
None |
Description
Modify the Bluetooth address of the device (only can be used in the power on status, and will take effect after a factory reset).
Command Parameters
bt_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
MAC address. |
ACI_CMD_XM_SPP_DATA_TRANSFER
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_SPP_DATA_TRANSFER |
0x8006 |
link_id, |
None |
Description
Send vendor SPP data.
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for BR/EDR link. |
payload_length:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Payload length in this packet. |
payload:
Size: N octets
Value |
Parameter Description |
---|---|
0xXXXX (N bytes) |
N octets of the payload in this packet. |
ACI_CMD_XM_GET_FACTORY_RESET
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_GET_FACTORY_RESET |
0x80C3 |
None |
Description
Get factory reset status.
Command Parameters
None.
ACI_CMD_XM_USER_CFM_REQ
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_USER_CFM_REQ |
0x8013 |
cfm_val |
None |
Description
The user confirms for BR/EDR pairing.
Command Parameters
cfm_val:
Size: 1 octet
Value |
Parameter Description |
---|---|
1 or 0 |
True or false. |
ACI_CMD_XM_LE_START_ADVERTISING
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_LE_START_ADVERTISING |
0x8040 |
duration |
None |
Description
Start LE advertising.
Command Parameters
duration:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
LE advertising duration in seconds, little endian. |
ACI_CMD_XM_LE_STOP_ADVERTISING
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_LE_STOP_ADVERTISING |
0x8041 |
None |
None |
Description
Stop LE advertising.
Command Parameters
None.
ACI_CMD_XM_LE_DISC
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_LE_DISC |
0x8042 |
link_id |
None |
Description
Disconnect LE link(s).
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00-0xfe |
Disconnect APP layer ID for LE link. |
0xff |
Disconnect all LE links. |
ACI_CMD_XM_LE_CONN_PARAM_UPDATE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_LE_CONN_PARAM_UPDATE |
0x8043 |
link_id, conn_interval, |
None |
Description
Update LE connection params.
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for a LE link. |
conn_interval:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Set LE preferred connection interval to conn_interval * 1.25 ms, little endian. |
conn_latency:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Set LE preferred connection latency to conn_latency, little endian. |
conn_supervision_timeout:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Set LE preferred connection supervision timeout to conn_supervision_timeout * 10ms, little endian. |
ACI_CMD_XM_LE_ADV_DATA_UPDATE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_LE_ADV_DATA_UPDATE |
0x8044 |
adv_data_len, adv_data |
None |
Description
Update LE advertising data.
Command Parameters
adv_data_len:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXX |
ADV data length, must be less than 31 bytes. |
adv_data:
Size: adv_data_len octets
Parameter Description |
---|
New advertising data payload. |
ACI_CMD_XM_LE_SCAN_RSP_DATA_UPDATE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_LE_SCAN_RSP_DATA_UPDATE |
0x8045 |
scan_rsp_data_len, |
None |
Description
Update LE scan response data.
Command Parameters
scan_rsp_data_len:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXX |
Scan response data length, must be less than 31 bytes, little-endian. |
scan_rsp_data:
Size: scan_rsp_data_len octets
Parameter Description |
---|
New scan response data payload. |
ACI_CMD_XM_LE_ADV_INTVAL_UPDATE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_LE_ADV_INTVAL_UPDATE |
0x8046 |
adv_interval |
None |
Description
Update LE advertising interval.
Command Parameters
adv_interval:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Set LE advertising interval to adv_interval * 0.625ms (must be between 20ms and 10.25s), |
ACI_CMD_XM_LE_ATT_GET_MTU
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_LE_ATT_GET_MTU |
0x8047 |
link_id |
Description
Command Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for an LE link. |
ACI_CMD_XM_LE_GET_ADDR
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_LE_GET_ADDR |
0x8048 |
None |
Description
Get LE address.
Command Parameters
None.
ACI_CMD_XM_LE_BOND_DEL
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_LE_BOND_DEL |
0x804A |
addr_type, addr |
None |
Description
Delete LE bond with the address.
Command Parameters
addr_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
GAP_REMOTE_ADDR_LE_PUBLIC |
0x01 |
GAP_REMOTE_ADDR_LE_RANDOM |
0x02 |
GAP_REMOTE_ADDR_LE_PUBLIC_IDENTITY |
0x03 |
GAP_REMOTE_ADDR_LE_RANDOM_IDENTITY |
0x10 |
GAP_REMOTE_ADDR_CLASSIC |
0xff |
GAP_REMOTE_ADDR_LE_ANONYMOUS |
addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
Address for every remote device. |
ACI_CMD_XM_LE_ADV_CREATE
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
CMD_XM_LE_ADV_CREATE |
0x804B |
adv_handle, adv_prop, interval_min, interval_max, own_addr_type, own_addr, peer_addr_type, peer_addr, adv_data_len, adv_data, scan_rsp_len, scan_rsp |
Description
Create a customized advertisement.
Command Parameters
adv_handle:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Handle for an ADV set. For this command, it is useless. |
adv_prop:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x13 |
LE_EXT_ADV_LEGACY_ADV_CONN_SCAN_UNDIRECTED |
0x15 |
LE_EXT_ADV_LEGACY_ADV_CONN_LOW_DUTY_DIRECTED |
0x1D |
LE_EXT_ADV_LEGACY_ADV_CONN_HIGH_DUTY_DIRECTED |
0x12 |
LE_EXT_ADV_LEGACY_ADV_SCAN_UNDIRECTED |
0x10 |
LE_EXT_ADV_LEGACY_ADV_NON_SCAN_NON_CONN_UNDIRECTED |
interval_min, interval_max:
Size: 2 octet, in units of 0.625ms, range: 0x000020 to 0xFFFFFF
Value |
Parameter Description |
---|---|
0xXXXX |
ADV interval. |
own_addr_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
GAP_LOCAL_ADDR_LE_PUBLIC |
0x01 |
GAP_LOCAL_ADDR_LE_RANDOM |
0x02 |
GAP_LOCAL_ADDR_LE_RAP_OR_PUBLIC |
0x03 |
GAP_LOCAL_ADDR_LE_RAP_OR_RAND |
own_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXXXX |
own_addr |
peer_addr_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
GAP_REMOTE_ADDR_LE_PUBLIC |
0x01 |
GAP_REMOTE_ADDR_LE_RANDOM |
0x02 |
GAP_REMOTE_ADDR_LE_PUBLIC_IDENTITY |
0x03 |
GAP_REMOTE_ADDR_LE_RANDOM_IDENTITY |
0x10 |
GAP_REMOTE_ADDR_CLASSIC |
0xff |
GAP_REMOTE_ADDR_LE_ANONYMOUS |
peer_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXXXX |
peer_addr |
adv_data_len:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
adv_data_len |
adv_data:
Size: adv_data_len octet
Value |
Parameter Description |
---|---|
0xXX… |
adv_data |
adv_data_len:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
adv_data_len |
adv_data:
Size: adv_data_len octet
Value |
Parameter Description |
---|---|
0xXX… |
adv_data |
scan_rsp_len:
Size: 2 octet
Value |
Parameter Description |
---|---|
0xXXXX |
scan_rsp_len |
scan_rsp:
Size: scan_rsp_len octet
Value |
Parameter Description |
---|---|
0xXX… |
scan_rsp |
ACI_CMD_XM_LE_BOND_DEL_ALL
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_LE_BOND_DEL_ALL |
0x804C |
None |
None |
Description
Delete all bond info.
ACI_CMD_XM_MUSIC
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_MUSIC |
0x8080 |
type, seq, data |
Description
Control music session flow.
ACK
When the type is 0x05 (Music session send single frame), ACK status (ACI_EVENT_ACK
) would be 0x08, which means request MCU for another music frame.
Command Parameters
type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Music session open. |
0x01 |
Music session pause. |
0x02 |
Music session resume. |
0x03 |
Music session abort. |
0x04 |
Music session close. |
0x05 |
Music session send single frame. |
Others |
Reserved. |
seq:
Size: 1 octet
Value | Parameter Description |
---|---|
0x00 - 0xFF |
Seq is fixed at 0x00 when type is: Music session open. Music session pause. Music session resume. Music session abort. Music session close. Music session send single frame. |
data:
Size: N octets
Parameter Description |
---|
N octets of music data. |
ACI_CMD_XM_TTS
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_TTS |
0x8081 |
type, seq, len, data |
Description
Control TTS session flow.
ACK
When the type is 0x05 (TTS session send single frame) or 0x08 (TTS session send end frame), ACK status (ACI_EVENT_ACK
) would be 0x07, which means request MCU for another TTS frame.
Command Parameters
type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
TTS Session Open. |
0x01 |
TTS session pause. |
0x02 |
TTS session resume. |
0x03 |
TTS session abort. |
0x04 |
TTS session close. |
0x05 |
TTS session send single frame. |
0x06 |
TTS session send start frame. |
0x07 |
TTS session send continue frame. |
0x08 |
TTS session send end frame. |
Others |
Reserved. |
seq:
Size: 1 octet
Value | Parameter Description |
---|---|
0x00 - 0xFF |
Seq is fixed at 0x00 when type is: TTS session open. TTS session pause. TTS session resume. TTS session abort. TTS session close. TTS session send single frame. TTS session send start frame. Seq is increased by 1 when type is: TTS session send continue frame. TTS session send end frame. |
len:
Size: 2 octets
Value |
Parameter Description |
---|---|
0x0000-0xFFFF |
TTS encoded data length. |
data:
Size: len octets
Parameter Description |
---|
TTS encoded data. |
ACI_CMD_XM_START_RECORD
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_START_RECORD |
0x8082 |
audio_type, |
Description
Start recording.
Command Parameters
audio_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
PCM |
0x01 |
CVSD |
0x02 |
mSBC |
0x03 |
SBC |
0x04 |
AAC |
0x05 |
OPUS |
0x06 |
FLAC |
0x07 |
MP3 |
0x08 |
LC3 |
0x09 |
LDAC |
pcm_params:
Sample Rate(Hz) [4 Bytes] |
Frame Length(octets) |
Channel Number |
Bit Width |
---|---|---|---|
Supported values are 8000, 16000, 44100, 48000, |
xx. |
1 (Mono) or 2 (Stereo). |
16 or 24. |
opus_params:
Sample Rate(Hz) |
Channel Num |
CBR [1 byte] |
CVBR [1 byte] |
---|---|---|---|
Supported value is 16000. |
1 (Mono). |
0 for VBR and 1 for CBR. |
0 for VBR and 1 for CVBR. |
Mode |
Complexity |
frame_duration [1 byte] |
Bitrate [4 bytes] |
---|---|---|---|
The supported 3 for CELT-only. |
From 0 to 3. |
0 (2.5ms), 1 (5ms), 2 (10ms), 3 (20ms), 4 (40ms), 5 (60ms), 6 (80ms), 7 (100ms), 8 (120ms). |
From 6000 bit/s to 510000 bit/s. |
msbc_params or sbc_params:
Sample Rate(Hz) [4 Bytes] |
Channel Number |
block_length |
---|---|---|
Supported values are 8000, 16000, 44100, and 48000 in Hz. |
1 (Mono) or 2 (Stereo). |
4, 8, 12, 16. |
subband_num [1 byte] |
allocation_method [1 byte] |
Bitpool [1 byte] |
---|---|---|
4 or 8. |
0 for Loudness and 1 for SNR. |
from 2 to 250. |
lc3_params:
Sample Rate(Hz) [4 Bytes] |
Channel Allocation() [4 Byte] |
frame_length [2 byte] |
---|---|---|
Supported values are 16000, 48000. |
0 (Mono). |
40 for 16k and 120 for 48k. |
frame_duration [1 byte] |
Presentation Delay [4 byte] |
---|---|
0 for 7.5ms and 1 for 10ms. |
From 0 to 0xFFFFFFFF in microsecond units. |
ACI_CMD_XM_STOP_RECORD
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_STOP_RECORD |
0x8503 |
None |
None |
Description
Stop recording.
Command Parameters
None.
ACI_CMD_XM_START_RECORD_PLAY
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_START_RECORD_PLAY |
0x8504 |
audio_type |
None |
Description
Start record play.
Command Parameters
audio_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
PCM |
0x01 |
CVSD |
0x02 |
mSBC |
0x03 |
SBC |
0x04 |
AAC |
0x05 |
OPUS |
0x06 |
FLAC |
0x07 |
MP3 |
0x08 |
LC3 |
0x09 |
LDAC |
pcm_params:
Sample Rate(Hz) [4 Bytes] |
Frame Length |
Channel Number |
Bit Width |
---|---|---|---|
8000, 16000, 44100, 48000, |
xx. |
1 (Mono) or 2 (Stereo). |
16 or 24. |
opus_params:
Sample Rate(Hz) [4 Bytes] |
Channel Number |
CBR [1 byte] |
CVBR [1 byte] |
---|---|---|---|
8000, 16000, 44100, 48000, |
1 (Mono) or 2 (Stereo). |
0 for VBR and 1 for CBR. |
0 for VBR and 1 for CVBR. |
Mode [1 byte] |
Complexity [1 byte] |
---|---|
1 for SILK-only. |
From 0 to 10. |
frame_duration |
Bitrate [4 bytes] |
---|---|
0 (2.5ms), 1 (5ms), 2 (10ms), 3 (20ms), 4 (40ms), 5 (60ms), 6 (80ms), 7 (100ms), 8 (120ms). |
From 6000 bit/s to 510000 bit/s. |
ACI_CMD_XM_STOP_RECORD_PLAY
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_STOP_RECORD_PLAY |
0x8505 |
None |
None |
Description
Stop record play.
Command Parameters
None.
ACI_CMD_XM_RECORD_PLAY_DATA
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_RECORD_PLAY_DATA |
0x8086 |
record_data |
None |
Description
Send record data to play, need to start record play first.
Command Parameters
record_data:
Size: 1024 octets
Parameter Description |
---|
1024 octets of PCM data. |
ACI_CMD_XM_SET_VOLUME_LEVEL
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_SET_VOLUME_LEVEL |
0x8088 |
volume, type |
None |
Description
Set playback or voice volume depending on the scenario.
Command Parameters
volume:
level Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
0~15 (volume level). |
type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
HFP_VOL |
0x01 |
LOCAL_VOL |
0x02 |
A2DP_SRC_VOL |
0x03 |
RINGTONE_VOL |
0x04 |
VP_VOL |
0x05 |
TTS_VOL |
0x06 |
RECORD_VOL |
0x07 |
RECORD_MIC_VOL |
ACI_CMD_XM_AUDIO_TEST_GET_PA_ID
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_AUDIO_TEST_GET_PA_ID |
0x8089 |
None |
Description
Get PA ID.
Command Parameters
None.
ACI_CMD_XM_AUDIO_TEST_BYPASS
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_AUDIO_TEST_BYPASS |
0x808A |
audio_mode |
None |
Description
Set audio algorithm bypass mode or normal mode.
Command Parameters
audio_mode:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Normal mode. |
0x01 |
Bypass mode. |
ACI_CMD_XM_GATT_ACI
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_GATT_ACI |
0x8007 |
conn_handle, cid, pkt_type, |
None |
Description
Transfer GATT data from UART.
Command Parameters
conn_handle:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
The connection handle from HCI, 0x01 for BR/EDR and 0x13 for LE. |
cid:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
The channel ID for corresponding L2CAP channel, For BR/EDR, set it to 0x0000 for test. For LE, it is fixed to 0x0004. |
type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Single packet. |
0x01 |
Fragmented start packet. |
0x02 |
Fragmented continue packet. |
0x03 |
Fragmented end packet. |
handle_index:
Size: 1 octet
Value |
Attribute |
Parameter Description |
---|---|---|
0x01 |
fd04 |
Service 02fd. |
0x11 |
4 |
Service unlock. |
0x12 |
7 |
Service unlock. |
0x21 |
2 |
Service factory. |
0x61 |
17 |
Service HID. |
0x71 |
2 |
Service HRS. |
0x81 |
4 |
Service goodix. |
total_length:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Total payload length. |
payload_length:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Payload length in this packet. |
payload:
Size: N octets
Value |
Parameter Description |
---|---|
0xXXXX (N bytes) |
N octets of the payload in this packet. |
ACI_CMD_XM_SNIFF_MODE_CTRL
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_SNIFF_MODE_CTRL |
0x8009 |
sniff_mode_enabled, |
None |
Description
Enable or disable sniff mode for all BR/EDR links.
Command Parameters
sniff_mode_enabled:
Size: 1 octet
Value |
Parameter Description |
---|---|
0 or 1 |
Means false or true to enable sniff mode. |
sniff_mode_interval:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Sniff mode interval. |
ACI_CMD_XM_LE_USER_CFM_REQ
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_LE_USER_CFM_REQ |
0x8013 |
conn_id, cfm_result |
None |
Description
Confirm LE Connection.
Command Parameters
conn_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Default. |
cfm_result:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
False. |
0x01 |
True. |
ACI_CMD_XM_DISABLE_VERBOSE_LOG
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_XM_DISABLE_VERBOSE_LOG |
0x80C0 |
log_type, log_key, module, |
None |
Description
Close/open the log.
Command Parameters
log_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x01 |
Close/open all current logs. |
0x02 |
Close/open different module logs. |
log_key:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Close all current logs. |
0x01 |
Open all previously closed logs. |
module:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00~0x09 |
Platform modules. |
0x0c~0x23 |
Device modules. |
0x30~0x3f |
Stack modules. |
level:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
LEVEL_ERROR |
0x01 |
LEVEL_WARN |
0x02 |
LEVEL_INFO |
0x03 |
LEVEL_TRACE |
turn on:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Turn off. |
0x01 |
Turn on. |
ACI_CMD_CHARGING_CASE_LE_CONTROL
Command |
Opcode |
Command Parameters |
Return Event |
---|---|---|---|
ACI_CMD_CHARGING_CASE_LE_CONTROL |
0x8100 |
cmd_id, cmd_data |
None |
Description
Send CMD to the headset by LE.
Command Parameters
cmd_id:
Size: 2 octets
Value |
Parameter Description |
---|---|
0x0004 |
CMD_MMI |
0x001F |
CMD_SET_VP_VOLUME |
0x0205 |
CMD_AUDIO_EQ_INDEX_SET |
0x020A |
CMD_SET_VOLUME |
0x0704 |
CMD_SET_KEY_MMI_MAP |
mmi_data:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x02 |
End an outgoing call. |
0x03 |
Answer an incoming call. |
0x04 |
Reject an incoming call. |
0x05 |
End an active call. |
0x06 |
MIC mute toggle. |
0x07 |
MIC mute. |
0x08 |
MIC unmute. |
0x30 |
Volume up. |
0x31 |
Volume down. |
0x32 |
AV play/pause. |
0x34 |
AV forward. |
0x35 |
AV backward. |
0x36 |
AV fast forward. |
0x37 |
AV rewind. |
0x80 |
Switch to gaming mode. |
0xD3 |
Light sensor on/off. |
vp_volume_data:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 ~ 0x0F |
VP volume level. |
eq_set_data:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
EQ index. |
volume_data:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
0~maximum (volume level). |
mmi_map_data:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x30 |
Set MFB as volume up button. |
0x31 |
Set MFB as volume down button. |
ACI Events
Summary of ACI Events
Opcode |
Command |
Available |
---|---|---|
0x0000 |
Y |
|
0x0001 |
Y |
|
0x0002 |
Y |
|
0x0003 |
Y |
|
0x0004 |
Y |
|
0x0005 |
Y |
|
0x0007 |
Y |
|
0x0009 |
Y |
|
0x000A |
Y |
|
0x000B |
Y |
|
0x0013 |
Y |
|
0x0014 |
Y |
|
0x0018 |
Y |
|
0x0019 |
Y |
|
0x001A |
Y |
|
0x001C |
Y |
|
0x001D |
Y |
|
0x0020 |
Y |
|
0x0023 |
Y |
|
0x0025 |
Y |
|
0x0026 |
Y |
|
0x002B |
Y |
|
0x0100 |
Y |
|
0x0101 |
Y |
|
0x0102 |
Y |
|
0x0103 |
Y |
|
0x0110 |
Y |
|
0x0111 |
Y |
|
0x0112 |
Y |
|
0x0120 |
Y |
|
0x0121 |
Y |
|
0x0122 |
Y |
|
0x0123 |
Y |
|
0x0124 |
Y |
|
0x0140 |
Y |
|
0x0141 |
Y |
|
0x0142 |
Y |
|
0x0143 |
Y |
|
0x0144 |
Y |
|
0x0145 |
Y |
|
0x0146 |
Y |
|
0x0147 |
Y |
|
0x0300 |
Y |
|
0x0301 |
Y |
|
0x0306 |
Y |
|
0x0307 |
Y |
|
0x0308 |
Y |
|
0x0381 |
Y |
|
0x0389 |
Y |
|
0x038D |
Y |
|
0x0396 |
Y |
|
0x3160 |
Y |
|
0x3161 |
Y |
|
0x3162 |
Y |
|
0x3163 |
Y |
|
0x0A0E |
Y |
|
0x3252 |
Y |
|
0x3253 |
Y |
|
0x3256 |
Y |
|
0x0904 |
Y |
|
0x0909 |
Y |
|
0x0911 |
Y |
|
0x5001 |
Y |
|
0x8000 |
Y |
|
0x8001 |
Y |
|
0x8002 |
Y |
|
0x8003 |
Y |
|
0x8004 |
Y |
|
0x8005 |
Y |
|
0x8006 |
Y |
|
0x8040 |
Y |
|
0x8041 |
Y |
|
0x8042 |
Y |
|
0x8043 |
Y |
|
0x8044 |
Y |
|
0x8045 |
Y |
|
0x8046 |
Y |
|
0x8048 |
Y |
|
0x80C0 |
Y |
|
0x8500 |
Y |
|
0x8501 |
Y |
|
0x8502 |
Y |
|
0x8600 |
Y |
|
0x8700 |
Y |
|
0x8800 |
Y |
ACI_EVENT_ACK
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_ACK |
0x0000 |
cmd_id, status |
Description
Acks the received command for device.
Event Parameters
cmd_id:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXX |
The command ID to ACK. |
status:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Command complete: BTM can handle this command. |
0x01 |
Command disallow: BTM cannot handle this command. |
0x02 |
Unknown CMD. |
0x03 |
Parameters error. |
0x04 |
Busy. |
0x05 |
Process fail maybe due to stack resource. |
0x07 |
TTS frame send success and request for another TTS frame. |
0x08 |
Music frame send success and request for another music frame. |
0x09 |
SPP transfer success when sent to phone. |
0x10 |
SPP transfer failed when sent to phone. |
0x11 |
GATT transfer can continue sending to phone. |
0x12 |
GATT transfer cannot continue sending to phone. |
Others |
Reserved. |
ACI_EVENT_BT_REPLY_PAIRED_RECORD
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_BT_REPLY_PAIRED_RECORD |
0x0001 |
paired_device_number, paired_record |
Description
Reply to the Read_Paired_Device_Information command.
Event Parameters
paired_device_number:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
paired_device_number |
paired_record:
Size: (8*total_record) octets
Value | Parameter Description |
---|---|
byte0 | Link priority: 1 is the highest (newest device) and 4 (or 8) is the lowest (oldest device). |
byte1 |
bond_flag: Bit0: HFP or HSP profile bond. Bit1: A2DP profile bond. Bit2: SPP or IAP profile bond. Bit3: Reserved for PBAP. Bit4: Remote device supports content protection. Bit5: Remote device supports delay report. Bit6: Link key type is authenticated type. Bit7: Reserved. |
byte2~byte7 | Linked device Bluetooth address. |
ACI_EVENT_LEGACY_DATA_TRANSFER
Command |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_LEGACY_DATA_TRANSFER |
0x0002 |
link_id, payload_length, |
Description
Report SPP data to the MCU host.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Link_id, this index will be informed when the link is established (event: ACI_EVENT_PROFILE_CONN_STATUS). |
payload_length:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Payload length in this packet. |
payload:
Size: N octets
Parameter Description |
---|
N octets of the payload in this packet. |
ACI_EVENT_PROFILE_CONN_STATUS
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_PROFILE_CONN_STATUS |
0x0003 |
link_id, connect_status, |
Description
Report the current Bluetooth profiles connect status.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Bluetooth profile link ID. |
connect_status:
Size: 4 octets
Value |
Parameter Description |
---|---|
0x00 |
Reserved. |
0x00000001 |
A2DP_SINK_PROFILE_MASK |
0x00000002 |
AVRCP_CONTROLLER_PROFILE_MASK |
0x00000004 |
HFP_HF_PROFILE_MASK |
0x00000080 |
HSP_AG_PROFILE_MASK |
0x00000200 |
MAP_MSE_PROFILE_MASK |
0x00000400 |
A2DP_SRC_PROFILE_MASK |
0x00000800 |
AVRCP_TARGET_PROFILE_MASK |
0x00001000 |
HFP_AG_PROFILE_MASK |
0x00002000 |
PBAP_PSE_PROFILE_MASK |
0x00004000 |
HSP_HF_PROFILE_MASK |
address:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
The remote device Bluetooth address. |
ACI_EVENT_PROFILE_CONNECT_FAIL_STATUS
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_PROFILE_CONNECT_FAIL_STATUS |
0x0004 |
link_id, disconnect_status, |
Description
Report the Bluetooth profile’s disconnect status.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Bluetooth profile link ID. |
connect_status:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Reserved. |
0x00000001 |
A2DP_SINK_PROFILE_MASK |
0x00000002 |
AVRCP_CONTROLLER_PROFILE_MASK |
0x00000004 |
HFP_HF_PROFILE_MASK |
0x00000080 |
HSP_AG_PROFILE_MASK |
0x00000200 |
MAP_MSE_PROFILE_MASK |
0x00000400 |
A2DP_SRC_PROFILE_MASK |
0x00000800 |
AVRCP_TARGET_PROFILE_MASK |
0x00001000 |
HFP_AG_PROFILE_MASK |
0x00002000 |
PBAP_PSE_PROFILE_MASK |
0x00004000 |
HSP_HF_PROFILE_MASK |
address:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
The remote device Bluetooth address. |
cause:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXX |
Reason for disconnect. |
ACI_EVENT_HFP_CALLER_ID
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_HFP_CALLER_ID |
0x0005 |
reserved, type, length, string |
Description
Report the caller’s phone number and the caller’s name.
Event Parameters
reserved:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xFF |
Reserved. |
type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Caller phone number. |
0x01 |
Caller name. |
Others |
Reserved. |
length:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Length of caller ID unit in byte. |
string:
Size: N octets
Parameter Description |
---|
N octets of caller ID. If the type is number, the encoder is ASCII. If the type is name, the encoder is UTF-8. |
ACI_EVENT_AUDIO_DEVICE_STATE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_AUDIO_DEVICE_STATE |
0x0007 |
state |
Description
Report the device state.
Event Parameters
state:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
APP_STATE_OFF |
0x01 |
APP_STATE_ON |
0x02 |
APP_DEVICE_STATE_OFF_ING |
Others |
Reserved. |
ACI_EVENT_BR_REMOTE_NAME
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_BR_REMOTE_NAME |
0x0009 |
status, bd_addr, name |
Description
Report the remote device name when Bluetooth connected.
Event Parameters
status:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Success. |
Others |
Fail. |
bd_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
Remote device address with low byte first. |
name:
Size: N octets
Parameter Description |
---|
N octets of UTF-8 string with NULL terminate. |
ACI_EVENT_HFP_CALL_STATUS
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_HFP_CALL_STATUS |
0x000A |
bd_addr, prev_status, curr_status |
Description
Report the call status of the connected device.
Event Parameters
bd_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
MAC address of the remote connected device whose call status has changed. |
prev_status:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
CALL_IDLE |
0x01 |
VOICE_ACTIVATION_ONGOING |
0x02 |
INCOMING_CALL_ONGOING |
0x03 |
OUTGOING_CALL_ONGOING |
0x04 |
CALL_ACTIVE |
0x05 |
CALL_ACTIVE_WITH_CALL_WAITING |
0x06 |
CALL_ACTIVE_WITH_CALL_HOLD |
Others |
Reserved. |
curr_status:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
CALL_IDLE |
0x01 |
VOICE_ACTIVATION_ONGOING |
0x02 |
INCOMING_CALL_ONGOING |
0x03 |
OUTGOING_CALL_ONGOING |
0x04 |
CALL_ACTIVE |
0x05 |
CALL_ACTIVE_WITH_CALL_WAITING |
0x06 |
CALL_ACTIVE_WITH_CALL_HOLD |
Others |
Reserved. |
ACI_EVENT_AUDIO_PLAYER_STATUS
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_AUDIO_PLAYER_STATUS |
0x000B |
reserved, status, reserved |
Description
Report the current play status.
Event Parameters
reserved:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXX |
Reserved. |
status:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Stop. |
0x01 |
Playing. |
0x02 |
Paused. |
reserved:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Reserved. |
ACI_EVENT_VOLUME_SYNC
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_VOLUME_SYNC |
0x0013 |
address, volume |
Description
Report volume setting to sync with the remote device during calls.
Event Parameters
address:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXX |
The remote device Bluetooth address. |
volume:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
HFP volume. |
ACI_EVENT_BR_LINK_STATUS
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_BR_LINK_STATUS |
0x0014 |
link_state, bd_addr, link_id, conn_handle |
Description
Report ACL link status to MCU.
Event Parameters
link_state:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
LINK_STATE_STANDBY |
0x01 |
LINK_STATE_CONNECTED |
0x02 |
LINK_STATE_LOST |
0x03 |
LINK_STATE_CONN_FAIL |
0x04 |
LINK_STATE_KEY_MISSING |
0x05 |
LINK_STATE_AUTHENTIC_FAIL |
bd_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
Remote device address. |
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer link ID for BR/EDR link. |
conn_handle:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
It starts from 0x0001. For only one BR/EDR link, it will be 0x0001. |
ACI_EVENT_REPORT_CFG_TYPE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_REPORT_CFG_TYPE |
0x0018 |
get_type, name_len, name |
Description
Report configuration settings.
Event Parameters
get_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
LE name. |
0x01 |
Legacy name. |
name_len:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Name length. |
name:
Size: name_len octets
Parameter Description |
---|
Name payload. |
ACI_EVENT_REPORT_STATUS
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_REPORT_STATUS |
0x0019 |
status_index, |
Description
Report status information.
Event Parameters
status_index:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xA1 |
Volume. |
volume:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
0~maximum gain. |
maximum gain:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Maximum gain. |
ACI_EVENT_GET_BD_ADDR
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_GET_BD_ADDR |
0x001A |
bd_addr |
Description
Report the Bluetooth device address.
Event Parameters
bd_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
Bluetooth address. |
ACI_EVENT_REPORT_DLPS_STATUS
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_REPORT_DLPS_STATUS |
0x001C |
dlps_status |
Description
Report DLPS status.
Event Parameters
dlps_status:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
DLPS disabled. |
0x01 |
DLPS enabled. |
ACI_EVENT_REPORT_KEY_ACTION
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_REPORT_KEY_ACTION |
0x001D |
key_mask, scenario, action |
Description
Report GPIO key action.
Event Parameters
key_mask:
Size: 1 octet
Value | Parameter Description |
---|---|
0xXX | Bit mask: 0x01: KEY0_MASK. 0x02: KEY1_MASK. 0x04: KEY2_MASK. 0x08: KEY3_MASK. 0x10: KEY4_MASK. 0x20: KEY5_MASK. 0x40: KEY6_MASK. 0x80: KEY7_MASK. |
scenario:
Size: 1 octet
Value | Parameter Description |
---|---|
0xXX | 0x00: Short click. 0x01: Long press. 0x03: 2 clicks. 0x04: 3 clicks. 0x05: 4 clicks. 0x06: 5 clicks. |
action:
Size: 1 octet
Value | Parameter Description |
---|---|
0xXX | MMI action. |
ACI_EVENT_AUDIO_VOL_CHANGE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_AUDIO_VOL_CHANGE |
0x0020 |
status, current_vol |
Description
Report volume change information to the remote device.
Event Parameters
status:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
VolChangeNone |
0x01 |
VolChangeUp |
0x02 |
VolChangeDown |
0x03 |
VolChangeMax |
0x04 |
VolChangeMin |
current_vol:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Current volume. |
ACI_EVENT_BT_READY
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_BT_READY |
0x0023 |
bd_addr |
Description
Report both Bluetooth and Bluetooth LE stacks are checked ready.
Event Parameters
bd_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
Bluetooth address. |
ACI_EVENT_BR_INQUIRY_STATE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_BR_INQUIRY_STATE |
0x0025 |
state |
Description
Report the inquiry state.
Event Parameters
state:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Inquiry process has been completed. |
0x01 |
Inquiry process has been canceled. |
0x02 |
Inquiry process contains a valid inquiry result. |
0x03 |
Inquiry process failed. |
ACI_EVENT_SERVICES_SEARCH_STATE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_SERVICES_SEARCH_STATE |
0x0026 |
state, bd_addr |
Description
Report the service search state.
Event Parameters
state:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Service search process success. |
0x01 |
Service search process fail. |
0x02 |
Service search process stop. |
bd_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
Bluetooth address. |
ACI_EVENT_BR_INQUIRY_RESULT
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_BR_INQUIRY_RESULT |
0x002B |
bd_addr, cod, name_len, name |
Description
Report inquiry results.
Event Parameters
bd_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXX |
MAC address of inquired device. |
cod:
Size: 4 octets
Value |
Parameter Description |
---|---|
0xXX |
Class of device. |
name_len:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Length of the inquired device. |
name:
Size: name_len octets
Value |
Parameter Description |
---|---|
0xXX |
Device name of the inquired device. |
ACI_EVENT_LE_CONNECTED
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_LE_CONNECTED |
0x0100 |
link_id |
Description
Indicates LE link connected.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for LE link. |
ACI_EVENT_LE_DISCONNECTED
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_LE_DISCONNECTED |
0x0101 |
link_id, result_code |
Description
Indicates LE link disconnection.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for LE link. |
result_code:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Disconnect cause. |
ACI_EVENT_LE_PAIR_STATUS
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_LE_PAIR_STATUS |
0x0102 |
link_id, status |
Description
Indicate LE link pair status.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP link ID for LE link. |
status:
Size: 2 octets
Value |
Parameter Description |
---|---|
0x00 |
Success. |
Others |
Fail. |
ACI_EVENT_LE_VENDOR_DATA_TRANSFER
Command |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_LE_VENDOR_DATA_TRANSFER |
0x0103 |
link_id, pkt_type, total_length, payload_length = total_length, payload |
Description
Send data to SPP by LE link.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Link_id, the identifier for LE link. |
type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Single packet. |
0x02 |
Fragmented continue packet. |
0x03 |
Fragmented end packet. |
total_length:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Total payload length. |
payload_length:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Payload length in this packet. |
payload:
Size: payload_length octets
Parameter Description |
---|
N octets of the payload in this packet. |
ACI_EVENT_ANCS_REGISTER_COMPLETE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_ANCS_REGISTER_COMPLETE |
0x0110 |
link_id, result |
Description
Inform the ANCS discovery completed.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for LE link. |
result:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Register success. |
ACI_EVENT_ANCS_NOTIFICATION
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_ANCS_NOTIFICATION |
0x0111 |
link_id, |
Description
Send the ANCS notification data.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for LE link. |
ancs_data_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
ANCS_FROM_DATA_SOURCE |
0x01 |
ANCS_FROM_NOTIFICATION_SOURCE |
pkt_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
PKT_TYPE_SINGLE |
0x01 |
PKT_TYPE_START |
0x02 |
PKT_TYPE_CONT |
0x03 |
PKT_TYPE_END |
total len:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Total len. |
pkt_len:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
pkt_len |
pkt_data:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXX, … |
pkt_data |
ACI_EVENT_ANCS_ACTION_RESULT
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_ANCS_ACTION_RESULT |
0x0112 |
link_id, cause |
Description
Inform the action result.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for LE link. |
cause:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Success. |
0x4A0 |
Command ID was not recognized by the NP. |
0x4A1 |
Command was improperly formatted. |
0x4A2 |
One of the parameters (for example, the NotificationUID) does not refer to an existing object on the NP. |
0x4A3 |
The action was not performed. |
ACI_EVENT_AMS_ENTITY_UPD_NOTIFY
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_AMS_ENTITY_UPD_NOTIFY |
0x0121 |
link_id, pkt_type, total len, pkt_len, pkt_data |
Description
Notify the entity to update data.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for LE link. |
pkt_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
PKT_TYPE_SINGLE |
0x01 |
PKT_TYPE_START |
0x02 |
PKT_TYPE_CONT |
0x03 |
PKT_TYPE_END |
total len:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Total len. |
pkt_len:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
pkt_len |
pkt_data:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXX, … |
pkt_data |
ACI_EVENT_AMS_ENTITY_UPD_NOTIFY_EN
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_AMS_ENTITY_UPD_NOTIFY_EN |
0x0122 |
link_id |
Description
Entity update notification was enabled.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for LE link. |
ACI_EVENT_AMS_REMOTE_CMD_NOTIFY
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_AMS_REMOTE_CMD_NOTIFY |
0x0123 |
link_id, pkt_type, total len, pkt_len, pkt_data |
Description
Notify the remote CMD data.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for LE link. |
pkt_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
PKT_TYPE_SINGLE |
0x01 |
PKT_TYPE_START |
0x02 |
PKT_TYPE_CONT |
0x03 |
PKT_TYPE_END |
total len:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Total len. |
pkt_len:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
pkt_len |
pkt_data:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXX, … |
pkt_data |
ACI_EVENT_AMS_REMOTE_CMD_NOTIFY_EN
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_AMS_REMOTE_CMD_NOTIFY_EN |
0x0124 |
link_id |
Description
This event means the remote command notification is enabled.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for LE link. |
ACI_EVENT_LE_AUDIO_SCAN_INFO
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_LE_AUDIO_SCAN_INFO |
0x0140 |
event_type, |
Description
Report advertisements from devices supporting LE Audio.
Event Parameters
event_type:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Reported ADV type. |
addr_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Advertiser address type. |
addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
Advertiser address. |
name_len:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
Length of advertiser name. |
name:
Size: 40 octets
Value |
Parameter Description |
---|---|
0xXX, … |
Advertiser name. |
ACI_EVENT_LE_AUDIO_BAP_STATE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_LE_AUDIO_BAP_STATE |
0x0141 |
group_handle, state |
Description
Report BAP state.
Event Parameters
group_handle:
Size: 4 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXX |
Group handle. |
state:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
BAP streaming state. |
ACI_EVENT_LE_AUDIO_BAP_DISCOVERY_DONE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_LE_AUDIO_BAP_DISCOVERY_DONE |
0x0142 |
link_id |
Description
Indicates the BAP related info has been completely discovered.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Link ID. |
ACI_EVENT_LE_AUDIO_CSIS_SCAN_STATE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_LE_AUDIO_CSIS_SCAN_STATE |
0x0143 |
group_handle, state |
Description
Reports the group scan state of the group handle.
Event Parameters
group_handle:
Size: 4 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXX |
Group handle. |
state:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Scan stopped. |
0x01 |
Scan started. |
ACI_EVENT_LE_AUDIO_ADD_GROUP
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_LE_AUDIO_ADD_GROUP |
0x0144 |
group_handle_count |
Description
Report the count of group handles.
Event Parameters
group_handle_count:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
The count of group handles. |
ACI_EVENT_LE_AUDIO_ADD_SYNC_HANDLE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_LE_AUDIO_ADD_SYNC_HANDLE |
0x0145 |
sync_handle_count |
Description
Report the count of sync handles.
Event Parameters
sync_handle_count:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
The count of sync handles. |
ACI_EVENT_LE_AUDIO_BAAS_SCAN_INFO
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_LE_AUDIO_BAAS_SCAN_INFO |
0x0146 |
scan_baas_dev_count, |
Description
Report advertisement information of BAAS scan.
Event Parameters
scan_baas_dev_count:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Device count of BAAS scan. |
addr_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Advertiser address type. |
addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
Advertiser address. |
name_len:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
Length of advertiser name. |
name:
Size: 40 octet
Value |
Parameter Description |
---|---|
0xXX, … |
Advertiser name. |
ACI_EVENT_LE_AUDIO_PA_SYNC_STATE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_LE_AUDIO_PA_SYNC_STATE |
0x0147 |
sync_state |
Description
Report PA sync state.
Event Parameters
sync_state:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x04 |
GAP_PA_SYNC_STATE_SYNCHRONIZED |
0x05 |
GAP_PA_SYNC_STATE_TERMINATING |
ACI_EVENT_SCO_STATE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_SCO_STATE |
0x0300 |
connect_status, address |
Description
Report SCO connect state.
Event Parameters
connect_status:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
SCO connect indication. |
0x01 |
SCO link established. |
0x02 |
SCO link disconnect. |
address:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
The remote device Bluetooth address. |
ACI_EVENT_CALL_WAITING
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_CALL_WAITING |
0x0301 |
num_len, number |
Description
Report the third call information (can add other info if needed).
Event Parameters
num_len:
Size: 1 octet
Value |
Parameter Description |
---|---|
num_len |
Number length. |
number:
Size: num_len * 1 octet
Value |
Parameter Description |
---|---|
0x00… |
Caller phone number. |
ACI_EVENT_SUBSCRIBER_NUMBER
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_SUBSCRIBER_NUMBER |
0x0306 |
service, type, |
Description
Report local phone information.
Event Parameters
service:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Service. |
type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Type. |
num_len:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Length of phone number. |
number:
Size: N octets
Parameter Description |
---|
N octets of caller number. |
ACI_EVENT_CURRENT_CALLS
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_CURRENT_CALLS |
0x0307 |
call_idx, |
Description
Report current call info.
Event Parameters
call_idx:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
call_idx |
dir_incoming:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Outgoing. |
0x01 |
Incoming. |
status:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Active. |
0x01 |
Held. |
0x02 |
Dialing. |
0x03 |
Alerting. |
0x04 |
Incoming. |
0x05 |
Waiting. |
0x06 |
Call held by response and hold. |
mode:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Voice. |
0x01 |
Data. |
0x03 |
Fax. |
mpty:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Call is not a member of a multi-party call. |
0x01 |
Call is a member of a multi-party call. |
type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Type. |
num_len:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
num_len |
number:
Size: N octets
Parameter Description |
---|
N octets of number. |
ACI_EVENT_DTMF
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_DTMF |
0x0308 |
Vchar |
Description
Report the key value entered by the user.
Event Parameters
Vchar:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Vchar. |
ACI_EVENT_HFP_AG_CONN_CMPL
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_HFP_AG_CONN_CMPL |
0x0381 |
bd_addr |
Description
Report the key value entered by the user.
Event Parameters
bd_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXX |
MAC address of HFP AG connection. |
ACI_EVENT_HFP_AG_SUPPORTED_FEATURES
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_HFP_AG_SUPPORTED_FEATURES |
0x0389 |
link_id, feature_bitmap |
Description
This event is used to describe the HFP AG support features.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for BR/EDR link. |
feature_bitmap:
Size: 4 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXX |
HFP AG support features. |
ACI_EVENT_HFP_AG_CURR_CALLS_LIST_QUERY
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_HFP_AG_CURR_CALLS_LIST_QUERY |
0x038D |
link_id |
Description
Report the current calls list query.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for BR/EDR link. |
ACI_EVENT_HFP_AG_NETWORK_NAME_FORMAT_SET
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_HFP_AG_NETWORK_NAME_FORMAT_SET |
0x0396 |
link_id |
Description
Report the network name format set.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for BR/EDR link. |
ACI_EVENT_DFU_START_RSP
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_DFU_START_RSP |
0x3160 |
status |
Description
Accept or reject DFU request.
Event Parameters
status:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
UART_DFU_REJECT |
0x01 |
UART_DFU_ACCEPT |
ACI_EVENT_DFU_DATA_REQ
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_DFU_DATA_REQ |
0x3161 |
offset, length |
Description
Request specific DFU data.
Event Parameters
offset:
Size: 4 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXX |
next_block_offset |
length:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXX |
next_block_length |
ACI_EVENT_DFU_RESULT
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_DFU_RESULT |
0x3162 |
result |
Description
Report DFU result.
Event Parameters
result:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
UART_DFU_FAIL |
0x01 |
UART_DFU_SUCCESS |
ACI_EVENT_DFU_LOCAL_VERSION
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_DFU_LOCAL_VERSION |
0x3163 |
local_version |
Description
Report device’s local version.
Event Parameters
local_version:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXXXXXXXX |
Version. |
ACI_APP_EVENT_TRI_DONGLE_EVENT_REPORT
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_APP_EVENT_TRI_DONGLE_EVENT_REPORT |
0x0A0E |
sub_report_event_id, |
Description
Report event related to Tri dongle.
Event Parameters
sub_report_event_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
LE scan report. |
0x01 |
BR scan report. |
0x02 |
LE BAS not support report. |
0x03 |
LE RSSI not support report. |
0x04 |
LE DIS info report. |
0x05 |
LE BAS info report. |
0x06 |
HF battery info report. |
0x07 |
Connected LE link info report. |
0x08 |
Connected BR link info report. |
0x09 |
LE connection info report. |
0x0A |
PASSKEY value report. |
0x0B |
LE RSSI info report. |
0x0C |
BR RSSI info report. |
0x0D |
LE scan status report. |
0x0E |
BR inquiry scan status report. |
0x0F |
USB reset status report. |
0x10 |
PASSKEY status report. |
0x11 |
ACL authen success report. |
0x12 |
LE bond list report. |
0x13 |
LE DIS not support report. |
0x14 |
LE DIS SYSTEM info report. |
0x15 |
LE DIS PNP info report. |
0x16 |
BR bond list report. |
0x17 |
BR RSSI not support report. |
sub_event_report_parameters:
Size: 50 octets
Sub_report_event_id |
Sub Event Report Parameter Description |
---|---|
0x00 |
bd_addr (6 octets, Little-Endian), |
0x01 |
bd_addr (6 octets, Little-Endian), |
0x02 |
bd_addr (6 octets for 1 Device) |
0x03 |
bd_addr (6 octets for 1 Device) |
0x04 |
UUID (2 octets, Little-Endian), |
0x05 |
battery_level (1 octet), |
0x06 |
battery_level (1 octet), |
0x07 |
Connected_LE_link_num (1 octet), |
0x08 |
Connected_BR_link_num (1 octet), |
0x09 |
LE connection status (1 octet, 0 = disconnect, 1 = connected), |
0x0A |
PASSKEY INFO (3 octets, Little-Endian) |
0x0B |
RSSI (1 octet), |
0x0C |
RSSI (1 octet), |
0x0D |
status (1 octet, 0 = stop, 1 = start) |
0x0E |
status (1 octet, 0 = stop, 1 = start) |
0x0F |
status (1 octet, 0 = ready, 1 = reset) |
0x10 |
status (1 octet, 0 = disable, 1 = enable) |
0x11 |
bd_addr (6 octets for 1 Device), |
0x12 |
LE device number (1 octet) |
0x13 |
UUID (2 octets, Little-Endian), |
0x14 |
UUID (2 octets, Little-Endian), |
0x15 |
UUID (2 octets, Little-Endian), |
0x16 |
BR device number (1 octet), |
0x17 |
bd_addr (6 octets for 1 Device) |
ACI_APP_EVENT_CCP_CALL_STATUS
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_APP_EVENT_CCP_CALL_STATUS |
0x3252 |
conn_id, call_status |
Description
Report the device current call status.
Event Parameters
conn_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xxx |
Connect ID. |
call_status:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
APP_CALL_IDLE |
0x01 |
APP_VOICE_ACTIVATION_ONGOING |
0x02 |
APP_CALL_INCOMING |
0x03 |
APP_CALL_OUTGOING |
0x04 |
APP_CALL_ACTIVE |
0x05 |
APP_CALL_ACTIVE_WITH_CALL_WAITING |
0x06 |
APP_CALL_ACTIVE_WITH_CALL_HELD |
0x07 |
APP_MULTILINK_CALL_ACTIVE_WITH_CALL_WAIT |
0x08 |
APP_MULTILINK_CALL_ACTIVE_WITH_CALL_HELD |
ACI_APP_EVENT_MCP_MEDIA_STATE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_APP_EVENT_MCP_MEDIA_STATE |
0x3253 |
conn_id, media_state |
Description
Report the device current media state.
Event Parameters
conn_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xxx |
Connect ID. |
media_state:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
MCS_MEDIA_STATE_INACTIVE |
0x01 |
MCS_MEDIA_STATE_PLAYING |
0x02 |
MCS_MEDIA_STATE_PAUSED |
0x03 |
MCS_MEDIA_STATE_SEEKING |
ACI_APP_EVENT_VCS_STATE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_APP_EVENT_VCS_STATE |
0x3253 |
vol_setting, mute |
Description
Report the device current audio volume.
Event Parameters
vol_setting:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Current volume value of the audio. |
mute:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
SPK unmute state. |
0x01 |
SPK mute state. |
ACI_EVENT_BT_BOND_INFO_CLEAR
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_BT_BOND_INFO_CLEAR |
0x0904 |
status |
Description
Return the result of clearing the link keys of the target remote connection.
Event Parameters
status:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Clear link keys successful. |
0x01 |
Fail to clear link keys, or if there are no link keys, the device will return fail if still using clear band info CMD. |
ACI_EVENT_FW_VERSION
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_FW_VERSION |
0x0909 |
fw_version(app, patch, app_ui) |
Description
Report firmware version information.
Event Parameters
app:
Size: 5 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXX |
APP version. |
patch:
Size: 4 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXX |
Patch version. |
app_ui:
Size: 4 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXX |
APP UI version. |
ACI_EVENT_REPORT_PACKAGE_ID
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_REPORT_PACKAGE_ID |
0x0911 |
chip_id, package_id |
Description
Report chip ID and package ID.
Event Parameters
chip_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x1B |
RTL87x3E. |
package id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x04 |
Reserved. |
ACI_EVENT_REQ_MEDIA_FRAME
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_REQ_MEDIA_FRAME |
0x5001 |
audio_queue_state, water_level |
Description
Report SCO connect state.
Event Parameters
audio_queue_state:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
STATE_PRELOAD |
0x01 |
STATE_CONSUME |
0x02 |
STATE_CHARGE |
0x03 |
STATE_OFFLOAD |
0x04 |
STATE_EMPTY |
water_level:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Counts of buffered frames. |
ACI_EVENT_XM_SPP_DATA_TRANSFER
Command |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_SPP_DATA_TRANSFER |
0x8000 |
link_id, payload_length, payload |
Description
This command is used to report vendor SPP data to the MCU host.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for BR/EDR link. |
payload_length:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Payload length in this packet. |
payload:
Size: N octets
Parameter Description |
---|
N octets of the payload in this packet. |
ACI_EVENT_XM_SPP_CONNECT_STATUS
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_SPP_CONNECT_STATUS |
0x8001 |
connect_status, address |
Description
Report vendor SPP connect status.
Event Parameters
connect_status:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Reserved. |
0x10 |
VENDOR_SPP_PROFILE_MASK |
address:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
The remote device Bluetooth address. |
ACI_EVENT_XM_SPP_DISCONNECT_STATUS
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_SPP_DISCONNECT_STATUS |
0x8002 |
disconnect_status, address, |
Description
Report vendor SPP disconnect status.
Event Parameters
connect_status:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Reserved. |
0x10 |
VENDOR_SPP_PROFILE_MASK |
address:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
The remote device Bluetooth address. |
cause:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXX |
Reason of disconnect. |
ACI_EVENT_XM_LE_ADV_STATE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_LE_ADV_STATE |
0x8040 |
adv_state, adv_stop_cause |
Description
Report LE advertising state, adv_stop_cause
only valid when adv_state
is 0x00.
Event Parameters
adv_state:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Advertising disabled. |
0x01 |
Advertising enabled. |
adv_stop_cause:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
LE ADV stop cause UNKNOWN. |
0x01 |
LE ADV stop cause APP, user terminate ADV. |
0x02 |
LE ADV stop cause CONN, connection establish. |
0x03 |
LE ADV stop cause TIMEOUT, ADV timeout. |
0x04 |
LE ADV stop cause ENABLE_FAILED, ADV enable failed. |
ACI_EVENT_XM_LE_ATT_MTU
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_LE_ATT_MTU |
0x8041 |
mtu_size |
Description
Report LE ATT MTU size, only valid when LE is connected.
Event Parameters
mtu_size:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXX |
LE ATT MTU size. |
ACI_EVENT_XM_LE_ADDR
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_LE_ADDR |
0x8042 |
le_addr |
Description
Report the LE address.
Event Parameters
le_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXX |
LE address. |
ACI_EVENT_XM_LE_CON_STATE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_LE_CON_STATE |
0x8043 |
conn_state, |
Description
Report LE connect state after LE is connected.
Event Parameters
conn_state:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
LE_LINK_STATE_DISCONNECTED |
0x01 |
LE_LINK_STATE_CONNECTING |
0x02 |
LE_LINK_STATE_CONNECTED |
0x03 |
LE_LINK_STATE_DISCONNECTING |
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xxx |
APP layer ID for LE link. |
conn_handle:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
It starts from 0x0013. For only one LE link, it will be 0x0013. |
role:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
GAP_LINK_ROLE_UNDEFINED |
0x01 |
GAP_LINK_ROLE_MASTER |
0x02 |
GAP_LINK_ROLE_SLAVE |
remote_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
GAP_LINK_ROLE_UNDEFINED |
0x01 |
GAP_LINK_ROLE_MASTER |
0x02 |
GAP_LINK_ROLE_SLAVE |
remote_type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
LE Public device address type. |
0x01 |
LE Random device address type. |
0x02 |
LE Public identity address type. |
0x03 |
LE Random identity address type. |
0x04 |
BR/EDR device address type. |
0x05 |
LE anonymous device address type. |
remote_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xxx 0xxx 0xxx 0xxx 0xxx 0xxx |
Remote device address. |
connInterval:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
LE preferred connection interval to conn_interval * 1.25 ms, little endian. |
connLatency:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
LE preferred connection latency to conn_latency, little endian. |
supTimeout:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
LE preferred connection supervision timeout to conn_supervision_timeout * 10ms, |
ACI_EVENT_XM_LE_CON_PARAM
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_LE_CON_PARAM |
0x8044 |
link_id, |
Description
Report the LE Parameter state after LE update parameters.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xxx |
APP layer ID for LE link. |
connInterval_min:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
LE preferred connection interval to conn_interval * 1.25 ms, little endian. |
connInterval_max:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
LE preferred connection interval to conn_interval * 1.25 ms, little endian. |
connLatency:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
LE prefer connection latency to conn_latency, little endian. |
supTimeout:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
LE prefer connection supervision timeout to conn_supervision_timeout * 10ms, |
ACI_EVENT_XM_GATT_CON_NOTIFY
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_GATT_CON_NOTIFY |
0x8045 |
conn_handle, cid, xm_service, |
Description
Report GATT service notify state.
Event Parameters
conn_handle:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
The connection handle from HCI (for a simple test, it is 0x01 for BR/EDR and 0x13 for LE). |
cid:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
The channel ID for corresponding L2CAP channel. For BR/EDR, it is allocated dynamically. For LE, however, it is fixed to 0x0004. |
xm_service:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
T_DEVICE_SERVICE |
0x01 |
T_XM_UNLOCK_SERVICE |
0x02 |
T_XM_FACTORY_SERVICE |
0x03 |
T_XM_SERVICE |
0x04 |
T_XM_ALIPAY_SERVICE |
0x05 |
T_XM_WECHAT_SERVICE |
0x06 |
T_HID_SERVICE |
0x07 |
T_HRS_SERVICE |
0x08 |
T_GOODIX_SERVICE |
attr_index:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Each service has its attr and show this latter. |
value:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x01 |
Enable. |
0x02 |
Disable. |
ACI_EVENT_XM_GATT_DATA_TRANSFER
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_GATT_DATA_TRANSFER |
0x8005 |
conn_handle, |
Description
Report GATT data to UART.
Event Parameters
conn_handle:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
The connection handle from HCI (for a simple test, it is 0x01 for BR/EDR and 0x13 for LE). |
cid:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
The channel ID for corresponding L2CAP channel. For BR/EDR, it is allocated dynamically. For LE, however, it is fixed to 0x0004. |
type:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Single packet. |
0x01 |
Fragmented start packet. |
0x02 |
Fragmented continue packet. |
0x03 |
Fragmented end packet. |
handle_index:
Size: 1 octet
Value |
Attribute |
Parameter Description |
---|---|---|
0x01 |
fd04 |
Service 02fd. |
0x11 |
4 |
Service unlock. |
0x12 |
7 |
Service unlock. |
0x21 |
2 |
Service factory. |
0x61 |
20 |
Service HID. |
0x71 |
7 |
Service HRS. |
0x81 |
2 |
Service goodix. |
total_length:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Total payload length. |
payload_length:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Payload length in this packet. |
payload:
Size: N octets
Parameter Description |
---|
N octets of the payload in this packet. |
ACI_EVENT_XM_GATT_CREDIT_UPDATE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_GATT_CREDIT_UPDATE |
0x8006 |
conn_handle, |
Description
Report GATT credit updated.
Event Parameters
conn_handle:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
The connection handle from HCI (for a simple test, it is 0x01 for BR/EDR and 0x13 for LE). |
cid:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
The channel ID for the corresponding L2CAP channel. For BR/EDR, it is allocated dynamically. For LE, however, it is fixed to 0x0004. |
credit:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
Number of credit for GATT TX. |
ACI_EVENT_XM_FACTORY_RESET_STATUS
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_FACTORY_RESET_STATUS |
0x80c0 |
freset_done |
Description
Report device factory reset status.
Event Parameters
freset_done:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Factory reset not done. |
0x01 |
Factory reset done. |
ACI_EVENT_XM_MUSIC_REQ_FRAME
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_MUSIC_REQ_FRAME |
0x8500 |
None |
Description
Request MCU to send the next music frame.
Event Parameters
None.
ACI_EVENT_XM_TTS_REQ_FRAME
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_TTS_REQ_FRAME |
0x8501 |
tts_state |
Description
Request MCU to send the next TTS frame.
Event Parameters
tts_state:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x01 |
TTS_STATE_STARTED |
0x04 |
TTS_STATE_RESUMED |
0x06 |
TTS_STATE_ABORTING |
0x07 |
TTS_STATE_STOPPED |
ACI_EVENT_XM_RECORDING_DATA
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_RECORDING_DATA |
0x8502 |
recording_data |
Description
Report recording data format.
Event Parameters
recording_data:
Size: 1024 octets
Parameter Description |
---|
1024 octets of recording data. |
ACI_EVENT_XM_AUDIO_TEST_PA_ID
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_AUDIO_TEST_PA_ID |
0x8600 |
pa_id |
Description
Report PA ID.
Event Parameters
pa_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x76 |
PA ID. |
ACI_EVENT_XM_BT_AVRCP_STATUS
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_BT_AVRCP_STATUS |
0x8700 |
avrcp_state, |
Description
Report the AVRCP command status.
Event Parameters
avrcp_state:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x01 |
AVRCP_STATE_PLAY |
0x02 |
AVRCP_STATE_PAUSE |
0x03 |
AVRCP_STATE_STOP |
0x04 |
AVRCP_STATE_FORWARD |
0x05 |
AVRCP_STATE_BACKWARD |
0x06 |
AVRCP_STATE_VOL_CHANGED |
vol_number:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Only AVRCP_STATE_VOL_CHANGED have the Parameters. |
address:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXX |
The remote device Bluetooth address. |
ACI_EVENT_XM_BR_ATT_CONNECTED
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_BR_ATT_CONNECTED |
0x8003 |
conn_handle, |
Description
Reports the BR/EDR ATT protocol is connected.
Event Parameters
conn_handle:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
It starts from 0x0001. For only one BR/EDR link, it will be 0x0001. |
cid:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
The L2CAP channel ID, it is currently set to 0x0000. |
ACI_EVENT_XM_BR_ATT_DISCONNECTED
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_BR_ATT_DISCONNECTED |
0x8006 |
conn_handle, |
Description
Report that the BR/EDR ATT protocol is disconnected.
Event Parameters
conn_handle:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
It starts from 0x0001. For only one BR/EDR link, it will be 0x0001. |
cid:
Size: 2 octets
Value |
Parameter Description |
---|---|
0xXXXX |
The L2CAP channel ID, it is currently set to 0x0000. |
ACI_EVENT_XM_USER_CONFIRMATION_REQ
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_USER_CONFIRMATION_REQ |
0x8800 |
remote_addr, |
Description
Request confirmation to connect.
Event Parameters
remote_addr:
Size: 6 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXXXXXX |
Remote address. |
cfmcode:
Size: 4 octets
Value |
Parameter Description |
---|---|
0xXXXXXXXX |
Confirm code, need to convert to decimal. |
handle_idx:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
Connect handle_idx. |
ACI_EVENT_XM_LE_USER_CONFIRMATION_REQ
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_LE_USER_CONFIRMATION_REQ |
0x8046 |
conn_id, |
Description
Request LE confirmation to connect.
Event Parameters
conn_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xxx |
Connect ID. |
display_value:
Size: 4 octets
Value |
Parameter Description |
---|---|
0xxxxxxxxx |
Confirm code, need to convert to decimal. |
ACI_EVENT_XM_LE_ADV_CREATED
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_XM_LE_ADV_CREATED |
0x8048 |
adv_handle |
Description
Report adv_handle for the ADV created by ACI_CMD_XM_LE_ADV_CREATE.
Event Parameters
adv_handle:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
adv_handle |
ACI_EVENT_AMS_REGISTER_COMPLETE
Event |
Opcode |
Event Parameters |
---|---|---|
ACI_EVENT_AMS_REGISTER_COMPLETE |
0x0120 |
link_id, |
Description
Report AMS discovery completed.
Event Parameters
link_id:
Size: 1 octet
Value |
Parameter Description |
---|---|
0xXX |
APP layer ID for LE link. |
result:
Size: 1 octet
Value |
Parameter Description |
---|---|
0x00 |
Register success. |
ACI Host CLI Tool
ACI Host CLI Tool is a test tool running on PC under the path RTL87X3E-MCU-SDK-Common-v3.1x.x.xx_20xxxxxx\tool\AciHostCLI-v1.0.0.xx-Common_SDK
, which is used to demo ACI usage. It can perform CMD/event communication tests with ACI Device through USB serial port.
The steps to run ACI Host CLI Tool are as follows:
Open
config.yml
to modify the device’s serial port and baud rate settings.Run
AciHostCLI.exe
to start the application.Execute
mmi freset
to perform a factory reset.Enter
mmi pwron
to power on the device.Wait for
EVENT_DEVICE_STATE
to return 1 (Power on).
Command Introduction
BR Connection
Use case: Connection and Linkback Function.
Command | Description | ACI Command |
---|---|---|
connect headset_sample | Connect to a BUD with a specific address. | ACI_CMD_BT_CREATE_CONNECTION |
connect idx | Need inquiry first, select an index, connect to that BUD. | |
connect phone_sample | Connect to a phone with a specific address. | |
disconnect headset_sample | Disconnect BUD. | ACI_CMD_BT_DISCONNECT |
disconnect phone_sample | Disconnect phone. |
Man Machine Interface
Command | Description | ACI Command |
---|---|---|
mmi end_outgoing_call | End an outgoing call. | ACI_CMD_MMI |
mmi answer | Answer an incoming call. | |
mmi reject | Reject an incoming call. | |
mmi end_active_call | End an active call. | |
mmi pwron | Power on the device. | |
mmi pwroff | Power off the device. | |
mmi freset | Device factory reset. |
SPP Transfer
Command | Description | ACI Command |
---|---|---|
spp t0_sig | Send single frame data to ACI_Device and relay to phone via SPP profile. | ACI_CMD_LEGACY_DATA_TRANSFER |
spp t2_start | Send start frame data to ACI_Device and relay to phone via SPP profile. | |
spp t3_con | Send continue frame data to ACI_Device and relay to phone via SPP profile. | |
spp t4_end | Send end frame data to ACI_Device and relay to phone via SPP profile. |
Assign RX Buffer Size
Command | Description | ACI Command |
---|---|---|
assign buffer | Assign UART RX buffer size, if set to 128, SPP/LE data will split into several frames with max size 128. | ACI_CMD_ASSIGN_BUFFER_SIZE |
Set Configuration
Command | Description | ACI Command |
---|---|---|
set le_name | Set the LE name (represented in UTF-8), which will be effective after restart. | ACI_CMD_SET_CFG |
set legacy_name | Set Bluetooth legacy name, which will be effective after restart. |
Get Configuration
Command | Description | ACI Command |
---|---|---|
get le_name | Get the LE name (represented in UTF-8). | ACI_CMD_GET_CFG_SETTING |
get legacy_name | Get Bluetooth legacy device name. |
Get Status
Command | Description | ACI Command |
---|---|---|
get volume | Get playback or HFP volume depending on scenario. | ACI_CMD_GET_STATUS |
Phone Call
Use case: HFP Function.
Command | Description | ACI Command |
---|---|---|
call 10086 | Make phone call to 10086. | ACI_APP_CMD_BT_HFP_DIAL_WITH_NUMBER |
call 10010 | Make phone call to 10010. |
Send Msg During Phone Call
Use case: Send numbers during a call, adjust SPK volume, and adjust MIC volume.
Command | Description | ACI Command |
---|---|---|
dtmf num_2 | Send number 2 to phone. | ACI_CMD_SEND_DTMF |
VGS num_1 | Send VGS 1 to phone and set SPK. | ACI_CMD_SEND_VGS |
VGS num_10 | Send VGS 10 to phone and set SPK. | |
VGM num_6 | Send VGM 6 to phone and set MIC. | ACI_CMD_SEND_VGM |
VGM num_10 | Send VGM 10 to phone and set MIC. |
Bluetooth Address Get/Set
Command | Description | ACI Command |
---|---|---|
get bd_addr | Get Bluetooth address set by MCUConfig Tool. | ACI_CMD_GET_BD_ADDR |
set Bluetooth address | Update Bluetooth MAC to new address. | ACI_CMD_XM_BT_SET_ADDR |
Voice Prompt Volume
Command | Description | ACI Command |
---|---|---|
VP volume1 | Set voice prompt volume level to 1. | ACI_CMD_SET_VP_VOLUME |
VP volume9 | Set voice prompt volume level to 9. |
Deep Low Power State Control
Command | Description | ACI Command |
---|---|---|
dlps enable | Allow device to enter DLPS mode automatically. | ACI_CMD_SET_AND_READ_DLPS |
dlps disable | Disallow device to enter DLPS mode. |
Device Mode
Command | Description | ACI Command |
---|---|---|
mode idle | Disable page scan and inquiry scan. | ACI_APP_CMD_XM_SET_MODE |
mode inq_scan | Enable inquiry scan only. | |
mode page_scan | Enable page scan only. | |
mode all_enable | Enable inquiry scan and page scan. |
SCO Manage
Command | Description | ACI Command |
---|---|---|
hfp reject | Reject SCO connection indication. | ACI_CMD_BT_HFP_SCO_MAG |
hfp agree | Accept SCO connection indication. | |
hfp disc | Disconnect SCO connection. |
LE Data Transfer
Command | Description | ACI Command |
---|---|---|
le send1 | Send LE data to phone via transmit service. | ACI_CMD_LE_DATA_TRANSFER |
Volume Control
Command | Description | ACI Command |
---|---|---|
volume level0 | Set volume to level 0. | ACI_CMD_SET_VOLUME |
volume level3 | Set volume to level 3. | |
volume level7 | Set volume to level 7. | |
volume level10 | Set volume to level 10. |
Firmware Version
Command | Description | ACI Command |
---|---|---|
fw version | Get firmware version. | ACI_CMD_GET_FW_VERSION |
Clear Bond Info
Command | Description | ACI Command |
---|---|---|
clear ufo | Clear a device bond info named 'ufo'. | ACI_CMD_BT_BOND_INFO_CLEAR |
HCI Mode
Command | Description | ACI Command |
---|---|---|
hci download | Enter HCI download mode. | ACI_CMD_SWITCH_TO_HCI_DOWNLOAD_MODE |
Inquiry
Use case: Connect to BUD.
Command | Description | ACI Command |
---|---|---|
inquiry start | Start inquiry Bluetooth devices. | ACI_APP_CMD_INQUIRY |
inquiry stop | Stop inquiry Bluetooth devices. |
RF Test
Command | Description | ACI Command |
---|---|---|
hci enter | Enter HCI mode for RF test. | ACI_CMD_XM_ENTER_HCI_MODE |
Device
Command | Description | ACI Command |
---|---|---|
device reboot | Software reboot. | ACI_CMD_XM_DEVICE_REBOOT |
XMMI
Command | Description | ACI Command |
---|---|---|
xmmi local | Switch to local playback mode. | ACI_CMD_XM_MMI |
xmmi source | Switch to A2DP Source music mode. | |
xmmi clear | Delete all bond information in bond storage. |
LE Advertising
Use case: Bluetooth Low Energy Function.
Command | Description | ACI Command |
---|---|---|
le advstart | Create customized LE advertising. | ACI_CMD_XM_LE_ADV_CREATE |
le advstart | Start LE advertising. | ACI_CMD_XM_LE_START_ADVERTISING |
le advstop | Stop LE advertising. | ACI_CMD_XM_LE_STOP_ADVERTISING |
le adv_data | Update LE advertising data. | ACI_CMD_XM_LE_ADV_DATA_UPDATE |
le scan_rsp_data | Update LE scan response data. | ACI_CMD_XM_LE_SCAN_RSP_DATA_UPDATE |
le adv500ms | Change LE advertising interval to 500ms. | ACI_CMD_XM_LE_ADV_INTVAL_UPDATE |
le adv200ms | Change LE advertising interval to 200ms. |
LE Connect
Use case: Bluetooth Low Energy Function.
Command | Description | ACI Command |
---|---|---|
le disconn | Disconnect LE link. | ACI_CMD_XM_LE_DISC |
le conn_param | Update LE connection parameters. | ACI_CMD_XM_LE_CONN_PARAM_UPDATE |
le mtu | Get LE MTU size. | ACI_CMD_XM_LE_ATT_GET_MTU |
Music Control
Use case: Music Play Function.
Command | Description | ACI Command |
---|---|---|
music open | Open and start music session. | ACI_CMD_XM_MUSIC |
music pause | Pause music session. | |
music resume | Resume music session. | |
music abort | Abort music session when an unexpected situation happens. | |
music close | Close music session. | |
music single | Send single MP3 frame to device. |
Recording
Command | Description | ACI Command |
---|---|---|
rc start_pcm | Start recording with the format of PCM. | ACI_CMD_XM_START_RECORD |
rc start_opus | Start recording with the format of OPUS. | |
rc start_msbc | Start recording with the format of mSBC. | |
rc start_sbc | Start recording with the format of SBC. | |
rc start_lc3 | Start recording with the format of LC3. | |
rc stop | Stop recording. | ACI_CMD_XM_STOP_RECORD |
rc play | Initialize record playing. | ACI_CMD_XM_START_RECORD_PLAY |
rc s | Stop record playing. | ACI_CMD_XM_STOP_RECORD_PLAY |
Audio Test
Command | Description | ACI Command |
---|---|---|
pa id | Get PA chip ID. | ACI_CMD_XM_AUDIO_TEST_GET_PA_ID |
algo bypass | Set PA and DSP into bypass mode. | ACI_CMD_XM_AUDIO_TEST_BYPASS |
algo normal | Set PA and DSP into normal mode. |
Others Debug Only
Command | Description | ACI Command |
---|---|---|
dis log | Disable verbose log. | ACI_CMD_XM_DISABLE_VERBOSE_LOG |
A2DP Transfer
Transfer to A2DP Source
Use case: A2DP Transparent Transmission (A2DP Output).
Command | Description | ACI Command |
---|---|---|
a2dpxmitroute a2dpsrc | Set A2DP Source as a transparent transmission play path (from SPI). | ACI_CMD_A2DP_XMIT_SET_ROUTE_OUT |
a2dpxmitctrl start | Enable A2DP Source music (from SPI). | ACI_CMD_A2DP_XMIT_ROUTE_OUT_CTRL |
a2dpxmitctrl stop | Disable A2DP Source music (from SPI). |
Transfer to LE Audio (Broadcast Source)
Use case: A2DP Transparent Transmission (BIS Output).
Command | Description | ACI Command |
---|---|---|
bsrcinit 48k_1bis | Initialize broadcast source | ACI_CMD_LEA_BSRC_INIT |
a2dpxmitroute bis | Set broadcast source as transparent transmission play path (from SPI). | ACI_CMD_A2DP_XMIT_SET_ROUTE_OUT |
a2dpxmitctrl start | Enable broadcast source music (from SPI). | ACI_CMD_A2DP_XMIT_ROUTE_OUT_CTRL |
a2dpxmitctrl stop | Disable broadcast source music (from SPI). |
Source Play
Use case: Source Play Function.
Command | Description | ACI Command |
---|---|---|
set_route_in mic | Set input route as MIC. | ACI_CMD_SRC_PLAY_SET_SRC_ROUTE |
set_route_in linein | Set input route as line-in. | |
set_route_in usb | Set input route as USB. | |
set_route_in sd_card | Set input route as SD card. | |
set_route_out A2DP | Set output route as A2DP. | ACI_CMD_SRC_PLAY_SET_PLAY_ROUTE |
set_route_out hfp_ag | Set output route as HFP AG. | |
set_route_out bis | Set output route as BIS. | |
set_route_out cis | Set output route as CIS. | |
set_route_out local | Set output route as Local. | |
route_in start | Start input route source. | ACI_CMD_SRC_PLAY_ROUTE_IN_START |
route_in stop | Stop input route source. | ACI_CMD_SRC_PLAY_ROUTE_IN_STOP |
route_out start | Start output route play. | ACI_CMD_SRC_PLAY_ROUTE_OUT_START |
route_out stop | Stop output route play. | ACI_CMD_SRC_PLAY_ROUTE_OUT_STOP |
String Mode
Command | Description | ACI Command |
---|---|---|
set string_mode | Enter string mode. | ACI_CMD_STRING_MODE |
HFP Transfer
Use case: HFP Transparent Transmission.
Command | Description | ACI Command |
---|---|---|
hfpag conn | Connect SCO between device and BUD. | ACI_CMD_HFP_AG_CONNECT_SCO |
hfpag disconn | Disconnect SCO between device and BUD. | ACI_CMD_HFP_AG_DISCONNECT_SCO |
hfpag call_incoming | Notify the incoming call. | ACI_CMD_HFP_AG_CALL_INCOMING |
hfpag call_answer | Answer the incoming call. | ACI_CMD_HFP_AG_CALL_ANSWER |
hfpag call_terminate | Terminate the outgoing call. | ACI_CMD_HFP_AG_CALL_TERMINATE |
hfpag mic_mute | Mute the MIC. | ACI_CMD_HFP_AG_MIC_GAIN_LEVEL_SET |
hfpag mic_unmute | Unmute the MIC. | |
hfpag spk_vol_up | Turn the SPK volume up. | ACI_CMD_HFP_AG_SPEAKER_GAIN_LEVEL_SET |
hfpag spk_vol_down | Turn the SPK volume down. |
Find My Action
Command | Description | ACI Command |
---|---|---|
findmy enter_pairing | Enter Find My pairing mode. | ACI_CMD_FINDMY_FEATURE |
findmy put_serial_number | Put the state of serial number. |
GFPS Finder Action
Command | Description | ACI Command |
---|---|---|
gfps_finder_ring_stop | Stop ring. | ACI_CMD_GFPS_FINDER_FEATURE |
LEA Advertising
Command | Description | ACI Command |
---|---|---|
lea_adv_start | Start LE Audio advertising. | ACI_CMD_LEA_ADV_START |
lea_adv_stop | Stop LE Audio advertising. | ACI_CMD_LEA_ADV_STOP |
LEA CCP(F_APP_CCP_SUPPORT, CLIENT)
Command | Description | ACI Command |
---|---|---|
lea_call_cp accept | Answer the incoming call on the specified link. | ACI_CMD_LEA_CCP_CALL_CP |
lea_call_cp terminate | Terminate the call on the specified link. | |
lea_call_cp local_hold | Move the call on the specified link to local hold status. | |
lea_call_cp local_retrieve | Move the call on the specified link from local hold status to active status. | |
lea_call_cp originate | Originate call on the specified link. | |
lea_call_cp join | Join the call on the specified link. |
LEA MCP(F_APP_MCP_SUPPORT, CLIENT)
Command | Description | ACI Command |
---|---|---|
lea_media_cp play | Play current track. | ACI_CMD_LEA_MCP_MEDIA_CP |
lea_media_cp pause | Pause current track. | |
lea_media_cp fast_rewind | Fast rewind. | |
lea_media_cp fast_forward | Fast forward. | |
lea_media_cp stop | Stop current track. | |
lea_media_cp previous_track | Move to previous track. | |
lea_media_cp next_track | Move to next track. |
LEA SYNC INIT
Command | Description | ACI Command |
---|---|---|
bis_sync_init random | Init the role as a sink, which will sync any device around. | ACI_CMD_LEA_SYNC_INIT |
bis_sync_init spec | Init the role as a sink, which will sync a specific device according to the address. | |
bis_sync_init delegator | Init the role as a scan delegator. |
LEA SYNC
Command | Description | ACI Command |
---|---|---|
bis_sync start | Start syncing broadcast according to the init policy. | ACI_CMD_LEA_SYNC |
bis_sync stop | Stop syncing the broadcast. |
CHARGING CASE COMMANDS
Command | Description | ACI Command |
---|---|---|
chargingcase end_outgoing_call | End an outgoing call. | ACI_CMD_LEA_MCP_MEDIA_CP |
chargingcase answer_call | Answer an incoming call. | |
chargingcase reject_call | Reject an incoming call. | |
chargingcase end_active_call | End an active call. | |
chargingcase mic_mute_unmute | MIC mute toggle. | |
chargingcase mic_mute | MIC mute. | |
chargingcase mic_unmute | MIC unmute. | |
chargingcase volume_up | Volume up. | |
chargingcase volume_down | Volume down. | |
chargingcase play_pause | AV play/pause. | |
chargingcase av_fwd | AV forward. | |
chargingcase av_bwd | AV backward. | |
chargingcase av_fastforward | AV fast forward. | |
chargingcase av_rewind | AV rewind. | |
chargingcase gaming_mode_switch | Switch to gaming mode. | |
chargingcase light_sensor_on_off | Light sensor on/off. | |
chargingcase vp_level3 | Set voice prompt volume level to 3. | |
chargingcase vp_level10 | Set voice prompt volume level to 10. | |
chargingcase audio_eq_index_set0 | Set audio EQ index to 0. | |
chargingcase audio_eq_index_set1 | Set audio EQ index to 1. | |
chargingcase volume_level0 | Set volume to level 0. | |
chargingcase volume_level3 | Set volume to level 3. | |
chargingcase volume_level7 | Set volume to level 7. | |
chargingcase volume_level10 | Set volume to level 10. | |
chargingcase volume_level15 | Set volume to level 15. | |
chargingcase set_key_mmi_map_volume_up | Set MFB as volume up button. | |
chargingcase set_key_mmi_map_volume_down | Set MFB as volume down button. |
LEA BAP
Command | Description | ACI Command |
---|---|---|
bst_start group_0_sync_0 | Start broadcast on group 0 and sync 0. | ACI_CMD_LEA_BST_START |
bst_start group_0_sync_1 | Start broadcast on group 0 and sync 1. | |
bst_start group_1_sync_0 | Start broadcast on group 1 and sync 0. | |
bst_start group_1_sync_1 | start broadcast on group 1 and sync 1 | |
bst_stop group_0_sync_0 | Stop broadcast on group 0 and sync 0. | ACI_CMD_LEA_BST_STOP |
bst_stop group_0_sync_1 | Stop broadcast on group 0 and sync 1. | |
bst_stop group_1_sync_0 | Stop broadcast on group 1 and sync 0. | |
bst_stop group_1_sync_1 | Stop broadcast on group 1 and sync 1. | |
bst_remove group_0_sync_0 | Remove broadcast on group 0 and sync 0. | ACI_CMD_LEA_BST_REMOVE |
bst_remove group_0_sync_1 | Remove broadcast on group 0 and sync 1. | |
bst_remove group_1_sync_0 | Remove broadcast on group 1 and sync 0. | |
bst_remove group_1_sync_1 | Remove broadcast on group 1 and sync 1. | |
baas scan | Start extended scan for BAAS. | ACI_CMD_LEA_BAAS_SCAN |
pa_sync dev0 | PA sync with device 0. | ACI_CMD_LEA_PA_SYNC_DEV |
pa_sync dev1 | PA sync with device 1. | |
pa_sync dev2 | PA sync with device 2. |
LEA VCP VOLUME CONTROL
Command | Description | ACI Command |
---|---|---|
gvcs volume | Set VCS volume. | ACI_CMD_LEA_GVCS_VOLUME |
gvcs mute | Set VCS mute. | ACI_CMD_LEA_GVCS_MUTE |
gvcs unmute | Set VCS unmute. |
UART DFU
Command | Description | ACI Command |
---|---|---|
dfu start | Start DFU process through UART. | ACI_CMD_UART_DFU |
dfu abort | Abort DFU process. | |
dfu get_ver | Get device's version. | |
dfu test_enable | Enable test mode to downgrade. |
LEA VCS
Command | Description | ACI Command |
---|---|---|
lea_vcs vol_up | Volume up. | ACI_CMD_LEA_VCS_SET |
lea_vcs vol_down | Volume down. | |
lea_vcs spk_mute | SPK mute. | |
lea_vcs spk_unmute | SPK unmute. |
LEA CCP(CCP_CALL_CONTROL_SERVER)
Command | Description | ACI Command |
---|---|---|
ccp_action incomingcall | Incoming call action. | ACI_CMD_LEA_CCP_ACTION |
ccp_action local_accept1 | Local accept call index 1. | |
ccp_action local_accept2 | Local accept call index 2. | |
ccp_action local_terminate1 | Local terminate call index 1. | |
ccp_action local_terminate2 | Local terminate call index 2. |
LEA MCP(MCP_MEDIA_CONTROL_SERVER)
Command | Description | ACI Command |
---|---|---|
mcp_state playing | The media player starts playing the current track. | ACI_CMD_LEA_MCP_STATE |
mcp_state paused | The media player paused the current track. | |
mcp_notify track_changed | Send track changed notification. | ACI_CMD_LEA_MCP_NOTIFY |
mcp_notify track_duration | Send track duration notification. | |
mcp_notify track_position | Send track position notification. |
LEA MICP MIC CONTROL
Command | Description | ACI Command |
---|---|---|
gmic mute | Set GMIC MIC mute. | ACI_CMD_LEA_GMIC_MUTE |
gmic unmute | Set GMIC MIC unmute. |