1 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef __ESP_A2DP_API_H__
16 #define __ESP_A2DP_API_H__
17 
18 #include "esp_err.h"
19 #include "esp_bt_defs.h"
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 /// Media codec types supported by A2DP
26 #define ESP_A2D_MCT_SBC         (0)             /*!< SBC */
27 #define ESP_A2D_MCT_M12         (0x01)          /*!< MPEG-1, 2 Audio */
28 #define ESP_A2D_MCT_M24         (0x02)          /*!< MPEG-2, 4 AAC */
29 #define ESP_A2D_MCT_ATRAC       (0x04)          /*!< ATRAC family */
30 #define ESP_A2D_MCT_NON_A2DP    (0xff)
31 
32 typedef uint8_t esp_a2d_mct_t;
33 
34 /** 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 /// Bluetooth A2DP connection states
51 typedef enum {
52     ESP_A2D_CONNECTION_STATE_DISCONNECTED = 0, /*!< connection released  */
53     ESP_A2D_CONNECTION_STATE_CONNECTING,       /*!< connecting remote device */
54     ESP_A2D_CONNECTION_STATE_CONNECTED,        /*!< connection established */
55     ESP_A2D_CONNECTION_STATE_DISCONNECTING     /*!< disconnecting remote device */
56 } esp_a2d_connection_state_t;
57 
58 /// Bluetooth A2DP disconnection reason
59 typedef enum {
60     ESP_A2D_DISC_RSN_NORMAL = 0,               /*!< Finished disconnection that is initiated by local or remote device */
61     ESP_A2D_DISC_RSN_ABNORMAL                  /*!< Abnormal disconnection caused by signal loss */
62 } esp_a2d_disc_rsn_t;
63 
64 /// Bluetooth A2DP datapath states
65 typedef enum {
66     ESP_A2D_AUDIO_STATE_REMOTE_SUSPEND = 0,    /*!< audio stream datapath suspended by remote device */
67     ESP_A2D_AUDIO_STATE_STOPPED,               /*!< audio stream datapath stopped */
68     ESP_A2D_AUDIO_STATE_STARTED,               /*!< audio stream datapath started */
69 } esp_a2d_audio_state_t;
70 
71 /// A2DP media control command acknowledgement code
72 typedef enum {
73     ESP_A2D_MEDIA_CTRL_ACK_SUCCESS = 0,        /*!< media control command is acknowledged with success */
74     ESP_A2D_MEDIA_CTRL_ACK_FAILURE,            /*!< media control command is acknowledged with failure */
75     ESP_A2D_MEDIA_CTRL_ACK_BUSY,               /*!< media control command is rejected, as previous command is not yet acknowledged */
76 } esp_a2d_media_ctrl_ack_t;
77 
78 /// A2DP media control commands
79 typedef enum {
80     ESP_A2D_MEDIA_CTRL_NONE = 0,               /*!< Not for application use, use inside stack only. */
81     ESP_A2D_MEDIA_CTRL_CHECK_SRC_RDY,          /*!< check whether AVDTP is connected, only used in A2DP source */
82     ESP_A2D_MEDIA_CTRL_START,                  /*!< command to set up media transmission channel */
83     ESP_A2D_MEDIA_CTRL_STOP,                   /*!< command to stop media transmission */
84     ESP_A2D_MEDIA_CTRL_SUSPEND,                /*!< command to suspend media transmission  */
85 } esp_a2d_media_ctrl_t;
86 
87 /// Bluetooth A2DP Initiation states
88 typedef enum {
89     ESP_A2D_DEINIT_SUCCESS = 0,                /*!< A2DP profile deinit successful event */
90     ESP_A2D_INIT_SUCCESS                       /*!< A2DP profile deinit successful event */
91 } esp_a2d_init_state_t;
92 
93 /// A2DP callback events
94 typedef enum {
95     ESP_A2D_CONNECTION_STATE_EVT = 0,          /*!< connection state changed event */
96     ESP_A2D_AUDIO_STATE_EVT,                   /*!< audio stream transmission state changed event */
97     ESP_A2D_AUDIO_CFG_EVT,                     /*!< audio codec is configured, only used for A2DP SINK */
98     ESP_A2D_MEDIA_CTRL_ACK_EVT,                /*!< acknowledge event in response to media control commands */
99     ESP_A2D_PROF_STATE_EVT,                    /*!< indicate a2dp init&deinit complete */
100 } esp_a2d_cb_event_t;
101 
102 /// A2DP state callback parameters
103 typedef union {
104     /**
105      * @brief  ESP_A2D_CONNECTION_STATE_EVT
106      */
107     struct a2d_conn_stat_param {
108         esp_a2d_connection_state_t state;      /*!< one of values from esp_a2d_connection_state_t */
109         esp_bd_addr_t remote_bda;              /*!< remote bluetooth device address */
110         esp_a2d_disc_rsn_t disc_rsn;           /*!< reason of disconnection for "DISCONNECTED" */
111     } conn_stat;                               /*!< A2DP connection status */
112 
113     /**
114      * @brief ESP_A2D_AUDIO_STATE_EVT
115      */
116     struct a2d_audio_stat_param {
117         esp_a2d_audio_state_t state;           /*!< one of the values from esp_a2d_audio_state_t */
118         esp_bd_addr_t remote_bda;              /*!< remote bluetooth device address */
119     } audio_stat;                              /*!< audio stream playing state */
120 
121     /**
122      * @brief ESP_A2D_AUDIO_CFG_EVT
123      */
124     struct a2d_audio_cfg_param {
125         esp_bd_addr_t remote_bda;              /*!< remote bluetooth device address */
126         esp_a2d_mcc_t mcc;                     /*!< A2DP media codec capability information */
127     } audio_cfg;                               /*!< media codec configuration information */
128 
129     /**
130      * @brief ESP_A2D_MEDIA_CTRL_ACK_EVT
131      */
132     struct media_ctrl_stat_param {
133         esp_a2d_media_ctrl_t cmd;              /*!< media control commands to acknowledge */
134         esp_a2d_media_ctrl_ack_t status;       /*!< acknowledgement to media control commands */
135     } media_ctrl_stat;                         /*!< status in acknowledgement to media control commands */
136     /**
137      * @brief ESP_A2D_PROF_STATE_EVT
138      */
139     struct a2d_prof_stat_param {
140         esp_a2d_init_state_t init_state;       /*!< a2dp profile state param */
141     } a2d_prof_stat;                           /*!< status to indicate a2d prof init or deinit */
142 } esp_a2d_cb_param_t;
143 
144 /**
145  * @brief           A2DP profile callback function type
146  *
147  * @param           event : Event type
148  *
149  * @param           param : Pointer to callback parameter
150  */
151 typedef void (* esp_a2d_cb_t)(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param);
152 
153 /**
154  * @brief           A2DP sink data callback function
155  *
156  * @param[in]       buf : pointer to the data received from A2DP source device and is PCM format decoded from SBC decoder;
157  *                  buf references to a static memory block and can be overwritten by upcoming data
158  *
159  * @param[in]       len : size(in bytes) in buf
160  */
161 typedef void (* esp_a2d_sink_data_cb_t)(const uint8_t *buf, uint32_t len);
162 
163 /**
164  * @brief           A2DP source data read callback function
165  *
166  * @param[in]       buf : buffer to be filled with PCM data stream from higher layer
167  *
168  * @param[in]       len : size(in bytes) of data block to be copied to buf. -1 is an indication to user
169  *                  that data buffer shall be flushed
170  *
171  * @return          size of bytes read successfully, if the argument len is -1, this value is ignored.
172  *
173  */
174 typedef int32_t (* esp_a2d_source_data_cb_t)(uint8_t *buf, int32_t len);
175 
176 /**
177  * @brief           Register application callback function to A2DP module. This function should be called
178  *                  only after esp_bluedroid_enable() completes successfully, used by both A2DP source
179  *                  and sink.
180  *
181  * @param[in]       callback: A2DP event callback function
182  *
183  * @return
184  *                  - ESP_OK: success
185  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
186  *                  - ESP_FAIL: if callback is a NULL function pointer
187  *
188  */
189 esp_err_t esp_a2d_register_callback(esp_a2d_cb_t callback);
190 
191 
192 /**
193  * @brief           Register A2DP sink data output function; For now the output is PCM data stream decoded
194  *                  from SBC format. This function should be called only after esp_bluedroid_enable()
195  *                  completes successfully, used only by A2DP sink. The callback is invoked in the context
196  *                  of A2DP sink task whose stack size is configurable through menuconfig.
197  *
198  * @param[in]       callback: A2DP sink data callback function
199  *
200  * @return
201  *                  - ESP_OK: success
202  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
203  *                  - ESP_FAIL: if callback is a NULL function pointer
204  *
205  */
206 esp_err_t esp_a2d_sink_register_data_callback(esp_a2d_sink_data_cb_t callback);
207 
208 
209 /**
210  *
211  * @brief           Initialize the bluetooth A2DP sink module. This function should be called
212  *                  after esp_bluedroid_enable() completes successfully, and ESP_A2D_PROF_STATE_EVT
213  *                  with ESP_A2D_INIT_SUCCESS will reported to the APP layer. Note: A2DP can work independently.
214  *                  If you want to use AVRC together, you should initiate AVRC first. This
215  *                  function should be called after esp_bluedroid_enable() completes successfully.
216  *
217  * @return
218  *                  - ESP_OK: if the initialization request is sent successfully
219  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
220  *                  - ESP_FAIL: others
221  *
222  */
223 esp_err_t esp_a2d_sink_init(void);
224 
225 
226 /**
227  *
228  * @brief           De-initialize for A2DP sink module. This function
229  *                  should be called only after esp_bluedroid_enable() completes successfully,
230  *                  and ESP_A2D_PROF_STATE_EVT with ESP_A2D_DEINIT_SUCCESS will reported to APP layer.
231  *
232  * @return
233  *                  - ESP_OK: if the deinitialization request is sent successfully
234  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
235  *                  - ESP_FAIL: others
236  *
237  */
238 esp_err_t esp_a2d_sink_deinit(void);
239 
240 
241 /**
242  *
243  * @brief           Connect to remote bluetooth A2DP source device. This API must be called after
244  *                  esp_a2d_sink_init() and before esp_a2d_sink_deinit().
245  *
246  * @param[in]       remote_bda: remote bluetooth device address
247  *
248  * @return
249  *                  - ESP_OK: connect request is sent to lower layer successfully
250  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
251  *                  - ESP_FAIL: others
252  *
253  */
254 esp_err_t esp_a2d_sink_connect(esp_bd_addr_t remote_bda);
255 
256 
257 /**
258  *
259  * @brief           Disconnect from the remote A2DP source device. This API must be called after
260  *                  esp_a2d_sink_init() and before esp_a2d_sink_deinit().
261  *
262  * @param[in]       remote_bda: remote bluetooth device address
263  *
264  * @return
265  *                  - ESP_OK: disconnect request is sent to lower layer successfully
266  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
267  *                  - ESP_FAIL: others
268  *
269  */
270 esp_err_t esp_a2d_sink_disconnect(esp_bd_addr_t remote_bda);
271 
272 
273 /**
274  *
275  * @brief           Media control commands. This API can be used for both A2DP sink and source
276  *                  and must be called after esp_a2d_sink_init() and before esp_a2d_sink_deinit().
277  *
278  * @param[in]       ctrl: control commands for A2DP data channel
279  *
280  * @return
281  *                  - ESP_OK: control command is sent to lower layer successfully
282  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
283  *                  - ESP_FAIL: others
284  *
285  */
286 esp_err_t esp_a2d_media_ctrl(esp_a2d_media_ctrl_t ctrl);
287 
288 
289 /**
290  *
291  * @brief           Initialize the bluetooth A2DP source module. A2DP can work independently.
292  *                  If you want to use AVRC together, you should initiate AVRC first. This function should be called
293  *                  after esp_bluedroid_enable() completes successfully, and ESP_A2D_PROF_STATE_EVT
294  *                  with ESP_A2D_INIT_SUCCESS will reported to the APP layer. Note: A2DP can work independently.
295  *                  If you want to use AVRC together, you should initiate AVRC first.
296  *
297  * @return
298  *                  - ESP_OK: if the initialization request is sent to lower layer successfully
299  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
300  *                  - ESP_FAIL: others
301  *
302  */
303 esp_err_t esp_a2d_source_init(void);
304 
305 
306 /**
307  *
308  * @brief           De-initialize for A2DP source module. This function
309  *                  should be called only after esp_bluedroid_enable() completes successfully,
310  *                  and ESP_A2D_PROF_STATE_EVT with ESP_A2D_DEINIT_SUCCESS will reported to APP layer.
311  *
312  * @return
313  *                  - ESP_OK: success
314  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
315  *                  - ESP_FAIL: others
316  *
317  */
318 esp_err_t esp_a2d_source_deinit(void);
319 
320 
321 /**
322  * @brief           Register A2DP source data input function. For now, the input shoule be PCM data stream.
323  *                  This function should be called only after esp_bluedroid_enable() completes
324  *                  successfully. The callback is invoked in the context of A2DP source task whose
325  *                  stack size is configurable through menuconfig.
326  *
327  * @param[in]       callback: A2DP source data callback function
328  *
329  * @return
330  *                  - ESP_OK: success
331  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
332  *                  - ESP_FAIL: if callback is a NULL function pointer
333  *
334  */
335 esp_err_t esp_a2d_source_register_data_callback(esp_a2d_source_data_cb_t callback);
336 
337 
338 /**
339  *
340  * @brief           Connect to remote A2DP sink device. This API must be called
341  *                  after esp_a2d_source_init() and before esp_a2d_source_deinit().
342  *
343  * @param[in]       remote_bda: remote bluetooth device address
344  *
345  * @return
346  *                  - ESP_OK: connect request is sent to lower layer successfully
347  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
348  *                  - ESP_FAIL: others
349  *
350  */
351 esp_err_t esp_a2d_source_connect(esp_bd_addr_t remote_bda);
352 
353 
354 /**
355  *
356  * @brief           Disconnect from the remote A2DP sink device. This API must be called
357  *                  after esp_a2d_source_init() and before esp_a2d_source_deinit().
358  *
359  * @param[in]       remote_bda: remote bluetooth device address
360  * @return
361  *                  - ESP_OK: disconnect request is sent to lower layer
362  *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
363  *                  - ESP_FAIL: others
364  *
365  */
366 esp_err_t esp_a2d_source_disconnect(esp_bd_addr_t remote_bda);
367 
368 #ifdef __cplusplus
369 }
370 #endif
371 
372 
373 #endif /* __ESP_A2DP_API_H__ */
374