1 /*
2  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef __ESP_A2DP_API_H__
8 #define __ESP_A2DP_API_H__
9 
10 #include "esp_err.h"
11 #include "esp_bt_defs.h"
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
17 /**
18  * @brief Media codec types supported by A2DP.
19  */
20 #define ESP_A2D_MCT_SBC         (0)             /*!< SBC */
21 #define ESP_A2D_MCT_M12         (0x01)          /*!< MPEG-1, 2 Audio */
22 #define ESP_A2D_MCT_M24         (0x02)          /*!< MPEG-2, 4 AAC */
23 #define ESP_A2D_MCT_ATRAC       (0x04)          /*!< ATRAC family */
24 #define ESP_A2D_MCT_NON_A2DP    (0xff)          /*!< NON-A2DP */
25 typedef uint8_t esp_a2d_mct_t;
26 
27 /**
28  * @brief Protocol service capabilities. This value is a mask.
29  */
30 #define ESP_A2D_PSC_DELAY_RPT          (1<<0)  /*!< Delay Report */
31 typedef uint16_t esp_a2d_psc_t;
32 
33 /**
34  * @brief A2DP media codec capabilities union
35  */
36 typedef struct {
37     esp_a2d_mct_t type;                        /*!< A2DP media codec type */
38 #define ESP_A2D_CIE_LEN_SBC          (4)
39 #define ESP_A2D_CIE_LEN_M12          (4)
40 #define ESP_A2D_CIE_LEN_M24          (6)
41 #define ESP_A2D_CIE_LEN_ATRAC        (7)
42     union {
43         uint8_t sbc[ESP_A2D_CIE_LEN_SBC];      /*!< SBC codec capabilities */
44         uint8_t m12[ESP_A2D_CIE_LEN_M12];      /*!< MPEG-1,2 audio codec capabilities */
45         uint8_t m24[ESP_A2D_CIE_LEN_M24];      /*!< MPEG-2, 4 AAC audio codec capabilities */
46         uint8_t atrac[ESP_A2D_CIE_LEN_ATRAC];  /*!< ATRAC family codec capabilities */
47     } cie;                                     /*!< A2DP codec information element */
48 } __attribute__((packed)) esp_a2d_mcc_t;
49 
50 /**
51  * @brief Bluetooth A2DP connection states
52  */
53 typedef enum {
54     ESP_A2D_CONNECTION_STATE_DISCONNECTED = 0, /*!< connection released  */
55     ESP_A2D_CONNECTION_STATE_CONNECTING,       /*!< connecting remote device */
56     ESP_A2D_CONNECTION_STATE_CONNECTED,        /*!< connection established */
57     ESP_A2D_CONNECTION_STATE_DISCONNECTING     /*!< disconnecting remote device */
58 } esp_a2d_connection_state_t;
59 
60 /**
61  * @brief Bluetooth A2DP disconnection reason
62  */
63 typedef enum {
64     ESP_A2D_DISC_RSN_NORMAL = 0,               /*!< Finished disconnection that is initiated by local or remote device */
65     ESP_A2D_DISC_RSN_ABNORMAL                  /*!< Abnormal disconnection caused by signal loss */
66 } esp_a2d_disc_rsn_t;
67 
68 /**
69  * @brief Bluetooth A2DP datapath states
70  */
71 typedef enum {
72     ESP_A2D_AUDIO_STATE_REMOTE_SUSPEND = 0,    /*!< audio stream datapath suspended by remote device */
73     ESP_A2D_AUDIO_STATE_STOPPED,               /*!< audio stream datapath stopped */
74     ESP_A2D_AUDIO_STATE_STARTED,               /*!< audio stream datapath started */
75 } esp_a2d_audio_state_t;
76 
77 /**
78  * @brief A2DP media control command acknowledgement code
79  */
80 typedef enum {
81     ESP_A2D_MEDIA_CTRL_ACK_SUCCESS = 0,        /*!< media control command is acknowledged with success */
82     ESP_A2D_MEDIA_CTRL_ACK_FAILURE,            /*!< media control command is acknowledged with failure */
83     ESP_A2D_MEDIA_CTRL_ACK_BUSY,               /*!< media control command is rejected, as previous command is not yet acknowledged */
84 } esp_a2d_media_ctrl_ack_t;
85 
86 /**
87  * @brief A2DP media control commands
88  */
89 typedef enum {
90     ESP_A2D_MEDIA_CTRL_NONE = 0,               /*!< Not for application use, use inside stack only. */
91     ESP_A2D_MEDIA_CTRL_CHECK_SRC_RDY,          /*!< check whether AVDTP is connected, only used in A2DP source */
92     ESP_A2D_MEDIA_CTRL_START,                  /*!< command to set up media transmission channel */
93     ESP_A2D_MEDIA_CTRL_STOP,                   /*!< command to stop media transmission */
94     ESP_A2D_MEDIA_CTRL_SUSPEND,                /*!< command to suspend media transmission  */
95 } esp_a2d_media_ctrl_t;
96 
97 /**
98  * @brief Bluetooth A2DP Initiation states
99  */
100 typedef enum {
101     ESP_A2D_DEINIT_SUCCESS = 0,                /*!< A2DP profile deinit successful event */
102     ESP_A2D_INIT_SUCCESS                       /*!< A2DP profile deinit successful event */
103 } esp_a2d_init_state_t;
104 
105 /**
106  * @brief Bluetooth A2DP set delay report value states
107  */
108 typedef enum {
109     ESP_A2D_SET_SUCCESS = 0,                /*!< A2DP profile set delay report value successful */
110     ESP_A2D_SET_INVALID_PARAMS              /*!< A2DP profile set delay report value is invalid parameter */
111 } esp_a2d_set_delay_value_state_t;
112 
113 /**
114  * @brief A2DP callback events
115  */
116 typedef enum {
117     ESP_A2D_CONNECTION_STATE_EVT = 0,          /*!< connection state changed event */
118     ESP_A2D_AUDIO_STATE_EVT,                   /*!< audio stream transmission state changed event */
119     ESP_A2D_AUDIO_CFG_EVT,                     /*!< audio codec is configured, only used for A2DP SINK */
120     ESP_A2D_MEDIA_CTRL_ACK_EVT,                /*!< acknowledge event in response to media control commands */
121     ESP_A2D_PROF_STATE_EVT,                    /*!< indicate a2dp init&deinit complete */
122     ESP_A2D_SNK_PSC_CFG_EVT,                   /*!< protocol service capabilities configured,only used for A2DP SINK */
123     ESP_A2D_SNK_SET_DELAY_VALUE_EVT,           /*!< indicate a2dp sink set delay report value complete,  only used for A2DP SINK */
124     ESP_A2D_SNK_GET_DELAY_VALUE_EVT,           /*!< indicate a2dp sink get delay report value complete,  only used for A2DP SINK */
125     ESP_A2D_REPORT_SNK_DELAY_VALUE_EVT,        /*!< report delay value,  only used for A2DP SRC */
126 } esp_a2d_cb_event_t;
127 
128 /**
129  * @brief A2DP state callback parameters
130  */
131 typedef union {
132     /**
133      * @brief  ESP_A2D_CONNECTION_STATE_EVT
134      */
135     struct a2d_conn_stat_param {
136         esp_a2d_connection_state_t state;      /*!< one of values from esp_a2d_connection_state_t */
137         esp_bd_addr_t remote_bda;              /*!< remote bluetooth device address */
138         esp_a2d_disc_rsn_t disc_rsn;           /*!< reason of disconnection for "DISCONNECTED" */
139     } conn_stat;                               /*!< A2DP connection status */
140 
141     /**
142      * @brief ESP_A2D_AUDIO_STATE_EVT
143      */
144     struct a2d_audio_stat_param {
145         esp_a2d_audio_state_t state;           /*!< one of the values from esp_a2d_audio_state_t */
146         esp_bd_addr_t remote_bda;              /*!< remote bluetooth device address */
147     } audio_stat;                              /*!< audio stream playing state */
148 
149     /**
150      * @brief ESP_A2D_AUDIO_CFG_EVT
151      */
152     struct a2d_audio_cfg_param {
153         esp_bd_addr_t remote_bda;              /*!< remote bluetooth device address */
154         esp_a2d_mcc_t mcc;                     /*!< A2DP media codec capability information */
155     } audio_cfg;                               /*!< media codec configuration information */
156 
157     /**
158      * @brief ESP_A2D_MEDIA_CTRL_ACK_EVT
159      */
160     struct media_ctrl_stat_param {
161         esp_a2d_media_ctrl_t cmd;              /*!< media control commands to acknowledge */
162         esp_a2d_media_ctrl_ack_t status;       /*!< acknowledgement to media control commands */
163     } media_ctrl_stat;                         /*!< status in acknowledgement to media control commands */
164 
165     /**
166      * @brief ESP_A2D_PROF_STATE_EVT
167      */
168     struct a2d_prof_stat_param {
169         esp_a2d_init_state_t init_state;       /*!< a2dp profile state param */
170     } a2d_prof_stat;                           /*!< status to indicate a2d prof init or deinit */
171 
172     /**
173      * @brief ESP_A2D_SNK_PSC_CFG_EVT
174      */
175     struct a2d_psc_cfg_param {
176         esp_a2d_psc_t psc_mask;                /*!< protocol service capabilities configured */
177     } a2d_psc_cfg_stat;                        /*!< status to indicate protocol service capabilities configured */
178 
179     /**
180      * @brief ESP_A2D_SNK_SET_DELAY_VALUE_EVT
181      */
182     struct a2d_set_stat_param {
183         esp_a2d_set_delay_value_state_t set_state;       /*!< a2dp profile state param */
184         uint16_t delay_value;                            /*!< delay report value */
185     } a2d_set_delay_value_stat;                          /*!< A2DP sink set delay report value status */
186 
187     /**
188      * @brief ESP_A2D_SNK_GET_DELAY_VALUE_EVT
189      */
190     struct a2d_get_stat_param {
191         uint16_t delay_value;                  /*!< delay report value */
192     } a2d_get_delay_value_stat;                /*!< A2DP sink get delay report value status */
193 
194     /**
195      * @brief ESP_A2D_REPORT_SNK_DELAY_VALUE_EVT
196      */
197     struct a2d_report_delay_stat_param {
198         uint16_t delay_value;                  /*!< delay report value */
199     } a2d_report_delay_value_stat;             /*!< A2DP source received sink report value status */
200 
201 } esp_a2d_cb_param_t;
202 
203 /**
204  * @brief           A2DP profile callback function type
205  *
206  * @param           event : Event type
207  *
208  * @param           param : Pointer to callback parameter
209  */
210 typedef void (* esp_a2d_cb_t)(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param);
211 
212 /**
213  * @brief           A2DP sink data callback function
214  *
215  * @param[in]       buf : pointer to the data received from A2DP source device and is PCM format decoded from SBC decoder;
216  *                  buf references to a static memory block and can be overwritten by upcoming data
217  *
218  * @param[in]       len : size(in bytes) in buf
219  */
220 typedef void (* esp_a2d_sink_data_cb_t)(const uint8_t *buf, uint32_t len);
221 
222 /**
223  * @brief           A2DP source data read callback function
224  *
225  * @param[in]       buf : buffer to be filled with PCM data stream from higher layer
226  *
227  * @param[in]       len : size(in bytes) of data block to be copied to buf. -1 is an indication to user
228  *                  that data buffer shall be flushed
229  *
230  * @return          size of bytes read successfully, if the argument len is -1, this value is ignored.
231  *
232  */
233 typedef int32_t (* esp_a2d_source_data_cb_t)(uint8_t *buf, int32_t len);
234 
235 /**
236  * @brief           Register application callback function to A2DP module. This function should be called
237  *                  only after esp_bluedroid_enable() completes successfully, used by both A2DP source
238  *                  and sink.
239  *
240  * @param[in]       callback: A2DP event callback function
241  *
242  * @return
243  *                  - ESP_OK: success
244  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
245  *                  - ESP_FAIL: if callback is a NULL function pointer
246  *
247  */
248 esp_err_t esp_a2d_register_callback(esp_a2d_cb_t callback);
249 
250 
251 /**
252  * @brief           Register A2DP sink data output function; For now the output is PCM data stream decoded
253  *                  from SBC format. This function should be called only after esp_bluedroid_enable()
254  *                  completes successfully, used only by A2DP sink. The callback is invoked in the context
255  *                  of A2DP sink task whose stack size is configurable through menuconfig.
256  *
257  * @param[in]       callback: A2DP sink data callback function
258  *
259  * @return
260  *                  - ESP_OK: success
261  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
262  *                  - ESP_FAIL: if callback is a NULL function pointer
263  *
264  */
265 esp_err_t esp_a2d_sink_register_data_callback(esp_a2d_sink_data_cb_t callback);
266 
267 
268 /**
269  *
270  * @brief           Initialize the bluetooth A2DP sink module. This function should be called
271  *                  after esp_bluedroid_enable() completes successfully, and ESP_A2D_PROF_STATE_EVT
272  *                  with ESP_A2D_INIT_SUCCESS will reported to the APP layer. Note: A2DP can work independently.
273  *                  If you want to use AVRC together, you should initiate AVRC first. This
274  *                  function should be called after esp_bluedroid_enable() completes successfully.
275  *
276  * @return
277  *                  - ESP_OK: if the initialization request is sent successfully
278  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
279  *                  - ESP_FAIL: others
280  *
281  */
282 esp_err_t esp_a2d_sink_init(void);
283 
284 
285 /**
286  *
287  * @brief           De-initialize for A2DP sink module. This function
288  *                  should be called only after esp_bluedroid_enable() completes successfully,
289  *                  and ESP_A2D_PROF_STATE_EVT with ESP_A2D_DEINIT_SUCCESS will reported to APP layer.
290  *
291  * @return
292  *                  - ESP_OK: if the deinitialization request is sent successfully
293  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
294  *                  - ESP_FAIL: others
295  *
296  */
297 esp_err_t esp_a2d_sink_deinit(void);
298 
299 
300 /**
301  *
302  * @brief           Connect to remote bluetooth A2DP source device. This API must be called after
303  *                  esp_a2d_sink_init() and before esp_a2d_sink_deinit().
304  *
305  * @param[in]       remote_bda: remote bluetooth device address
306  *
307  * @return
308  *                  - ESP_OK: connect request is sent to lower layer successfully
309  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
310  *                  - ESP_FAIL: others
311  *
312  */
313 esp_err_t esp_a2d_sink_connect(esp_bd_addr_t remote_bda);
314 
315 
316 /**
317  *
318  * @brief           Disconnect from the remote A2DP source device. This API must be called after
319  *                  esp_a2d_sink_init() and before esp_a2d_sink_deinit().
320  *
321  * @param[in]       remote_bda: remote bluetooth device address
322  *
323  * @return
324  *                  - ESP_OK: disconnect request is sent to lower layer successfully
325  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
326  *                  - ESP_FAIL: others
327  *
328  */
329 esp_err_t esp_a2d_sink_disconnect(esp_bd_addr_t remote_bda);
330 
331 /**
332  *
333  * @brief           Set delay reporting value. The delay value of sink is caused by buffering (including
334  *                  protocol stack and application layer), decoding and rendering. The default delay
335  *                  value is 120ms, if the set value is less than 120ms, the setting will fail. This API
336  *                  must be called after esp_a2d_sink_init() and before esp_a2d_sink_deinit().
337  *
338  * @param[in]       delay_value: reporting value is in 1/10 millisecond
339  *
340  * @return
341  *                  - ESP_OK: delay value is sent to lower layer successfully
342  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
343  *                  - ESP_FAIL: others
344  *
345  */
346 esp_err_t esp_a2d_sink_set_delay_value(uint16_t delay_value);
347 
348 /**
349  *
350  * @brief           Get delay reporting value. This API must be called after
351  *                  esp_a2d_sink_init() and before esp_a2d_sink_deinit().
352  *
353  * @return
354  *                  - ESP_OK: if the request is sent successfully
355  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
356  *                  - ESP_FAIL: others
357  *
358  */
359 esp_err_t esp_a2d_sink_get_delay_value(void);
360 
361 
362 /**
363  *
364  * @brief           Media control commands. This API can be used for both A2DP sink and source
365  *                  and must be called after esp_a2d_sink_init() and before esp_a2d_sink_deinit().
366  *
367  * @param[in]       ctrl: control commands for A2DP data channel
368  *
369  * @return
370  *                  - ESP_OK: control command is sent to lower layer successfully
371  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
372  *                  - ESP_FAIL: others
373  *
374  */
375 esp_err_t esp_a2d_media_ctrl(esp_a2d_media_ctrl_t ctrl);
376 
377 
378 /**
379  *
380  * @brief           Initialize the bluetooth A2DP source module. A2DP can work independently.
381  *                  If you want to use AVRC together, you should initiate AVRC first. This function should be called
382  *                  after esp_bluedroid_enable() completes successfully, and ESP_A2D_PROF_STATE_EVT
383  *                  with ESP_A2D_INIT_SUCCESS will reported to the APP layer. Note: A2DP can work independently.
384  *                  If you want to use AVRC together, you should initiate AVRC first.
385  *
386  * @return
387  *                  - ESP_OK: if the initialization request is sent to lower layer successfully
388  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
389  *                  - ESP_FAIL: others
390  *
391  */
392 esp_err_t esp_a2d_source_init(void);
393 
394 
395 /**
396  *
397  * @brief           De-initialize for A2DP source module. This function
398  *                  should be called only after esp_bluedroid_enable() completes successfully,
399  *                  and ESP_A2D_PROF_STATE_EVT with ESP_A2D_DEINIT_SUCCESS will reported to APP layer.
400  *
401  * @return
402  *                  - ESP_OK: success
403  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
404  *                  - ESP_FAIL: others
405  *
406  */
407 esp_err_t esp_a2d_source_deinit(void);
408 
409 
410 /**
411  * @brief           Register A2DP source data input function. For now, the input shoule be PCM data stream.
412  *                  This function should be called only after esp_bluedroid_enable() completes
413  *                  successfully. The callback is invoked in the context of A2DP source task whose
414  *                  stack size is configurable through menuconfig.
415  *
416  * @param[in]       callback: A2DP source data callback function
417  *
418  * @return
419  *                  - ESP_OK: success
420  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
421  *                  - ESP_FAIL: if callback is a NULL function pointer
422  *
423  */
424 esp_err_t esp_a2d_source_register_data_callback(esp_a2d_source_data_cb_t callback);
425 
426 
427 /**
428  *
429  * @brief           Connect to remote A2DP sink device. This API must be called
430  *                  after esp_a2d_source_init() and before esp_a2d_source_deinit().
431  *
432  * @param[in]       remote_bda: remote bluetooth device address
433  *
434  * @return
435  *                  - ESP_OK: connect request is sent to lower layer successfully
436  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
437  *                  - ESP_FAIL: others
438  *
439  */
440 esp_err_t esp_a2d_source_connect(esp_bd_addr_t remote_bda);
441 
442 
443 /**
444  *
445  * @brief           Disconnect from the remote A2DP sink device. This API must be called
446  *                  after esp_a2d_source_init() and before esp_a2d_source_deinit().
447  *
448  * @param[in]       remote_bda: remote bluetooth device address
449  * @return
450  *                  - ESP_OK: disconnect request is sent to lower layer
451  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
452  *                  - ESP_FAIL: others
453  *
454  */
455 esp_err_t esp_a2d_source_disconnect(esp_bd_addr_t remote_bda);
456 
457 #ifdef __cplusplus
458 }
459 #endif
460 
461 
462 #endif /* __ESP_A2DP_API_H__ */
463