/******************************************************************************* ** ** Function bta_hl_co_get_mdl_config ** ** Description This function is called to get the MDL configuration ** from the persistent memory. This function shall only be called *8 once after the device is powered up ** ** Parameters app_id - HDP application ID ** buffer_size - the unit of the buffer size is sizeof(tBTA_HL_MDL_CFG) ** p_mdl_buf - Point to the starting location of the buffer ** ** Returns BOOLEAN ** ** *******************************************************************************/ BOOLEAN bta_hl_co_load_mdl_config (UINT8 app_id, UINT8 buffer_size, tBTA_HL_MDL_CFG *p_mdl_buf ) { BOOLEAN result = TRUE; UINT8 i; tBTA_HL_MDL_CFG *p; BTIF_TRACE_DEBUG3("%s app_id=%d, num_items=%d", __FUNCTION__, app_id, buffer_size); if (buffer_size > BTA_HL_NUM_MDL_CFGS) { result = FALSE; return result; } result = btif_hl_load_mdl_config(app_id, buffer_size, p_mdl_buf); if (result) { for (i=0, p=p_mdl_buf; i<buffer_size; i++, p++ ) { if (p->active) { BTIF_TRACE_DEBUG6("i=%d mdl_id=0x%x dch_mode=%d local mdep_role=%d mdep_id=%d mtu=%d", i, p->mdl_id, p->dch_mode, p->local_mdep_role, p->local_mdep_role, p->mtu); } } } BTIF_TRACE_DEBUG3("%s success=%d num_items=%d", __FUNCTION__, result, buffer_size); return result; }
/******************************************************************************* ** ** Function bta_hl_co_delete_mdl ** ** Description This function is called to delete a MDL configuration item in persistent ** storage ** ** Parameters app_id - HDP application ID ** item_idx - the MDL configuration storage index ** ** Returns void ** *******************************************************************************/ void bta_hl_co_delete_mdl(UINT8 app_id, UINT8 item_idx) { BTIF_TRACE_DEBUG3("%s app_id=%d, item_idx=%d", __FUNCTION__, app_id, item_idx); btif_hl_delete_mdl_cfg(app_id, item_idx); }
void send_key (int fd, uint16_t key, int pressed) { BTIF_TRACE_DEBUG4("%s fd:%d key:%u pressed:%d", __FUNCTION__, fd, key, pressed); if (fd < 0) { return; } BTIF_TRACE_DEBUG3("AVRCP: Send key %d (%d) fd=%d", key, pressed, fd); send_event(fd, EV_KEY, key, pressed); send_event(fd, EV_SYN, SYN_REPORT, 0); }
BOOLEAN btif_av_stream_started_ready(void) { btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle); BTIF_TRACE_DEBUG3("btif_av_stream_started : sm hdl %d, state %d, flags %x", btif_av_cb.sm_handle, state, btif_av_cb.flags); /* don't allow media task to start if we are suspending or remotely suspended (not yet changed state) */ if (btif_av_cb.flags & (BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING | BTIF_AV_FLAG_REMOTE_SUSPEND)) return FALSE; return (state == BTIF_AV_STATE_STARTED); }
int init_uinput (void) { char *name = "AVRCP"; BTIF_TRACE_DEBUG1("%s", __FUNCTION__); uinput_fd = uinput_create(name); if (uinput_fd < 0) { BTIF_TRACE_ERROR3("%s AVRCP: Failed to initialize uinput for %s (%d)", __FUNCTION__, name, uinput_fd); } else { BTIF_TRACE_DEBUG3("%s AVRCP: Initialized uinput for %s (fd=%d)", __FUNCTION__, name, uinput_fd); } return uinput_fd; }
/******************************************************************************* ** ** Function bta_hl_co_get_num_of_mdep ** ** Description This function is called to get the number of MDEPs for this ** application ID ** ** Parameters app_id - application ID ** p_num_of_mdep (output) - number of MDEP configurations supported ** by the application ** ** Returns Bloolean - TRUE success ** *******************************************************************************/ BOOLEAN bta_hl_co_get_num_of_mdep(UINT8 app_id, UINT8 *p_num_of_mdep) { UINT8 app_idx; BOOLEAN success = FALSE; if (btif_hl_find_app_idx(app_id, &app_idx)) { *p_num_of_mdep = p_btif_hl_cb->acb[app_idx].sup_feature.num_of_mdeps; success = TRUE; } BTIF_TRACE_DEBUG3("%s success=%d num_mdeps=%d", __FUNCTION__, success, *p_num_of_mdep ); return success; }
/*************************************************************************** ** ** Function btif_rc_handler ** ** Description RC event handler ** ***************************************************************************/ void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data) { BTIF_TRACE_DEBUG2 ("%s event:%s", __FUNCTION__, dump_rc_event(event)); switch (event) { case BTA_AV_RC_OPEN_EVT: { BTIF_TRACE_DEBUG1("Peer_features:%x", p_data->rc_open.peer_features); handle_rc_connect( &(p_data->rc_open) ); }break; case BTA_AV_RC_CLOSE_EVT: { handle_rc_disconnect( &(p_data->rc_close) ); }break; case BTA_AV_REMOTE_CMD_EVT: { BTIF_TRACE_DEBUG2("rc_id:0x%x key_state:%d", p_data->remote_cmd.rc_id, p_data->remote_cmd.key_state); handle_rc_passthrough_cmd( (&p_data->remote_cmd) ); } break; case BTA_AV_RC_FEAT_EVT: { BTIF_TRACE_DEBUG1("Peer_features:%x", p_data->rc_feat.peer_features); btif_rc_cb.rc_features = p_data->rc_feat.peer_features; /* TODO Handle RC_FEAT_EVT*/ } break; case BTA_AV_META_MSG_EVT: { BTIF_TRACE_DEBUG2("BTA_AV_META_MSG_EVT code:%d label:%d", p_data->meta_msg.code, p_data->meta_msg.label); BTIF_TRACE_DEBUG3(" company_id:0x%x len:%d handle:%d", p_data->meta_msg.company_id, p_data->meta_msg.len, p_data->meta_msg.rc_handle); /* handle the metamsg command */ handle_rc_metamsg_cmd(&(p_data->meta_msg)); } break; default: BTIF_TRACE_DEBUG1("Unhandled RC event : 0x%x", event); } }
btpan_conn_t* btpan_new_conn(int handle, const BD_ADDR addr, int local_role, int remote_role ) { int i; for(i = 0; i < MAX_PAN_CONNS; i++) { BTIF_TRACE_DEBUG2("conns[%d]:%d", i, btpan_cb.conns[i].handle); if(btpan_cb.conns[i].handle == -1) { BTIF_TRACE_DEBUG3("handle:%d, local_role:%d, remote_role:%d", handle, local_role, remote_role); btpan_cb.conns[i].handle = handle; bdcpy(btpan_cb.conns[i].peer, addr); btpan_cb.conns[i].local_role = local_role; btpan_cb.conns[i].remote_role = remote_role; return &btpan_cb.conns[i]; } } BTIF_TRACE_DEBUG1("MAX_PAN_CONNS:%d exceeded, return NULL as failed", MAX_PAN_CONNS); return NULL; }
BOOLEAN btif_av_stream_ready(void) { btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle); BTIF_TRACE_DEBUG3("btif_av_stream_ready : sm hdl %d, state %d, flags %x", btif_av_cb.sm_handle, state, btif_av_cb.flags); /* also make sure main adapter is enabled */ if (btif_is_enabled() == 0) { BTIF_TRACE_EVENT0("main adapter not enabled"); return FALSE; } /* check if we are remotely suspended */ if (btif_av_cb.flags & BTIF_AV_FLAG_REMOTE_SUSPEND) return FALSE; return (state == BTIF_AV_STATE_OPENED); }
/*************************************************************************** * Function send_metamsg_rsp * * - Argument: * rc_handle RC handle corresponding to the connected RC * label Label of the RC response * code Response type * pmetamsg_resp Vendor response * * - Description: Remote control metamsg response handler (AVRCP 1.3) * ***************************************************************************/ static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label, tBTA_AV_CODE code, tAVRC_RESPONSE *pmetamsg_resp) { UINT8 ctype; tAVRC_STS status; if (!pmetamsg_resp) { BTIF_TRACE_WARNING1("%s: Invalid response received from application", __FUNCTION__); return; } BTIF_TRACE_EVENT5("+%s: rc_handle: %d, label: %d, code: 0x%02x, pdu: %s", __FUNCTION__, rc_handle, label, code, dump_rc_pdu(pmetamsg_resp->rsp.pdu)); if (pmetamsg_resp->rsp.status != AVRC_STS_NO_ERROR) { ctype = AVRC_RSP_REJ; } else { if ( code < AVRC_RSP_NOT_IMPL) { if (code == AVRC_CMD_NOTIF) { ctype = AVRC_RSP_INTERIM; } else if (code == AVRC_CMD_STATUS) { ctype = AVRC_RSP_IMPL_STBL; } else { ctype = AVRC_RSP_ACCEPT; } } else { ctype = code; } } /* if response is for register_notification, make sure the rc has actually registered for this */ if((pmetamsg_resp->rsp.pdu == AVRC_PDU_REGISTER_NOTIFICATION) && (code == AVRC_RSP_CHANGED)) { BOOLEAN bSent = FALSE; UINT8 event_id = pmetamsg_resp->reg_notif.event_id; BOOLEAN bNotify = (btif_rc_cb.rc_connected) && (btif_rc_cb.rc_notif[event_id-1].bNotify); /* de-register this notification for a CHANGED response */ btif_rc_cb.rc_notif[event_id-1].bNotify = FALSE; BTIF_TRACE_DEBUG4("%s rc_handle: %d. event_id: 0x%02d bNotify:%u", __FUNCTION__, btif_rc_cb.rc_handle, event_id, bNotify); if (bNotify) { BT_HDR *p_msg = NULL; tAVRC_STS status; if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(btif_rc_cb.rc_handle, pmetamsg_resp, &p_msg)) ) { BTIF_TRACE_DEBUG3("%s Sending notification to rc_handle: %d. event_id: 0x%02d", __FUNCTION__, btif_rc_cb.rc_handle, event_id); bSent = TRUE; BTA_AvMetaRsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_notif[event_id-1].label, ctype, p_msg); } else { BTIF_TRACE_WARNING2("%s failed to build metamsg response. status: 0x%02x", __FUNCTION__, status); } } if (!bSent) { BTIF_TRACE_DEBUG2("%s: Notification not sent, as there are no RC connections or the \ CT has not subscribed for event_id: %s", __FUNCTION__, dump_rc_notification_event_id(event_id)); }
/*************************************************************************** * Function handle_rc_metamsg_cmd * * - Argument: tBTA_AV_VENDOR Structure containing the received * metamsg command * * - Description: Remote control metamsg command handler (AVRCP 1.3) * ***************************************************************************/ void handle_rc_metamsg_cmd (tBTA_AV_META_MSG *pmeta_msg) { /* Parse the metamsg command and pass it on to BTL-IFS */ UINT8 scratch_buf[512] = {0}; tAVRC_COMMAND avrc_command = {0}; tAVRC_STS status; int param_len; BTIF_TRACE_EVENT1("+ %s", __FUNCTION__); if (pmeta_msg->p_msg->hdr.opcode != AVRC_OP_VENDOR) { BTIF_TRACE_WARNING1("Invalid opcode: %x", pmeta_msg->p_msg->hdr.opcode); return; } if (pmeta_msg->len < 3) { BTIF_TRACE_WARNING2("Invalid length.Opcode: 0x%x, len: 0x%x", pmeta_msg->p_msg->hdr.opcode, pmeta_msg->len); return; } if (pmeta_msg->code >= AVRC_RSP_NOT_IMPL) { BTIF_TRACE_DEBUG3("%s:Received vendor dependent rsp. code: %d len: %d. Not processing it.", __FUNCTION__, pmeta_msg->code, pmeta_msg->len); return; } status = AVRC_ParsCommand(pmeta_msg->p_msg, &avrc_command, scratch_buf, sizeof(scratch_buf)); if (status != AVRC_STS_NO_ERROR) { /* return error */ BTIF_TRACE_WARNING2("%s: Error in parsing received metamsg command. status: 0x%02x", __FUNCTION__, status); send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_command.pdu, status); } else { /* if RegisterNotification, add it to our registered queue */ if (avrc_command.cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION) { UINT8 event_id = avrc_command.reg_notif.event_id; param_len = sizeof(tAVRC_REG_NOTIF_CMD); BTIF_TRACE_EVENT3("%s: New register notification received. event_id:%s, label:0x%x", __FUNCTION__, dump_rc_notification_event_id(event_id), pmeta_msg->label); btif_rc_cb.rc_notif[event_id-1].bNotify = TRUE; btif_rc_cb.rc_notif[event_id-1].label = pmeta_msg->label; if(event_id == AVRC_EVT_UIDS_CHANGE) { handle_uid_changed_notification(pmeta_msg, &avrc_command); return; } } BTIF_TRACE_EVENT2("%s: Passing received metamsg command to app. pdu: %s", __FUNCTION__, dump_rc_pdu(avrc_command.cmd.pdu)); /* Since handle_rc_metamsg_cmd() itself is called from *btif context, no context switching is required. Invoke * btif_rc_upstreams_evt directly from here. */ btif_rc_upstreams_evt((uint16_t)avrc_command.cmd.pdu, &avrc_command, pmeta_msg->code, pmeta_msg->label); } }
/*************************************************************************** * Function handle_rc_passthrough_cmd * * - Argument: tBTA_AV_RC rc_id remote control command ID * tBTA_AV_STATE key_state status of key press * * - Description: Remote control command handler * ***************************************************************************/ void handle_rc_passthrough_cmd ( tBTA_AV_REMOTE_CMD *p_remote_cmd) { const char *status; int pressed, i; /* If AVRC is open and peer sends PLAY but there is no AVDT, then we queue-up this PLAY */ if (p_remote_cmd) { /* queue AVRC PLAY if GAVDTP Open notification to app is pending (2 second timer) */ if ((p_remote_cmd->rc_id == BTA_AV_RC_PLAY) && (!btif_av_is_connected())) { if (p_remote_cmd->key_state == AVRC_STATE_PRESS) { APPL_TRACE_WARNING1("%s: AVDT not open, queuing the PLAY command", __FUNCTION__); btif_rc_cb.rc_pending_play = TRUE; } return; } if ((p_remote_cmd->rc_id == BTA_AV_RC_PAUSE) && (btif_rc_cb.rc_pending_play)) { APPL_TRACE_WARNING1("%s: Clear the pending PLAY on PAUSE received", __FUNCTION__); btif_rc_cb.rc_pending_play = FALSE; return; } } if (p_remote_cmd->key_state == AVRC_STATE_RELEASE) { status = "released"; pressed = 0; } else { status = "pressed"; pressed = 1; } /* If this is Play/Pause command (press or release) before processing, check the following * a voice call has ended recently * the remote device is not of type headset * If the above conditions meet, drop the Play/Pause command * This fix is to interop with certain carkits which sends an automatic PLAY or PAUSE * commands right after call ends */ if((p_remote_cmd->rc_id == BTA_AV_RC_PLAY || p_remote_cmd->rc_id == BTA_AV_RC_PAUSE)&& (btif_hf_call_terminated_recently() == TRUE) && (check_cod( (const bt_bdaddr_t*)&(btif_rc_cb.rc_addr), COD_AV_HEADSETS) != TRUE)) { BTIF_TRACE_DEBUG2("%s:Dropping the play/Pause command received right after call end cmd:%d", __FUNCTION__,p_remote_cmd->rc_id); return; } for (i = 0; key_map[i].name != NULL; i++) { if (p_remote_cmd->rc_id == key_map[i].avrcp) { BTIF_TRACE_DEBUG3("%s: %s %s", __FUNCTION__, key_map[i].name, status); /* MusicPlayer uses a long_press_timeout of 1 second for PLAYPAUSE button * and maps that to autoshuffle. So if for some reason release for PLAY/PAUSE * comes 1 second after the press, the MediaPlayer UI goes into a bad state. * The reason for the delay could be sniff mode exit or some AVDTP procedure etc. * The fix is to generate a release right after the press and drown the 'actual' * release. */ if ((key_map[i].release_quirk == 1) && (pressed == 0)) { BTIF_TRACE_DEBUG2("%s: AVRC %s Release Faked earlier, drowned now", __FUNCTION__, key_map[i].name); return; } send_key(uinput_fd, key_map[i].mapped_id, pressed); if ((key_map[i].release_quirk == 1) && (pressed == 1)) { GKI_delay(30); // 30ms BTIF_TRACE_DEBUG2("%s: AVRC %s Release quirk enabled, send release now", __FUNCTION__, key_map[i].name); send_key(uinput_fd, key_map[i].mapped_id, 0); } break; } } if (key_map[i].name == NULL) BTIF_TRACE_ERROR3("%s AVRCP: unknown button 0x%02X %s", __FUNCTION__, p_remote_cmd->rc_id, status); }
/*************************************************************************** * Function handle_rc_passthrough_cmd * * - Argument: tBTA_AV_RC rc_id remote control command ID * tBTA_AV_STATE key_state status of key press * * - Description: Remote control command handler * ***************************************************************************/ void handle_rc_passthrough_cmd ( tBTA_AV_REMOTE_CMD *p_remote_cmd) { const char *status; int pressed, i; /* If AVRC is open and peer sends PLAY but there is no AVDT, then we queue-up this PLAY */ if (p_remote_cmd) { /* queue AVRC PLAY if GAVDTP Open notification to app is pending (2 second timer) */ if ((p_remote_cmd->rc_id == BTA_AV_RC_PLAY) && (!btif_av_is_connected())) { if (p_remote_cmd->key_state == AVRC_STATE_PRESS) { APPL_TRACE_WARNING1("%s: AVDT not open, queuing the PLAY command", __FUNCTION__); btif_rc_cb.rc_pending_play = TRUE; } return; } if ((p_remote_cmd->rc_id == BTA_AV_RC_PAUSE) && (btif_rc_cb.rc_pending_play)) { APPL_TRACE_WARNING1("%s: Clear the pending PLAY on PAUSE received", __FUNCTION__); btif_rc_cb.rc_pending_play = FALSE; return; } } if (p_remote_cmd->key_state == AVRC_STATE_RELEASE) { status = "released"; pressed = 0; } else { status = "pressed"; pressed = 1; } for (i = 0; key_map[i].name != NULL; i++) { if (p_remote_cmd->rc_id == key_map[i].avrcp) { BTIF_TRACE_DEBUG3("%s: %s %s", __FUNCTION__, key_map[i].name, status); /* MusicPlayer uses a long_press_timeout of 1 second for PLAYPAUSE button * and maps that to autoshuffle. So if for some reason release for PLAY/PAUSE * comes 1 second after the press, the MediaPlayer UI goes into a bad state. * The reason for the delay could be sniff mode exit or some AVDTP procedure etc. * The fix is to generate a release right after the press and drown the 'actual' * release. */ if ((key_map[i].release_quirk == 1) && (pressed == 0)) { BTIF_TRACE_DEBUG2("%s: AVRC %s Release Faked earlier, drowned now", __FUNCTION__, key_map[i].name); return; } send_key(uinput_fd, key_map[i].mapped_id, pressed); if ((key_map[i].release_quirk == 1) && (pressed == 1)) { GKI_delay(30); // 30ms BTIF_TRACE_DEBUG2("%s: AVRC %s Release quirk enabled, send release now", __FUNCTION__, key_map[i].name); send_key(uinput_fd, key_map[i].mapped_id, 0); } break; } } if (key_map[i].name == NULL) BTIF_TRACE_ERROR3("%s AVRCP: unknown button 0x%02X %s", __FUNCTION__, p_remote_cmd->rc_id, status); }
static bt_status_t phone_state_change(int num_active, int num_held, bthf_call_state_t call_setup_state, const char *number, bthf_call_addrtype_t type) { tBTA_AG_RES res = 0xff; tBTA_AG_RES_DATA ag_res; bt_status_t status = BT_STATUS_SUCCESS; BOOLEAN activeCallUpdated = FALSE; CHECK_BTHF_SLC_CONNECTED(); BTIF_TRACE_DEBUG6("phone_state_change: num_active=%d [prev: %d] num_held=%d[prev: %d]"\ " call_setup=%s [prev: %s]", num_active, btif_hf_cb.num_active, num_held, btif_hf_cb.num_held, dump_hf_call_state(call_setup_state), dump_hf_call_state(btif_hf_cb.call_setup_state)); /* if all indicators are 0, send end call and return */ if (num_active == 0 && num_held == 0 && call_setup_state == BTHF_CALL_STATE_IDLE) { BTIF_TRACE_DEBUG1("%s: Phone on hook", __FUNCTION__); /* record call termination timestamp if there was an active/held call or callsetup state > BTHF_CALL_STATE_IDLE */ if ((btif_hf_cb.call_setup_state != BTHF_CALL_STATE_IDLE ) || (btif_hf_cb.num_active) ||(btif_hf_cb.num_held)) { BTIF_TRACE_DEBUG1("%s: Record call termination timestamp", __FUNCTION__); clock_gettime(CLOCK_MONOTONIC, &btif_hf_cb.call_end_timestamp); } BTA_AgResult (BTA_AG_HANDLE_ALL, BTA_AG_END_CALL_RES, NULL); /* if held call was present, reset that as well */ if (btif_hf_cb.num_held) send_indicator_update(BTA_AG_IND_CALLHELD, 0); goto update_call_states; } /* active state can change when: ** 1. an outgoing/incoming call was answered ** 2. an held was resumed ** 3. without callsetup notifications, call became active ** (3) can happen if call is active and a headset connects to us ** ** In the case of (3), we will have to notify the stack of an active ** call, instead of sending an indicator update. This will also ** force the SCO to be setup. Handle this special case here prior to ** call setup handling */ if ( (num_active == 1) && (btif_hf_cb.num_active == 0) && (btif_hf_cb.num_held == 0) && (btif_hf_cb.call_setup_state == BTHF_CALL_STATE_IDLE) ) { BTIF_TRACE_DEBUG1("%s: Active call notification received without call setup update", __FUNCTION__); memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA)); ag_res.audio_handle = btif_hf_cb.handle; res = BTA_AG_OUT_CALL_CONN_RES; BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res); activeCallUpdated = TRUE; } /* Ringing call changed? */ if (call_setup_state != btif_hf_cb.call_setup_state) { BTIF_TRACE_DEBUG3("%s: Call setup states changed. old: %s new: %s", __FUNCTION__, dump_hf_call_state(btif_hf_cb.call_setup_state), dump_hf_call_state(call_setup_state)); memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA)); switch (call_setup_state) { case BTHF_CALL_STATE_IDLE: { switch (btif_hf_cb.call_setup_state) { case BTHF_CALL_STATE_INCOMING: if (num_active > btif_hf_cb.num_active) { res = BTA_AG_IN_CALL_CONN_RES; ag_res.audio_handle = btif_hf_cb.handle; } else if (num_held > btif_hf_cb.num_held) res = BTA_AG_IN_CALL_HELD_RES; else res = BTA_AG_CALL_CANCEL_RES; break; case BTHF_CALL_STATE_DIALING: case BTHF_CALL_STATE_ALERTING: if (num_active > btif_hf_cb.num_active) { ag_res.audio_handle = BTA_AG_HANDLE_SCO_NO_CHANGE; res = BTA_AG_OUT_CALL_CONN_RES; } else res = BTA_AG_CALL_CANCEL_RES; break; default: BTIF_TRACE_ERROR1("%s: Incorrect Call setup state transition", __FUNCTION__); status = BT_STATUS_PARM_INVALID; break; } } break; case BTHF_CALL_STATE_INCOMING: if (num_active || num_held) res = BTA_AG_CALL_WAIT_RES; else res = BTA_AG_IN_CALL_RES; if (number) { int xx = 0; if ((type == BTHF_CALL_ADDRTYPE_INTERNATIONAL) && (*number != '+')) xx = sprintf (ag_res.str, "\"+%s\"", number); else xx = sprintf (ag_res.str, "\"%s\"", number); ag_res.num = type; if (res == BTA_AG_CALL_WAIT_RES) sprintf(&ag_res.str[xx], ",%d", type); } break; case BTHF_CALL_STATE_DIALING: ag_res.audio_handle = btif_hf_cb.handle; res = BTA_AG_OUT_CALL_ORIG_RES; break; case BTHF_CALL_STATE_ALERTING: /* if we went from idle->alert, force SCO setup here. dialing usually triggers it */ if (btif_hf_cb.call_setup_state == BTHF_CALL_STATE_IDLE) ag_res.audio_handle = btif_hf_cb.handle; res = BTA_AG_OUT_CALL_ALERT_RES; break; default: BTIF_TRACE_ERROR1("%s: Incorrect new ringing call state", __FUNCTION__); status = BT_STATUS_PARM_INVALID; break; } BTIF_TRACE_DEBUG3("%s: Call setup state changed. res=%d, audio_handle=%d", __FUNCTION__, res, ag_res.audio_handle); if (res) BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res); /* if call setup is idle, we have already updated call indicator, jump out */ if (call_setup_state == BTHF_CALL_STATE_IDLE) { /* check & update callheld */ if ((num_held > 0) && (num_active > 0)) send_indicator_update(BTA_AG_IND_CALLHELD, 1); goto update_call_states; } } memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA)); /* per the errata 2043, call=1 implies atleast one call is in progress (active/held) ** https://www.bluetooth.org/errata/errata_view.cfm?errata_id=2043 ** Handle call indicator change **/ if (!activeCallUpdated && ((num_active + num_held) != (btif_hf_cb.num_active + btif_hf_cb.num_held)) ) { BTIF_TRACE_DEBUG3("%s: Active call states changed. old: %d new: %d", __FUNCTION__, btif_hf_cb.num_active, num_active); send_indicator_update(BTA_AG_IND_CALL, ((num_active + num_held) > 0) ? 1 : 0); } /* Held Changed? */ if (num_held != btif_hf_cb.num_held) { BTIF_TRACE_DEBUG3("%s: Held call states changed. old: %d new: %d", __FUNCTION__, btif_hf_cb.num_held, num_held); send_indicator_update(BTA_AG_IND_CALLHELD, ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1))); } /* Calls Swapped? */ if ( (call_setup_state == btif_hf_cb.call_setup_state) && (num_active && num_held) && (num_active == btif_hf_cb.num_active) && (num_held == btif_hf_cb.num_held) ) { BTIF_TRACE_DEBUG1("%s: Calls swapped", __FUNCTION__); send_indicator_update(BTA_AG_IND_CALLHELD, 1); } update_call_states: btif_hf_cb.num_active = num_active; btif_hf_cb.num_held = num_held; btif_hf_cb.call_setup_state = call_setup_state; return status; }