1*3deb3ec6SMatthias Ringwald /* 2*3deb3ec6SMatthias Ringwald * Copyright (C) 2014 BlueKitchen GmbH 3*3deb3ec6SMatthias Ringwald * 4*3deb3ec6SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5*3deb3ec6SMatthias Ringwald * modification, are permitted provided that the following conditions 6*3deb3ec6SMatthias Ringwald * are met: 7*3deb3ec6SMatthias Ringwald * 8*3deb3ec6SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9*3deb3ec6SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10*3deb3ec6SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11*3deb3ec6SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12*3deb3ec6SMatthias Ringwald * documentation and/or other materials provided with the distribution. 13*3deb3ec6SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14*3deb3ec6SMatthias Ringwald * contributors may be used to endorse or promote products derived 15*3deb3ec6SMatthias Ringwald * from this software without specific prior written permission. 16*3deb3ec6SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17*3deb3ec6SMatthias Ringwald * personal benefit and not for any commercial purpose or for 18*3deb3ec6SMatthias Ringwald * monetary gain. 19*3deb3ec6SMatthias Ringwald * 20*3deb3ec6SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21*3deb3ec6SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*3deb3ec6SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23*3deb3ec6SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24*3deb3ec6SMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25*3deb3ec6SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26*3deb3ec6SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27*3deb3ec6SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28*3deb3ec6SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29*3deb3ec6SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30*3deb3ec6SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*3deb3ec6SMatthias Ringwald * SUCH DAMAGE. 32*3deb3ec6SMatthias Ringwald * 33*3deb3ec6SMatthias Ringwald * Please inquire about commercial licensing options at 34*3deb3ec6SMatthias Ringwald * [email protected] 35*3deb3ec6SMatthias Ringwald * 36*3deb3ec6SMatthias Ringwald */ 37*3deb3ec6SMatthias Ringwald 38*3deb3ec6SMatthias Ringwald // ***************************************************************************** 39*3deb3ec6SMatthias Ringwald // 40*3deb3ec6SMatthias Ringwald // Minimal setup for HFP Hands-Free (HF) unit (!! UNDER DEVELOPMENT !!) 41*3deb3ec6SMatthias Ringwald // 42*3deb3ec6SMatthias Ringwald // ***************************************************************************** 43*3deb3ec6SMatthias Ringwald 44*3deb3ec6SMatthias Ringwald #include "btstack-config.h" 45*3deb3ec6SMatthias Ringwald 46*3deb3ec6SMatthias Ringwald #include <stdint.h> 47*3deb3ec6SMatthias Ringwald #include <stdio.h> 48*3deb3ec6SMatthias Ringwald #include <stdlib.h> 49*3deb3ec6SMatthias Ringwald #include <string.h> 50*3deb3ec6SMatthias Ringwald 51*3deb3ec6SMatthias Ringwald #include "hci_cmds.h" 52*3deb3ec6SMatthias Ringwald #include "run_loop.h" 53*3deb3ec6SMatthias Ringwald 54*3deb3ec6SMatthias Ringwald #include "hci.h" 55*3deb3ec6SMatthias Ringwald #include "btstack_memory.h" 56*3deb3ec6SMatthias Ringwald #include "hci_dump.h" 57*3deb3ec6SMatthias Ringwald #include "l2cap.h" 58*3deb3ec6SMatthias Ringwald #include "sdp_query_rfcomm.h" 59*3deb3ec6SMatthias Ringwald #include "sdp.h" 60*3deb3ec6SMatthias Ringwald #include "debug.h" 61*3deb3ec6SMatthias Ringwald #include "hfp.h" 62*3deb3ec6SMatthias Ringwald #include "hfp_hf.h" 63*3deb3ec6SMatthias Ringwald 64*3deb3ec6SMatthias Ringwald 65*3deb3ec6SMatthias Ringwald static const char default_hfp_hf_service_name[] = "Hands-Free unit"; 66*3deb3ec6SMatthias Ringwald static uint16_t hfp_supported_features = HFP_DEFAULT_HF_SUPPORTED_FEATURES; 67*3deb3ec6SMatthias Ringwald static uint8_t hfp_codecs_nr = 0; 68*3deb3ec6SMatthias Ringwald static uint8_t hfp_codecs[HFP_MAX_NUM_CODECS]; 69*3deb3ec6SMatthias Ringwald 70*3deb3ec6SMatthias Ringwald static uint8_t hfp_indicators_nr = 0; 71*3deb3ec6SMatthias Ringwald static uint8_t hfp_indicators[HFP_MAX_NUM_HF_INDICATORS]; 72*3deb3ec6SMatthias Ringwald static uint8_t hfp_indicators_status; 73*3deb3ec6SMatthias Ringwald 74*3deb3ec6SMatthias Ringwald static hfp_callback_t hfp_callback; 75*3deb3ec6SMatthias Ringwald 76*3deb3ec6SMatthias Ringwald void hfp_hf_register_packet_handler(hfp_callback_t callback){ 77*3deb3ec6SMatthias Ringwald hfp_callback = callback; 78*3deb3ec6SMatthias Ringwald if (callback == NULL){ 79*3deb3ec6SMatthias Ringwald log_error("hfp_hf_register_packet_handler called with NULL callback"); 80*3deb3ec6SMatthias Ringwald return; 81*3deb3ec6SMatthias Ringwald } 82*3deb3ec6SMatthias Ringwald hfp_callback = callback; 83*3deb3ec6SMatthias Ringwald } 84*3deb3ec6SMatthias Ringwald 85*3deb3ec6SMatthias Ringwald static int hfp_hf_supports_codec(uint8_t codec){ 86*3deb3ec6SMatthias Ringwald int i; 87*3deb3ec6SMatthias Ringwald for (i = 0; i < hfp_codecs_nr; i++){ 88*3deb3ec6SMatthias Ringwald if (hfp_codecs[i] == codec) return 1; 89*3deb3ec6SMatthias Ringwald } 90*3deb3ec6SMatthias Ringwald return 0; 91*3deb3ec6SMatthias Ringwald } 92*3deb3ec6SMatthias Ringwald static int has_codec_negotiation_feature(hfp_connection_t * connection){ 93*3deb3ec6SMatthias Ringwald int hf = get_bit(hfp_supported_features, HFP_HFSF_CODEC_NEGOTIATION); 94*3deb3ec6SMatthias Ringwald int ag = get_bit(connection->remote_supported_features, HFP_AGSF_CODEC_NEGOTIATION); 95*3deb3ec6SMatthias Ringwald return hf && ag; 96*3deb3ec6SMatthias Ringwald } 97*3deb3ec6SMatthias Ringwald 98*3deb3ec6SMatthias Ringwald static int has_call_waiting_and_3way_calling_feature(hfp_connection_t * connection){ 99*3deb3ec6SMatthias Ringwald int hf = get_bit(hfp_supported_features, HFP_HFSF_THREE_WAY_CALLING); 100*3deb3ec6SMatthias Ringwald int ag = get_bit(connection->remote_supported_features, HFP_AGSF_THREE_WAY_CALLING); 101*3deb3ec6SMatthias Ringwald return hf && ag; 102*3deb3ec6SMatthias Ringwald } 103*3deb3ec6SMatthias Ringwald 104*3deb3ec6SMatthias Ringwald 105*3deb3ec6SMatthias Ringwald static int has_hf_indicators_feature(hfp_connection_t * connection){ 106*3deb3ec6SMatthias Ringwald int hf = get_bit(hfp_supported_features, HFP_HFSF_HF_INDICATORS); 107*3deb3ec6SMatthias Ringwald int ag = get_bit(connection->remote_supported_features, HFP_AGSF_HF_INDICATORS); 108*3deb3ec6SMatthias Ringwald return hf && ag; 109*3deb3ec6SMatthias Ringwald } 110*3deb3ec6SMatthias Ringwald 111*3deb3ec6SMatthias Ringwald static void packet_handler(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 112*3deb3ec6SMatthias Ringwald 113*3deb3ec6SMatthias Ringwald void hfp_hf_create_sdp_record(uint8_t * service, int rfcomm_channel_nr, const char * name, uint16_t supported_features){ 114*3deb3ec6SMatthias Ringwald if (!name){ 115*3deb3ec6SMatthias Ringwald name = default_hfp_hf_service_name; 116*3deb3ec6SMatthias Ringwald } 117*3deb3ec6SMatthias Ringwald hfp_create_sdp_record(service, SDP_Handsfree, rfcomm_channel_nr, name, supported_features); 118*3deb3ec6SMatthias Ringwald } 119*3deb3ec6SMatthias Ringwald 120*3deb3ec6SMatthias Ringwald 121*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_exchange_supported_features(uint16_t cid){ 122*3deb3ec6SMatthias Ringwald char buffer[20]; 123*3deb3ec6SMatthias Ringwald sprintf(buffer, "AT%s=%d\r\n", HFP_SUPPORTED_FEATURES, hfp_supported_features); 124*3deb3ec6SMatthias Ringwald // printf("exchange_supported_features %s\n", buffer); 125*3deb3ec6SMatthias Ringwald return send_str_over_rfcomm(cid, buffer); 126*3deb3ec6SMatthias Ringwald } 127*3deb3ec6SMatthias Ringwald 128*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_notify_on_codecs(uint16_t cid){ 129*3deb3ec6SMatthias Ringwald char buffer[30]; 130*3deb3ec6SMatthias Ringwald int offset = snprintf(buffer, sizeof(buffer), "AT%s=", HFP_AVAILABLE_CODECS); 131*3deb3ec6SMatthias Ringwald offset += join(buffer+offset, sizeof(buffer)-offset, hfp_codecs, hfp_codecs_nr); 132*3deb3ec6SMatthias Ringwald offset += snprintf(buffer+offset, sizeof(buffer)-offset, "\r\n"); 133*3deb3ec6SMatthias Ringwald buffer[offset] = 0; 134*3deb3ec6SMatthias Ringwald return send_str_over_rfcomm(cid, buffer); 135*3deb3ec6SMatthias Ringwald } 136*3deb3ec6SMatthias Ringwald 137*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_retrieve_indicators(uint16_t cid){ 138*3deb3ec6SMatthias Ringwald char buffer[20]; 139*3deb3ec6SMatthias Ringwald sprintf(buffer, "AT%s=?\r\n", HFP_INDICATOR); 140*3deb3ec6SMatthias Ringwald // printf("retrieve_indicators %s\n", buffer); 141*3deb3ec6SMatthias Ringwald return send_str_over_rfcomm(cid, buffer); 142*3deb3ec6SMatthias Ringwald } 143*3deb3ec6SMatthias Ringwald 144*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_retrieve_indicators_status(uint16_t cid){ 145*3deb3ec6SMatthias Ringwald char buffer[20]; 146*3deb3ec6SMatthias Ringwald sprintf(buffer, "AT%s?\r\n", HFP_INDICATOR); 147*3deb3ec6SMatthias Ringwald // printf("retrieve_indicators_status %s\n", buffer); 148*3deb3ec6SMatthias Ringwald return send_str_over_rfcomm(cid, buffer); 149*3deb3ec6SMatthias Ringwald } 150*3deb3ec6SMatthias Ringwald 151*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_activate_status_update_for_all_ag_indicators(uint16_t cid, uint8_t activate){ 152*3deb3ec6SMatthias Ringwald char buffer[20]; 153*3deb3ec6SMatthias Ringwald sprintf(buffer, "AT%s=3,0,0,%d\r\n", HFP_ENABLE_STATUS_UPDATE_FOR_AG_INDICATORS, activate); 154*3deb3ec6SMatthias Ringwald // printf("toggle_indicator_status_update %s\n", buffer); 155*3deb3ec6SMatthias Ringwald return send_str_over_rfcomm(cid, buffer); 156*3deb3ec6SMatthias Ringwald } 157*3deb3ec6SMatthias Ringwald 158*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_activate_status_update_for_ag_indicator(uint16_t cid, uint32_t indicators_status, int indicators_nr){ 159*3deb3ec6SMatthias Ringwald char buffer[50]; 160*3deb3ec6SMatthias Ringwald int offset = snprintf(buffer, sizeof(buffer), "AT%s=", HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS); 161*3deb3ec6SMatthias Ringwald offset += join_bitmap(buffer+offset, sizeof(buffer)-offset, indicators_status, indicators_nr); 162*3deb3ec6SMatthias Ringwald offset += snprintf(buffer+offset, sizeof(buffer)-offset, "\r\n"); 163*3deb3ec6SMatthias Ringwald buffer[offset] = 0; 164*3deb3ec6SMatthias Ringwald return send_str_over_rfcomm(cid, buffer); 165*3deb3ec6SMatthias Ringwald } 166*3deb3ec6SMatthias Ringwald 167*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_retrieve_can_hold_call(uint16_t cid){ 168*3deb3ec6SMatthias Ringwald char buffer[20]; 169*3deb3ec6SMatthias Ringwald sprintf(buffer, "AT%s=?\r\n", HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES); 170*3deb3ec6SMatthias Ringwald // printf("retrieve_can_hold_call %s\n", buffer); 171*3deb3ec6SMatthias Ringwald return send_str_over_rfcomm(cid, buffer); 172*3deb3ec6SMatthias Ringwald } 173*3deb3ec6SMatthias Ringwald 174*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_list_supported_generic_status_indicators(uint16_t cid){ 175*3deb3ec6SMatthias Ringwald char buffer[30]; 176*3deb3ec6SMatthias Ringwald int offset = snprintf(buffer, sizeof(buffer), "AT%s=", HFP_GENERIC_STATUS_INDICATOR); 177*3deb3ec6SMatthias Ringwald offset += join(buffer+offset, sizeof(buffer)-offset, hfp_indicators, hfp_indicators_nr); 178*3deb3ec6SMatthias Ringwald offset += snprintf(buffer+offset, sizeof(buffer)-offset, "\r\n"); 179*3deb3ec6SMatthias Ringwald buffer[offset] = 0; 180*3deb3ec6SMatthias Ringwald return send_str_over_rfcomm(cid, buffer); 181*3deb3ec6SMatthias Ringwald } 182*3deb3ec6SMatthias Ringwald 183*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_retrieve_supported_generic_status_indicators(uint16_t cid){ 184*3deb3ec6SMatthias Ringwald char buffer[20]; 185*3deb3ec6SMatthias Ringwald sprintf(buffer, "AT%s=?\r\n", HFP_GENERIC_STATUS_INDICATOR); 186*3deb3ec6SMatthias Ringwald // printf("retrieve_supported_generic_status_indicators %s\n", buffer); 187*3deb3ec6SMatthias Ringwald return send_str_over_rfcomm(cid, buffer); 188*3deb3ec6SMatthias Ringwald } 189*3deb3ec6SMatthias Ringwald 190*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_list_initital_supported_generic_status_indicators(uint16_t cid){ 191*3deb3ec6SMatthias Ringwald char buffer[20]; 192*3deb3ec6SMatthias Ringwald sprintf(buffer, "AT%s?\r\n", HFP_GENERIC_STATUS_INDICATOR); 193*3deb3ec6SMatthias Ringwald // printf("list_initital_supported_generic_status_indicators %s\n", buffer); 194*3deb3ec6SMatthias Ringwald return send_str_over_rfcomm(cid, buffer); 195*3deb3ec6SMatthias Ringwald } 196*3deb3ec6SMatthias Ringwald 197*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_query_operator_name_format(uint16_t cid){ 198*3deb3ec6SMatthias Ringwald char buffer[20]; 199*3deb3ec6SMatthias Ringwald sprintf(buffer, "AT%s=3,0\r\n", HFP_QUERY_OPERATOR_SELECTION); 200*3deb3ec6SMatthias Ringwald return send_str_over_rfcomm(cid, buffer); 201*3deb3ec6SMatthias Ringwald } 202*3deb3ec6SMatthias Ringwald 203*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_query_operator_name(uint16_t cid){ 204*3deb3ec6SMatthias Ringwald char buffer[20]; 205*3deb3ec6SMatthias Ringwald sprintf(buffer, "AT%s?\r\n", HFP_QUERY_OPERATOR_SELECTION); 206*3deb3ec6SMatthias Ringwald return send_str_over_rfcomm(cid, buffer); 207*3deb3ec6SMatthias Ringwald } 208*3deb3ec6SMatthias Ringwald 209*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_enable_extended_audio_gateway_error_report(uint16_t cid, uint8_t enable){ 210*3deb3ec6SMatthias Ringwald char buffer[20]; 211*3deb3ec6SMatthias Ringwald sprintf(buffer, "AT%s=%d\r\n", HFP_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR, enable); 212*3deb3ec6SMatthias Ringwald return send_str_over_rfcomm(cid, buffer); 213*3deb3ec6SMatthias Ringwald } 214*3deb3ec6SMatthias Ringwald 215*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_trigger_codec_connection_setup(uint16_t cid){ 216*3deb3ec6SMatthias Ringwald char buffer[20]; 217*3deb3ec6SMatthias Ringwald sprintf(buffer, "AT%s\r\n", HFP_TRIGGER_CODEC_CONNECTION_SETUP); 218*3deb3ec6SMatthias Ringwald return send_str_over_rfcomm(cid, buffer); 219*3deb3ec6SMatthias Ringwald } 220*3deb3ec6SMatthias Ringwald 221*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_confirm_codec(uint16_t cid, uint8_t codec){ 222*3deb3ec6SMatthias Ringwald char buffer[20]; 223*3deb3ec6SMatthias Ringwald sprintf(buffer, "AT%s=%d\r\n", HFP_CONFIRM_COMMON_CODEC, codec); 224*3deb3ec6SMatthias Ringwald return send_str_over_rfcomm(cid, buffer); 225*3deb3ec6SMatthias Ringwald } 226*3deb3ec6SMatthias Ringwald 227*3deb3ec6SMatthias Ringwald static void hfp_emit_ag_indicator_event(hfp_callback_t callback, int status, hfp_ag_indicator_t indicator){ 228*3deb3ec6SMatthias Ringwald if (!callback) return; 229*3deb3ec6SMatthias Ringwald uint8_t event[6]; 230*3deb3ec6SMatthias Ringwald event[0] = HCI_EVENT_HFP_META; 231*3deb3ec6SMatthias Ringwald event[1] = sizeof(event) - 2; 232*3deb3ec6SMatthias Ringwald event[2] = HFP_SUBEVENT_AG_INDICATOR_STATUS_CHANGED; 233*3deb3ec6SMatthias Ringwald event[3] = status; 234*3deb3ec6SMatthias Ringwald event[4] = indicator.index; 235*3deb3ec6SMatthias Ringwald event[5] = indicator.status; 236*3deb3ec6SMatthias Ringwald (*callback)(event, sizeof(event)); 237*3deb3ec6SMatthias Ringwald } 238*3deb3ec6SMatthias Ringwald 239*3deb3ec6SMatthias Ringwald static void hfp_emit_network_operator_event(hfp_callback_t callback, int status, hfp_network_opearator_t network_operator){ 240*3deb3ec6SMatthias Ringwald if (!callback) return; 241*3deb3ec6SMatthias Ringwald uint8_t event[24]; 242*3deb3ec6SMatthias Ringwald event[0] = HCI_EVENT_HFP_META; 243*3deb3ec6SMatthias Ringwald event[1] = sizeof(event) - 2; 244*3deb3ec6SMatthias Ringwald event[2] = HFP_SUBEVENT_NETWORK_OPERATOR_CHANGED; 245*3deb3ec6SMatthias Ringwald event[3] = status; 246*3deb3ec6SMatthias Ringwald event[4] = network_operator.mode; 247*3deb3ec6SMatthias Ringwald event[5] = network_operator.format; 248*3deb3ec6SMatthias Ringwald strcpy((char*)&event[6], network_operator.name); 249*3deb3ec6SMatthias Ringwald (*callback)(event, sizeof(event)); 250*3deb3ec6SMatthias Ringwald } 251*3deb3ec6SMatthias Ringwald 252*3deb3ec6SMatthias Ringwald static int hfp_hf_run_for_context_service_level_connection(hfp_connection_t * context){ 253*3deb3ec6SMatthias Ringwald if (context->state >= HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return 0; 254*3deb3ec6SMatthias Ringwald int done = 0; 255*3deb3ec6SMatthias Ringwald if (context->wait_ok) return done; 256*3deb3ec6SMatthias Ringwald 257*3deb3ec6SMatthias Ringwald switch (context->state){ 258*3deb3ec6SMatthias Ringwald case HFP_EXCHANGE_SUPPORTED_FEATURES: 259*3deb3ec6SMatthias Ringwald hfp_hf_cmd_exchange_supported_features(context->rfcomm_cid); 260*3deb3ec6SMatthias Ringwald context->state = HFP_W4_EXCHANGE_SUPPORTED_FEATURES; 261*3deb3ec6SMatthias Ringwald break; 262*3deb3ec6SMatthias Ringwald case HFP_NOTIFY_ON_CODECS: 263*3deb3ec6SMatthias Ringwald hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid); 264*3deb3ec6SMatthias Ringwald context->state = HFP_W4_NOTIFY_ON_CODECS; 265*3deb3ec6SMatthias Ringwald break; 266*3deb3ec6SMatthias Ringwald case HFP_RETRIEVE_INDICATORS: 267*3deb3ec6SMatthias Ringwald hfp_hf_cmd_retrieve_indicators(context->rfcomm_cid); 268*3deb3ec6SMatthias Ringwald context->state = HFP_W4_RETRIEVE_INDICATORS; 269*3deb3ec6SMatthias Ringwald context->retrieve_ag_indicators = 1; 270*3deb3ec6SMatthias Ringwald context->retrieve_ag_indicators_status = 0; 271*3deb3ec6SMatthias Ringwald break; 272*3deb3ec6SMatthias Ringwald case HFP_RETRIEVE_INDICATORS_STATUS: 273*3deb3ec6SMatthias Ringwald hfp_hf_cmd_retrieve_indicators_status(context->rfcomm_cid); 274*3deb3ec6SMatthias Ringwald context->state = HFP_W4_RETRIEVE_INDICATORS_STATUS; 275*3deb3ec6SMatthias Ringwald context->retrieve_ag_indicators_status = 1; 276*3deb3ec6SMatthias Ringwald context->retrieve_ag_indicators = 0; 277*3deb3ec6SMatthias Ringwald break; 278*3deb3ec6SMatthias Ringwald case HFP_ENABLE_INDICATORS_STATUS_UPDATE: 279*3deb3ec6SMatthias Ringwald hfp_hf_cmd_activate_status_update_for_all_ag_indicators(context->rfcomm_cid, 1); 280*3deb3ec6SMatthias Ringwald context->state = HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE; 281*3deb3ec6SMatthias Ringwald break; 282*3deb3ec6SMatthias Ringwald case HFP_RETRIEVE_CAN_HOLD_CALL: 283*3deb3ec6SMatthias Ringwald hfp_hf_cmd_retrieve_can_hold_call(context->rfcomm_cid); 284*3deb3ec6SMatthias Ringwald context->state = HFP_W4_RETRIEVE_CAN_HOLD_CALL; 285*3deb3ec6SMatthias Ringwald break; 286*3deb3ec6SMatthias Ringwald case HFP_LIST_GENERIC_STATUS_INDICATORS: 287*3deb3ec6SMatthias Ringwald hfp_hf_cmd_list_supported_generic_status_indicators(context->rfcomm_cid); 288*3deb3ec6SMatthias Ringwald context->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS; 289*3deb3ec6SMatthias Ringwald context->list_generic_status_indicators = 1; 290*3deb3ec6SMatthias Ringwald context->retrieve_generic_status_indicators = 0; 291*3deb3ec6SMatthias Ringwald context->retrieve_generic_status_indicators_state = 0; 292*3deb3ec6SMatthias Ringwald break; 293*3deb3ec6SMatthias Ringwald case HFP_RETRIEVE_GENERIC_STATUS_INDICATORS: 294*3deb3ec6SMatthias Ringwald hfp_hf_cmd_retrieve_supported_generic_status_indicators(context->rfcomm_cid); 295*3deb3ec6SMatthias Ringwald context->state = HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS; 296*3deb3ec6SMatthias Ringwald context->list_generic_status_indicators = 0; 297*3deb3ec6SMatthias Ringwald context->retrieve_generic_status_indicators = 1; 298*3deb3ec6SMatthias Ringwald context->retrieve_generic_status_indicators_state = 0; 299*3deb3ec6SMatthias Ringwald break; 300*3deb3ec6SMatthias Ringwald case HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS: 301*3deb3ec6SMatthias Ringwald hfp_hf_cmd_list_initital_supported_generic_status_indicators(context->rfcomm_cid); 302*3deb3ec6SMatthias Ringwald context->state = HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS; 303*3deb3ec6SMatthias Ringwald context->list_generic_status_indicators = 0; 304*3deb3ec6SMatthias Ringwald context->retrieve_generic_status_indicators = 0; 305*3deb3ec6SMatthias Ringwald context->retrieve_generic_status_indicators_state = 1; 306*3deb3ec6SMatthias Ringwald break; 307*3deb3ec6SMatthias Ringwald default: 308*3deb3ec6SMatthias Ringwald break; 309*3deb3ec6SMatthias Ringwald } 310*3deb3ec6SMatthias Ringwald return done; 311*3deb3ec6SMatthias Ringwald } 312*3deb3ec6SMatthias Ringwald 313*3deb3ec6SMatthias Ringwald static void hfp_hf_handle_ok_service_level_connection_establishment(hfp_connection_t *context){ 314*3deb3ec6SMatthias Ringwald if (context->state >= HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return; 315*3deb3ec6SMatthias Ringwald switch (context->state){ 316*3deb3ec6SMatthias Ringwald case HFP_W4_EXCHANGE_SUPPORTED_FEATURES: 317*3deb3ec6SMatthias Ringwald if (has_codec_negotiation_feature(context)){ 318*3deb3ec6SMatthias Ringwald context->state = HFP_NOTIFY_ON_CODECS; 319*3deb3ec6SMatthias Ringwald break; 320*3deb3ec6SMatthias Ringwald } 321*3deb3ec6SMatthias Ringwald context->state = HFP_RETRIEVE_INDICATORS; 322*3deb3ec6SMatthias Ringwald break; 323*3deb3ec6SMatthias Ringwald 324*3deb3ec6SMatthias Ringwald case HFP_W4_NOTIFY_ON_CODECS: 325*3deb3ec6SMatthias Ringwald context->state = HFP_RETRIEVE_INDICATORS; 326*3deb3ec6SMatthias Ringwald break; 327*3deb3ec6SMatthias Ringwald 328*3deb3ec6SMatthias Ringwald case HFP_W4_RETRIEVE_INDICATORS: 329*3deb3ec6SMatthias Ringwald context->state = HFP_RETRIEVE_INDICATORS_STATUS; 330*3deb3ec6SMatthias Ringwald context->retrieve_ag_indicators = 0; 331*3deb3ec6SMatthias Ringwald break; 332*3deb3ec6SMatthias Ringwald 333*3deb3ec6SMatthias Ringwald case HFP_W4_RETRIEVE_INDICATORS_STATUS: 334*3deb3ec6SMatthias Ringwald context->state = HFP_ENABLE_INDICATORS_STATUS_UPDATE; 335*3deb3ec6SMatthias Ringwald context->retrieve_ag_indicators_status = 0; 336*3deb3ec6SMatthias Ringwald break; 337*3deb3ec6SMatthias Ringwald 338*3deb3ec6SMatthias Ringwald case HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE: 339*3deb3ec6SMatthias Ringwald if (has_call_waiting_and_3way_calling_feature(context)){ 340*3deb3ec6SMatthias Ringwald context->state = HFP_RETRIEVE_CAN_HOLD_CALL; 341*3deb3ec6SMatthias Ringwald break; 342*3deb3ec6SMatthias Ringwald } 343*3deb3ec6SMatthias Ringwald if (has_hf_indicators_feature(context)){ 344*3deb3ec6SMatthias Ringwald context->state = HFP_LIST_GENERIC_STATUS_INDICATORS; 345*3deb3ec6SMatthias Ringwald break; 346*3deb3ec6SMatthias Ringwald } 347*3deb3ec6SMatthias Ringwald context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; 348*3deb3ec6SMatthias Ringwald hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0); 349*3deb3ec6SMatthias Ringwald break; 350*3deb3ec6SMatthias Ringwald 351*3deb3ec6SMatthias Ringwald case HFP_W4_RETRIEVE_CAN_HOLD_CALL: 352*3deb3ec6SMatthias Ringwald if (has_hf_indicators_feature(context)){ 353*3deb3ec6SMatthias Ringwald context->state = HFP_LIST_GENERIC_STATUS_INDICATORS; 354*3deb3ec6SMatthias Ringwald break; 355*3deb3ec6SMatthias Ringwald } 356*3deb3ec6SMatthias Ringwald context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; 357*3deb3ec6SMatthias Ringwald hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0); 358*3deb3ec6SMatthias Ringwald break; 359*3deb3ec6SMatthias Ringwald 360*3deb3ec6SMatthias Ringwald case HFP_W4_LIST_GENERIC_STATUS_INDICATORS: 361*3deb3ec6SMatthias Ringwald context->state = HFP_RETRIEVE_GENERIC_STATUS_INDICATORS; 362*3deb3ec6SMatthias Ringwald context->retrieve_generic_status_indicators = 0; 363*3deb3ec6SMatthias Ringwald break; 364*3deb3ec6SMatthias Ringwald 365*3deb3ec6SMatthias Ringwald case HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS: 366*3deb3ec6SMatthias Ringwald context->state = HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS; 367*3deb3ec6SMatthias Ringwald context->retrieve_generic_status_indicators = 0; 368*3deb3ec6SMatthias Ringwald break; 369*3deb3ec6SMatthias Ringwald 370*3deb3ec6SMatthias Ringwald case HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS: 371*3deb3ec6SMatthias Ringwald context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; 372*3deb3ec6SMatthias Ringwald context->retrieve_generic_status_indicators_state = 0; 373*3deb3ec6SMatthias Ringwald hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0); 374*3deb3ec6SMatthias Ringwald break; 375*3deb3ec6SMatthias Ringwald default: 376*3deb3ec6SMatthias Ringwald break; 377*3deb3ec6SMatthias Ringwald } 378*3deb3ec6SMatthias Ringwald } 379*3deb3ec6SMatthias Ringwald 380*3deb3ec6SMatthias Ringwald static void hfp_hf_run_for_context_service_level_connection_queries(hfp_connection_t * context){ 381*3deb3ec6SMatthias Ringwald if (context->state != HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return; 382*3deb3ec6SMatthias Ringwald if (context->wait_ok) return; 383*3deb3ec6SMatthias Ringwald 384*3deb3ec6SMatthias Ringwald if (context->enable_status_update_for_ag_indicators != 0xFF){ 385*3deb3ec6SMatthias Ringwald hfp_hf_cmd_activate_status_update_for_all_ag_indicators(context->rfcomm_cid, context->enable_status_update_for_ag_indicators); 386*3deb3ec6SMatthias Ringwald context->wait_ok = 1; 387*3deb3ec6SMatthias Ringwald return; 388*3deb3ec6SMatthias Ringwald }; 389*3deb3ec6SMatthias Ringwald if (context->change_status_update_for_individual_ag_indicators){ 390*3deb3ec6SMatthias Ringwald hfp_hf_cmd_activate_status_update_for_ag_indicator(context->rfcomm_cid, 391*3deb3ec6SMatthias Ringwald context->ag_indicators_status_update_bitmap, 392*3deb3ec6SMatthias Ringwald context->ag_indicators_nr); 393*3deb3ec6SMatthias Ringwald context->wait_ok = 1; 394*3deb3ec6SMatthias Ringwald return; 395*3deb3ec6SMatthias Ringwald } 396*3deb3ec6SMatthias Ringwald 397*3deb3ec6SMatthias Ringwald if (context->operator_name_format){ 398*3deb3ec6SMatthias Ringwald hfp_hf_cmd_query_operator_name_format(context->rfcomm_cid); 399*3deb3ec6SMatthias Ringwald context->wait_ok = 1; 400*3deb3ec6SMatthias Ringwald return; 401*3deb3ec6SMatthias Ringwald } 402*3deb3ec6SMatthias Ringwald if (context->operator_name){ 403*3deb3ec6SMatthias Ringwald hfp_hf_cmd_query_operator_name(context->rfcomm_cid); 404*3deb3ec6SMatthias Ringwald context->wait_ok = 1; 405*3deb3ec6SMatthias Ringwald return; 406*3deb3ec6SMatthias Ringwald } 407*3deb3ec6SMatthias Ringwald 408*3deb3ec6SMatthias Ringwald if (context->enable_extended_audio_gateway_error_report){ 409*3deb3ec6SMatthias Ringwald hfp_hf_cmd_enable_extended_audio_gateway_error_report(context->rfcomm_cid, context->enable_extended_audio_gateway_error_report); 410*3deb3ec6SMatthias Ringwald context->wait_ok = 1; 411*3deb3ec6SMatthias Ringwald return; 412*3deb3ec6SMatthias Ringwald } 413*3deb3ec6SMatthias Ringwald } 414*3deb3ec6SMatthias Ringwald 415*3deb3ec6SMatthias Ringwald static void hfp_hf_handle_ok_service_level_connection_queries(hfp_connection_t * context){ 416*3deb3ec6SMatthias Ringwald if (context->state != HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return; 417*3deb3ec6SMatthias Ringwald 418*3deb3ec6SMatthias Ringwald if (context->enable_status_update_for_ag_indicators != 0xFF){ 419*3deb3ec6SMatthias Ringwald context->enable_status_update_for_ag_indicators = 0xFF; 420*3deb3ec6SMatthias Ringwald hfp_emit_event(hfp_callback, HFP_SUBEVENT_COMPLETE, 0); 421*3deb3ec6SMatthias Ringwald return; 422*3deb3ec6SMatthias Ringwald }; 423*3deb3ec6SMatthias Ringwald 424*3deb3ec6SMatthias Ringwald if (context->change_status_update_for_individual_ag_indicators == 1){ 425*3deb3ec6SMatthias Ringwald context->change_status_update_for_individual_ag_indicators = 0; 426*3deb3ec6SMatthias Ringwald hfp_emit_event(hfp_callback, HFP_SUBEVENT_COMPLETE, 0); 427*3deb3ec6SMatthias Ringwald return; 428*3deb3ec6SMatthias Ringwald } 429*3deb3ec6SMatthias Ringwald 430*3deb3ec6SMatthias Ringwald if (context->operator_name_format){ 431*3deb3ec6SMatthias Ringwald context->operator_name_format = 0; 432*3deb3ec6SMatthias Ringwald context->operator_name = 1; 433*3deb3ec6SMatthias Ringwald return; 434*3deb3ec6SMatthias Ringwald } 435*3deb3ec6SMatthias Ringwald 436*3deb3ec6SMatthias Ringwald if (context->operator_name){ 437*3deb3ec6SMatthias Ringwald context->operator_name = 0; 438*3deb3ec6SMatthias Ringwald hfp_emit_network_operator_event(hfp_callback, 0, context->network_operator); 439*3deb3ec6SMatthias Ringwald return; 440*3deb3ec6SMatthias Ringwald } 441*3deb3ec6SMatthias Ringwald if (context->enable_extended_audio_gateway_error_report){ 442*3deb3ec6SMatthias Ringwald context->enable_extended_audio_gateway_error_report = 0; 443*3deb3ec6SMatthias Ringwald return; 444*3deb3ec6SMatthias Ringwald } 445*3deb3ec6SMatthias Ringwald } 446*3deb3ec6SMatthias Ringwald 447*3deb3ec6SMatthias Ringwald 448*3deb3ec6SMatthias Ringwald static void hfp_hf_run_for_context_codecs_connection(hfp_connection_t * context){ 449*3deb3ec6SMatthias Ringwald // if (context->state >= HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED && context->state <= HFP_AUDIO_CONNECTION_ESTABLISHED){ 450*3deb3ec6SMatthias Ringwald 451*3deb3ec6SMatthias Ringwald // handle audio connection setup 452*3deb3ec6SMatthias Ringwald // printf("hfp_run_for_context state %d \n", context->state); 453*3deb3ec6SMatthias Ringwald if (context->wait_ok) return; 454*3deb3ec6SMatthias Ringwald 455*3deb3ec6SMatthias Ringwald switch (context->state){ 456*3deb3ec6SMatthias Ringwald case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED: 457*3deb3ec6SMatthias Ringwald if (context->notify_ag_on_new_codecs){ 458*3deb3ec6SMatthias Ringwald context->wait_ok = 1; 459*3deb3ec6SMatthias Ringwald hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid); 460*3deb3ec6SMatthias Ringwald break; 461*3deb3ec6SMatthias Ringwald } 462*3deb3ec6SMatthias Ringwald 463*3deb3ec6SMatthias Ringwald if (context->hf_trigger_codec_connection_setup){ 464*3deb3ec6SMatthias Ringwald context->state = HFP_SLE_W2_EXCHANGE_COMMON_CODEC; 465*3deb3ec6SMatthias Ringwald context->wait_ok = 1; 466*3deb3ec6SMatthias Ringwald hfp_hf_cmd_trigger_codec_connection_setup(context->rfcomm_cid); 467*3deb3ec6SMatthias Ringwald break; 468*3deb3ec6SMatthias Ringwald } 469*3deb3ec6SMatthias Ringwald 470*3deb3ec6SMatthias Ringwald if (context->suggested_codec){ 471*3deb3ec6SMatthias Ringwald context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC; 472*3deb3ec6SMatthias Ringwald context->codec_confirmed = 1; 473*3deb3ec6SMatthias Ringwald context->wait_ok = 1; 474*3deb3ec6SMatthias Ringwald hfp_hf_cmd_confirm_codec(context->rfcomm_cid, context->suggested_codec); 475*3deb3ec6SMatthias Ringwald break; 476*3deb3ec6SMatthias Ringwald } 477*3deb3ec6SMatthias Ringwald break; 478*3deb3ec6SMatthias Ringwald 479*3deb3ec6SMatthias Ringwald case HFP_SLE_W4_EXCHANGE_COMMON_CODEC: 480*3deb3ec6SMatthias Ringwald if (context->notify_ag_on_new_codecs){ 481*3deb3ec6SMatthias Ringwald context->wait_ok = 1; 482*3deb3ec6SMatthias Ringwald context->codec_confirmed = 0; 483*3deb3ec6SMatthias Ringwald context->suggested_codec = 0; 484*3deb3ec6SMatthias Ringwald context->negotiated_codec = 0; 485*3deb3ec6SMatthias Ringwald hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid); 486*3deb3ec6SMatthias Ringwald break; 487*3deb3ec6SMatthias Ringwald } 488*3deb3ec6SMatthias Ringwald if (context->suggested_codec){ 489*3deb3ec6SMatthias Ringwald if (hfp_hf_supports_codec(context->suggested_codec)){ 490*3deb3ec6SMatthias Ringwald context->codec_confirmed = context->suggested_codec; 491*3deb3ec6SMatthias Ringwald context->wait_ok = 1; 492*3deb3ec6SMatthias Ringwald hfp_hf_cmd_confirm_codec(context->rfcomm_cid, context->suggested_codec); 493*3deb3ec6SMatthias Ringwald } else { 494*3deb3ec6SMatthias Ringwald context->notify_ag_on_new_codecs = 1; 495*3deb3ec6SMatthias Ringwald context->wait_ok = 1; 496*3deb3ec6SMatthias Ringwald context->codec_confirmed = 0; 497*3deb3ec6SMatthias Ringwald context->suggested_codec = 0; 498*3deb3ec6SMatthias Ringwald context->negotiated_codec = 0; 499*3deb3ec6SMatthias Ringwald hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid); 500*3deb3ec6SMatthias Ringwald } 501*3deb3ec6SMatthias Ringwald 502*3deb3ec6SMatthias Ringwald break; 503*3deb3ec6SMatthias Ringwald } 504*3deb3ec6SMatthias Ringwald 505*3deb3ec6SMatthias Ringwald break; 506*3deb3ec6SMatthias Ringwald 507*3deb3ec6SMatthias Ringwald case HFP_CODECS_CONNECTION_ESTABLISHED: 508*3deb3ec6SMatthias Ringwald if (context->notify_ag_on_new_codecs){ 509*3deb3ec6SMatthias Ringwald context->negotiated_codec = 0; 510*3deb3ec6SMatthias Ringwald context->wait_ok = 1; 511*3deb3ec6SMatthias Ringwald context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC; 512*3deb3ec6SMatthias Ringwald hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid); 513*3deb3ec6SMatthias Ringwald break; 514*3deb3ec6SMatthias Ringwald } 515*3deb3ec6SMatthias Ringwald 516*3deb3ec6SMatthias Ringwald if (context->hf_trigger_codec_connection_setup){ 517*3deb3ec6SMatthias Ringwald context->state = HFP_SLE_W2_EXCHANGE_COMMON_CODEC; 518*3deb3ec6SMatthias Ringwald context->wait_ok = 1; 519*3deb3ec6SMatthias Ringwald hfp_hf_cmd_trigger_codec_connection_setup(context->rfcomm_cid); 520*3deb3ec6SMatthias Ringwald break; 521*3deb3ec6SMatthias Ringwald } 522*3deb3ec6SMatthias Ringwald 523*3deb3ec6SMatthias Ringwald if (context->establish_audio_connection){ 524*3deb3ec6SMatthias Ringwald // TODO AUDIO CONNECTION 525*3deb3ec6SMatthias Ringwald } 526*3deb3ec6SMatthias Ringwald break; 527*3deb3ec6SMatthias Ringwald default: 528*3deb3ec6SMatthias Ringwald break; 529*3deb3ec6SMatthias Ringwald } 530*3deb3ec6SMatthias Ringwald } 531*3deb3ec6SMatthias Ringwald 532*3deb3ec6SMatthias Ringwald static void hfp_hf_handle_ok_codecs_connection(hfp_connection_t * context){ 533*3deb3ec6SMatthias Ringwald // handle audio connection setup 534*3deb3ec6SMatthias Ringwald switch (context->state){ 535*3deb3ec6SMatthias Ringwald case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED: 536*3deb3ec6SMatthias Ringwald if (context->notify_ag_on_new_codecs){ 537*3deb3ec6SMatthias Ringwald context->notify_ag_on_new_codecs = 0; 538*3deb3ec6SMatthias Ringwald break; 539*3deb3ec6SMatthias Ringwald } 540*3deb3ec6SMatthias Ringwald case HFP_SLE_W2_EXCHANGE_COMMON_CODEC: 541*3deb3ec6SMatthias Ringwald if (context->hf_trigger_codec_connection_setup){ 542*3deb3ec6SMatthias Ringwald context->hf_trigger_codec_connection_setup = 0; 543*3deb3ec6SMatthias Ringwald context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC; 544*3deb3ec6SMatthias Ringwald break; 545*3deb3ec6SMatthias Ringwald } 546*3deb3ec6SMatthias Ringwald break; 547*3deb3ec6SMatthias Ringwald case HFP_SLE_W4_EXCHANGE_COMMON_CODEC: 548*3deb3ec6SMatthias Ringwald if (context->notify_ag_on_new_codecs){ 549*3deb3ec6SMatthias Ringwald context->codec_confirmed = 0; 550*3deb3ec6SMatthias Ringwald context->suggested_codec = 0; 551*3deb3ec6SMatthias Ringwald context->notify_ag_on_new_codecs = 0; 552*3deb3ec6SMatthias Ringwald break; 553*3deb3ec6SMatthias Ringwald } 554*3deb3ec6SMatthias Ringwald if (context->codec_confirmed && context->suggested_codec){ 555*3deb3ec6SMatthias Ringwald context->negotiated_codec = context->suggested_codec; 556*3deb3ec6SMatthias Ringwald context->codec_confirmed = 0; 557*3deb3ec6SMatthias Ringwald context->suggested_codec = 0; 558*3deb3ec6SMatthias Ringwald context->state = HFP_CODECS_CONNECTION_ESTABLISHED; 559*3deb3ec6SMatthias Ringwald hfp_emit_event(hfp_callback, HFP_SUBEVENT_CODECS_CONNECTION_COMPLETE, 0); 560*3deb3ec6SMatthias Ringwald break; 561*3deb3ec6SMatthias Ringwald } 562*3deb3ec6SMatthias Ringwald break; 563*3deb3ec6SMatthias Ringwald 564*3deb3ec6SMatthias Ringwald case HFP_AUDIO_CONNECTION_ESTABLISHED: 565*3deb3ec6SMatthias Ringwald printf("HFP_AUDIO_CONNECTION_ESTABLISHED \n"); 566*3deb3ec6SMatthias Ringwald break; 567*3deb3ec6SMatthias Ringwald 568*3deb3ec6SMatthias Ringwald default: 569*3deb3ec6SMatthias Ringwald break; 570*3deb3ec6SMatthias Ringwald } 571*3deb3ec6SMatthias Ringwald } 572*3deb3ec6SMatthias Ringwald 573*3deb3ec6SMatthias Ringwald static void hfp_run_for_context(hfp_connection_t * context){ 574*3deb3ec6SMatthias Ringwald 575*3deb3ec6SMatthias Ringwald if (!context) return; 576*3deb3ec6SMatthias Ringwald if (!rfcomm_can_send_packet_now(context->rfcomm_cid)) return; 577*3deb3ec6SMatthias Ringwald 578*3deb3ec6SMatthias Ringwald hfp_hf_run_for_context_service_level_connection(context); 579*3deb3ec6SMatthias Ringwald hfp_hf_run_for_context_service_level_connection_queries(context); 580*3deb3ec6SMatthias Ringwald hfp_hf_run_for_context_codecs_connection(context); 581*3deb3ec6SMatthias Ringwald 582*3deb3ec6SMatthias Ringwald // deal with disconnect 583*3deb3ec6SMatthias Ringwald switch (context->state){ 584*3deb3ec6SMatthias Ringwald case HFP_W2_DISCONNECT_RFCOMM: 585*3deb3ec6SMatthias Ringwald context->state = HFP_W4_RFCOMM_DISCONNECTED; 586*3deb3ec6SMatthias Ringwald rfcomm_disconnect_internal(context->rfcomm_cid); 587*3deb3ec6SMatthias Ringwald break; 588*3deb3ec6SMatthias Ringwald 589*3deb3ec6SMatthias Ringwald default: 590*3deb3ec6SMatthias Ringwald break; 591*3deb3ec6SMatthias Ringwald } 592*3deb3ec6SMatthias Ringwald } 593*3deb3ec6SMatthias Ringwald 594*3deb3ec6SMatthias Ringwald static void hfp_hf_switch_on_ok(hfp_connection_t *context){ 595*3deb3ec6SMatthias Ringwald // printf("switch on ok\n"); 596*3deb3ec6SMatthias Ringwald context->wait_ok = 0; 597*3deb3ec6SMatthias Ringwald 598*3deb3ec6SMatthias Ringwald hfp_hf_handle_ok_service_level_connection_establishment(context); 599*3deb3ec6SMatthias Ringwald hfp_hf_handle_ok_service_level_connection_queries(context); 600*3deb3ec6SMatthias Ringwald hfp_hf_handle_ok_codecs_connection(context); 601*3deb3ec6SMatthias Ringwald 602*3deb3ec6SMatthias Ringwald // done 603*3deb3ec6SMatthias Ringwald context->command = HFP_CMD_NONE; 604*3deb3ec6SMatthias Ringwald } 605*3deb3ec6SMatthias Ringwald 606*3deb3ec6SMatthias Ringwald 607*3deb3ec6SMatthias Ringwald static void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 608*3deb3ec6SMatthias Ringwald hfp_connection_t * context = get_hfp_connection_context_for_rfcomm_cid(channel); 609*3deb3ec6SMatthias Ringwald if (!context) return; 610*3deb3ec6SMatthias Ringwald 611*3deb3ec6SMatthias Ringwald packet[size] = 0; 612*3deb3ec6SMatthias Ringwald int pos, i; 613*3deb3ec6SMatthias Ringwald //printf("\nHF received: %s", packet+2); 614*3deb3ec6SMatthias Ringwald for (pos = 0; pos < size ; pos++){ 615*3deb3ec6SMatthias Ringwald hfp_parse(context, packet[pos]); 616*3deb3ec6SMatthias Ringwald 617*3deb3ec6SMatthias Ringwald // emit indicators status changed 618*3deb3ec6SMatthias Ringwald for (i = 0; i < context->ag_indicators_nr; i++){ 619*3deb3ec6SMatthias Ringwald if (context->ag_indicators[i].status_changed) { 620*3deb3ec6SMatthias Ringwald hfp_emit_ag_indicator_event(hfp_callback, 0, context->ag_indicators[i]); 621*3deb3ec6SMatthias Ringwald context->ag_indicators[i].status_changed = 0; 622*3deb3ec6SMatthias Ringwald break; 623*3deb3ec6SMatthias Ringwald } 624*3deb3ec6SMatthias Ringwald } 625*3deb3ec6SMatthias Ringwald 626*3deb3ec6SMatthias Ringwald if (context->command == HFP_CMD_ERROR){ 627*3deb3ec6SMatthias Ringwald context->wait_ok = 0; 628*3deb3ec6SMatthias Ringwald hfp_reset_context_flags(context); 629*3deb3ec6SMatthias Ringwald hfp_emit_event(hfp_callback, HFP_SUBEVENT_COMPLETE, 1); 630*3deb3ec6SMatthias Ringwald return; 631*3deb3ec6SMatthias Ringwald } 632*3deb3ec6SMatthias Ringwald if (context->command == HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR){ 633*3deb3ec6SMatthias Ringwald context->wait_ok = 0; 634*3deb3ec6SMatthias Ringwald hfp_emit_event(hfp_callback, HFP_SUBEVENT_EXTENDED_AUDIO_GATEWAY_ERROR, context->extended_audio_gateway_error); 635*3deb3ec6SMatthias Ringwald context->extended_audio_gateway_error = 0; 636*3deb3ec6SMatthias Ringwald return; 637*3deb3ec6SMatthias Ringwald } 638*3deb3ec6SMatthias Ringwald 639*3deb3ec6SMatthias Ringwald if (context->command != HFP_CMD_OK) continue; 640*3deb3ec6SMatthias Ringwald hfp_hf_switch_on_ok(context); 641*3deb3ec6SMatthias Ringwald } 642*3deb3ec6SMatthias Ringwald } 643*3deb3ec6SMatthias Ringwald 644*3deb3ec6SMatthias Ringwald static void hfp_run(){ 645*3deb3ec6SMatthias Ringwald linked_list_iterator_t it; 646*3deb3ec6SMatthias Ringwald linked_list_iterator_init(&it, hfp_get_connections()); 647*3deb3ec6SMatthias Ringwald while (linked_list_iterator_has_next(&it)){ 648*3deb3ec6SMatthias Ringwald hfp_connection_t * connection = (hfp_connection_t *)linked_list_iterator_next(&it); 649*3deb3ec6SMatthias Ringwald hfp_run_for_context(connection); 650*3deb3ec6SMatthias Ringwald } 651*3deb3ec6SMatthias Ringwald } 652*3deb3ec6SMatthias Ringwald 653*3deb3ec6SMatthias Ringwald static void packet_handler(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 654*3deb3ec6SMatthias Ringwald switch (packet_type){ 655*3deb3ec6SMatthias Ringwald case RFCOMM_DATA_PACKET: 656*3deb3ec6SMatthias Ringwald hfp_handle_rfcomm_event(packet_type, channel, packet, size); 657*3deb3ec6SMatthias Ringwald break; 658*3deb3ec6SMatthias Ringwald case HCI_EVENT_PACKET: 659*3deb3ec6SMatthias Ringwald hfp_handle_hci_event(hfp_callback, packet_type, packet, size); 660*3deb3ec6SMatthias Ringwald default: 661*3deb3ec6SMatthias Ringwald break; 662*3deb3ec6SMatthias Ringwald } 663*3deb3ec6SMatthias Ringwald hfp_run(); 664*3deb3ec6SMatthias Ringwald } 665*3deb3ec6SMatthias Ringwald 666*3deb3ec6SMatthias Ringwald void hfp_hf_set_codecs(uint8_t * codecs, int codecs_nr){ 667*3deb3ec6SMatthias Ringwald if (codecs_nr > HFP_MAX_NUM_CODECS){ 668*3deb3ec6SMatthias Ringwald log_error("hfp_hf_set_codecs: codecs_nr (%d) > HFP_MAX_NUM_CODECS (%d)", codecs_nr, HFP_MAX_NUM_CODECS); 669*3deb3ec6SMatthias Ringwald return; 670*3deb3ec6SMatthias Ringwald } 671*3deb3ec6SMatthias Ringwald 672*3deb3ec6SMatthias Ringwald hfp_codecs_nr = codecs_nr; 673*3deb3ec6SMatthias Ringwald int i; 674*3deb3ec6SMatthias Ringwald for (i=0; i<codecs_nr; i++){ 675*3deb3ec6SMatthias Ringwald hfp_codecs[i] = codecs[i]; 676*3deb3ec6SMatthias Ringwald } 677*3deb3ec6SMatthias Ringwald 678*3deb3ec6SMatthias Ringwald char buffer[30]; 679*3deb3ec6SMatthias Ringwald int offset = join(buffer, sizeof(buffer), hfp_codecs, hfp_codecs_nr); 680*3deb3ec6SMatthias Ringwald buffer[offset] = 0; 681*3deb3ec6SMatthias Ringwald printf("set codecs %s\n", buffer); 682*3deb3ec6SMatthias Ringwald 683*3deb3ec6SMatthias Ringwald linked_list_iterator_t it; 684*3deb3ec6SMatthias Ringwald linked_list_iterator_init(&it, hfp_get_connections()); 685*3deb3ec6SMatthias Ringwald while (linked_list_iterator_has_next(&it)){ 686*3deb3ec6SMatthias Ringwald hfp_connection_t * connection = (hfp_connection_t *)linked_list_iterator_next(&it); 687*3deb3ec6SMatthias Ringwald if (!connection) continue; 688*3deb3ec6SMatthias Ringwald connection->notify_ag_on_new_codecs = 1; 689*3deb3ec6SMatthias Ringwald hfp_run_for_context(connection); 690*3deb3ec6SMatthias Ringwald } 691*3deb3ec6SMatthias Ringwald } 692*3deb3ec6SMatthias Ringwald 693*3deb3ec6SMatthias Ringwald void hfp_hf_init(uint16_t rfcomm_channel_nr, uint32_t supported_features, uint16_t * indicators, int indicators_nr, uint32_t indicators_status){ 694*3deb3ec6SMatthias Ringwald rfcomm_register_packet_handler(packet_handler); 695*3deb3ec6SMatthias Ringwald hfp_init(rfcomm_channel_nr); 696*3deb3ec6SMatthias Ringwald 697*3deb3ec6SMatthias Ringwald hfp_supported_features = supported_features; 698*3deb3ec6SMatthias Ringwald 699*3deb3ec6SMatthias Ringwald hfp_indicators_nr = indicators_nr; 700*3deb3ec6SMatthias Ringwald hfp_indicators_status = indicators_status; 701*3deb3ec6SMatthias Ringwald int i; 702*3deb3ec6SMatthias Ringwald for (i=0; i<indicators_nr; i++){ 703*3deb3ec6SMatthias Ringwald hfp_indicators[i] = indicators[i]; 704*3deb3ec6SMatthias Ringwald } 705*3deb3ec6SMatthias Ringwald } 706*3deb3ec6SMatthias Ringwald 707*3deb3ec6SMatthias Ringwald void hfp_hf_establish_service_level_connection(bd_addr_t bd_addr){ 708*3deb3ec6SMatthias Ringwald hfp_establish_service_level_connection(bd_addr, SDP_HandsfreeAudioGateway); 709*3deb3ec6SMatthias Ringwald } 710*3deb3ec6SMatthias Ringwald 711*3deb3ec6SMatthias Ringwald void hfp_hf_release_service_level_connection(bd_addr_t bd_addr){ 712*3deb3ec6SMatthias Ringwald hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr); 713*3deb3ec6SMatthias Ringwald hfp_release_service_level_connection(connection); 714*3deb3ec6SMatthias Ringwald hfp_run_for_context(connection); 715*3deb3ec6SMatthias Ringwald } 716*3deb3ec6SMatthias Ringwald 717*3deb3ec6SMatthias Ringwald void hfp_hf_enable_status_update_for_all_ag_indicators(bd_addr_t bd_addr, uint8_t enable){ 718*3deb3ec6SMatthias Ringwald hfp_hf_establish_service_level_connection(bd_addr); 719*3deb3ec6SMatthias Ringwald hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr); 720*3deb3ec6SMatthias Ringwald if (!connection){ 721*3deb3ec6SMatthias Ringwald log_error("HFP HF: connection doesn't exist."); 722*3deb3ec6SMatthias Ringwald return; 723*3deb3ec6SMatthias Ringwald } 724*3deb3ec6SMatthias Ringwald connection->enable_status_update_for_ag_indicators = enable; 725*3deb3ec6SMatthias Ringwald hfp_run_for_context(connection); 726*3deb3ec6SMatthias Ringwald } 727*3deb3ec6SMatthias Ringwald 728*3deb3ec6SMatthias Ringwald // TODO: returned ERROR - wrong format 729*3deb3ec6SMatthias Ringwald void hfp_hf_enable_status_update_for_individual_ag_indicators(bd_addr_t bd_addr, uint32_t indicators_status_bitmap){ 730*3deb3ec6SMatthias Ringwald hfp_hf_establish_service_level_connection(bd_addr); 731*3deb3ec6SMatthias Ringwald hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr); 732*3deb3ec6SMatthias Ringwald if (!connection){ 733*3deb3ec6SMatthias Ringwald log_error("HFP HF: connection doesn't exist."); 734*3deb3ec6SMatthias Ringwald return; 735*3deb3ec6SMatthias Ringwald } 736*3deb3ec6SMatthias Ringwald connection->change_status_update_for_individual_ag_indicators = 1; 737*3deb3ec6SMatthias Ringwald connection->ag_indicators_status_update_bitmap = indicators_status_bitmap; 738*3deb3ec6SMatthias Ringwald hfp_run_for_context(connection); 739*3deb3ec6SMatthias Ringwald } 740*3deb3ec6SMatthias Ringwald 741*3deb3ec6SMatthias Ringwald void hfp_hf_query_operator_selection(bd_addr_t bd_addr){ 742*3deb3ec6SMatthias Ringwald hfp_hf_establish_service_level_connection(bd_addr); 743*3deb3ec6SMatthias Ringwald hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr); 744*3deb3ec6SMatthias Ringwald if (!connection){ 745*3deb3ec6SMatthias Ringwald log_error("HFP HF: connection doesn't exist."); 746*3deb3ec6SMatthias Ringwald return; 747*3deb3ec6SMatthias Ringwald } 748*3deb3ec6SMatthias Ringwald connection->operator_name_format = 1; 749*3deb3ec6SMatthias Ringwald hfp_run_for_context(connection); 750*3deb3ec6SMatthias Ringwald } 751*3deb3ec6SMatthias Ringwald 752*3deb3ec6SMatthias Ringwald void hfp_hf_enable_report_extended_audio_gateway_error_result_code(bd_addr_t bd_addr, uint8_t enable){ 753*3deb3ec6SMatthias Ringwald hfp_hf_establish_service_level_connection(bd_addr); 754*3deb3ec6SMatthias Ringwald hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr); 755*3deb3ec6SMatthias Ringwald if (!connection){ 756*3deb3ec6SMatthias Ringwald log_error("HFP HF: connection doesn't exist."); 757*3deb3ec6SMatthias Ringwald return; 758*3deb3ec6SMatthias Ringwald } 759*3deb3ec6SMatthias Ringwald connection->enable_extended_audio_gateway_error_report = enable; 760*3deb3ec6SMatthias Ringwald hfp_run_for_context(connection); 761*3deb3ec6SMatthias Ringwald } 762*3deb3ec6SMatthias Ringwald 763*3deb3ec6SMatthias Ringwald void hfp_hf_negotiate_codecs(bd_addr_t bd_addr){ 764*3deb3ec6SMatthias Ringwald hfp_hf_establish_service_level_connection(bd_addr); 765*3deb3ec6SMatthias Ringwald hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr); 766*3deb3ec6SMatthias Ringwald if (!has_codec_negotiation_feature(connection)) return; 767*3deb3ec6SMatthias Ringwald if (connection->remote_codecs_nr == 0) return; 768*3deb3ec6SMatthias Ringwald 769*3deb3ec6SMatthias Ringwald if (connection->state >= HFP_W2_DISCONNECT_SCO) return; 770*3deb3ec6SMatthias Ringwald 771*3deb3ec6SMatthias Ringwald if (connection->state != HFP_SLE_W2_EXCHANGE_COMMON_CODEC && 772*3deb3ec6SMatthias Ringwald connection->state != HFP_SLE_W4_EXCHANGE_COMMON_CODEC){ 773*3deb3ec6SMatthias Ringwald connection->hf_trigger_codec_connection_setup = 1; 774*3deb3ec6SMatthias Ringwald } 775*3deb3ec6SMatthias Ringwald hfp_run_for_context(connection); 776*3deb3ec6SMatthias Ringwald } 777*3deb3ec6SMatthias Ringwald 778*3deb3ec6SMatthias Ringwald 779*3deb3ec6SMatthias Ringwald void hfp_hf_establish_audio_connection(bd_addr_t bd_addr){ 780*3deb3ec6SMatthias Ringwald hfp_hf_establish_service_level_connection(bd_addr); 781*3deb3ec6SMatthias Ringwald hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr); 782*3deb3ec6SMatthias Ringwald if (!has_codec_negotiation_feature(connection)) return; 783*3deb3ec6SMatthias Ringwald connection->establish_audio_connection = 0; 784*3deb3ec6SMatthias Ringwald if (connection->state == HFP_AUDIO_CONNECTION_ESTABLISHED) return; 785*3deb3ec6SMatthias Ringwald if (connection->state >= HFP_W2_DISCONNECT_SCO) return; 786*3deb3ec6SMatthias Ringwald 787*3deb3ec6SMatthias Ringwald connection->establish_audio_connection = 1; 788*3deb3ec6SMatthias Ringwald if (connection->state < HFP_SLE_W4_EXCHANGE_COMMON_CODEC){ 789*3deb3ec6SMatthias Ringwald connection->hf_trigger_codec_connection_setup = 1; 790*3deb3ec6SMatthias Ringwald } 791*3deb3ec6SMatthias Ringwald hfp_run_for_context(connection); 792*3deb3ec6SMatthias Ringwald } 793*3deb3ec6SMatthias Ringwald 794*3deb3ec6SMatthias Ringwald void hfp_hf_release_audio_connection(bd_addr_t bd_addr){ 795*3deb3ec6SMatthias Ringwald hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr); 796*3deb3ec6SMatthias Ringwald hfp_release_audio_connection(connection); 797*3deb3ec6SMatthias Ringwald hfp_run_for_context(connection); 798*3deb3ec6SMatthias Ringwald } 799*3deb3ec6SMatthias Ringwald 800*3deb3ec6SMatthias Ringwald 801