xref: /btstack/src/classic/hfp_hf.c (revision ce263fc8087b85d5dc9a00ecb73252242caf68b5)
13deb3ec6SMatthias Ringwald /*
23deb3ec6SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
33deb3ec6SMatthias Ringwald  *
43deb3ec6SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
53deb3ec6SMatthias Ringwald  * modification, are permitted provided that the following conditions
63deb3ec6SMatthias Ringwald  * are met:
73deb3ec6SMatthias Ringwald  *
83deb3ec6SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
93deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
103deb3ec6SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
113deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
123deb3ec6SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
133deb3ec6SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
143deb3ec6SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
153deb3ec6SMatthias Ringwald  *    from this software without specific prior written permission.
163deb3ec6SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
173deb3ec6SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
183deb3ec6SMatthias Ringwald  *    monetary gain.
193deb3ec6SMatthias Ringwald  *
203deb3ec6SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
213deb3ec6SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
223deb3ec6SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
233deb3ec6SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
243deb3ec6SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
253deb3ec6SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
263deb3ec6SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
273deb3ec6SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
283deb3ec6SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
293deb3ec6SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
303deb3ec6SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
313deb3ec6SMatthias Ringwald  * SUCH DAMAGE.
323deb3ec6SMatthias Ringwald  *
333deb3ec6SMatthias Ringwald  * Please inquire about commercial licensing options at
343deb3ec6SMatthias Ringwald  * [email protected]
353deb3ec6SMatthias Ringwald  *
363deb3ec6SMatthias Ringwald  */
373deb3ec6SMatthias Ringwald 
383deb3ec6SMatthias Ringwald // *****************************************************************************
393deb3ec6SMatthias Ringwald //
403deb3ec6SMatthias Ringwald // Minimal setup for HFP Hands-Free (HF) unit (!! UNDER DEVELOPMENT !!)
413deb3ec6SMatthias Ringwald //
423deb3ec6SMatthias Ringwald // *****************************************************************************
433deb3ec6SMatthias Ringwald 
443deb3ec6SMatthias Ringwald #include "btstack-config.h"
453deb3ec6SMatthias Ringwald 
463deb3ec6SMatthias Ringwald #include <stdint.h>
473deb3ec6SMatthias Ringwald #include <stdio.h>
483deb3ec6SMatthias Ringwald #include <stdlib.h>
493deb3ec6SMatthias Ringwald #include <string.h>
503deb3ec6SMatthias Ringwald 
513deb3ec6SMatthias Ringwald #include "hci_cmds.h"
523deb3ec6SMatthias Ringwald #include "run_loop.h"
533deb3ec6SMatthias Ringwald 
543deb3ec6SMatthias Ringwald #include "hci.h"
553deb3ec6SMatthias Ringwald #include "btstack_memory.h"
563deb3ec6SMatthias Ringwald #include "hci_dump.h"
573deb3ec6SMatthias Ringwald #include "l2cap.h"
583edc84c5SMatthias Ringwald #include "classic/sdp_query_rfcomm.h"
593edc84c5SMatthias Ringwald #include "classic/sdp.h"
603deb3ec6SMatthias Ringwald #include "debug.h"
613edc84c5SMatthias Ringwald #include "classic/hfp.h"
623edc84c5SMatthias Ringwald #include "classic/hfp_hf.h"
633deb3ec6SMatthias Ringwald 
643deb3ec6SMatthias Ringwald 
653deb3ec6SMatthias Ringwald static const char default_hfp_hf_service_name[] = "Hands-Free unit";
663deb3ec6SMatthias Ringwald static uint16_t hfp_supported_features = HFP_DEFAULT_HF_SUPPORTED_FEATURES;
673deb3ec6SMatthias Ringwald static uint8_t hfp_codecs_nr = 0;
683deb3ec6SMatthias Ringwald static uint8_t hfp_codecs[HFP_MAX_NUM_CODECS];
693deb3ec6SMatthias Ringwald 
703deb3ec6SMatthias Ringwald static uint8_t hfp_indicators_nr = 0;
713deb3ec6SMatthias Ringwald static uint8_t hfp_indicators[HFP_MAX_NUM_HF_INDICATORS];
723deb3ec6SMatthias Ringwald static uint8_t hfp_indicators_status;
733deb3ec6SMatthias Ringwald 
743deb3ec6SMatthias Ringwald static hfp_callback_t hfp_callback;
753deb3ec6SMatthias Ringwald 
76*ce263fc8SMatthias Ringwald static hfp_call_status_t hfp_call_status;
77*ce263fc8SMatthias Ringwald static hfp_callsetup_status_t hfp_callsetup_status;
78*ce263fc8SMatthias Ringwald static hfp_callheld_status_t hfp_callheld_status;
79*ce263fc8SMatthias Ringwald 
80*ce263fc8SMatthias Ringwald static char phone_number[25];
81*ce263fc8SMatthias Ringwald 
823deb3ec6SMatthias Ringwald void hfp_hf_register_packet_handler(hfp_callback_t callback){
833deb3ec6SMatthias Ringwald     hfp_callback = callback;
843deb3ec6SMatthias Ringwald     if (callback == NULL){
853deb3ec6SMatthias Ringwald         log_error("hfp_hf_register_packet_handler called with NULL callback");
863deb3ec6SMatthias Ringwald         return;
873deb3ec6SMatthias Ringwald     }
883deb3ec6SMatthias Ringwald     hfp_callback = callback;
893deb3ec6SMatthias Ringwald }
903deb3ec6SMatthias Ringwald 
913deb3ec6SMatthias Ringwald static int hfp_hf_supports_codec(uint8_t codec){
923deb3ec6SMatthias Ringwald     int i;
933deb3ec6SMatthias Ringwald     for (i = 0; i < hfp_codecs_nr; i++){
943deb3ec6SMatthias Ringwald         if (hfp_codecs[i] == codec) return 1;
953deb3ec6SMatthias Ringwald     }
96*ce263fc8SMatthias Ringwald     return HFP_CODEC_CVSD;
973deb3ec6SMatthias Ringwald }
983deb3ec6SMatthias Ringwald static int has_codec_negotiation_feature(hfp_connection_t * connection){
993deb3ec6SMatthias Ringwald     int hf = get_bit(hfp_supported_features, HFP_HFSF_CODEC_NEGOTIATION);
1003deb3ec6SMatthias Ringwald     int ag = get_bit(connection->remote_supported_features, HFP_AGSF_CODEC_NEGOTIATION);
1013deb3ec6SMatthias Ringwald     return hf && ag;
1023deb3ec6SMatthias Ringwald }
1033deb3ec6SMatthias Ringwald 
1043deb3ec6SMatthias Ringwald static int has_call_waiting_and_3way_calling_feature(hfp_connection_t * connection){
1053deb3ec6SMatthias Ringwald     int hf = get_bit(hfp_supported_features, HFP_HFSF_THREE_WAY_CALLING);
1063deb3ec6SMatthias Ringwald     int ag = get_bit(connection->remote_supported_features, HFP_AGSF_THREE_WAY_CALLING);
1073deb3ec6SMatthias Ringwald     return hf && ag;
1083deb3ec6SMatthias Ringwald }
1093deb3ec6SMatthias Ringwald 
1103deb3ec6SMatthias Ringwald 
1113deb3ec6SMatthias Ringwald static int has_hf_indicators_feature(hfp_connection_t * connection){
1123deb3ec6SMatthias Ringwald     int hf = get_bit(hfp_supported_features, HFP_HFSF_HF_INDICATORS);
1133deb3ec6SMatthias Ringwald     int ag = get_bit(connection->remote_supported_features, HFP_AGSF_HF_INDICATORS);
1143deb3ec6SMatthias Ringwald     return hf && ag;
1153deb3ec6SMatthias Ringwald }
1163deb3ec6SMatthias Ringwald 
117ffbf8201SMatthias Ringwald static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
1183deb3ec6SMatthias Ringwald 
1192ef54b27SMatthias Ringwald void hfp_hf_create_sdp_record(uint8_t * service, uint32_t service_record_handle, int rfcomm_channel_nr, const char * name, uint16_t supported_features){
1203deb3ec6SMatthias Ringwald     if (!name){
1213deb3ec6SMatthias Ringwald         name = default_hfp_hf_service_name;
1223deb3ec6SMatthias Ringwald     }
1232ef54b27SMatthias Ringwald     hfp_create_sdp_record(service, service_record_handle, SDP_Handsfree, rfcomm_channel_nr, name);
1243deb3ec6SMatthias Ringwald 
125aa4dd815SMatthias Ringwald     de_add_number(service, DE_UINT, DE_SIZE_16, 0x0311);    // Hands-Free Profile - SupportedFeatures
126aa4dd815SMatthias Ringwald     de_add_number(service, DE_UINT, DE_SIZE_16, supported_features);
127aa4dd815SMatthias Ringwald }
1283deb3ec6SMatthias Ringwald 
1293deb3ec6SMatthias Ringwald static int hfp_hf_cmd_exchange_supported_features(uint16_t cid){
1303deb3ec6SMatthias Ringwald     char buffer[20];
1313deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s=%d\r\n", HFP_SUPPORTED_FEATURES, hfp_supported_features);
1323deb3ec6SMatthias Ringwald     // printf("exchange_supported_features %s\n", buffer);
1333deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
1343deb3ec6SMatthias Ringwald }
1353deb3ec6SMatthias Ringwald 
1363deb3ec6SMatthias Ringwald static int hfp_hf_cmd_notify_on_codecs(uint16_t cid){
1373deb3ec6SMatthias Ringwald     char buffer[30];
1383deb3ec6SMatthias Ringwald     int offset = snprintf(buffer, sizeof(buffer), "AT%s=", HFP_AVAILABLE_CODECS);
1393deb3ec6SMatthias Ringwald     offset += join(buffer+offset, sizeof(buffer)-offset, hfp_codecs, hfp_codecs_nr);
1403deb3ec6SMatthias Ringwald     offset += snprintf(buffer+offset, sizeof(buffer)-offset, "\r\n");
1413deb3ec6SMatthias Ringwald     buffer[offset] = 0;
1423deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
1433deb3ec6SMatthias Ringwald }
1443deb3ec6SMatthias Ringwald 
1453deb3ec6SMatthias Ringwald static int hfp_hf_cmd_retrieve_indicators(uint16_t cid){
1463deb3ec6SMatthias Ringwald     char buffer[20];
1473deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s=?\r\n", HFP_INDICATOR);
1483deb3ec6SMatthias Ringwald     // printf("retrieve_indicators %s\n", buffer);
1493deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
1503deb3ec6SMatthias Ringwald }
1513deb3ec6SMatthias Ringwald 
1523deb3ec6SMatthias Ringwald static int hfp_hf_cmd_retrieve_indicators_status(uint16_t cid){
1533deb3ec6SMatthias Ringwald     char buffer[20];
1543deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s?\r\n", HFP_INDICATOR);
1553deb3ec6SMatthias Ringwald     // printf("retrieve_indicators_status %s\n", buffer);
1563deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
1573deb3ec6SMatthias Ringwald }
1583deb3ec6SMatthias Ringwald 
1593deb3ec6SMatthias Ringwald static int hfp_hf_cmd_activate_status_update_for_all_ag_indicators(uint16_t cid, uint8_t activate){
1603deb3ec6SMatthias Ringwald     char buffer[20];
1613deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s=3,0,0,%d\r\n", HFP_ENABLE_STATUS_UPDATE_FOR_AG_INDICATORS, activate);
1623deb3ec6SMatthias Ringwald     // printf("toggle_indicator_status_update %s\n", buffer);
1633deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
1643deb3ec6SMatthias Ringwald }
1653deb3ec6SMatthias Ringwald 
1663deb3ec6SMatthias Ringwald static int hfp_hf_cmd_activate_status_update_for_ag_indicator(uint16_t cid, uint32_t indicators_status, int indicators_nr){
1673deb3ec6SMatthias Ringwald     char buffer[50];
1683deb3ec6SMatthias Ringwald     int offset = snprintf(buffer, sizeof(buffer), "AT%s=", HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS);
1693deb3ec6SMatthias Ringwald     offset += join_bitmap(buffer+offset, sizeof(buffer)-offset, indicators_status, indicators_nr);
1703deb3ec6SMatthias Ringwald     offset += snprintf(buffer+offset, sizeof(buffer)-offset, "\r\n");
1713deb3ec6SMatthias Ringwald     buffer[offset] = 0;
1723deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
1733deb3ec6SMatthias Ringwald }
1743deb3ec6SMatthias Ringwald 
1753deb3ec6SMatthias Ringwald static int hfp_hf_cmd_retrieve_can_hold_call(uint16_t cid){
1763deb3ec6SMatthias Ringwald     char buffer[20];
1773deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s=?\r\n", HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES);
1783deb3ec6SMatthias Ringwald     // printf("retrieve_can_hold_call %s\n", buffer);
1793deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
1803deb3ec6SMatthias Ringwald }
1813deb3ec6SMatthias Ringwald 
1823deb3ec6SMatthias Ringwald static int hfp_hf_cmd_list_supported_generic_status_indicators(uint16_t cid){
1833deb3ec6SMatthias Ringwald     char buffer[30];
1843deb3ec6SMatthias Ringwald     int offset = snprintf(buffer, sizeof(buffer), "AT%s=", HFP_GENERIC_STATUS_INDICATOR);
1853deb3ec6SMatthias Ringwald     offset += join(buffer+offset, sizeof(buffer)-offset, hfp_indicators, hfp_indicators_nr);
1863deb3ec6SMatthias Ringwald     offset += snprintf(buffer+offset, sizeof(buffer)-offset, "\r\n");
1873deb3ec6SMatthias Ringwald     buffer[offset] = 0;
1883deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
1893deb3ec6SMatthias Ringwald }
1903deb3ec6SMatthias Ringwald 
1913deb3ec6SMatthias Ringwald static int hfp_hf_cmd_retrieve_supported_generic_status_indicators(uint16_t cid){
1923deb3ec6SMatthias Ringwald     char buffer[20];
1933deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s=?\r\n", HFP_GENERIC_STATUS_INDICATOR);
1943deb3ec6SMatthias Ringwald     // printf("retrieve_supported_generic_status_indicators %s\n", buffer);
1953deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
1963deb3ec6SMatthias Ringwald }
1973deb3ec6SMatthias Ringwald 
1983deb3ec6SMatthias Ringwald static int hfp_hf_cmd_list_initital_supported_generic_status_indicators(uint16_t cid){
1993deb3ec6SMatthias Ringwald     char buffer[20];
2003deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s?\r\n", HFP_GENERIC_STATUS_INDICATOR);
2013deb3ec6SMatthias Ringwald     // printf("list_initital_supported_generic_status_indicators %s\n", buffer);
2023deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
2033deb3ec6SMatthias Ringwald }
2043deb3ec6SMatthias Ringwald 
2053deb3ec6SMatthias Ringwald static int hfp_hf_cmd_query_operator_name_format(uint16_t cid){
2063deb3ec6SMatthias Ringwald     char buffer[20];
2073deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s=3,0\r\n", HFP_QUERY_OPERATOR_SELECTION);
2083deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
2093deb3ec6SMatthias Ringwald }
2103deb3ec6SMatthias Ringwald 
2113deb3ec6SMatthias Ringwald static int hfp_hf_cmd_query_operator_name(uint16_t cid){
2123deb3ec6SMatthias Ringwald     char buffer[20];
2133deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s?\r\n", HFP_QUERY_OPERATOR_SELECTION);
2143deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
2153deb3ec6SMatthias Ringwald }
2163deb3ec6SMatthias Ringwald 
2173deb3ec6SMatthias Ringwald static int hfp_hf_cmd_enable_extended_audio_gateway_error_report(uint16_t cid, uint8_t enable){
2183deb3ec6SMatthias Ringwald     char buffer[20];
2193deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s=%d\r\n", HFP_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR, enable);
2203deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
2213deb3ec6SMatthias Ringwald }
2223deb3ec6SMatthias Ringwald 
2233deb3ec6SMatthias Ringwald static int hfp_hf_cmd_trigger_codec_connection_setup(uint16_t cid){
2243deb3ec6SMatthias Ringwald     char buffer[20];
2253deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s\r\n", HFP_TRIGGER_CODEC_CONNECTION_SETUP);
2263deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
2273deb3ec6SMatthias Ringwald }
2283deb3ec6SMatthias Ringwald 
2293deb3ec6SMatthias Ringwald static int hfp_hf_cmd_confirm_codec(uint16_t cid, uint8_t codec){
2303deb3ec6SMatthias Ringwald     char buffer[20];
2313deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s=%d\r\n", HFP_CONFIRM_COMMON_CODEC, codec);
2323deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
2333deb3ec6SMatthias Ringwald }
2343deb3ec6SMatthias Ringwald 
235*ce263fc8SMatthias Ringwald static int hfp_hf_cmd_ata(uint16_t cid){
236*ce263fc8SMatthias Ringwald     char buffer[10];
237*ce263fc8SMatthias Ringwald     sprintf(buffer, "%s\r\n", HFP_CALL_ANSWERED);
238*ce263fc8SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
239*ce263fc8SMatthias Ringwald }
240*ce263fc8SMatthias Ringwald 
241*ce263fc8SMatthias Ringwald static int hfp_hf_set_microphone_gain_cmd(uint16_t cid, int gain){
242*ce263fc8SMatthias Ringwald     char buffer[40];
243*ce263fc8SMatthias Ringwald     sprintf(buffer, "AT%s=%d\r\n", HFP_SET_MICROPHONE_GAIN, gain);
244*ce263fc8SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
245*ce263fc8SMatthias Ringwald }
246*ce263fc8SMatthias Ringwald 
247*ce263fc8SMatthias Ringwald static int hfp_hf_set_speaker_gain_cmd(uint16_t cid, int gain){
248*ce263fc8SMatthias Ringwald     char buffer[40];
249*ce263fc8SMatthias Ringwald     sprintf(buffer, "AT%s=%d\r\n", HFP_SET_SPEAKER_GAIN, gain);
250*ce263fc8SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
251*ce263fc8SMatthias Ringwald }
252*ce263fc8SMatthias Ringwald 
253*ce263fc8SMatthias Ringwald static int hfp_hf_set_calling_line_notification_cmd(uint16_t cid, uint8_t activate){
254*ce263fc8SMatthias Ringwald     char buffer[40];
255*ce263fc8SMatthias Ringwald     sprintf(buffer, "AT%s=%d\r\n", HFP_ENABLE_CLIP, activate);
256*ce263fc8SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
257*ce263fc8SMatthias Ringwald }
258*ce263fc8SMatthias Ringwald 
259*ce263fc8SMatthias Ringwald static int hfp_hf_set_echo_canceling_and_noise_reduction_cmd(uint16_t cid, uint8_t activate){
260*ce263fc8SMatthias Ringwald     char buffer[40];
261*ce263fc8SMatthias Ringwald     sprintf(buffer, "AT%s=%d\r\n", HFP_TURN_OFF_EC_AND_NR, activate);
262*ce263fc8SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
263*ce263fc8SMatthias Ringwald }
264*ce263fc8SMatthias Ringwald 
265*ce263fc8SMatthias Ringwald static int hfp_hf_set_voice_recognition_notification_cmd(uint16_t cid, uint8_t activate){
266*ce263fc8SMatthias Ringwald     char buffer[40];
267*ce263fc8SMatthias Ringwald     sprintf(buffer, "AT%s=%d\r\n", HFP_ACTIVATE_VOICE_RECOGNITION, activate);
268*ce263fc8SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
269*ce263fc8SMatthias Ringwald }
270*ce263fc8SMatthias Ringwald 
271*ce263fc8SMatthias Ringwald static int hfp_hf_set_call_waiting_notification_cmd(uint16_t cid, uint8_t activate){
272*ce263fc8SMatthias Ringwald     char buffer[40];
273*ce263fc8SMatthias Ringwald     sprintf(buffer, "AT%s=%d\r\n", HFP_ENABLE_CALL_WAITING_NOTIFICATION, activate);
274*ce263fc8SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
275*ce263fc8SMatthias Ringwald }
276*ce263fc8SMatthias Ringwald 
277*ce263fc8SMatthias Ringwald static int hfp_hf_initiate_outgoing_call_cmd(uint16_t cid){
278*ce263fc8SMatthias Ringwald     char buffer[40];
279*ce263fc8SMatthias Ringwald     sprintf(buffer, "%s%s;\r\n", HFP_CALL_PHONE_NUMBER, phone_number);
280*ce263fc8SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
281*ce263fc8SMatthias Ringwald }
282*ce263fc8SMatthias Ringwald 
283*ce263fc8SMatthias Ringwald static int hfp_hf_send_memory_dial_cmd(uint16_t cid){
284*ce263fc8SMatthias Ringwald     char buffer[40];
285*ce263fc8SMatthias Ringwald     sprintf(buffer, "%s>%s;\r\n", HFP_CALL_PHONE_NUMBER, phone_number);
286*ce263fc8SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
287*ce263fc8SMatthias Ringwald }
288*ce263fc8SMatthias Ringwald 
289*ce263fc8SMatthias Ringwald static int hfp_hf_send_redial_last_number_cmd(uint16_t cid){
290*ce263fc8SMatthias Ringwald     char buffer[20];
291*ce263fc8SMatthias Ringwald     sprintf(buffer, "AT%s\r\n", HFP_REDIAL_LAST_NUMBER);
292*ce263fc8SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
293*ce263fc8SMatthias Ringwald }
294*ce263fc8SMatthias Ringwald 
295*ce263fc8SMatthias Ringwald static int hfp_hf_send_chup(uint16_t cid){
296*ce263fc8SMatthias Ringwald     char buffer[20];
297*ce263fc8SMatthias Ringwald     sprintf(buffer, "AT%s\r\n", HFP_HANG_UP_CALL);
298*ce263fc8SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
299*ce263fc8SMatthias Ringwald }
300*ce263fc8SMatthias Ringwald 
301*ce263fc8SMatthias Ringwald static int hfp_hf_send_chld(uint16_t cid, int number){
302*ce263fc8SMatthias Ringwald     char buffer[20];
303*ce263fc8SMatthias Ringwald     sprintf(buffer, "AT%s=%u\r\n", HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES, number);
304*ce263fc8SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
305*ce263fc8SMatthias Ringwald }
306*ce263fc8SMatthias Ringwald 
307*ce263fc8SMatthias Ringwald static int hfp_hf_send_dtmf(uint16_t cid, char code){
308*ce263fc8SMatthias Ringwald     char buffer[20];
309*ce263fc8SMatthias Ringwald     sprintf(buffer, "AT%s=%c\r\n", HFP_TRANSMIT_DTMF_CODES, code);
310*ce263fc8SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
311*ce263fc8SMatthias Ringwald }
312*ce263fc8SMatthias Ringwald 
313*ce263fc8SMatthias Ringwald static int hfp_hf_send_binp(uint16_t cid){
314*ce263fc8SMatthias Ringwald     char buffer[20];
315*ce263fc8SMatthias Ringwald     sprintf(buffer, "AT%s=1\r\n", HFP_PHONE_NUMBER_FOR_VOICE_TAG);
316*ce263fc8SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
317*ce263fc8SMatthias Ringwald }
318*ce263fc8SMatthias Ringwald 
3193deb3ec6SMatthias Ringwald static void hfp_emit_ag_indicator_event(hfp_callback_t callback, int status, hfp_ag_indicator_t indicator){
3203deb3ec6SMatthias Ringwald     if (!callback) return;
321*ce263fc8SMatthias Ringwald     uint8_t event[6+HFP_MAX_INDICATOR_DESC_SIZE+1];
3223deb3ec6SMatthias Ringwald     event[0] = HCI_EVENT_HFP_META;
3233deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
3243deb3ec6SMatthias Ringwald     event[2] = HFP_SUBEVENT_AG_INDICATOR_STATUS_CHANGED;
3253deb3ec6SMatthias Ringwald     event[3] = status;
3263deb3ec6SMatthias Ringwald     event[4] = indicator.index;
3273deb3ec6SMatthias Ringwald     event[5] = indicator.status;
328*ce263fc8SMatthias Ringwald     strncpy((char*)&event[6], indicator.name, HFP_MAX_INDICATOR_DESC_SIZE);
329*ce263fc8SMatthias Ringwald     event[6+HFP_MAX_INDICATOR_DESC_SIZE] = 0;
3303deb3ec6SMatthias Ringwald     (*callback)(event, sizeof(event));
3313deb3ec6SMatthias Ringwald }
3323deb3ec6SMatthias Ringwald 
3333deb3ec6SMatthias Ringwald static void hfp_emit_network_operator_event(hfp_callback_t callback, int status, hfp_network_opearator_t network_operator){
3343deb3ec6SMatthias Ringwald     if (!callback) return;
3353deb3ec6SMatthias Ringwald     uint8_t event[24];
3363deb3ec6SMatthias Ringwald     event[0] = HCI_EVENT_HFP_META;
3373deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
3383deb3ec6SMatthias Ringwald     event[2] = HFP_SUBEVENT_NETWORK_OPERATOR_CHANGED;
3393deb3ec6SMatthias Ringwald     event[3] = status;
3403deb3ec6SMatthias Ringwald     event[4] = network_operator.mode;
3413deb3ec6SMatthias Ringwald     event[5] = network_operator.format;
3423deb3ec6SMatthias Ringwald     strcpy((char*)&event[6], network_operator.name);
3433deb3ec6SMatthias Ringwald     (*callback)(event, sizeof(event));
3443deb3ec6SMatthias Ringwald }
3453deb3ec6SMatthias Ringwald 
3463deb3ec6SMatthias Ringwald static int hfp_hf_run_for_context_service_level_connection(hfp_connection_t * context){
3473deb3ec6SMatthias Ringwald     if (context->state >= HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return 0;
348aa4dd815SMatthias Ringwald     if (context->ok_pending) return 0;
349aa4dd815SMatthias Ringwald     int done = 1;
3503deb3ec6SMatthias Ringwald 
3513deb3ec6SMatthias Ringwald     switch (context->state){
3523deb3ec6SMatthias Ringwald         case HFP_EXCHANGE_SUPPORTED_FEATURES:
3533deb3ec6SMatthias Ringwald             context->state = HFP_W4_EXCHANGE_SUPPORTED_FEATURES;
354aa4dd815SMatthias Ringwald             hfp_hf_cmd_exchange_supported_features(context->rfcomm_cid);
3553deb3ec6SMatthias Ringwald             break;
3563deb3ec6SMatthias Ringwald         case HFP_NOTIFY_ON_CODECS:
3573deb3ec6SMatthias Ringwald             context->state = HFP_W4_NOTIFY_ON_CODECS;
358aa4dd815SMatthias Ringwald             hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid);
3593deb3ec6SMatthias Ringwald             break;
3603deb3ec6SMatthias Ringwald         case HFP_RETRIEVE_INDICATORS:
3613deb3ec6SMatthias Ringwald             context->state = HFP_W4_RETRIEVE_INDICATORS;
362aa4dd815SMatthias Ringwald             hfp_hf_cmd_retrieve_indicators(context->rfcomm_cid);
3633deb3ec6SMatthias Ringwald             break;
3643deb3ec6SMatthias Ringwald         case HFP_RETRIEVE_INDICATORS_STATUS:
3653deb3ec6SMatthias Ringwald             context->state = HFP_W4_RETRIEVE_INDICATORS_STATUS;
366aa4dd815SMatthias Ringwald             hfp_hf_cmd_retrieve_indicators_status(context->rfcomm_cid);
3673deb3ec6SMatthias Ringwald             break;
3683deb3ec6SMatthias Ringwald         case HFP_ENABLE_INDICATORS_STATUS_UPDATE:
3693deb3ec6SMatthias Ringwald             context->state = HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE;
370aa4dd815SMatthias Ringwald             hfp_hf_cmd_activate_status_update_for_all_ag_indicators(context->rfcomm_cid, 1);
3713deb3ec6SMatthias Ringwald             break;
3723deb3ec6SMatthias Ringwald         case HFP_RETRIEVE_CAN_HOLD_CALL:
3733deb3ec6SMatthias Ringwald             context->state = HFP_W4_RETRIEVE_CAN_HOLD_CALL;
374aa4dd815SMatthias Ringwald             hfp_hf_cmd_retrieve_can_hold_call(context->rfcomm_cid);
3753deb3ec6SMatthias Ringwald             break;
3763deb3ec6SMatthias Ringwald         case HFP_LIST_GENERIC_STATUS_INDICATORS:
3773deb3ec6SMatthias Ringwald             context->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS;
378aa4dd815SMatthias Ringwald             hfp_hf_cmd_list_supported_generic_status_indicators(context->rfcomm_cid);
3793deb3ec6SMatthias Ringwald             break;
3803deb3ec6SMatthias Ringwald         case HFP_RETRIEVE_GENERIC_STATUS_INDICATORS:
3813deb3ec6SMatthias Ringwald             context->state = HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS;
382aa4dd815SMatthias Ringwald             hfp_hf_cmd_retrieve_supported_generic_status_indicators(context->rfcomm_cid);
3833deb3ec6SMatthias Ringwald             break;
3843deb3ec6SMatthias Ringwald         case HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:
3853deb3ec6SMatthias Ringwald             context->state = HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS;
386aa4dd815SMatthias Ringwald             hfp_hf_cmd_list_initital_supported_generic_status_indicators(context->rfcomm_cid);
3873deb3ec6SMatthias Ringwald             break;
3883deb3ec6SMatthias Ringwald         default:
389aa4dd815SMatthias Ringwald             done = 0;
3903deb3ec6SMatthias Ringwald             break;
3913deb3ec6SMatthias Ringwald     }
3923deb3ec6SMatthias Ringwald     return done;
3933deb3ec6SMatthias Ringwald }
3943deb3ec6SMatthias Ringwald 
395*ce263fc8SMatthias Ringwald 
396*ce263fc8SMatthias Ringwald static int hfp_hf_run_for_context_service_level_connection_queries(hfp_connection_t * context){
397*ce263fc8SMatthias Ringwald     if (context->state != HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return 0;
398*ce263fc8SMatthias Ringwald     if (context->ok_pending) return 0;
399*ce263fc8SMatthias Ringwald 
400*ce263fc8SMatthias Ringwald     int done = 0;
401*ce263fc8SMatthias Ringwald     if (context->enable_status_update_for_ag_indicators != 0xFF){
402*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
403*ce263fc8SMatthias Ringwald         done = 1;
404*ce263fc8SMatthias Ringwald         hfp_hf_cmd_activate_status_update_for_all_ag_indicators(context->rfcomm_cid, context->enable_status_update_for_ag_indicators);
405*ce263fc8SMatthias Ringwald         return done;
406*ce263fc8SMatthias Ringwald     };
407*ce263fc8SMatthias Ringwald     if (context->change_status_update_for_individual_ag_indicators){
408*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
409*ce263fc8SMatthias Ringwald         done = 1;
410*ce263fc8SMatthias Ringwald         hfp_hf_cmd_activate_status_update_for_ag_indicator(context->rfcomm_cid,
411*ce263fc8SMatthias Ringwald                 context->ag_indicators_status_update_bitmap,
412*ce263fc8SMatthias Ringwald                 context->ag_indicators_nr);
413*ce263fc8SMatthias Ringwald         return done;
414*ce263fc8SMatthias Ringwald     }
415*ce263fc8SMatthias Ringwald 
416*ce263fc8SMatthias Ringwald     switch (context->hf_query_operator_state){
417*ce263fc8SMatthias Ringwald         case HFP_HF_QUERY_OPERATOR_SET_FORMAT:
418*ce263fc8SMatthias Ringwald             context->hf_query_operator_state = HFP_HF_QUERY_OPERATOR_W4_SET_FORMAT_OK;
419*ce263fc8SMatthias Ringwald             context->ok_pending = 1;
420*ce263fc8SMatthias Ringwald             hfp_hf_cmd_query_operator_name_format(context->rfcomm_cid);
421*ce263fc8SMatthias Ringwald             return 1;
422*ce263fc8SMatthias Ringwald         case HFP_HF_QUERY_OPERATOR_SEND_QUERY:
423*ce263fc8SMatthias Ringwald             context->hf_query_operator_state = HPF_HF_QUERY_OPERATOR_W4_RESULT;
424*ce263fc8SMatthias Ringwald             context->ok_pending = 1;
425*ce263fc8SMatthias Ringwald             hfp_hf_cmd_query_operator_name(context->rfcomm_cid);
426*ce263fc8SMatthias Ringwald             return 1;
427*ce263fc8SMatthias Ringwald         default:
428*ce263fc8SMatthias Ringwald             break;
429*ce263fc8SMatthias Ringwald     }
430*ce263fc8SMatthias Ringwald 
431*ce263fc8SMatthias Ringwald     if (context->enable_extended_audio_gateway_error_report){
432*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
433*ce263fc8SMatthias Ringwald         done = 1;
434*ce263fc8SMatthias Ringwald         hfp_hf_cmd_enable_extended_audio_gateway_error_report(context->rfcomm_cid, context->enable_extended_audio_gateway_error_report);
435*ce263fc8SMatthias Ringwald         return done;
436*ce263fc8SMatthias Ringwald     }
437*ce263fc8SMatthias Ringwald 
438*ce263fc8SMatthias Ringwald     return done;
439*ce263fc8SMatthias Ringwald }
440*ce263fc8SMatthias Ringwald 
441*ce263fc8SMatthias Ringwald static int codecs_exchange_state_machine(hfp_connection_t * context){
442*ce263fc8SMatthias Ringwald     /* events ( == commands):
443*ce263fc8SMatthias Ringwald         HFP_CMD_AVAILABLE_CODECS == received AT+BAC with list of codecs
444*ce263fc8SMatthias Ringwald         HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP:
445*ce263fc8SMatthias Ringwald             hf_trigger_codec_connection_setup == received BCC
446*ce263fc8SMatthias Ringwald             ag_trigger_codec_connection_setup == received from AG to send BCS
447*ce263fc8SMatthias Ringwald         HFP_CMD_HF_CONFIRMED_CODEC == received AT+BCS
448*ce263fc8SMatthias Ringwald     */
449*ce263fc8SMatthias Ringwald 
450*ce263fc8SMatthias Ringwald     if (context->ok_pending) return 0;
451*ce263fc8SMatthias Ringwald 
452*ce263fc8SMatthias Ringwald     switch (context->command){
453*ce263fc8SMatthias Ringwald         case HFP_CMD_AVAILABLE_CODECS:
454*ce263fc8SMatthias Ringwald             if (context->codecs_state == HFP_CODECS_W4_AG_COMMON_CODEC) return 0;
455*ce263fc8SMatthias Ringwald 
456*ce263fc8SMatthias Ringwald             context->codecs_state = HFP_CODECS_W4_AG_COMMON_CODEC;
457*ce263fc8SMatthias Ringwald             context->ok_pending = 1;
458*ce263fc8SMatthias Ringwald             hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid);
459*ce263fc8SMatthias Ringwald             return 1;
460*ce263fc8SMatthias Ringwald         case HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP:
461*ce263fc8SMatthias Ringwald             context->codec_confirmed = 0;
462*ce263fc8SMatthias Ringwald             context->suggested_codec = 0;
463*ce263fc8SMatthias Ringwald             context->negotiated_codec = 0;
464*ce263fc8SMatthias Ringwald 
465*ce263fc8SMatthias Ringwald             context->codecs_state = HFP_CODECS_RECEIVED_TRIGGER_CODEC_EXCHANGE;
466*ce263fc8SMatthias Ringwald             context->ok_pending = 1;
467*ce263fc8SMatthias Ringwald             hfp_hf_cmd_trigger_codec_connection_setup(context->rfcomm_cid);
468*ce263fc8SMatthias Ringwald             break;
469*ce263fc8SMatthias Ringwald 
470*ce263fc8SMatthias Ringwald          case HFP_CMD_AG_SUGGESTED_CODEC:
471*ce263fc8SMatthias Ringwald             if (hfp_hf_supports_codec(context->suggested_codec)){
472*ce263fc8SMatthias Ringwald                 context->codec_confirmed = context->suggested_codec;
473*ce263fc8SMatthias Ringwald                 context->ok_pending = 1;
474*ce263fc8SMatthias Ringwald                 context->codecs_state = HFP_CODECS_HF_CONFIRMED_CODEC;
475*ce263fc8SMatthias Ringwald                 hfp_hf_cmd_confirm_codec(context->rfcomm_cid, context->suggested_codec);
476*ce263fc8SMatthias Ringwald             } else {
477*ce263fc8SMatthias Ringwald                 context->codec_confirmed = 0;
478*ce263fc8SMatthias Ringwald                 context->suggested_codec = 0;
479*ce263fc8SMatthias Ringwald                 context->negotiated_codec = 0;
480*ce263fc8SMatthias Ringwald                 context->codecs_state = HFP_CODECS_W4_AG_COMMON_CODEC;
481*ce263fc8SMatthias Ringwald                 context->ok_pending = 1;
482*ce263fc8SMatthias Ringwald                 hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid);
483*ce263fc8SMatthias Ringwald 
484*ce263fc8SMatthias Ringwald             }
485*ce263fc8SMatthias Ringwald             break;
486*ce263fc8SMatthias Ringwald 
487*ce263fc8SMatthias Ringwald         default:
488*ce263fc8SMatthias Ringwald             break;
489*ce263fc8SMatthias Ringwald     }
490*ce263fc8SMatthias Ringwald     return 0;
491*ce263fc8SMatthias Ringwald }
492*ce263fc8SMatthias Ringwald 
493*ce263fc8SMatthias Ringwald static int hfp_hf_run_for_audio_connection(hfp_connection_t * context){
494*ce263fc8SMatthias Ringwald     if (context->state < HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED ||
495*ce263fc8SMatthias Ringwald         context->state > HFP_W2_DISCONNECT_SCO) return 0;
496*ce263fc8SMatthias Ringwald 
497*ce263fc8SMatthias Ringwald 
498*ce263fc8SMatthias Ringwald     if (context->state == HFP_AUDIO_CONNECTION_ESTABLISHED && context->release_audio_connection){
499*ce263fc8SMatthias Ringwald         context->state = HFP_W4_SCO_DISCONNECTED;
500*ce263fc8SMatthias Ringwald         context->release_audio_connection = 0;
501*ce263fc8SMatthias Ringwald         gap_disconnect(context->sco_handle);
502*ce263fc8SMatthias Ringwald         return 1;
503*ce263fc8SMatthias Ringwald     }
504*ce263fc8SMatthias Ringwald 
505*ce263fc8SMatthias Ringwald     if (context->state == HFP_AUDIO_CONNECTION_ESTABLISHED) return 0;
506*ce263fc8SMatthias Ringwald 
507*ce263fc8SMatthias Ringwald     // run codecs exchange
508*ce263fc8SMatthias Ringwald     int done = codecs_exchange_state_machine(context);
509*ce263fc8SMatthias Ringwald     if (done) return 1;
510*ce263fc8SMatthias Ringwald 
511*ce263fc8SMatthias Ringwald     if (context->establish_audio_connection){
512*ce263fc8SMatthias Ringwald         context->state = HFP_W4_SCO_CONNECTED;
513*ce263fc8SMatthias Ringwald         context->establish_audio_connection = 0;
514*ce263fc8SMatthias Ringwald         hfp_setup_synchronous_connection(context->con_handle, context->link_setting);
515*ce263fc8SMatthias Ringwald         return 1;
516*ce263fc8SMatthias Ringwald     }
517*ce263fc8SMatthias Ringwald 
518*ce263fc8SMatthias Ringwald     return 0;
519*ce263fc8SMatthias Ringwald }
520*ce263fc8SMatthias Ringwald 
521*ce263fc8SMatthias Ringwald static int call_setup_state_machine(hfp_connection_t * context){
522*ce263fc8SMatthias Ringwald     if (context->hf_answer_incoming_call){
523*ce263fc8SMatthias Ringwald         hfp_hf_cmd_ata(context->rfcomm_cid);
524*ce263fc8SMatthias Ringwald         context->hf_answer_incoming_call = 0;
525*ce263fc8SMatthias Ringwald         return 1;
526*ce263fc8SMatthias Ringwald     }
527*ce263fc8SMatthias Ringwald     return 0;
528*ce263fc8SMatthias Ringwald }
529*ce263fc8SMatthias Ringwald 
530*ce263fc8SMatthias Ringwald static void hfp_run_for_context(hfp_connection_t * context){
531*ce263fc8SMatthias Ringwald     if (!context) return;
532*ce263fc8SMatthias Ringwald     if (!rfcomm_can_send_packet_now(context->rfcomm_cid)) return;
533*ce263fc8SMatthias Ringwald 
534*ce263fc8SMatthias Ringwald     int done = hfp_hf_run_for_context_service_level_connection(context);
535*ce263fc8SMatthias Ringwald     if (!done){
536*ce263fc8SMatthias Ringwald         done = hfp_hf_run_for_context_service_level_connection_queries(context);
537*ce263fc8SMatthias Ringwald     }
538*ce263fc8SMatthias Ringwald     if (!done){
539*ce263fc8SMatthias Ringwald         done = hfp_hf_run_for_audio_connection(context);
540*ce263fc8SMatthias Ringwald     }
541*ce263fc8SMatthias Ringwald     if (!done){
542*ce263fc8SMatthias Ringwald         done = call_setup_state_machine(context);
543*ce263fc8SMatthias Ringwald     }
544*ce263fc8SMatthias Ringwald 
545*ce263fc8SMatthias Ringwald     if (context->send_microphone_gain){
546*ce263fc8SMatthias Ringwald         context->send_microphone_gain = 0;
547*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
548*ce263fc8SMatthias Ringwald         hfp_hf_set_microphone_gain_cmd(context->rfcomm_cid, context->microphone_gain);
549*ce263fc8SMatthias Ringwald         return;
550*ce263fc8SMatthias Ringwald     }
551*ce263fc8SMatthias Ringwald 
552*ce263fc8SMatthias Ringwald     if (context->send_speaker_gain){
553*ce263fc8SMatthias Ringwald         context->send_speaker_gain = 0;
554*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
555*ce263fc8SMatthias Ringwald         hfp_hf_set_speaker_gain_cmd(context->rfcomm_cid, context->speaker_gain);
556*ce263fc8SMatthias Ringwald         return;
557*ce263fc8SMatthias Ringwald     }
558*ce263fc8SMatthias Ringwald 
559*ce263fc8SMatthias Ringwald     if (context->hf_deactivate_calling_line_notification){
560*ce263fc8SMatthias Ringwald         context->hf_deactivate_calling_line_notification = 0;
561*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
562*ce263fc8SMatthias Ringwald         hfp_hf_set_calling_line_notification_cmd(context->rfcomm_cid, 0);
563*ce263fc8SMatthias Ringwald         return;
564*ce263fc8SMatthias Ringwald     }
565*ce263fc8SMatthias Ringwald 
566*ce263fc8SMatthias Ringwald     if (context->hf_activate_calling_line_notification){
567*ce263fc8SMatthias Ringwald         context->hf_activate_calling_line_notification = 0;
568*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
569*ce263fc8SMatthias Ringwald         hfp_hf_set_calling_line_notification_cmd(context->rfcomm_cid, 1);
570*ce263fc8SMatthias Ringwald         return;
571*ce263fc8SMatthias Ringwald     }
572*ce263fc8SMatthias Ringwald 
573*ce263fc8SMatthias Ringwald     if (context->hf_deactivate_echo_canceling_and_noise_reduction){
574*ce263fc8SMatthias Ringwald         context->hf_deactivate_echo_canceling_and_noise_reduction = 0;
575*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
576*ce263fc8SMatthias Ringwald         hfp_hf_set_echo_canceling_and_noise_reduction_cmd(context->rfcomm_cid, 0);
577*ce263fc8SMatthias Ringwald         return;
578*ce263fc8SMatthias Ringwald     }
579*ce263fc8SMatthias Ringwald 
580*ce263fc8SMatthias Ringwald     if (context->hf_activate_echo_canceling_and_noise_reduction){
581*ce263fc8SMatthias Ringwald         context->hf_activate_echo_canceling_and_noise_reduction = 0;
582*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
583*ce263fc8SMatthias Ringwald         hfp_hf_set_echo_canceling_and_noise_reduction_cmd(context->rfcomm_cid, 1);
584*ce263fc8SMatthias Ringwald         return;
585*ce263fc8SMatthias Ringwald     }
586*ce263fc8SMatthias Ringwald 
587*ce263fc8SMatthias Ringwald     if (context->hf_deactivate_voice_recognition_notification){
588*ce263fc8SMatthias Ringwald         context->hf_deactivate_voice_recognition_notification = 0;
589*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
590*ce263fc8SMatthias Ringwald         hfp_hf_set_voice_recognition_notification_cmd(context->rfcomm_cid, 0);
591*ce263fc8SMatthias Ringwald         return;
592*ce263fc8SMatthias Ringwald     }
593*ce263fc8SMatthias Ringwald 
594*ce263fc8SMatthias Ringwald     if (context->hf_activate_voice_recognition_notification){
595*ce263fc8SMatthias Ringwald         context->hf_activate_voice_recognition_notification = 0;
596*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
597*ce263fc8SMatthias Ringwald         hfp_hf_set_voice_recognition_notification_cmd(context->rfcomm_cid, 1);
598*ce263fc8SMatthias Ringwald         return;
599*ce263fc8SMatthias Ringwald     }
600*ce263fc8SMatthias Ringwald 
601*ce263fc8SMatthias Ringwald 
602*ce263fc8SMatthias Ringwald     if (context->hf_deactivate_call_waiting_notification){
603*ce263fc8SMatthias Ringwald         context->hf_deactivate_call_waiting_notification = 0;
604*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
605*ce263fc8SMatthias Ringwald         hfp_hf_set_call_waiting_notification_cmd(context->rfcomm_cid, 0);
606*ce263fc8SMatthias Ringwald         return;
607*ce263fc8SMatthias Ringwald     }
608*ce263fc8SMatthias Ringwald 
609*ce263fc8SMatthias Ringwald     if (context->hf_activate_call_waiting_notification){
610*ce263fc8SMatthias Ringwald         context->hf_activate_call_waiting_notification = 0;
611*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
612*ce263fc8SMatthias Ringwald         hfp_hf_set_call_waiting_notification_cmd(context->rfcomm_cid, 1);
613*ce263fc8SMatthias Ringwald         return;
614*ce263fc8SMatthias Ringwald     }
615*ce263fc8SMatthias Ringwald 
616*ce263fc8SMatthias Ringwald     if (context->hf_initiate_outgoing_call){
617*ce263fc8SMatthias Ringwald         context->hf_initiate_outgoing_call = 0;
618*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
619*ce263fc8SMatthias Ringwald         hfp_hf_initiate_outgoing_call_cmd(context->rfcomm_cid);
620*ce263fc8SMatthias Ringwald         return;
621*ce263fc8SMatthias Ringwald     }
622*ce263fc8SMatthias Ringwald 
623*ce263fc8SMatthias Ringwald     if (context->hf_initiate_memory_dialing){
624*ce263fc8SMatthias Ringwald         context->hf_initiate_memory_dialing = 0;
625*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
626*ce263fc8SMatthias Ringwald         hfp_hf_send_memory_dial_cmd(context->rfcomm_cid);
627*ce263fc8SMatthias Ringwald         return;
628*ce263fc8SMatthias Ringwald     }
629*ce263fc8SMatthias Ringwald 
630*ce263fc8SMatthias Ringwald     if (context->hf_initiate_redial_last_number){
631*ce263fc8SMatthias Ringwald         context->hf_initiate_redial_last_number = 0;
632*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
633*ce263fc8SMatthias Ringwald         hfp_hf_send_redial_last_number_cmd(context->rfcomm_cid);
634*ce263fc8SMatthias Ringwald         return;
635*ce263fc8SMatthias Ringwald     }
636*ce263fc8SMatthias Ringwald 
637*ce263fc8SMatthias Ringwald     if (context->hf_send_chup){
638*ce263fc8SMatthias Ringwald         context->hf_send_chup = 0;
639*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
640*ce263fc8SMatthias Ringwald         hfp_hf_send_chup(context->rfcomm_cid);
641*ce263fc8SMatthias Ringwald         return;
642*ce263fc8SMatthias Ringwald     }
643*ce263fc8SMatthias Ringwald 
644*ce263fc8SMatthias Ringwald     if (context->hf_send_chld_0){
645*ce263fc8SMatthias Ringwald         context->hf_send_chld_0 = 0;
646*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
647*ce263fc8SMatthias Ringwald         hfp_hf_send_chld(context->rfcomm_cid, 0);
648*ce263fc8SMatthias Ringwald         return;
649*ce263fc8SMatthias Ringwald     }
650*ce263fc8SMatthias Ringwald 
651*ce263fc8SMatthias Ringwald     if (context->hf_send_chld_1){
652*ce263fc8SMatthias Ringwald         context->hf_send_chld_1 = 0;
653*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
654*ce263fc8SMatthias Ringwald         hfp_hf_send_chld(context->rfcomm_cid, 1);
655*ce263fc8SMatthias Ringwald         return;
656*ce263fc8SMatthias Ringwald     }
657*ce263fc8SMatthias Ringwald 
658*ce263fc8SMatthias Ringwald     if (context->hf_send_chld_2){
659*ce263fc8SMatthias Ringwald         context->hf_send_chld_2 = 0;
660*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
661*ce263fc8SMatthias Ringwald         hfp_hf_send_chld(context->rfcomm_cid, 2);
662*ce263fc8SMatthias Ringwald         return;
663*ce263fc8SMatthias Ringwald     }
664*ce263fc8SMatthias Ringwald 
665*ce263fc8SMatthias Ringwald     if (context->hf_send_chld_3){
666*ce263fc8SMatthias Ringwald         context->hf_send_chld_3 = 0;
667*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
668*ce263fc8SMatthias Ringwald         hfp_hf_send_chld(context->rfcomm_cid, 3);
669*ce263fc8SMatthias Ringwald         return;
670*ce263fc8SMatthias Ringwald     }
671*ce263fc8SMatthias Ringwald 
672*ce263fc8SMatthias Ringwald     if (context->hf_send_chld_4){
673*ce263fc8SMatthias Ringwald         context->hf_send_chld_4 = 0;
674*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
675*ce263fc8SMatthias Ringwald         hfp_hf_send_chld(context->rfcomm_cid, 4);
676*ce263fc8SMatthias Ringwald         return;
677*ce263fc8SMatthias Ringwald     }
678*ce263fc8SMatthias Ringwald 
679*ce263fc8SMatthias Ringwald     if (context->hf_send_dtmf_code){
680*ce263fc8SMatthias Ringwald         char code = context->hf_send_dtmf_code;
681*ce263fc8SMatthias Ringwald         context->hf_send_dtmf_code = 0;
682*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
683*ce263fc8SMatthias Ringwald         hfp_hf_send_dtmf(context->rfcomm_cid, code);
684*ce263fc8SMatthias Ringwald         return;
685*ce263fc8SMatthias Ringwald     }
686*ce263fc8SMatthias Ringwald 
687*ce263fc8SMatthias Ringwald     if (context->hf_send_binp){
688*ce263fc8SMatthias Ringwald         context->hf_send_binp = 0;
689*ce263fc8SMatthias Ringwald         context->ok_pending = 1;
690*ce263fc8SMatthias Ringwald         hfp_hf_send_binp(context->rfcomm_cid);
691*ce263fc8SMatthias Ringwald         return;
692*ce263fc8SMatthias Ringwald     }
693*ce263fc8SMatthias Ringwald 
694*ce263fc8SMatthias Ringwald     if (done) return;
695*ce263fc8SMatthias Ringwald     // deal with disconnect
696*ce263fc8SMatthias Ringwald     switch (context->state){
697*ce263fc8SMatthias Ringwald         case HFP_W2_DISCONNECT_RFCOMM:
698*ce263fc8SMatthias Ringwald             context->state = HFP_W4_RFCOMM_DISCONNECTED;
699*ce263fc8SMatthias Ringwald             rfcomm_disconnect_internal(context->rfcomm_cid);
700*ce263fc8SMatthias Ringwald             break;
701*ce263fc8SMatthias Ringwald 
702*ce263fc8SMatthias Ringwald         default:
703*ce263fc8SMatthias Ringwald             break;
704*ce263fc8SMatthias Ringwald     }
705*ce263fc8SMatthias Ringwald }
706*ce263fc8SMatthias Ringwald 
707*ce263fc8SMatthias Ringwald static void hfp_init_link_settings(hfp_connection_t * context){
708*ce263fc8SMatthias Ringwald     // determine highest possible link setting
709*ce263fc8SMatthias Ringwald     context->link_setting = HFP_LINK_SETTINGS_D1;
710*ce263fc8SMatthias Ringwald     if (hci_remote_eSCO_supported(context->con_handle)){
711*ce263fc8SMatthias Ringwald         context->link_setting = HFP_LINK_SETTINGS_S3;
712*ce263fc8SMatthias Ringwald         if ((hfp_supported_features             & (1<<HFP_HFSF_ESCO_S4))
713*ce263fc8SMatthias Ringwald         &&  (context->remote_supported_features & (1<<HFP_AGSF_ESCO_S4))){
714*ce263fc8SMatthias Ringwald             context->link_setting = HFP_LINK_SETTINGS_S4;
715*ce263fc8SMatthias Ringwald         }
716*ce263fc8SMatthias Ringwald     }
717*ce263fc8SMatthias Ringwald }
718*ce263fc8SMatthias Ringwald 
719*ce263fc8SMatthias Ringwald static void hfp_ag_slc_established(hfp_connection_t * context){
720*ce263fc8SMatthias Ringwald     context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
721*ce263fc8SMatthias Ringwald     hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0);
722*ce263fc8SMatthias Ringwald     hfp_init_link_settings(context);
723*ce263fc8SMatthias Ringwald }
724*ce263fc8SMatthias Ringwald 
725*ce263fc8SMatthias Ringwald static void hfp_hf_switch_on_ok(hfp_connection_t *context){
726*ce263fc8SMatthias Ringwald     context->ok_pending = 0;
727*ce263fc8SMatthias Ringwald     int done = 1;
7283deb3ec6SMatthias Ringwald     switch (context->state){
7293deb3ec6SMatthias Ringwald         case HFP_W4_EXCHANGE_SUPPORTED_FEATURES:
7303deb3ec6SMatthias Ringwald             if (has_codec_negotiation_feature(context)){
7313deb3ec6SMatthias Ringwald                 context->state = HFP_NOTIFY_ON_CODECS;
7323deb3ec6SMatthias Ringwald                 break;
7333deb3ec6SMatthias Ringwald             }
7343deb3ec6SMatthias Ringwald             context->state = HFP_RETRIEVE_INDICATORS;
7353deb3ec6SMatthias Ringwald             break;
7363deb3ec6SMatthias Ringwald 
7373deb3ec6SMatthias Ringwald         case HFP_W4_NOTIFY_ON_CODECS:
7383deb3ec6SMatthias Ringwald             context->state = HFP_RETRIEVE_INDICATORS;
7393deb3ec6SMatthias Ringwald             break;
7403deb3ec6SMatthias Ringwald 
7413deb3ec6SMatthias Ringwald         case HFP_W4_RETRIEVE_INDICATORS:
7423deb3ec6SMatthias Ringwald             context->state = HFP_RETRIEVE_INDICATORS_STATUS;
7433deb3ec6SMatthias Ringwald             break;
7443deb3ec6SMatthias Ringwald 
7453deb3ec6SMatthias Ringwald         case HFP_W4_RETRIEVE_INDICATORS_STATUS:
7463deb3ec6SMatthias Ringwald             context->state = HFP_ENABLE_INDICATORS_STATUS_UPDATE;
7473deb3ec6SMatthias Ringwald             break;
7483deb3ec6SMatthias Ringwald 
7493deb3ec6SMatthias Ringwald         case HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE:
7503deb3ec6SMatthias Ringwald             if (has_call_waiting_and_3way_calling_feature(context)){
7513deb3ec6SMatthias Ringwald                 context->state = HFP_RETRIEVE_CAN_HOLD_CALL;
7523deb3ec6SMatthias Ringwald                 break;
7533deb3ec6SMatthias Ringwald             }
7543deb3ec6SMatthias Ringwald             if (has_hf_indicators_feature(context)){
7553deb3ec6SMatthias Ringwald                 context->state = HFP_LIST_GENERIC_STATUS_INDICATORS;
7563deb3ec6SMatthias Ringwald                 break;
7573deb3ec6SMatthias Ringwald             }
758*ce263fc8SMatthias Ringwald             hfp_ag_slc_established(context);
7593deb3ec6SMatthias Ringwald             break;
7603deb3ec6SMatthias Ringwald 
7613deb3ec6SMatthias Ringwald         case HFP_W4_RETRIEVE_CAN_HOLD_CALL:
7623deb3ec6SMatthias Ringwald             if (has_hf_indicators_feature(context)){
7633deb3ec6SMatthias Ringwald                 context->state = HFP_LIST_GENERIC_STATUS_INDICATORS;
7643deb3ec6SMatthias Ringwald                 break;
7653deb3ec6SMatthias Ringwald             }
766*ce263fc8SMatthias Ringwald             hfp_ag_slc_established(context);
7673deb3ec6SMatthias Ringwald             break;
7683deb3ec6SMatthias Ringwald 
7693deb3ec6SMatthias Ringwald         case HFP_W4_LIST_GENERIC_STATUS_INDICATORS:
7703deb3ec6SMatthias Ringwald             context->state = HFP_RETRIEVE_GENERIC_STATUS_INDICATORS;
7713deb3ec6SMatthias Ringwald             break;
7723deb3ec6SMatthias Ringwald 
7733deb3ec6SMatthias Ringwald         case HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS:
7743deb3ec6SMatthias Ringwald             context->state = HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS;
7753deb3ec6SMatthias Ringwald             break;
7763deb3ec6SMatthias Ringwald 
7773deb3ec6SMatthias Ringwald         case HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:
778*ce263fc8SMatthias Ringwald             hfp_ag_slc_established(context);
7793deb3ec6SMatthias Ringwald             break;
780*ce263fc8SMatthias Ringwald         case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
7813deb3ec6SMatthias Ringwald             if (context->enable_status_update_for_ag_indicators != 0xFF){
7823deb3ec6SMatthias Ringwald                 context->enable_status_update_for_ag_indicators = 0xFF;
7833deb3ec6SMatthias Ringwald                 hfp_emit_event(hfp_callback, HFP_SUBEVENT_COMPLETE, 0);
784*ce263fc8SMatthias Ringwald                 break;
785*ce263fc8SMatthias Ringwald             }
7863deb3ec6SMatthias Ringwald 
7873deb3ec6SMatthias Ringwald             if (context->change_status_update_for_individual_ag_indicators == 1){
7883deb3ec6SMatthias Ringwald                 context->change_status_update_for_individual_ag_indicators = 0;
7893deb3ec6SMatthias Ringwald                 hfp_emit_event(hfp_callback, HFP_SUBEVENT_COMPLETE, 0);
790*ce263fc8SMatthias Ringwald                 break;
7913deb3ec6SMatthias Ringwald             }
7923deb3ec6SMatthias Ringwald 
793*ce263fc8SMatthias Ringwald             switch (context->hf_query_operator_state){
794*ce263fc8SMatthias Ringwald                 case HFP_HF_QUERY_OPERATOR_W4_SET_FORMAT_OK:
795*ce263fc8SMatthias Ringwald                     printf("Format set, querying name\n");
796*ce263fc8SMatthias Ringwald                     context->hf_query_operator_state = HFP_HF_QUERY_OPERATOR_SEND_QUERY;
797*ce263fc8SMatthias Ringwald                     break;
798*ce263fc8SMatthias Ringwald                 case HPF_HF_QUERY_OPERATOR_W4_RESULT:
799*ce263fc8SMatthias Ringwald                     context->hf_query_operator_state = HFP_HF_QUERY_OPERATOR_FORMAT_SET;
8003deb3ec6SMatthias Ringwald                     hfp_emit_network_operator_event(hfp_callback, 0, context->network_operator);
801*ce263fc8SMatthias Ringwald                     break;
802*ce263fc8SMatthias Ringwald                 default:
803*ce263fc8SMatthias Ringwald                     break;
8043deb3ec6SMatthias Ringwald             }
805*ce263fc8SMatthias Ringwald 
8063deb3ec6SMatthias Ringwald             if (context->enable_extended_audio_gateway_error_report){
8073deb3ec6SMatthias Ringwald                 context->enable_extended_audio_gateway_error_report = 0;
808*ce263fc8SMatthias Ringwald                 break;
8093deb3ec6SMatthias Ringwald             }
8103deb3ec6SMatthias Ringwald 
811aa4dd815SMatthias Ringwald             switch (context->codecs_state){
812aa4dd815SMatthias Ringwald                 case HFP_CODECS_RECEIVED_TRIGGER_CODEC_EXCHANGE:
813aa4dd815SMatthias Ringwald                     context->codecs_state = HFP_CODECS_W4_AG_COMMON_CODEC;
8143deb3ec6SMatthias Ringwald                     break;
815*ce263fc8SMatthias Ringwald                 case HFP_CODECS_HF_CONFIRMED_CODEC:
816*ce263fc8SMatthias Ringwald                     context->codecs_state = HFP_CODECS_EXCHANGED;
817*ce263fc8SMatthias Ringwald                     hfp_emit_event(hfp_callback, HFP_SUBEVENT_CODECS_CONNECTION_COMPLETE, 0);
818*ce263fc8SMatthias Ringwald                     break;
8193deb3ec6SMatthias Ringwald                 default:
820*ce263fc8SMatthias Ringwald                     done = 0;
8213deb3ec6SMatthias Ringwald                     break;
8223deb3ec6SMatthias Ringwald             }
8233deb3ec6SMatthias Ringwald             break;
8243deb3ec6SMatthias Ringwald         default:
825*ce263fc8SMatthias Ringwald             done = 0;
8263deb3ec6SMatthias Ringwald             break;
8273deb3ec6SMatthias Ringwald     }
8283deb3ec6SMatthias Ringwald 
8293deb3ec6SMatthias Ringwald     // done
8303deb3ec6SMatthias Ringwald     context->command = HFP_CMD_NONE;
8313deb3ec6SMatthias Ringwald }
8323deb3ec6SMatthias Ringwald 
8333deb3ec6SMatthias Ringwald 
8343deb3ec6SMatthias Ringwald static void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
8353deb3ec6SMatthias Ringwald     hfp_connection_t * context = get_hfp_connection_context_for_rfcomm_cid(channel);
8363deb3ec6SMatthias Ringwald     if (!context) return;
8373deb3ec6SMatthias Ringwald 
8383deb3ec6SMatthias Ringwald     packet[size] = 0;
8393deb3ec6SMatthias Ringwald     int pos, i;
8403deb3ec6SMatthias Ringwald     //printf("\nHF received: %s", packet+2);
8413deb3ec6SMatthias Ringwald     for (pos = 0; pos < size ; pos++){
842aa4dd815SMatthias Ringwald         hfp_parse(context, packet[pos], 1);
843*ce263fc8SMatthias Ringwald     }
8443deb3ec6SMatthias Ringwald 
845*ce263fc8SMatthias Ringwald     switch (context->command){
846*ce263fc8SMatthias Ringwald         case HFP_CMD_SET_SPEAKER_GAIN:
847*ce263fc8SMatthias Ringwald             context->command = HFP_CMD_NONE;
848*ce263fc8SMatthias Ringwald             hfp_emit_event(hfp_callback, HFP_SUBEVENT_SPEAKER_VOLUME, atoi((char*)context->line_buffer));
849*ce263fc8SMatthias Ringwald             break;
850*ce263fc8SMatthias Ringwald         case HFP_CMD_SET_MICROPHONE_GAIN:
851*ce263fc8SMatthias Ringwald             context->command = HFP_CMD_NONE;
852*ce263fc8SMatthias Ringwald             hfp_emit_event(hfp_callback, HFP_SUBEVENT_MICROPHONE_VOLUME, atoi((char*)context->line_buffer));
853*ce263fc8SMatthias Ringwald             break;
854*ce263fc8SMatthias Ringwald         case HFP_CMD_AG_SENT_PHONE_NUMBER:
855*ce263fc8SMatthias Ringwald             context->command = HFP_CMD_NONE;
856*ce263fc8SMatthias Ringwald             hfp_emit_string_event(hfp_callback, HFP_SUBEVENT_NUMBER_FOR_VOICE_TAG, context->bnip_number);
857*ce263fc8SMatthias Ringwald             break;
858*ce263fc8SMatthias Ringwald         case HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR:
859*ce263fc8SMatthias Ringwald             context->ok_pending = 0;
860*ce263fc8SMatthias Ringwald             context->extended_audio_gateway_error = 0;
861*ce263fc8SMatthias Ringwald             context->command = HFP_CMD_NONE;
862*ce263fc8SMatthias Ringwald             hfp_emit_event(hfp_callback, HFP_SUBEVENT_EXTENDED_AUDIO_GATEWAY_ERROR, context->extended_audio_gateway_error);
863*ce263fc8SMatthias Ringwald             break;
864*ce263fc8SMatthias Ringwald         case HFP_CMD_ERROR:
865*ce263fc8SMatthias Ringwald             context->ok_pending = 0;
866*ce263fc8SMatthias Ringwald             hfp_reset_context_flags(context);
867*ce263fc8SMatthias Ringwald             context->command = HFP_CMD_NONE;
868*ce263fc8SMatthias Ringwald             hfp_emit_event(hfp_callback, HFP_SUBEVENT_COMPLETE, 1);
869*ce263fc8SMatthias Ringwald             break;
870*ce263fc8SMatthias Ringwald         case HFP_CMD_OK:
871*ce263fc8SMatthias Ringwald             hfp_hf_switch_on_ok(context);
872*ce263fc8SMatthias Ringwald             break;
873*ce263fc8SMatthias Ringwald         case HFP_CMD_RING:
874*ce263fc8SMatthias Ringwald             hfp_emit_event(hfp_callback, HFP_SUBEVENT_RING, 0);
875*ce263fc8SMatthias Ringwald             break;
876*ce263fc8SMatthias Ringwald         case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS:
8773deb3ec6SMatthias Ringwald             for (i = 0; i < context->ag_indicators_nr; i++){
8783deb3ec6SMatthias Ringwald                 if (context->ag_indicators[i].status_changed) {
879*ce263fc8SMatthias Ringwald                     if (strcmp(context->ag_indicators[i].name, "callsetup") == 0){
880*ce263fc8SMatthias Ringwald                         hfp_callsetup_status = (hfp_callsetup_status_t) context->ag_indicators[i].status;
881*ce263fc8SMatthias Ringwald                     } else if (strcmp(context->ag_indicators[i].name, "callheld") == 0){
882*ce263fc8SMatthias Ringwald                         hfp_callheld_status = (hfp_callheld_status_t) context->ag_indicators[i].status;
883*ce263fc8SMatthias Ringwald                     } else if (strcmp(context->ag_indicators[i].name, "call") == 0){
884*ce263fc8SMatthias Ringwald                         hfp_call_status = (hfp_call_status_t) context->ag_indicators[i].status;
885*ce263fc8SMatthias Ringwald                     }
8863deb3ec6SMatthias Ringwald                     context->ag_indicators[i].status_changed = 0;
887aa4dd815SMatthias Ringwald                     hfp_emit_ag_indicator_event(hfp_callback, 0, context->ag_indicators[i]);
8883deb3ec6SMatthias Ringwald                     break;
8893deb3ec6SMatthias Ringwald                 }
8903deb3ec6SMatthias Ringwald             }
891*ce263fc8SMatthias Ringwald             break;
892*ce263fc8SMatthias Ringwald         default:
893*ce263fc8SMatthias Ringwald             break;
8943deb3ec6SMatthias Ringwald     }
895*ce263fc8SMatthias Ringwald     hfp_run_for_context(context);
8963deb3ec6SMatthias Ringwald }
8973deb3ec6SMatthias Ringwald 
8983deb3ec6SMatthias Ringwald static void hfp_run(){
8993deb3ec6SMatthias Ringwald     linked_list_iterator_t it;
9003deb3ec6SMatthias Ringwald     linked_list_iterator_init(&it, hfp_get_connections());
9013deb3ec6SMatthias Ringwald     while (linked_list_iterator_has_next(&it)){
9023deb3ec6SMatthias Ringwald         hfp_connection_t * connection = (hfp_connection_t *)linked_list_iterator_next(&it);
9033deb3ec6SMatthias Ringwald         hfp_run_for_context(connection);
9043deb3ec6SMatthias Ringwald     }
9053deb3ec6SMatthias Ringwald }
9063deb3ec6SMatthias Ringwald 
907ffbf8201SMatthias Ringwald static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
9083deb3ec6SMatthias Ringwald     switch (packet_type){
9093deb3ec6SMatthias Ringwald         case RFCOMM_DATA_PACKET:
9103deb3ec6SMatthias Ringwald             hfp_handle_rfcomm_event(packet_type, channel, packet, size);
9113deb3ec6SMatthias Ringwald             break;
9123deb3ec6SMatthias Ringwald         case HCI_EVENT_PACKET:
9133deb3ec6SMatthias Ringwald             hfp_handle_hci_event(hfp_callback, packet_type, packet, size);
9143deb3ec6SMatthias Ringwald         default:
9153deb3ec6SMatthias Ringwald             break;
9163deb3ec6SMatthias Ringwald     }
9173deb3ec6SMatthias Ringwald     hfp_run();
9183deb3ec6SMatthias Ringwald }
9193deb3ec6SMatthias Ringwald 
9203deb3ec6SMatthias Ringwald void hfp_hf_set_codecs(uint8_t * codecs, int codecs_nr){
9213deb3ec6SMatthias Ringwald     if (codecs_nr > HFP_MAX_NUM_CODECS){
9223deb3ec6SMatthias Ringwald         log_error("hfp_hf_set_codecs: codecs_nr (%d) > HFP_MAX_NUM_CODECS (%d)", codecs_nr, HFP_MAX_NUM_CODECS);
9233deb3ec6SMatthias Ringwald         return;
9243deb3ec6SMatthias Ringwald     }
9253deb3ec6SMatthias Ringwald 
9263deb3ec6SMatthias Ringwald     hfp_codecs_nr = codecs_nr;
9273deb3ec6SMatthias Ringwald     int i;
9283deb3ec6SMatthias Ringwald     for (i=0; i<codecs_nr; i++){
9293deb3ec6SMatthias Ringwald         hfp_codecs[i] = codecs[i];
9303deb3ec6SMatthias Ringwald     }
9313deb3ec6SMatthias Ringwald 
9323deb3ec6SMatthias Ringwald     char buffer[30];
9333deb3ec6SMatthias Ringwald     int offset = join(buffer, sizeof(buffer), hfp_codecs, hfp_codecs_nr);
9343deb3ec6SMatthias Ringwald     buffer[offset] = 0;
9353deb3ec6SMatthias Ringwald     printf("set codecs %s\n", buffer);
9363deb3ec6SMatthias Ringwald 
9373deb3ec6SMatthias Ringwald     linked_list_iterator_t it;
9383deb3ec6SMatthias Ringwald     linked_list_iterator_init(&it, hfp_get_connections());
9393deb3ec6SMatthias Ringwald     while (linked_list_iterator_has_next(&it)){
9403deb3ec6SMatthias Ringwald         hfp_connection_t * connection = (hfp_connection_t *)linked_list_iterator_next(&it);
9413deb3ec6SMatthias Ringwald         if (!connection) continue;
942aa4dd815SMatthias Ringwald         connection->command = HFP_CMD_AVAILABLE_CODECS;
9433deb3ec6SMatthias Ringwald         hfp_run_for_context(connection);
9443deb3ec6SMatthias Ringwald     }
9453deb3ec6SMatthias Ringwald }
9463deb3ec6SMatthias Ringwald 
9473deb3ec6SMatthias Ringwald void hfp_hf_init(uint16_t rfcomm_channel_nr, uint32_t supported_features, uint16_t * indicators, int indicators_nr, uint32_t indicators_status){
948aa4dd815SMatthias Ringwald     l2cap_init();
949aa4dd815SMatthias Ringwald     l2cap_register_packet_handler(packet_handler);
950e4dd59a7SMatthias Ringwald     rfcomm_register_packet_handler(packet_handler);
9513deb3ec6SMatthias Ringwald     hfp_init(rfcomm_channel_nr);
9523deb3ec6SMatthias Ringwald 
9533deb3ec6SMatthias Ringwald     hfp_supported_features = supported_features;
9543deb3ec6SMatthias Ringwald 
9553deb3ec6SMatthias Ringwald     hfp_indicators_nr = indicators_nr;
9563deb3ec6SMatthias Ringwald     hfp_indicators_status = indicators_status;
9573deb3ec6SMatthias Ringwald     int i;
9583deb3ec6SMatthias Ringwald     for (i=0; i<indicators_nr; i++){
9593deb3ec6SMatthias Ringwald         hfp_indicators[i] = indicators[i];
9603deb3ec6SMatthias Ringwald     }
9613deb3ec6SMatthias Ringwald }
9623deb3ec6SMatthias Ringwald 
9633deb3ec6SMatthias Ringwald void hfp_hf_establish_service_level_connection(bd_addr_t bd_addr){
9643deb3ec6SMatthias Ringwald     hfp_establish_service_level_connection(bd_addr, SDP_HandsfreeAudioGateway);
9653deb3ec6SMatthias Ringwald }
9663deb3ec6SMatthias Ringwald 
9673deb3ec6SMatthias Ringwald void hfp_hf_release_service_level_connection(bd_addr_t bd_addr){
9683deb3ec6SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
9693deb3ec6SMatthias Ringwald     hfp_release_service_level_connection(connection);
9703deb3ec6SMatthias Ringwald     hfp_run_for_context(connection);
9713deb3ec6SMatthias Ringwald }
9723deb3ec6SMatthias Ringwald 
973*ce263fc8SMatthias Ringwald static void hfp_hf_set_status_update_for_all_ag_indicators(bd_addr_t bd_addr, uint8_t enable){
9743deb3ec6SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
9753deb3ec6SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
9763deb3ec6SMatthias Ringwald     if (!connection){
9773deb3ec6SMatthias Ringwald         log_error("HFP HF: connection doesn't exist.");
9783deb3ec6SMatthias Ringwald         return;
9793deb3ec6SMatthias Ringwald     }
9803deb3ec6SMatthias Ringwald     connection->enable_status_update_for_ag_indicators = enable;
9813deb3ec6SMatthias Ringwald     hfp_run_for_context(connection);
9823deb3ec6SMatthias Ringwald }
9833deb3ec6SMatthias Ringwald 
984*ce263fc8SMatthias Ringwald void hfp_hf_enable_status_update_for_all_ag_indicators(bd_addr_t bd_addr){
985*ce263fc8SMatthias Ringwald     hfp_hf_set_status_update_for_all_ag_indicators(bd_addr, 1);
986*ce263fc8SMatthias Ringwald }
987*ce263fc8SMatthias Ringwald 
988*ce263fc8SMatthias Ringwald void hfp_hf_disable_status_update_for_all_ag_indicators(bd_addr_t bd_addr){
989*ce263fc8SMatthias Ringwald     hfp_hf_set_status_update_for_all_ag_indicators(bd_addr, 0);
990*ce263fc8SMatthias Ringwald }
991*ce263fc8SMatthias Ringwald 
9923deb3ec6SMatthias Ringwald // TODO: returned ERROR - wrong format
993*ce263fc8SMatthias Ringwald void hfp_hf_set_status_update_for_individual_ag_indicators(bd_addr_t bd_addr, uint32_t indicators_status_bitmap){
9943deb3ec6SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
9953deb3ec6SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
9963deb3ec6SMatthias Ringwald     if (!connection){
9973deb3ec6SMatthias Ringwald         log_error("HFP HF: connection doesn't exist.");
9983deb3ec6SMatthias Ringwald         return;
9993deb3ec6SMatthias Ringwald     }
10003deb3ec6SMatthias Ringwald     connection->change_status_update_for_individual_ag_indicators = 1;
10013deb3ec6SMatthias Ringwald     connection->ag_indicators_status_update_bitmap = indicators_status_bitmap;
10023deb3ec6SMatthias Ringwald     hfp_run_for_context(connection);
10033deb3ec6SMatthias Ringwald }
10043deb3ec6SMatthias Ringwald 
10053deb3ec6SMatthias Ringwald void hfp_hf_query_operator_selection(bd_addr_t bd_addr){
10063deb3ec6SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
10073deb3ec6SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
10083deb3ec6SMatthias Ringwald     if (!connection){
10093deb3ec6SMatthias Ringwald         log_error("HFP HF: connection doesn't exist.");
10103deb3ec6SMatthias Ringwald         return;
10113deb3ec6SMatthias Ringwald     }
1012*ce263fc8SMatthias Ringwald     switch (connection->hf_query_operator_state){
1013*ce263fc8SMatthias Ringwald         case HFP_HF_QUERY_OPERATOR_FORMAT_NOT_SET:
1014*ce263fc8SMatthias Ringwald             connection->hf_query_operator_state = HFP_HF_QUERY_OPERATOR_SET_FORMAT;
1015*ce263fc8SMatthias Ringwald             break;
1016*ce263fc8SMatthias Ringwald         case HFP_HF_QUERY_OPERATOR_FORMAT_SET:
1017*ce263fc8SMatthias Ringwald             connection->hf_query_operator_state = HFP_HF_QUERY_OPERATOR_SEND_QUERY;
1018*ce263fc8SMatthias Ringwald             break;
1019*ce263fc8SMatthias Ringwald         default:
1020*ce263fc8SMatthias Ringwald             break;
1021*ce263fc8SMatthias Ringwald     }
10223deb3ec6SMatthias Ringwald     hfp_run_for_context(connection);
10233deb3ec6SMatthias Ringwald }
10243deb3ec6SMatthias Ringwald 
1025*ce263fc8SMatthias Ringwald static void hfp_hf_set_report_extended_audio_gateway_error_result_code(bd_addr_t bd_addr, uint8_t enable){
10263deb3ec6SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
10273deb3ec6SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
10283deb3ec6SMatthias Ringwald     if (!connection){
10293deb3ec6SMatthias Ringwald         log_error("HFP HF: connection doesn't exist.");
10303deb3ec6SMatthias Ringwald         return;
10313deb3ec6SMatthias Ringwald     }
10323deb3ec6SMatthias Ringwald     connection->enable_extended_audio_gateway_error_report = enable;
10333deb3ec6SMatthias Ringwald     hfp_run_for_context(connection);
10343deb3ec6SMatthias Ringwald }
10353deb3ec6SMatthias Ringwald 
1036*ce263fc8SMatthias Ringwald 
1037*ce263fc8SMatthias Ringwald void hfp_hf_enable_report_extended_audio_gateway_error_result_code(bd_addr_t bd_addr){
1038*ce263fc8SMatthias Ringwald     hfp_hf_set_report_extended_audio_gateway_error_result_code(bd_addr, 1);
1039*ce263fc8SMatthias Ringwald }
1040*ce263fc8SMatthias Ringwald 
1041*ce263fc8SMatthias Ringwald void hfp_hf_disable_report_extended_audio_gateway_error_result_code(bd_addr_t bd_addr){
1042*ce263fc8SMatthias Ringwald     hfp_hf_set_report_extended_audio_gateway_error_result_code(bd_addr, 0);
1043*ce263fc8SMatthias Ringwald }
1044*ce263fc8SMatthias Ringwald 
1045*ce263fc8SMatthias Ringwald 
10463deb3ec6SMatthias Ringwald void hfp_hf_establish_audio_connection(bd_addr_t bd_addr){
10473deb3ec6SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
10483deb3ec6SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
10493deb3ec6SMatthias Ringwald     connection->establish_audio_connection = 0;
1050*ce263fc8SMatthias Ringwald 
10513deb3ec6SMatthias Ringwald     if (connection->state == HFP_AUDIO_CONNECTION_ESTABLISHED) return;
10523deb3ec6SMatthias Ringwald     if (connection->state >= HFP_W2_DISCONNECT_SCO) return;
10533deb3ec6SMatthias Ringwald 
1054*ce263fc8SMatthias Ringwald     if (!has_codec_negotiation_feature(connection)){
1055*ce263fc8SMatthias Ringwald         log_info("hfp_ag_establish_audio_connection - no codec negotiation feature, using defaults");
1056*ce263fc8SMatthias Ringwald         connection->codecs_state = HFP_CODECS_EXCHANGED;
10573deb3ec6SMatthias Ringwald         connection->establish_audio_connection = 1;
1058*ce263fc8SMatthias Ringwald     } else {
1059aa4dd815SMatthias Ringwald         switch (connection->codecs_state){
1060aa4dd815SMatthias Ringwald             case HFP_CODECS_W4_AG_COMMON_CODEC:
1061aa4dd815SMatthias Ringwald                 break;
1062aa4dd815SMatthias Ringwald             default:
1063aa4dd815SMatthias Ringwald                 connection->command = HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP;
1064aa4dd815SMatthias Ringwald                 break;
10653deb3ec6SMatthias Ringwald         }
1066*ce263fc8SMatthias Ringwald     }
1067*ce263fc8SMatthias Ringwald 
10683deb3ec6SMatthias Ringwald     hfp_run_for_context(connection);
10693deb3ec6SMatthias Ringwald }
10703deb3ec6SMatthias Ringwald 
10713deb3ec6SMatthias Ringwald void hfp_hf_release_audio_connection(bd_addr_t bd_addr){
10723deb3ec6SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
10733deb3ec6SMatthias Ringwald     hfp_release_audio_connection(connection);
10743deb3ec6SMatthias Ringwald     hfp_run_for_context(connection);
10753deb3ec6SMatthias Ringwald }
10763deb3ec6SMatthias Ringwald 
1077*ce263fc8SMatthias Ringwald void hfp_hf_answer_incoming_call(bd_addr_t bd_addr){
1078*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
1079*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
1080*ce263fc8SMatthias Ringwald 
1081*ce263fc8SMatthias Ringwald     if (hfp_callsetup_status == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS){
1082*ce263fc8SMatthias Ringwald         connection->hf_answer_incoming_call = 1;
1083*ce263fc8SMatthias Ringwald         hfp_run_for_context(connection);
1084*ce263fc8SMatthias Ringwald     } else {
1085*ce263fc8SMatthias Ringwald         log_error("HFP HF: answering incoming call with wrong callsetup status %u", hfp_callsetup_status);
1086*ce263fc8SMatthias Ringwald     }
1087*ce263fc8SMatthias Ringwald }
1088*ce263fc8SMatthias Ringwald 
1089*ce263fc8SMatthias Ringwald void hfp_hf_terminate_call(bd_addr_t bd_addr){
1090*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
1091*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
1092*ce263fc8SMatthias Ringwald 
1093*ce263fc8SMatthias Ringwald     // if (hfp_call_status == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){
1094*ce263fc8SMatthias Ringwald     connection->hf_send_chup = 1;
1095*ce263fc8SMatthias Ringwald     hfp_run_for_context(connection);
1096*ce263fc8SMatthias Ringwald     // } else {
1097*ce263fc8SMatthias Ringwald     //     log_error("HFP HF: terminating incoming call with wrong call status %u", hfp_call_status);
1098*ce263fc8SMatthias Ringwald     // }
1099*ce263fc8SMatthias Ringwald }
1100*ce263fc8SMatthias Ringwald 
1101*ce263fc8SMatthias Ringwald void hfp_hf_reject_call(bd_addr_t bd_addr){
1102*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
1103*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
1104*ce263fc8SMatthias Ringwald 
1105*ce263fc8SMatthias Ringwald     if (hfp_callsetup_status == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS){
1106*ce263fc8SMatthias Ringwald         connection->hf_send_chup = 1;
1107*ce263fc8SMatthias Ringwald         hfp_run_for_context(connection);
1108*ce263fc8SMatthias Ringwald     }
1109*ce263fc8SMatthias Ringwald }
1110*ce263fc8SMatthias Ringwald 
1111*ce263fc8SMatthias Ringwald void hfp_hf_user_busy(bd_addr_t addr){
1112*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(addr);
1113*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(addr);
1114*ce263fc8SMatthias Ringwald 
1115*ce263fc8SMatthias Ringwald     if (hfp_callsetup_status == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS){
1116*ce263fc8SMatthias Ringwald         connection->hf_send_chld_0 = 1;
1117*ce263fc8SMatthias Ringwald         hfp_run_for_context(connection);
1118*ce263fc8SMatthias Ringwald     }
1119*ce263fc8SMatthias Ringwald }
1120*ce263fc8SMatthias Ringwald 
1121*ce263fc8SMatthias Ringwald void hfp_hf_end_active_and_accept_other(bd_addr_t addr){
1122*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(addr);
1123*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(addr);
1124*ce263fc8SMatthias Ringwald 
1125*ce263fc8SMatthias Ringwald     if (hfp_callsetup_status == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS ||
1126*ce263fc8SMatthias Ringwald         hfp_call_status == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){
1127*ce263fc8SMatthias Ringwald         connection->hf_send_chld_1 = 1;
1128*ce263fc8SMatthias Ringwald         hfp_run_for_context(connection);
1129*ce263fc8SMatthias Ringwald     }
1130*ce263fc8SMatthias Ringwald }
1131*ce263fc8SMatthias Ringwald 
1132*ce263fc8SMatthias Ringwald void hfp_hf_swap_calls(bd_addr_t addr){
1133*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(addr);
1134*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(addr);
1135*ce263fc8SMatthias Ringwald 
1136*ce263fc8SMatthias Ringwald     if (hfp_callsetup_status == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS ||
1137*ce263fc8SMatthias Ringwald         hfp_call_status == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){
1138*ce263fc8SMatthias Ringwald         connection->hf_send_chld_2 = 1;
1139*ce263fc8SMatthias Ringwald         hfp_run_for_context(connection);
1140*ce263fc8SMatthias Ringwald     }
1141*ce263fc8SMatthias Ringwald }
1142*ce263fc8SMatthias Ringwald 
1143*ce263fc8SMatthias Ringwald void hfp_hf_join_held_call(bd_addr_t addr){
1144*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(addr);
1145*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(addr);
1146*ce263fc8SMatthias Ringwald 
1147*ce263fc8SMatthias Ringwald     if (hfp_callsetup_status == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS ||
1148*ce263fc8SMatthias Ringwald         hfp_call_status == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){
1149*ce263fc8SMatthias Ringwald         connection->hf_send_chld_3 = 1;
1150*ce263fc8SMatthias Ringwald         hfp_run_for_context(connection);
1151*ce263fc8SMatthias Ringwald     }
1152*ce263fc8SMatthias Ringwald }
1153*ce263fc8SMatthias Ringwald 
1154*ce263fc8SMatthias Ringwald void hfp_hf_connect_calls(bd_addr_t addr){
1155*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(addr);
1156*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(addr);
1157*ce263fc8SMatthias Ringwald 
1158*ce263fc8SMatthias Ringwald     if (hfp_callsetup_status == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS ||
1159*ce263fc8SMatthias Ringwald         hfp_call_status == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){
1160*ce263fc8SMatthias Ringwald         connection->hf_send_chld_4 = 1;
1161*ce263fc8SMatthias Ringwald         hfp_run_for_context(connection);
1162*ce263fc8SMatthias Ringwald     }
1163*ce263fc8SMatthias Ringwald }
1164*ce263fc8SMatthias Ringwald 
1165*ce263fc8SMatthias Ringwald /**
1166*ce263fc8SMatthias Ringwald  * @brief
1167*ce263fc8SMatthias Ringwald  */
1168*ce263fc8SMatthias Ringwald void hfp_hf_connect_calls(bd_addr_t addr);
1169*ce263fc8SMatthias Ringwald 
1170*ce263fc8SMatthias Ringwald void hfp_hf_dial_number(bd_addr_t bd_addr, char * number){
1171*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
1172*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
1173*ce263fc8SMatthias Ringwald 
1174*ce263fc8SMatthias Ringwald     connection->hf_initiate_outgoing_call = 1;
1175*ce263fc8SMatthias Ringwald     snprintf(phone_number, sizeof(phone_number), "%s", number);
1176*ce263fc8SMatthias Ringwald     hfp_run_for_context(connection);
1177*ce263fc8SMatthias Ringwald }
1178*ce263fc8SMatthias Ringwald 
1179*ce263fc8SMatthias Ringwald void hfp_hf_dial_memory(bd_addr_t bd_addr, char * number){
1180*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
1181*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
1182*ce263fc8SMatthias Ringwald 
1183*ce263fc8SMatthias Ringwald     connection->hf_initiate_memory_dialing = 1;
1184*ce263fc8SMatthias Ringwald     snprintf(phone_number, sizeof(phone_number), "%s", number);
1185*ce263fc8SMatthias Ringwald     hfp_run_for_context(connection);
1186*ce263fc8SMatthias Ringwald }
1187*ce263fc8SMatthias Ringwald 
1188*ce263fc8SMatthias Ringwald void hfp_hf_redial_last_number(bd_addr_t bd_addr){
1189*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
1190*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
1191*ce263fc8SMatthias Ringwald 
1192*ce263fc8SMatthias Ringwald     connection->hf_initiate_redial_last_number = 1;
1193*ce263fc8SMatthias Ringwald     hfp_run_for_context(connection);
1194*ce263fc8SMatthias Ringwald }
1195*ce263fc8SMatthias Ringwald 
1196*ce263fc8SMatthias Ringwald void hfp_hf_activate_call_waiting_notification(bd_addr_t bd_addr){
1197*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
1198*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
1199*ce263fc8SMatthias Ringwald 
1200*ce263fc8SMatthias Ringwald     connection->hf_activate_call_waiting_notification = 1;
1201*ce263fc8SMatthias Ringwald     hfp_run_for_context(connection);
1202*ce263fc8SMatthias Ringwald }
1203*ce263fc8SMatthias Ringwald 
1204*ce263fc8SMatthias Ringwald 
1205*ce263fc8SMatthias Ringwald void hfp_hf_deactivate_call_waiting_notification(bd_addr_t bd_addr){
1206*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
1207*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
1208*ce263fc8SMatthias Ringwald 
1209*ce263fc8SMatthias Ringwald     connection->hf_deactivate_call_waiting_notification = 1;
1210*ce263fc8SMatthias Ringwald     hfp_run_for_context(connection);
1211*ce263fc8SMatthias Ringwald }
1212*ce263fc8SMatthias Ringwald 
1213*ce263fc8SMatthias Ringwald 
1214*ce263fc8SMatthias Ringwald void hfp_hf_activate_calling_line_notification(bd_addr_t bd_addr){
1215*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
1216*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
1217*ce263fc8SMatthias Ringwald 
1218*ce263fc8SMatthias Ringwald     connection->hf_deactivate_calling_line_notification = 1;
1219*ce263fc8SMatthias Ringwald     hfp_run_for_context(connection);
1220*ce263fc8SMatthias Ringwald }
1221*ce263fc8SMatthias Ringwald 
1222*ce263fc8SMatthias Ringwald /*
1223*ce263fc8SMatthias Ringwald  * @brief
1224*ce263fc8SMatthias Ringwald  */
1225*ce263fc8SMatthias Ringwald void hfp_hf_deactivate_calling_line_notification(bd_addr_t bd_addr){
1226*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
1227*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
1228*ce263fc8SMatthias Ringwald 
1229*ce263fc8SMatthias Ringwald     connection->hf_deactivate_calling_line_notification = 1;
1230*ce263fc8SMatthias Ringwald     hfp_run_for_context(connection);
1231*ce263fc8SMatthias Ringwald }
1232*ce263fc8SMatthias Ringwald 
1233*ce263fc8SMatthias Ringwald 
1234*ce263fc8SMatthias Ringwald /*
1235*ce263fc8SMatthias Ringwald  * @brief
1236*ce263fc8SMatthias Ringwald  */
1237*ce263fc8SMatthias Ringwald void hfp_hf_activate_echo_canceling_and_noise_reduction(bd_addr_t bd_addr){
1238*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
1239*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
1240*ce263fc8SMatthias Ringwald 
1241*ce263fc8SMatthias Ringwald     connection->hf_deactivate_echo_canceling_and_noise_reduction = 1;
1242*ce263fc8SMatthias Ringwald     hfp_run_for_context(connection);
1243*ce263fc8SMatthias Ringwald }
1244*ce263fc8SMatthias Ringwald 
1245*ce263fc8SMatthias Ringwald /*
1246*ce263fc8SMatthias Ringwald  * @brief
1247*ce263fc8SMatthias Ringwald  */
1248*ce263fc8SMatthias Ringwald void hfp_hf_deactivate_echo_canceling_and_noise_reduction(bd_addr_t bd_addr){
1249*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
1250*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
1251*ce263fc8SMatthias Ringwald 
1252*ce263fc8SMatthias Ringwald     connection->hf_deactivate_echo_canceling_and_noise_reduction = 1;
1253*ce263fc8SMatthias Ringwald     hfp_run_for_context(connection);
1254*ce263fc8SMatthias Ringwald }
1255*ce263fc8SMatthias Ringwald 
1256*ce263fc8SMatthias Ringwald /*
1257*ce263fc8SMatthias Ringwald  * @brief
1258*ce263fc8SMatthias Ringwald  */
1259*ce263fc8SMatthias Ringwald void hfp_hf_activate_voice_recognition_notification(bd_addr_t bd_addr){
1260*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
1261*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
1262*ce263fc8SMatthias Ringwald 
1263*ce263fc8SMatthias Ringwald     connection->hf_activate_voice_recognition_notification = 1;
1264*ce263fc8SMatthias Ringwald     hfp_run_for_context(connection);
1265*ce263fc8SMatthias Ringwald }
1266*ce263fc8SMatthias Ringwald 
1267*ce263fc8SMatthias Ringwald /*
1268*ce263fc8SMatthias Ringwald  * @brief
1269*ce263fc8SMatthias Ringwald  */
1270*ce263fc8SMatthias Ringwald void hfp_hf_deactivate_voice_recognition_notification(bd_addr_t bd_addr){
1271*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
1272*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
1273*ce263fc8SMatthias Ringwald 
1274*ce263fc8SMatthias Ringwald     connection->hf_deactivate_voice_recognition_notification = 1;
1275*ce263fc8SMatthias Ringwald     hfp_run_for_context(connection);
1276*ce263fc8SMatthias Ringwald }
1277*ce263fc8SMatthias Ringwald 
1278*ce263fc8SMatthias Ringwald /*
1279*ce263fc8SMatthias Ringwald  * @brief
1280*ce263fc8SMatthias Ringwald  */
1281*ce263fc8SMatthias Ringwald void hfp_hf_set_microphone_gain(bd_addr_t bd_addr, int gain){
1282*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
1283*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
1284*ce263fc8SMatthias Ringwald     if (connection->microphone_gain == gain) return;
1285*ce263fc8SMatthias Ringwald 
1286*ce263fc8SMatthias Ringwald     connection->microphone_gain = gain;
1287*ce263fc8SMatthias Ringwald     connection->send_microphone_gain = 1;
1288*ce263fc8SMatthias Ringwald     hfp_run_for_context(connection);
1289*ce263fc8SMatthias Ringwald }
1290*ce263fc8SMatthias Ringwald 
1291*ce263fc8SMatthias Ringwald /*
1292*ce263fc8SMatthias Ringwald  * @brief
1293*ce263fc8SMatthias Ringwald  */
1294*ce263fc8SMatthias Ringwald void hfp_hf_set_speaker_gain(bd_addr_t bd_addr, int gain){
1295*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
1296*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
1297*ce263fc8SMatthias Ringwald     if (connection->speaker_gain == gain) return;
1298*ce263fc8SMatthias Ringwald 
1299*ce263fc8SMatthias Ringwald     connection->speaker_gain = gain;
1300*ce263fc8SMatthias Ringwald     connection->send_speaker_gain = 1;
1301*ce263fc8SMatthias Ringwald     hfp_run_for_context(connection);
1302*ce263fc8SMatthias Ringwald }
1303*ce263fc8SMatthias Ringwald 
1304*ce263fc8SMatthias Ringwald /*
1305*ce263fc8SMatthias Ringwald  * @brief
1306*ce263fc8SMatthias Ringwald  */
1307*ce263fc8SMatthias Ringwald void hfp_hf_send_dtmf_code(bd_addr_t addr, char code){
1308*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(addr);
1309*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(addr);
1310*ce263fc8SMatthias Ringwald     connection->hf_send_dtmf_code = code;
1311*ce263fc8SMatthias Ringwald     hfp_run_for_context(connection);
1312*ce263fc8SMatthias Ringwald }
1313*ce263fc8SMatthias Ringwald 
1314*ce263fc8SMatthias Ringwald /*
1315*ce263fc8SMatthias Ringwald  * @brief
1316*ce263fc8SMatthias Ringwald  */
1317*ce263fc8SMatthias Ringwald void hfp_hf_request_phone_number_for_voice_tag(bd_addr_t addr){
1318*ce263fc8SMatthias Ringwald     hfp_hf_establish_service_level_connection(addr);
1319*ce263fc8SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(addr);
1320*ce263fc8SMatthias Ringwald     connection->hf_send_binp = 1;
1321*ce263fc8SMatthias Ringwald     hfp_run_for_context(connection);
1322*ce263fc8SMatthias Ringwald }
13233deb3ec6SMatthias Ringwald 
1324