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