1 // Copyright 2018 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 #include "common/bt_target.h"
16 #include <string.h>
17 #include "esp_err.h"
18 #include "esp_hf_client_api.h"
19 #include "esp_bt_main.h"
20 #include "btc/btc_manage.h"
21 #include "btc_hf_client.h"
22 #include "bta/bta_api.h"
23 #include "bta/bta_hf_client_api.h"
24 
25 #if BTC_HF_CLIENT_INCLUDED
esp_hf_client_register_callback(esp_hf_client_cb_t callback)26 esp_err_t esp_hf_client_register_callback(esp_hf_client_cb_t callback)
27 {
28     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
29         return ESP_ERR_INVALID_STATE;
30     }
31 
32     if (callback == NULL) {
33         return ESP_FAIL;
34     }
35 
36     btc_profile_cb_set(BTC_PID_HF_CLIENT, callback);
37     return ESP_OK;
38 }
39 
esp_hf_client_init(void)40 esp_err_t esp_hf_client_init(void)
41 {
42     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
43         return ESP_ERR_INVALID_STATE;
44     }
45 
46     btc_msg_t msg;
47 
48     msg.sig = BTC_SIG_API_CALL;
49     msg.pid = BTC_PID_HF_CLIENT;
50     msg.act = BTC_HF_CLIENT_INIT_EVT;
51 
52     /* Switch to BTC context */
53     bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
54     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
55 }
56 
esp_hf_client_deinit(void)57 esp_err_t esp_hf_client_deinit(void)
58 {
59     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
60         return ESP_ERR_INVALID_STATE;
61     }
62 
63     btc_msg_t msg;
64 
65     msg.sig = BTC_SIG_API_CALL;
66     msg.pid = BTC_PID_HF_CLIENT;
67     msg.act = BTC_HF_CLIENT_DEINIT_EVT;
68 
69     /* Switch to BTC context */
70     bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
71     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
72 }
73 
esp_hf_client_connect(esp_bd_addr_t remote_bda)74 esp_err_t esp_hf_client_connect(esp_bd_addr_t remote_bda)
75 {
76     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
77         return ESP_ERR_INVALID_STATE;
78     }
79 
80     bt_status_t stat;
81     btc_hf_client_args_t arg;
82     btc_msg_t msg;
83 
84     msg.sig = BTC_SIG_API_CALL;
85     msg.pid = BTC_PID_HF_CLIENT;
86     msg.act = BTC_HF_CLIENT_CONNECT_EVT;
87 
88     memset(&arg, 0, sizeof(btc_hf_client_args_t));
89 
90     /* Switch to BTC context */
91     memcpy(&(arg.connect), remote_bda, sizeof(bt_bdaddr_t));
92     stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
93     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
94 }
95 
esp_hf_client_disconnect(esp_bd_addr_t remote_bda)96 esp_err_t esp_hf_client_disconnect(esp_bd_addr_t remote_bda)
97 {
98     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
99         return ESP_ERR_INVALID_STATE;
100     }
101 
102     bt_status_t stat;
103     btc_hf_client_args_t arg;
104     btc_msg_t msg;
105 
106     msg.sig = BTC_SIG_API_CALL;
107     msg.pid = BTC_PID_HF_CLIENT;
108     msg.act = BTC_HF_CLIENT_DISCONNECT_EVT;
109 
110     memset(&arg, 0, sizeof(btc_hf_client_args_t));
111 
112     /* Switch to BTC context */
113     memcpy(&(arg.disconnect), remote_bda, sizeof(bt_bdaddr_t));
114     stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
115     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
116 }
117 
esp_hf_client_connect_audio(esp_bd_addr_t remote_bda)118 esp_err_t esp_hf_client_connect_audio(esp_bd_addr_t remote_bda)
119 {
120     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
121         return ESP_ERR_INVALID_STATE;
122     }
123 
124     bt_status_t stat;
125     btc_hf_client_args_t arg;
126     btc_msg_t msg;
127 
128     msg.sig = BTC_SIG_API_CALL;
129     msg.pid = BTC_PID_HF_CLIENT;
130     msg.act = BTC_HF_CLIENT_CONNECT_AUDIO_EVT;
131 
132     memset(&arg, 0, sizeof(btc_hf_client_args_t));
133 
134     /* Switch to BTC context */
135     memcpy(&(arg.connect_audio), remote_bda, sizeof(bt_bdaddr_t));
136     stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
137     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
138 }
139 
esp_hf_client_disconnect_audio(esp_bd_addr_t remote_bda)140 esp_err_t esp_hf_client_disconnect_audio(esp_bd_addr_t remote_bda)
141 {
142     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
143         return ESP_ERR_INVALID_STATE;
144     }
145 
146     bt_status_t stat;
147     btc_hf_client_args_t arg;
148     btc_msg_t msg;
149 
150     msg.sig = BTC_SIG_API_CALL;
151     msg.pid = BTC_PID_HF_CLIENT;
152     msg.act = BTC_HF_CLIENT_DISCONNECT_AUDIO_EVT;
153 
154     memset(&arg, 0, sizeof(btc_hf_client_args_t));
155 
156     /* Switch to BTC context */
157     memcpy(&(arg.disconnect_audio), remote_bda, sizeof(bt_bdaddr_t));
158     stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
159     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
160 }
161 
162 
esp_hf_client_start_voice_recognition(void)163 esp_err_t esp_hf_client_start_voice_recognition(void)
164 {
165     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
166         return ESP_ERR_INVALID_STATE;
167     }
168 
169     btc_msg_t msg;
170 
171     msg.sig = BTC_SIG_API_CALL;
172     msg.pid = BTC_PID_HF_CLIENT;
173     msg.act = BTC_HF_CLIENT_START_VOICE_RECOGNITION_EVT;
174 
175     /* Switch to BTC context */
176     bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
177     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
178 }
179 
esp_hf_client_stop_voice_recognition(void)180 esp_err_t esp_hf_client_stop_voice_recognition(void)
181 {
182     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
183         return ESP_ERR_INVALID_STATE;
184     }
185 
186     btc_msg_t msg;
187 
188     msg.sig = BTC_SIG_API_CALL;
189     msg.pid = BTC_PID_HF_CLIENT;
190     msg.act = BTC_HF_CLIENT_STOP_VOICE_RECOGNITION_EVT;
191 
192     /* Switch to BTC context */
193     bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
194     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
195 }
196 
esp_hf_client_volume_update(esp_hf_volume_control_target_t type,int volume)197 esp_err_t esp_hf_client_volume_update(esp_hf_volume_control_target_t type, int volume)
198 {
199     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
200         return ESP_ERR_INVALID_STATE;
201     }
202 
203     btc_msg_t msg;
204     btc_hf_client_args_t arg;
205 
206     msg.sig = BTC_SIG_API_CALL;
207     msg.pid = BTC_PID_HF_CLIENT;
208     msg.act = BTC_HF_CLIENT_VOLUME_UPDATE_EVT;
209 
210     memset(&arg, 0, sizeof(btc_hf_client_args_t));
211     arg.volume_update.type = type;
212     arg.volume_update.volume = volume;
213 
214     /* Switch to BTC context */
215     bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
216     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
217 }
218 
esp_hf_client_dial(const char * number)219 esp_err_t esp_hf_client_dial(const char *number)
220 {
221     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
222         return ESP_ERR_INVALID_STATE;
223     }
224 
225     btc_msg_t msg;
226     btc_hf_client_args_t arg;
227 
228     if (number != NULL && strlen(number) > ESP_BT_HF_CLIENT_NUMBER_LEN) {
229         return ESP_ERR_INVALID_ARG;
230     }
231 
232     msg.sig = BTC_SIG_API_CALL;
233     msg.pid = BTC_PID_HF_CLIENT;
234     msg.act = BTC_HF_CLIENT_DIAL_EVT;
235 
236     memset(&arg, 0, sizeof(btc_hf_client_args_t));
237     if (number != NULL) {
238         strcpy(arg.dial.number, number);
239     } else {
240         arg.dial.number[0] = '\0';
241     }
242 
243     /* Switch to BTC context */
244     bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
245     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
246 }
247 
esp_hf_client_dial_memory(int location)248 esp_err_t esp_hf_client_dial_memory(int location)
249 {
250     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
251         return ESP_ERR_INVALID_STATE;
252     }
253 
254     btc_msg_t msg;
255     btc_hf_client_args_t arg;
256 
257     msg.sig = BTC_SIG_API_CALL;
258     msg.pid = BTC_PID_HF_CLIENT;
259     msg.act = BTC_HF_CLIENT_DIAL_MEMORY_EVT;
260 
261     memset(&arg, 0, sizeof(btc_hf_client_args_t));
262     arg.dial_memory.location = location;
263 
264     /* Switch to BTC context */
265     bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
266     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
267 }
268 
esp_hf_client_send_chld_cmd(esp_hf_chld_type_t chld,int idx)269 esp_err_t esp_hf_client_send_chld_cmd(esp_hf_chld_type_t chld, int idx)
270 {
271     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
272         return ESP_ERR_INVALID_STATE;
273     }
274 
275     btc_msg_t msg;
276     btc_hf_client_args_t arg;
277 
278     msg.sig = BTC_SIG_API_CALL;
279     msg.pid = BTC_PID_HF_CLIENT;
280     msg.act = BTC_HF_CLIENT_SEND_CHLD_CMD_EVT;
281 
282     memset(&arg, 0, sizeof(btc_hf_client_args_t));
283     arg.chld.type = chld;
284     arg.chld.idx = idx;
285 
286     /* Switch to BTC context */
287     bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
288     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
289 }
290 
esp_hf_client_send_btrh_cmd(esp_hf_btrh_cmd_t btrh)291 esp_err_t esp_hf_client_send_btrh_cmd(esp_hf_btrh_cmd_t btrh)
292 {
293     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
294         return ESP_ERR_INVALID_STATE;
295     }
296 
297     btc_msg_t msg;
298     btc_hf_client_args_t arg;
299 
300     msg.sig = BTC_SIG_API_CALL;
301     msg.pid = BTC_PID_HF_CLIENT;
302     msg.act = BTC_HF_CLIENT_SEND_BTRH_CMD_EVT;
303 
304     memset(&arg, 0, sizeof(btc_hf_client_args_t));
305     arg.btrh.cmd = btrh;
306 
307     /* Switch to BTC context */
308     bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
309     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
310 }
311 
esp_hf_client_answer_call(void)312 esp_err_t esp_hf_client_answer_call(void)
313 {
314     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
315         return ESP_ERR_INVALID_STATE;
316     }
317 
318     btc_msg_t msg;
319 
320     msg.sig = BTC_SIG_API_CALL;
321     msg.pid = BTC_PID_HF_CLIENT;
322     msg.act = BTC_HF_CLIENT_ANSWER_CALL_EVT;
323 
324     /* Switch to BTC context */
325     bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
326     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
327 }
328 
esp_hf_client_reject_call(void)329 esp_err_t esp_hf_client_reject_call(void)
330 {
331     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
332         return ESP_ERR_INVALID_STATE;
333     }
334 
335     btc_msg_t msg;
336 
337     msg.sig = BTC_SIG_API_CALL;
338     msg.pid = BTC_PID_HF_CLIENT;
339     msg.act = BTC_HF_CLIENT_REJECT_CALL_EVT;
340 
341     /* Switch to BTC context */
342     bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
343     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
344 }
345 
esp_hf_client_query_current_calls(void)346 esp_err_t esp_hf_client_query_current_calls(void)
347 {
348     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
349         return ESP_ERR_INVALID_STATE;
350     }
351 
352     btc_msg_t msg;
353 
354     msg.sig = BTC_SIG_API_CALL;
355     msg.pid = BTC_PID_HF_CLIENT;
356     msg.act = BTC_HF_CLIENT_QUERY_CURRENT_CALLS_EVT;
357 
358     /* Switch to BTC context */
359     bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
360     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
361 }
362 
esp_hf_client_query_current_operator_name(void)363 esp_err_t esp_hf_client_query_current_operator_name(void)
364 {
365     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
366         return ESP_ERR_INVALID_STATE;
367     }
368 
369     btc_msg_t msg;
370 
371     msg.sig = BTC_SIG_API_CALL;
372     msg.pid = BTC_PID_HF_CLIENT;
373     msg.act = BTC_HF_CLIENT_QUERY_CURRENT_OPERATOR_NAME_EVT;
374 
375     /* Switch to BTC context */
376     bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
377     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
378 }
379 
esp_hf_client_retrieve_subscriber_info(void)380 esp_err_t esp_hf_client_retrieve_subscriber_info(void)
381 {
382     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
383         return ESP_ERR_INVALID_STATE;
384     }
385 
386     btc_msg_t msg;
387 
388     msg.sig = BTC_SIG_API_CALL;
389     msg.pid = BTC_PID_HF_CLIENT;
390     msg.act = BTC_HF_CLIENT_RETRIEVE_SUBSCRIBER_INFO_EVT;
391 
392     /* Switch to BTC context */
393     bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
394     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
395 }
396 
esp_hf_client_send_dtmf(char code)397 esp_err_t esp_hf_client_send_dtmf(char code)
398 {
399     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
400         return ESP_ERR_INVALID_STATE;
401     }
402 
403     btc_msg_t msg;
404     btc_hf_client_args_t arg;
405 
406     msg.sig = BTC_SIG_API_CALL;
407     msg.pid = BTC_PID_HF_CLIENT;
408     msg.act = BTC_HF_CLIENT_SEND_DTMF_EVT;
409 
410     memset(&arg, 0, sizeof(btc_hf_client_args_t));
411     arg.send_dtmf.code = code;
412 
413     /* Switch to BTC context */
414     bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
415     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
416 }
417 
esp_hf_client_request_last_voice_tag_number(void)418 esp_err_t esp_hf_client_request_last_voice_tag_number(void)
419 {
420     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
421         return ESP_ERR_INVALID_STATE;
422     }
423 
424     btc_msg_t msg;
425 
426     msg.sig = BTC_SIG_API_CALL;
427     msg.pid = BTC_PID_HF_CLIENT;
428     msg.act = BTC_HF_CLIENT_REQUEST_LAST_VOICE_TAG_NUMBER_EVT;
429 
430     /* Switch to BTC context */
431     bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
432     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
433 }
434 
esp_hf_client_send_nrec(void)435 esp_err_t esp_hf_client_send_nrec(void)
436 {
437     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
438         return ESP_ERR_INVALID_STATE;
439     }
440 
441     btc_msg_t msg;
442     msg.sig = BTC_SIG_API_CALL;
443     msg.pid = BTC_PID_HF_CLIENT;
444     msg.act = BTC_HF_CLIENT_SEND_NREC_EVT;
445 
446     /* Switch to BTC context */
447     bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
448     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
449 }
450 
esp_hf_client_register_data_callback(esp_hf_client_incoming_data_cb_t recv,esp_hf_client_outgoing_data_cb_t send)451 esp_err_t esp_hf_client_register_data_callback(esp_hf_client_incoming_data_cb_t recv,
452                                                esp_hf_client_outgoing_data_cb_t send)
453 {
454     if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
455         return ESP_ERR_INVALID_STATE;
456     }
457 
458     btc_msg_t msg;
459     msg.sig = BTC_SIG_API_CALL;
460     msg.pid = BTC_PID_HF_CLIENT;
461     msg.act = BTC_HF_CLIENT_REGISTER_DATA_CALLBACK_EVT;
462 
463     btc_hf_client_args_t arg;
464     memset(&arg, 0, sizeof(btc_hf_client_args_t));
465     arg.reg_data_cb.recv = recv;
466     arg.reg_data_cb.send = send;
467 
468     /* Switch to BTC context */
469     bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
470     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
471 }
472 
473 
474 #if (BTM_SCO_HCI_INCLUDED == TRUE )
esp_hf_client_outgoing_data_ready(void)475 void esp_hf_client_outgoing_data_ready(void)
476 {
477     BTA_HfClientCiData();
478 }
479 
esp_hf_client_pcm_resample_init(uint32_t src_sps,uint32_t bits,uint32_t channels)480 void esp_hf_client_pcm_resample_init(uint32_t src_sps, uint32_t bits, uint32_t channels)
481 {
482     BTA_DmPcmInitSamples(src_sps, bits, channels);
483 }
484 
esp_hf_client_pcm_resample_deinit(void)485 void esp_hf_client_pcm_resample_deinit(void)
486 {
487     BTA_DmPcmDeinitSamples();
488 }
489 
esp_hf_client_pcm_resample(void * src,uint32_t in_bytes,void * dst)490 int32_t esp_hf_client_pcm_resample(void *src, uint32_t in_bytes, void *dst)
491 {
492     return BTA_DmPcmResample(src, in_bytes, dst);
493 }
494 
495 #endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) */
496 
497 #endif /* BTC_HF_CLIENT_INCLUDED */
498