/******************************************************************************* ** ** Function bta_av_chk_mtu ** ** Description if this is audio channel, check if more than one audio ** channel is connected. ** ** Returns The smallest mtu of the connected audio channels ** *******************************************************************************/ UINT16 bta_av_chk_mtu(tBTA_AV_SCB *p_scb, UINT16 mtu) { UINT16 ret_mtu = BTA_AV_MAX_A2DP_MTU; tBTA_AV_SCB *p_scbi; int i; UINT8 mask; /* TODO_MV mess with the mtu according to the number of EDR/non-EDR headsets */ if(p_scb->chnl == BTA_AV_CHNL_AUDIO) { if(bta_av_cb.audio_open_cnt >= 2) { /* more than one audio channel is connected */ for(i=0; i<BTA_AV_NUM_STRS; i++) { p_scbi = bta_av_cb.p_scb[i]; if((p_scb != p_scbi) && p_scbi && (p_scbi->chnl == BTA_AV_CHNL_AUDIO) ) { mask = BTA_AV_HNDL_TO_MSK(i); APPL_TRACE_DEBUG3("[%d] mtu: %d, mask:0x%x", i, p_scbi->stream_mtu, mask); if(bta_av_cb.conn_audio & mask) { if(ret_mtu > p_scbi->stream_mtu) ret_mtu = p_scbi->stream_mtu; } } } } APPL_TRACE_DEBUG3("bta_av_chk_mtu audio count:%d, conn_audio:0x%x, ret:%d", bta_av_cb.audio_open_cnt, bta_av_cb.conn_audio, ret_mtu); } return ret_mtu; }
/******************************************************************************* ** ** Function bta_hf_client_remove_sco ** ** Description Removes the specified SCO from the system. ** If only_active is TRUE, then SCO is only removed if connected ** ** Returns BOOLEAN - TRUE if Sco removal was started ** *******************************************************************************/ static BOOLEAN bta_hf_client_sco_remove(BOOLEAN only_active) { BOOLEAN removed_started = FALSE; tBTM_STATUS status; APPL_TRACE_DEBUG2("%s %d", __FUNCTION__, only_active); if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) { status = BTM_RemoveSco(bta_hf_client_cb.scb.sco_idx); APPL_TRACE_DEBUG3("%s idx 0x%04x, status:0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx, status); if (status == BTM_CMD_STARTED) { removed_started = TRUE; } /* If no connection reset the sco handle */ else if ( (status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR) ) { bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX; } } return removed_started; }
static char *bta_hf_client_skip_unknown(char *buffer) { char *start; char *tmp; tmp = strstr(buffer, "\r\n"); if (tmp == NULL) { return NULL; } buffer += 2; start = buffer; tmp = strstr(buffer, "\r\n"); if (tmp == NULL) { return NULL; } buffer = tmp + 2; APPL_TRACE_DEBUG3("%s %.*s", __FUNCTION__, buffer - start - 2, start); return buffer; }
int btsock_thread_post_cmd(int h, int type, const unsigned char* data, int size, uint32_t user_id) { if(h < 0 || h >= MAX_THREAD) { APPL_TRACE_ERROR1("invalid bt thread handle:%d", h); return FALSE; } if(ts[h].cmd_fdw == -1) { APPL_TRACE_ERROR0("cmd socket is not created. socket thread may not initialized"); return FALSE; } sock_cmd_t cmd = {CMD_USER_PRIVATE, 0, type, size, user_id}; APPL_TRACE_DEBUG3("post cmd type:%d, size:%d, h:%d, ", type, size, h); sock_cmd_t* cmd_send = &cmd; int size_send = sizeof(cmd); if(data && size) { size_send = sizeof(cmd) + size; cmd_send = (sock_cmd_t*)alloca(size_send); if(cmd_send) { *cmd_send = cmd; memcpy(cmd_send + 1, data, size); } else { APPL_TRACE_ERROR3("alloca failed at h:%d, cmd type:%d, size:%d", h, type, size_send); return FALSE; } } return send(ts[h].cmd_fdw, cmd_send, size_send, 0) == size_send; }
static void bta_hf_client_handle_ciev(UINT32 index, UINT32 value) { INT8 realind = -1; APPL_TRACE_DEBUG3("%s index: %u value: %u", __FUNCTION__, index, value); if(index == 0 || index >= BTA_HF_CLIENT_AT_INDICATOR_COUNT) { return; } realind = bta_hf_client_cb.scb.at_cb.indicator_lookup[index - 1]; if(realind >= 0 && realind < BTA_HF_CLIENT_AT_SUPPORTED_INDICATOR_COUNT) { /* get the real in-array index from lookup table by index it comes at */ /* if there is no bug it should automatically be correctly calculated */ if(value > bta_hf_client_indicators[realind].max || value < bta_hf_client_indicators[realind].min) { return; } /* tBTA_HF_CLIENT_IND_TYPE match index in bta_hf_client_indicators */ bta_hf_client_ind(realind, value); } }
/******************************************************************************* ** ** Function bta_av_co_audio_disc_res ** ** Description This callout function is executed by AV to report the ** number of stream end points (SEP) were found during the ** AVDT stream discovery process. ** ** ** Returns void. ** *******************************************************************************/ BTA_API void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, UINT8 num_seps, UINT8 num_snk, BD_ADDR addr) { tBTA_AV_CO_PEER *p_peer; FUNC_TRACE(); APPL_TRACE_DEBUG3("bta_av_co_audio_disc_res h:x%x num_seps:%d num_snk:%d", hndl, num_seps, num_snk); /* Find the peer info */ p_peer = bta_av_co_get_peer(hndl); if (p_peer == NULL) { APPL_TRACE_ERROR0("bta_av_co_audio_disc_res could not find peer entry"); return; } /* Sanity check : this should never happen */ if (p_peer->opened) { APPL_TRACE_ERROR0("bta_av_co_audio_disc_res peer already opened"); } /* Copy the discovery results */ bdcpy(p_peer->addr, addr); p_peer->num_snks = num_snk; p_peer->num_seps = num_seps; p_peer->num_rx_snks = 0; p_peer->num_sup_snks = 0; }
/****************************************************************************** ** ** MAIN PARSING FUNCTION ** ** *******************************************************************************/ void bta_hf_client_at_parse(char *buf, unsigned int len) { APPL_TRACE_DEBUG3("%s offset: %u len: %u", __FUNCTION__, bta_hf_client_cb.scb.at_cb.offset, len); if (len + bta_hf_client_cb.scb.at_cb.offset > BTA_HF_CLIENT_AT_PARSER_MAX_LEN) { char tmp_buff[BTA_HF_CLIENT_AT_PARSER_MAX_LEN]; unsigned int tmp = bta_hf_client_cb.scb.at_cb.offset; unsigned int space_left = BTA_HF_CLIENT_AT_PARSER_MAX_LEN - bta_hf_client_cb.scb.at_cb.offset; APPL_TRACE_DEBUG1("%s overrun, trying to recover", __FUNCTION__); /* fill up parser buffer */ memcpy(bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, buf, space_left); len -= space_left; buf += space_left; bta_hf_client_cb.scb.at_cb.offset += space_left; /* find end of last complete command before proceeding */ while(bta_hf_client_check_at_complete() == FALSE) { if (bta_hf_client_cb.scb.at_cb.offset == 0) { APPL_TRACE_ERROR0("HFPClient: AT parser buffer overrun, disconnecting"); bta_hf_client_at_reset(); bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL); return; } bta_hf_client_cb.scb.at_cb.offset--; } /* cut buffer to complete AT event and keep cut data */ tmp += space_left - bta_hf_client_cb.scb.at_cb.offset; memcpy(tmp_buff, bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, tmp); bta_hf_client_cb.scb.at_cb.buf[bta_hf_client_cb.scb.at_cb.offset] = '\0'; /* parse */ bta_hf_client_at_parse_start(); bta_hf_client_at_clear_buf(); /* recover cut data */ memcpy(bta_hf_client_cb.scb.at_cb.buf, tmp_buff, tmp); bta_hf_client_cb.scb.at_cb.offset += tmp; } memcpy(bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, buf, len); bta_hf_client_cb.scb.at_cb.offset += len; /* If last event is complete, parsing can be started */ if (bta_hf_client_check_at_complete() == TRUE) { bta_hf_client_at_parse_start(); bta_hf_client_at_clear_buf(); } }
static void bta_hf_client_handle_clcc(UINT16 idx, UINT16 dir, UINT16 status, UINT16 mode, UINT16 mpty, char *numstr, UINT16 type) { APPL_TRACE_DEBUG6("%s idx: %u dir: %u status: %u mode: %u mpty: %u", __FUNCTION__, idx, dir, status, mode, mpty); if (numstr) { APPL_TRACE_DEBUG3("%s number: %s type: %u", __FUNCTION__, numstr, type); } bta_hf_client_clcc(idx, dir, status, mpty, numstr); }
/* create dummy socket pair used to wake up select loop */ static inline void init_cmd_fd(int h) { asrt(ts[h].cmd_fdr == -1 && ts[h].cmd_fdw == -1); if(socketpair(AF_UNIX, SOCK_STREAM, 0, &ts[h].cmd_fdr) < 0) { APPL_TRACE_ERROR1("socketpair failed: %s", strerror(errno)); return; } APPL_TRACE_DEBUG3("h:%d, cmd_fdr:%d, cmd_fdw:%d", h, ts[h].cmd_fdr, ts[h].cmd_fdw); //add the cmd fd for read & write add_poll(h, ts[h].cmd_fdr, 0, SOCK_THREAD_FD_RD, 0); }
/******************************************************************************* ** ** Function bta_gattc_sm_execute ** ** Description State machine event handling function for GATTC ** ** ** Returns void ** *******************************************************************************/ void bta_gattc_sm_execute(tBTA_GATTC_CLCB *p_clcb, UINT16 event, tBTA_GATTC_DATA *p_data) { tBTA_GATTC_ST_TBL state_table; UINT8 action; int i; #if BTA_GATT_DEBUG == TRUE tBTA_GATTC_STATE in_state = p_clcb->state; UINT16 in_event = event; APPL_TRACE_DEBUG4("bta_gattc_sm_execute: State 0x%02x [%s], Event 0x%x[%s]", in_state, gattc_state_code(in_state), in_event, gattc_evt_code(in_event)); #endif /* look up the state table for the current state */ state_table = bta_gattc_st_tbl[p_clcb->state]; event &= 0x00FF; /* set next state */ p_clcb->state = state_table[event][BTA_GATTC_NEXT_STATE]; /* execute action functions */ for (i = 0; i < BTA_GATTC_ACTIONS; i++) { if ((action = state_table[event][i]) != BTA_GATTC_IGNORE) { (*bta_gattc_action[action])(p_clcb, p_data); } else { break; } } #if BTA_GATT_DEBUG == TRUE if (in_state != p_clcb->state) { APPL_TRACE_DEBUG3("GATTC State Change: [%s] -> [%s] after Event [%s]", gattc_state_code(in_state), gattc_state_code(p_clcb->state), gattc_evt_code(in_event)); } #endif }
static void bta_hf_client_send_at(tBTA_HF_CLIENT_AT_CMD cmd, char *buf, UINT16 buf_len) { if ((bta_hf_client_cb.scb.at_cb.current_cmd == BTA_HF_CLIENT_AT_NONE || bta_hf_client_cb.scb.svc_conn == FALSE) && bta_hf_client_cb.scb.at_cb.hold_timer_on == FALSE) { UINT16 len; #ifdef BTA_HF_CLIENT_AT_DUMP APPL_TRACE_DEBUG3("%s %.*s", __FUNCTION__, buf_len - 1, buf); #endif bta_hf_client_cb.scb.at_cb.current_cmd = cmd; PORT_WriteData(bta_hf_client_cb.scb.conn_handle, buf, buf_len, &len); bta_hf_client_start_at_resp_timer(); return; } bta_hf_client_queue_at(cmd, buf, buf_len); }
static void bta_hf_client_handle_error(tBTA_HF_CLIENT_AT_RESULT_TYPE type, UINT16 cme) { APPL_TRACE_DEBUG3("%s %u %u", __FUNCTION__, type, cme); bta_hf_client_stop_at_resp_timer(); if (!bta_hf_client_cb.scb.svc_conn) { bta_hf_client_slc_seq(TRUE); return; } switch(bta_hf_client_cb.scb.at_cb.current_cmd) { case BTA_HF_CLIENT_AT_BIA: break; case BTA_HF_CLIENT_AT_BCC: case BTA_HF_CLIENT_AT_BCS: bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT); break; case BTA_HF_CLIENT_AT_CLIP: //last cmd is post slc seq if (bta_hf_client_cb.scb.send_at_reply == FALSE) { bta_hf_client_cb.scb.send_at_reply = TRUE; } break; default: if (bta_hf_client_cb.scb.send_at_reply) { bta_hf_client_at_result(type, cme); } break; } bta_hf_client_cb.scb.at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE; bta_hf_client_send_queued_at(); }
static void bta_hf_client_handle_cind_value(UINT32 index, UINT32 value) { APPL_TRACE_DEBUG3("%s index: %u value: %u", __FUNCTION__, index, value); if (index >= BTA_HF_CLIENT_AT_INDICATOR_COUNT) { return; } if (service_index == index) { if (value == 0) { service_availability = FALSE; } else { service_availability = TRUE; } } if (bta_hf_client_cb.scb.at_cb.indicator_lookup[index] == -1) { return; } /* get the real array index from lookup table */ index = bta_hf_client_cb.scb.at_cb.indicator_lookup[index]; /* Ignore out of range values */ if(value > bta_hf_client_indicators[index].max || value < bta_hf_client_indicators[index].min) { return; } /* tBTA_HF_CLIENT_IND_TYPE match index in bta_hf_client_indicators */ bta_hf_client_ind(index, value); }
static void on_cli_rfc_connect(tBTA_JV_RFCOMM_OPEN *p_open, uint32_t id) { lock_slot(&slot_lock); rfc_slot_t* rs = find_rfc_slot_by_id(id); if(rs && p_open->status == BTA_JV_SUCCESS) { rs->rfc_port_handle = BTA_JvRfcommGetPortHdl(p_open->handle); bd_copy(rs->addr.address, p_open->rem_bda, 0); //notify app rfc is connected APPL_TRACE_DEBUG4("call send_app_connect_signal, slot id:%d, fd:%d, rfc scn:%d, server:%d", rs->id, rs->fd, rs->scn, rs->f.server); if(send_app_connect_signal(rs->fd, &rs->addr, rs->scn, 0, -1)) { //start monitoring the socketpair to get call back when app writing data APPL_TRACE_DEBUG3("on_rfc_connect_ind, connect signal sent, slot id:%d, rfc scn:%d, server:%d", rs->id, rs->scn, rs->f.server); rs->f.connected = TRUE; } else APPL_TRACE_ERROR0("send_app_connect_signal failed"); } else if(rs) cleanup_rfc_slot(rs); unlock_slot(&slot_lock); }
static void jv_dm_cback(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data) { uint32_t id = (uint32_t)user_data; APPL_TRACE_DEBUG2("jv_dm_cback: event:%d, slot id:%d", event, id); switch(event) { case BTA_JV_CREATE_RECORD_EVT: { lock_slot(&slot_lock); rfc_slot_t* rs = find_rfc_slot_by_id(id); if(rs && create_server_sdp_record(rs)) { //now start the rfcomm server after sdp & channel # assigned BTA_JvRfcommStartServer(rs->security, rs->role, rs->scn, MAX_RFC_SESSION, rfcomm_cback, (void*)rs->id); } else if(rs) { APPL_TRACE_ERROR1("jv_dm_cback: cannot start server, slot found:%p", rs); cleanup_rfc_slot(rs); } unlock_slot(&slot_lock); break; } case BTA_JV_DISCOVERY_COMP_EVT: { rfc_slot_t* rs = NULL; lock_slot(&slot_lock); if(p_data->disc_comp.status == BTA_JV_SUCCESS && p_data->disc_comp.scn) { APPL_TRACE_DEBUG3("BTA_JV_DISCOVERY_COMP_EVT, slot id:%d, status:%d, scn:%d", id, p_data->disc_comp.status, p_data->disc_comp.scn); rs = find_rfc_slot_by_id(id); if(rs && rs->f.doing_sdp_request) { if(BTA_JvRfcommConnect(rs->security, rs->role, p_data->disc_comp.scn, rs->addr.address, rfcomm_cback, (void*)rs->id) == BTA_JV_SUCCESS) { rs->scn = p_data->disc_comp.scn; rs->f.doing_sdp_request = FALSE; if(!send_app_scn(rs)) cleanup_rfc_slot(rs); } else cleanup_rfc_slot(rs); } else if(rs) { APPL_TRACE_ERROR3("DISCOVERY_COMP_EVT no pending sdp request, slot id:%d, \ flag sdp pending:%d, flag sdp doing:%d", id, rs->f.pending_sdp_request, rs->f.doing_sdp_request); } } else { APPL_TRACE_ERROR3("DISCOVERY_COMP_EVT slot id:%d, failed to find channle, \ status:%d, scn:%d", id, p_data->disc_comp.status, p_data->disc_comp.scn); rs = find_rfc_slot_by_id(id); if(rs) cleanup_rfc_slot(rs); } rs = find_rfc_slot_by_pending_sdp(); if(rs) { APPL_TRACE_DEBUG0("BTA_JV_DISCOVERY_COMP_EVT, start another pending scn sdp request"); tSDP_UUID sdp_uuid; sdp_uuid.len = 16; memcpy(sdp_uuid.uu.uuid128, rs->service_uuid, sizeof(sdp_uuid.uu.uuid128)); BTA_JvStartDiscovery((UINT8*)rs->addr.address, 1, &sdp_uuid, (void*)rs->id); rs->f.pending_sdp_request = FALSE; rs->f.doing_sdp_request = TRUE; } unlock_slot(&slot_lock); break; }
static void bta_hf_client_handle_ccwa(char *numstr, UINT32 type) { APPL_TRACE_DEBUG3("%s %u %s", __FUNCTION__, type, numstr); bta_hf_client_ccwa(numstr); }
static void bta_hf_client_handle_cops(char *opstr, UINT32 mode) { APPL_TRACE_DEBUG3("%s %u %s", __FUNCTION__, mode, opstr); bta_hf_client_operator_name(opstr); }
/******************************************************************************* ** ** Function bta_av_sys_rs_cback ** ** Description Receives the role change event from dm ** ** Returns (BTA_SYS_ROLE_CHANGE, new_role, hci_status, p_bda) ** *******************************************************************************/ static void bta_av_sys_rs_cback (tBTA_SYS_CONN_STATUS status,UINT8 id, UINT8 app_id, BD_ADDR peer_addr) { int i; tBTA_AV_SCB *p_scb; tBTA_AV_ROLE_RES *p_buf; UINT8 cur_role; UINT8 peer_idx = 0; APPL_TRACE_DEBUG1("bta_av_sys_rs_cback: %d", bta_av_cb.rs_idx); for(i=0; i<BTA_AV_NUM_STRS; i++) { /* loop through all the SCBs to find matching peer addresses and report the role change event */ /* note that more than one SCB (a2dp & vdp) maybe waiting for this event */ p_scb = bta_av_cb.p_scb[i]; if (p_scb && (bdcmp (peer_addr, p_scb->peer_addr) == 0) && (p_buf = (tBTA_AV_ROLE_RES *) GKI_getbuf(sizeof(tBTA_AV_ROLE_RES))) != NULL) { APPL_TRACE_DEBUG3("new_role:%d, hci_status:x%x hndl: x%x", id, app_id, p_scb->hndl); /* if ((id != BTM_ROLE_MASTER) && (app_id != HCI_SUCCESS)) { bta_sys_set_policy(BTA_ID_AV, (HCI_ENABLE_MASTER_SLAVE_SWITCH|HCI_ENABLE_SNIFF_MODE), p_scb->peer_addr); } */ p_buf->hdr.event = BTA_AV_ROLE_CHANGE_EVT; p_buf->hdr.layer_specific = p_scb->hndl; p_buf->new_role = id; p_buf->hci_status = app_id; bta_sys_sendmsg(p_buf); peer_idx = p_scb->hdi + 1; /* Handle index for the peer_addr */ } } /* restore role switch policy, if role switch failed */ if ((HCI_SUCCESS != app_id) && (BTM_GetRole (peer_addr, &cur_role) == BTM_SUCCESS) && (cur_role == BTM_ROLE_SLAVE) ) { bta_sys_set_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH, peer_addr); } /* if BTA_AvOpen() was called for other device, which caused the role switch of the peer_addr, */ /* we need to continue opening process for the BTA_AvOpen(). */ if ((bta_av_cb.rs_idx != 0) && (bta_av_cb.rs_idx != peer_idx)) { p_scb = bta_av_cb.p_scb[bta_av_cb.rs_idx - 1]; if (p_scb && p_scb->q_tag == BTA_AV_Q_TAG_OPEN) { APPL_TRACE_DEBUG3 ("bta_av_sys_rs_cback: rs_idx(%d), hndl:x%x q_tag: %d", bta_av_cb.rs_idx, p_scb->hndl, p_scb->q_tag); if(HCI_SUCCESS == app_id || HCI_ERR_NO_CONNECTION == app_id) p_scb->q_info.open.switch_res = BTA_AV_RS_OK; else p_scb->q_info.open.switch_res = BTA_AV_RS_FAIL; /* Continue av open process */ bta_av_do_disc_a2d (p_scb, (tBTA_AV_DATA *)&(p_scb->q_info.open)); } bta_av_cb.rs_idx = 0; } }
/******************************************************************************* ** ** Function bta_av_api_register ** ** Description allocate stream control block, ** register the service to stack ** create SDP record ** ** Returns void ** *******************************************************************************/ static void bta_av_api_register(tBTA_AV_DATA *p_data) { tBTA_AV_REGISTER registr; tBTA_AV_SCB *p_scb; /* stream control block */ tAVDT_REG reg; tAVDT_CS cs; char *p_service_name; tBTA_AV_CODEC codec_type; tBTA_UTL_COD cod; UINT8 index = 0; memset(&cs,0,sizeof(tAVDT_CS)); registr.status = BTA_AV_FAIL_RESOURCES; registr.app_id = p_data->api_reg.app_id; registr.chnl = (tBTA_AV_CHNL)p_data->hdr.layer_specific; do { p_scb = bta_av_alloc_scb(registr.chnl); if(p_scb == NULL) { APPL_TRACE_ERROR0("failed to alloc SCB"); break; } registr.hndl = p_scb->hndl; p_scb->app_id = registr.app_id; /* initialize the stream control block */ p_scb->timer.p_cback = (TIMER_CBACK*)&bta_av_timer_cback; registr.status = BTA_AV_SUCCESS; if((bta_av_cb.reg_audio + bta_av_cb.reg_video) == 0) { /* the first channel registered. register to AVDTP */ reg.ctrl_mtu = p_bta_av_cfg->sig_mtu; reg.ret_tout = BTA_AV_RET_TOUT; reg.sig_tout = BTA_AV_SIG_TOUT; reg.idle_tout = BTA_AV_IDLE_TOUT; reg.sec_mask = bta_av_cb.sec_mask; #if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE) bta_ar_reg_avdt(®, bta_av_conn_cback, BTA_ID_AV); #endif bta_sys_role_chg_register(&bta_av_sys_rs_cback); /* create remote control TG service if required */ if (bta_av_cb.features & (BTA_AV_FEAT_RCTG)) { /* register with no authorization; let AVDTP use authorization instead */ #if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE) #if (BTA_AV_WITH_AVCTP_AUTHORIZATION == TRUE) bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu, bta_av_cb.sec_mask, BTA_ID_AV); #else bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu, (UINT8)(bta_av_cb.sec_mask & (~BTA_SEC_AUTHORIZE)), BTA_ID_AV); #endif bta_ar_reg_avrc(UUID_SERVCLASS_AV_REM_CTRL_TARGET, "AV Remote Control Target", NULL, p_bta_av_cfg->avrc_tg_cat, BTA_ID_AV); #endif } /* Set the Capturing service class bit */ cod.service = BTM_COD_SERVICE_CAPTURING; utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS); } /* if 1st channel */ /* get stream configuration and create stream */ /* memset(&cs.cfg,0,sizeof(tAVDT_CFG)); */ cs.cfg.num_codec = 1; #ifdef A2DP_SINK cs.tsep = AVDT_TSEP_SNK; #else cs.tsep = AVDT_TSEP_SRC; #endif /* * memset of cs takes care setting call back pointers to null. cs.p_data_cback = NULL; cs.p_report_cback = NULL; */ #ifdef A2DP_SINK cs.p_data_cback = bta_av_a2dp_data_cback; #endif cs.nsc_mask = AVDT_NSC_RECONFIG | ((bta_av_cb.features & BTA_AV_FEAT_PROTECT) ? 0 : AVDT_NSC_SECURITY); APPL_TRACE_DEBUG1("nsc_mask: 0x%x", cs.nsc_mask); if (p_data->api_reg.p_service_name[0] == 0) { p_service_name = NULL; } else { p_service_name = p_data->api_reg.p_service_name; } p_scb->suspend_sup = TRUE; p_scb->recfg_sup = TRUE; cs.p_ctrl_cback = bta_av_dt_cback[p_scb->hdi]; if(registr.chnl == BTA_AV_CHNL_AUDIO) { /* set up the audio stream control block */ p_scb->p_act_tbl = (const tBTA_AV_ACT *)bta_av_a2d_action; p_scb->p_cos = &bta_av_a2d_cos; p_scb->media_type= AVDT_MEDIA_AUDIO; cs.cfg.psc_mask = AVDT_PSC_TRANS; cs.media_type = AVDT_MEDIA_AUDIO; cs.mtu = p_bta_av_cfg->audio_mtu; cs.flush_to = L2CAP_DEFAULT_FLUSH_TO; #if AVDT_REPORTING == TRUE if(bta_av_cb.features & BTA_AV_FEAT_REPORT) { cs.cfg.psc_mask |= AVDT_PSC_REPORT; cs.p_report_cback = bta_av_a2dp_report_cback; #if AVDT_MULTIPLEXING == TRUE cs.cfg.mux_tsid_report = 2; #endif } #endif if(bta_av_cb.features & BTA_AV_FEAT_DELAY_RPT) cs.cfg.psc_mask |= AVDT_PSC_DELAY_RPT; /* keep the configuration in the stream control block */ memcpy(&p_scb->cfg, &cs.cfg, sizeof(tAVDT_CFG)); while(index < BTA_AV_MAX_SEPS && (*bta_av_a2d_cos.init)(&codec_type, cs.cfg.codec_info, &cs.cfg.num_protect, cs.cfg.protect_info, index) == TRUE) { if(AVDT_CreateStream(&p_scb->seps[index].av_handle, &cs) == AVDT_SUCCESS) { p_scb->seps[index].codec_type = codec_type; APPL_TRACE_DEBUG3("audio[%d] av_handle: %d codec_type: %d", index, p_scb->seps[index].av_handle, p_scb->seps[index].codec_type); index++; } else break; } if(!bta_av_cb.reg_audio) { /* create the SDP records on the 1st audio channel */ bta_av_cb.sdp_a2d_handle = SDP_CreateRecord(); #ifdef A2DP_SINK A2D_AddRecord(UUID_SERVCLASS_AUDIO_SINK, p_service_name, NULL, A2D_SUPF_SPEAKER, bta_av_cb.sdp_a2d_handle); bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SINK); #else A2D_AddRecord(UUID_SERVCLASS_AUDIO_SOURCE, p_service_name, NULL, A2D_SUPF_PLAYER, bta_av_cb.sdp_a2d_handle); bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SOURCE); #endif /* start listening when A2DP is registered */ if (bta_av_cb.features & BTA_AV_FEAT_RCTG) bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1); /* if the AV and AVK are both supported, it cannot support the CT role */ if (bta_av_cb.features & (BTA_AV_FEAT_RCCT)) { /* if TG is not supported, we need to register to AVCT now */ if ((bta_av_cb.features & (BTA_AV_FEAT_RCTG)) == 0) { #if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE) #if (BTA_AV_WITH_AVCTP_AUTHORIZATION == TRUE) bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu, bta_av_cb.sec_mask, BTA_ID_AV); #else bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu, (UINT8)(bta_av_cb.sec_mask & (~BTA_SEC_AUTHORIZE)), BTA_ID_AV); #endif #endif } #if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE) /* create an SDP record as AVRC CT. */ bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL, p_bta_av_cfg->avrc_ct_cat, BTA_ID_AV); #endif } } bta_av_cb.reg_audio |= BTA_AV_HNDL_TO_MSK(p_scb->hdi); APPL_TRACE_DEBUG1("reg_audio: 0x%x",bta_av_cb.reg_audio); } else { bta_av_cb.reg_video = BTA_AV_HNDL_TO_MSK(p_scb->hdi); bta_av_cb.sdp_vdp_handle = SDP_CreateRecord(); /* register the video channel */ /* no need to verify the function pointer here. it's verified prior */ (*p_bta_av_cfg->p_reg)(&cs, p_service_name, p_scb); } } while (0); /* call callback with register event */ (*bta_av_cb.p_cback)(BTA_AV_REGISTER_EVT, (tBTA_AV *)®istr); }
/******************************************************************************* ** ** Function bta_av_co_audio_getconfig ** ** Description This callout function is executed by AV to retrieve the ** desired codec and content protection configuration for the ** audio stream. ** ** ** Returns Stream codec and content protection configuration info. ** *******************************************************************************/ BTA_API UINT8 bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, UINT8 *p_codec_info, UINT8 *p_sep_info_idx, UINT8 seid, UINT8 *p_num_protect, UINT8 *p_protect_info) { UINT8 result = A2D_FAIL; BOOLEAN supported; tBTA_AV_CO_PEER *p_peer; tBTA_AV_CO_SINK *p_sink; UINT8 codec_cfg[AVDT_CODEC_SIZE]; UINT8 index; FUNC_TRACE(); APPL_TRACE_DEBUG3("bta_av_co_audio_getconfig handle:0x%x codec_type:%d seid:%d", hndl, codec_type, seid); APPL_TRACE_DEBUG4("num_protect:0x%02x protect_info:0x%02x%02x%02x", *p_num_protect, p_protect_info[0], p_protect_info[1], p_protect_info[2]); /* Retrieve the peer info */ p_peer = bta_av_co_get_peer(hndl); if (p_peer == NULL) { APPL_TRACE_ERROR0("bta_av_co_audio_getconfig could not find peer entry"); return A2D_FAIL; } APPL_TRACE_DEBUG4("bta_av_co_audio_getconfig peer(o=%d,n_snks=%d,n_rx_snks=%d,n_sup_snks=%d)", p_peer->opened, p_peer->num_snks, p_peer->num_rx_snks, p_peer->num_sup_snks); /* Increment the number of received sinks capabilities */ p_peer->num_rx_snks++; /* Check if this is a supported configuration */ supported = FALSE; switch (codec_type) { case BTA_AV_CODEC_SBC: supported = TRUE; break; default: break; } if (supported) { /* If there is room for a new one */ if (p_peer->num_sup_snks < BTA_AV_CO_NUM_ELEMENTS(p_peer->snks)) { p_sink = &p_peer->snks[p_peer->num_sup_snks++]; APPL_TRACE_DEBUG6("bta_av_co_audio_getconfig saved caps[%x:%x:%x:%x:%x:%x]", p_codec_info[1], p_codec_info[2], p_codec_info[3], p_codec_info[4], p_codec_info[5], p_codec_info[6]); memcpy(p_sink->codec_caps, p_codec_info, AVDT_CODEC_SIZE); p_sink->codec_type = codec_type; p_sink->sep_info_idx = *p_sep_info_idx; p_sink->seid = seid; p_sink->num_protect = *p_num_protect; memcpy(p_sink->protect_info, p_protect_info, BTA_AV_CP_INFO_LEN); } else { APPL_TRACE_ERROR0("bta_av_co_audio_getconfig no more room for SNK info"); } } /* If last SNK get capabilities or all supported codec capa retrieved */ if ((p_peer->num_rx_snks == p_peer->num_snks) || (p_peer->num_sup_snks == BTA_AV_CO_NUM_ELEMENTS(p_peer->snks))) { APPL_TRACE_DEBUG0("bta_av_co_audio_getconfig last sink reached"); /* Protect access to bta_av_co_cb.codec_cfg */ GKI_disable(); /* Find a sink that matches the codec config */ if (bta_av_co_audio_peer_supports_codec(p_peer, &index)) { /* stop fetching caps once we retrieved a supported codec */ if (p_peer->acp) { *p_sep_info_idx = p_peer->num_seps; APPL_TRACE_EVENT0("no need to fetch more SEPs"); } p_sink = &p_peer->snks[index]; /* Build the codec configuration for this sink */ if (bta_av_co_audio_codec_build_config(p_sink->codec_caps, codec_cfg)) { APPL_TRACE_DEBUG6("bta_av_co_audio_getconfig reconfig p_codec_info[%x:%x:%x:%x:%x:%x]", codec_cfg[1], codec_cfg[2], codec_cfg[3], codec_cfg[4], codec_cfg[5], codec_cfg[6]); /* Save the new configuration */ p_peer->p_snk = p_sink; memcpy(p_peer->codec_cfg, codec_cfg, AVDT_CODEC_SIZE); /* By default, no content protection */ *p_num_protect = 0; #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE) /* Check if this sink supports SCMS */ if (bta_av_co_audio_sink_has_scmst(p_sink)) { p_peer->cp_active = TRUE; bta_av_co_cb.cp.active = TRUE; *p_num_protect = BTA_AV_CP_INFO_LEN; memcpy(p_protect_info, bta_av_co_cp_scmst, BTA_AV_CP_INFO_LEN); } else { p_peer->cp_active = FALSE; bta_av_co_cb.cp.active = FALSE; } #endif /* If acceptor -> reconfig otherwise reply for configuration */ if (p_peer->acp) { if (p_peer->recfg_needed) { APPL_TRACE_DEBUG1("bta_av_co_audio_getconfig call BTA_AvReconfig(x%x)", hndl); BTA_AvReconfig(hndl, TRUE, p_sink->sep_info_idx, p_peer->codec_cfg, *p_num_protect, (UINT8 *)bta_av_co_cp_scmst); } } else { *p_sep_info_idx = p_sink->sep_info_idx; memcpy(p_codec_info, p_peer->codec_cfg, AVDT_CODEC_SIZE); } result = A2D_SUCCESS; } } /* Protect access to bta_av_co_cb.codec_cfg */ GKI_enable(); } return result; }
/******************************************************************************* ** ** Function bta_hh_sm_execute ** ** Description State machine event handling function for HID Host ** ** ** Returns void ** *******************************************************************************/ void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA * p_data) { tBTA_HH_ST_TBL state_table; UINT8 action; tBTA_HH cback_data; tBTA_HH_EVT cback_event = 0; #if BTA_HH_DEBUG == TRUE tBTA_HH_STATE in_state ; UINT16 debug_event = event; #endif memset(&cback_data, 0, sizeof(tBTA_HH)); /* handle exception, no valid control block was found */ if (!p_cb) { /* BTA HH enabled already? otherwise ignore the event although it's bad*/ if (bta_hh_cb.p_cback != NULL) { switch (event) { /* no control block available for new connection */ case BTA_HH_API_OPEN_EVT: cback_event = BTA_HH_OPEN_EVT; /* build cback data */ bdcpy(cback_data.conn.bda, ((tBTA_HH_API_CONN *)p_data)->bd_addr); cback_data.conn.status = BTA_HH_ERR_DB_FULL; cback_data.conn.handle = BTA_HH_INVALID_HANDLE; break; /* DB full, BTA_HhAddDev */ case BTA_HH_API_MAINT_DEV_EVT: cback_event = p_data->api_maintdev.sub_event; if (p_data->api_maintdev.sub_event == BTA_HH_ADD_DEV_EVT) { bdcpy(cback_data.dev_info.bda, p_data->api_maintdev.bda); cback_data.dev_info.status = BTA_HH_ERR_DB_FULL; cback_data.dev_info.handle = BTA_HH_INVALID_HANDLE; } else { cback_data.dev_info.status = BTA_HH_ERR_HDL; cback_data.dev_info.handle = (UINT8)p_data->api_maintdev.hdr.layer_specific; } break; case BTA_HH_API_WRITE_DEV_EVT: cback_event = (p_data->api_sndcmd.t_type - BTA_HH_FST_BTE_TRANS_EVT) + BTA_HH_FST_TRANS_CB_EVT; if (p_data->api_sndcmd.p_data != NULL) { GKI_freebuf(p_data->api_sndcmd.p_data); } if (p_data->api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL || p_data->api_sndcmd.t_type == HID_TRANS_SET_REPORT || p_data->api_sndcmd.t_type == HID_TRANS_SET_IDLE) { cback_data.dev_status.status = BTA_HH_ERR_HDL; cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific; } else if (p_data->api_sndcmd.t_type != HID_TRANS_DATA && p_data->api_sndcmd.t_type != HID_TRANS_CONTROL) { cback_data.hs_data.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific; cback_data.hs_data.status = BTA_HH_ERR_HDL; /* hs_data.rsp_data will be all zero, which is not valid value */ } else if (p_data->api_sndcmd.t_type == HID_TRANS_CONTROL && p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG) { cback_data.status = BTA_HH_ERR_HDL; cback_event = BTA_HH_VC_UNPLUG_EVT; } else cback_event = 0; break; case BTA_HH_API_CLOSE_EVT: cback_event = BTA_HH_CLOSE_EVT; cback_data.dev_status.status = BTA_HH_ERR_HDL; cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific; break; default: /* invalid handle, call bad API event */ APPL_TRACE_ERROR1("wrong device handle: [%d]", p_data->hdr.layer_specific); break; } if (cback_event) (* bta_hh_cb.p_cback)(cback_event, &cback_data); } } /* corresponding CB is found, go to state machine */ else { #if BTA_HH_DEBUG == TRUE in_state = p_cb->state; APPL_TRACE_EVENT3("bta_hh_sm_execute: State 0x%02x [%s], Event [%s]", in_state, bta_hh_state_code(in_state), bta_hh_evt_code(debug_event)); #endif if ((p_cb->state == BTA_HH_NULL_ST) || (p_cb->state >= BTA_HH_INVALID_ST)) { APPL_TRACE_ERROR2("bta_hh_sm_execute: Invalid state State = 0x%x, Event = %d", p_cb->state,event); return; } state_table = bta_hh_st_tbl[p_cb->state - 1]; event &= 0xff; p_cb->state = state_table[event][BTA_HH_NEXT_STATE] ; if ((action = state_table[event][BTA_HH_ACTION]) != BTA_HH_IGNORE) { (*bta_hh_action[action])(p_cb, p_data); } #if BTA_HH_DEBUG == TRUE if (in_state != p_cb->state) { APPL_TRACE_DEBUG3("HH State Change: [%s] -> [%s] after Event [%s]", bta_hh_state_code(in_state), bta_hh_state_code(p_cb->state), bta_hh_evt_code(debug_event)); } #endif } return; }
/******************************************************************************* ** ** Function bta_hf_client_sco_event ** ** Description Handle SCO events ** ** ** Returns void ** *******************************************************************************/ static void bta_hf_client_sco_event(UINT8 event) { APPL_TRACE_DEBUG3("%s state: %d event: %d", __FUNCTION__, bta_hf_client_cb.scb.sco_state, event); switch (bta_hf_client_cb.scb.sco_state) { case BTA_HF_CLIENT_SCO_SHUTDOWN_ST: switch (event) { case BTA_HF_CLIENT_SCO_LISTEN_E: /* create sco listen connection */ bta_hf_client_sco_create(FALSE); bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; break; default: APPL_TRACE_WARNING1("BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event %d", event); break; } break; case BTA_HF_CLIENT_SCO_LISTEN_ST: switch (event) { case BTA_HF_CLIENT_SCO_LISTEN_E: /* create sco listen connection (Additional channel) */ bta_hf_client_sco_create(FALSE); break; case BTA_HF_CLIENT_SCO_OPEN_E: /* remove listening connection */ bta_hf_client_sco_remove(FALSE); /* create sco connection to peer */ bta_hf_client_sco_create(TRUE); bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST; break; case BTA_HF_CLIENT_SCO_SHUTDOWN_E: /* remove listening connection */ bta_hf_client_sco_remove(FALSE); bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; break; case BTA_HF_CLIENT_SCO_CLOSE_E: /* remove listening connection */ /* Ignore the event. We need to keep listening SCO for the active SLC */ APPL_TRACE_WARNING1("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event); break; case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: /* sco failed; create sco listen connection */ bta_hf_client_sco_create(FALSE); bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; break; default: APPL_TRACE_WARNING1("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event); break; } break; case BTA_HF_CLIENT_SCO_OPENING_ST: switch (event) { case BTA_HF_CLIENT_SCO_CLOSE_E: bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_CL_ST; break; case BTA_HF_CLIENT_SCO_SHUTDOWN_E: bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; break; case BTA_HF_CLIENT_SCO_CONN_OPEN_E: bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_ST; break; case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: /* sco failed; create sco listen connection */ bta_hf_client_sco_create(FALSE); bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; break; default: APPL_TRACE_WARNING1("BTA_HF_CLIENT_SCO_OPENING_ST: Ignoring event %d", event); break; } break; case BTA_HF_CLIENT_SCO_OPEN_CL_ST: switch (event) { case BTA_HF_CLIENT_SCO_OPEN_E: bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST; break; case BTA_HF_CLIENT_SCO_SHUTDOWN_E: bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; break; case BTA_HF_CLIENT_SCO_CONN_OPEN_E: /* close sco connection */ bta_hf_client_sco_remove(TRUE); bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST; break; case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: /* sco failed; create sco listen connection */ bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; break; default: APPL_TRACE_WARNING1("BTA_HF_CLIENT_SCO_OPEN_CL_ST: Ignoring event %d", event); break; } break; case BTA_HF_CLIENT_SCO_OPEN_ST: switch (event) { case BTA_HF_CLIENT_SCO_CLOSE_E: /* close sco connection if active */ if (bta_hf_client_sco_remove(TRUE)) { bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST; } break; case BTA_HF_CLIENT_SCO_SHUTDOWN_E: /* remove all listening connections */ bta_hf_client_sco_remove(FALSE); bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; break; case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: /* peer closed sco; create sco listen connection */ bta_hf_client_sco_create(FALSE); bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; break; default: APPL_TRACE_WARNING1("BTA_HF_CLIENT_SCO_OPEN_ST: Ignoring event %d", event); break; } break; case BTA_HF_CLIENT_SCO_CLOSING_ST: switch (event) { case BTA_HF_CLIENT_SCO_OPEN_E: bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSE_OP_ST; break; case BTA_HF_CLIENT_SCO_SHUTDOWN_E: bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; break; case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: /* peer closed sco; create sco listen connection */ bta_hf_client_sco_create(FALSE); bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; break; default: APPL_TRACE_WARNING1("BTA_HF_CLIENT_SCO_CLOSING_ST: Ignoring event %d", event); break; } break; case BTA_HF_CLIENT_SCO_CLOSE_OP_ST: switch (event) { case BTA_HF_CLIENT_SCO_CLOSE_E: bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST; break; case BTA_HF_CLIENT_SCO_SHUTDOWN_E: bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; break; case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: /* open sco connection */ bta_hf_client_sco_create(TRUE); bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST; break; default: APPL_TRACE_WARNING1("BTA_HF_CLIENT_SCO_CLOSE_OP_ST: Ignoring event %d", event); break; } break; case BTA_HF_CLIENT_SCO_SHUTTING_ST: switch (event) { case BTA_HF_CLIENT_SCO_CONN_OPEN_E: /* close sco connection; wait for conn close event */ bta_hf_client_sco_remove(TRUE); break; case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; break; case BTA_HF_CLIENT_SCO_SHUTDOWN_E: bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; break; default: APPL_TRACE_WARNING1("BTA_HF_CLIENT_SCO_SHUTTING_ST: Ignoring event %d", event); break; } break; default: break; } }