/******************************************************************************* ** ** Function bta_gattc_clear_notif_registration ** ** Description clear up the notification registration information by BD_ADDR. ** ** Returns None. ** *******************************************************************************/ void bta_gattc_clear_notif_registration(UINT16 conn_id) { BD_ADDR remote_bda; tBTA_GATTC_IF gatt_if; tBTA_GATTC_RCB *p_clrcb ; UINT8 i; tGATT_TRANSPORT transport; if (GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda, &transport)) { if ((p_clrcb = bta_gattc_cl_get_regcb(gatt_if)) != NULL) { for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++) { if (p_clrcb->notif_reg[i].in_use && !bdcmp(p_clrcb->notif_reg[i].remote_bda, remote_bda)) memset(&p_clrcb->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG)); } } } else { APPL_TRACE_ERROR("can not clear indication/notif registration for unknown app"); } return; }
/******************************************************************************* ** ** Function bta_hf_client_sco_conn_cback ** ** Description BTM SCO connection callback. ** ** ** Returns void ** *******************************************************************************/ static void bta_hf_client_sco_conn_cback(UINT16 sco_idx) { BT_HDR *p_buf; UINT8 *rem_bd; APPL_TRACE_DEBUG2("%s %d", __FUNCTION__, sco_idx); rem_bd = BTM_ReadScoBdAddr(sco_idx); if (rem_bd && bdcmp(bta_hf_client_cb.scb.peer_addr, rem_bd) == 0 && bta_hf_client_cb.scb.svc_conn && bta_hf_client_cb.scb.sco_idx == sco_idx) { if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) { p_buf->event = BTA_HF_CLIENT_SCO_OPEN_EVT; p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle; bta_sys_sendmsg(p_buf); } } /* no match found; disconnect sco, init sco variables */ else { bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; BTM_RemoveSco(sco_idx); } }
static BOOLEAN is_connected(bt_bdaddr_t *bd_addr) { if (((btif_hf_client_cb.state == BTHF_CLIENT_CONNECTION_STATE_CONNECTED) || (btif_hf_client_cb.state == BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED))&& ((bd_addr == NULL) || (bdcmp(bd_addr->address, btif_hf_client_cb.connected_bda.address) == 0))) return TRUE; return FALSE; }
/******************************************************************************* ** ** Function bta_gattc_find_srvr_cache ** ** Description find server cache by remote bd address ** ** Returns pointer to the server cache. ** *******************************************************************************/ tBTA_GATTC_SERV * bta_gattc_find_srvr_cache(BD_ADDR bda) { tBTA_GATTC_SERV *p_srcb = &bta_gattc_cb.known_server[0]; UINT8 i; for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_srcb ++) { if (bdcmp(p_srcb->server_bda, bda) == 0) return p_srcb; } return NULL; }
/******************************************************************************* ** ** Function bta_gattc_check_bg_conn ** ** Description check if this is a background connection background connection. ** ** Returns TRUE if success; FALSE otherwise. ** *******************************************************************************/ BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR remote_bda, UINT8 role) { tBTA_GATTC_BG_TCK *p_bg_tck = &bta_gattc_cb.bg_track[0]; UINT8 i = 0; BOOLEAN is_bg_conn = FALSE; for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX && !is_bg_conn; i ++, p_bg_tck ++) { if (p_bg_tck->in_use && (bdcmp(p_bg_tck->remote_bda, remote_bda) == 0 || bdcmp(p_bg_tck->remote_bda, dummy_bda) == 0)) { if (((p_bg_tck->cif_mask &(1 <<(client_if - 1))) != 0) && role == HCI_ROLE_MASTER) is_bg_conn = TRUE; if (((p_bg_tck->cif_adv_mask &(1 <<(client_if - 1))) != 0) && role == HCI_ROLE_SLAVE) is_bg_conn = TRUE; } } return is_bg_conn; }
/******************************************************************************* ** ** Function bta_dm_find_peer_device ** ** Description Given an address, find the associated control block. ** ** Returns tBTA_DM_PEER_DEVICE ** *******************************************************************************/ tBTA_DM_PEER_DEVICE * bta_dm_find_peer_device(BD_ADDR peer_addr) { tBTA_DM_PEER_DEVICE *p_dev = NULL; int i; for(i=0; i<bta_dm_cb.device_list.count; i++) { if(!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, peer_addr)) { p_dev = &bta_dm_cb.device_list.peer_device[i]; break; } } return p_dev; }
/******************************************************************************* ** ** Function bta_gattc_find_clcb_by_cif ** ** Description get clcb by client interface and remote bd adddress ** ** Returns pointer to the clcb ** *******************************************************************************/ tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda, tBTA_TRANSPORT transport) { tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0]; UINT8 i; for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++) { if (p_clcb->in_use && p_clcb->p_rcb->client_if == client_if && p_clcb->transport == transport && bdcmp(p_clcb->bda, remote_bda) == 0) return p_clcb; } return NULL; }
/******************************************************************************* ** ** Function bta_dm_pm_stop_timer ** ** Description stop a PM timer ** ** ** Returns void ** *******************************************************************************/ static void bta_dm_pm_stop_timer(BD_ADDR peer_addr) { UINT8 i; for(i=0; i<BTA_DM_NUM_PM_TIMER; i++) { if(bta_dm_cb.pm_timer[i].in_use && !bdcmp(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr)) { APPL_TRACE_DEBUG("stop dm_pm_timer:%d", i); bta_sys_stop_timer(&bta_dm_cb.pm_timer[i].timer); bta_dm_cb.pm_timer[i].in_use = FALSE; break; } } }
/******************************************************************************* ** ** Function bta_hf_client_rfc_acp_open ** ** Description Handle RFCOMM channel open when accepting connection. ** ** ** Returns void ** *******************************************************************************/ void bta_hf_client_rfc_acp_open(tBTA_HF_CLIENT_DATA *p_data) { UINT16 lcid; BD_ADDR dev_addr; int status; /* set role */ bta_hf_client_cb.scb.role = BTA_HF_CLIENT_ACP; APPL_TRACE_DEBUG ("bta_hf_client_rfc_acp_open: serv_handle = %d rfc.port_handle = %d", bta_hf_client_cb.scb.serv_handle, p_data->rfc.port_handle); /* get bd addr of peer */ if (PORT_SUCCESS != (status=PORT_CheckConnection(p_data->rfc.port_handle, dev_addr, &lcid))) { APPL_TRACE_DEBUG ("bta_hf_client_rfc_acp_open error PORT_CheckConnection returned status %d", status); } /* Collision Handling */ if (bta_hf_client_cb.scb.colli_tmr_on) { /* stop collision timer */ bta_hf_client_cb.scb.colli_tmr_on = FALSE; bta_sys_stop_timer (&bta_hf_client_cb.scb.colli_timer); if (bdcmp (dev_addr, bta_hf_client_cb.scb.peer_addr) == 0) { /* If incoming and outgoing device are same, nothing more to do. */ /* Outgoing conn will be aborted because we have successful incoming conn. */ } else { /* Resume outgoing connection. */ bta_hf_client_resume_open (); } } bdcpy (bta_hf_client_cb.scb.peer_addr, dev_addr); bta_hf_client_cb.scb.conn_handle = p_data->rfc.port_handle; /* do service discovery to get features */ bta_hf_client_do_disc(); /* continue with open processing */ bta_hf_client_rfc_open(p_data); }
/******************************************************************************* ** ** Function bta_gattc_conn_find ** ** Description allocate connection tracking spot ** ** Returns pointer to the clcb ** *******************************************************************************/ tBTA_GATTC_CONN * bta_gattc_conn_find(BD_ADDR remote_bda) { UINT8 i_conn = 0; tBTA_GATTC_CONN *p_conn = &bta_gattc_cb.conn_track[0]; for (i_conn = 0; i_conn < BTA_GATTC_CONN_MAX; i_conn++, p_conn ++) { if (p_conn->in_use && bdcmp(remote_bda, p_conn->remote_bda) == 0) { #if BTA_GATT_DEBUG == TRUE APPL_TRACE_DEBUG("bta_gattc_conn_find: found conn_track[%d] matched",i_conn); #endif return p_conn; } } return NULL; }
/******************************************************************************* ** ** Function bta_gattc_check_notif_registry ** ** Description check if the service notificaition has been registered. ** ** Returns ** *******************************************************************************/ BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB *p_clreg, tBTA_GATTC_SERV *p_srcb, tBTA_GATTC_NOTIFY *p_notify) { UINT8 i; for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++) { if (p_clreg->notif_reg[i].in_use && bdcmp(p_clreg->notif_reg[i].remote_bda, p_srcb->server_bda) == 0 && bta_gattc_charid_compare (&p_clreg->notif_reg[i].char_id, &p_notify->char_id)) { APPL_TRACE_DEBUG("Notification registered!"); return TRUE; } } return FALSE; }
/******************************************************************************* ** ** Function bta_av_addr_to_scb ** ** Description find the stream control block by the peer addr ** ** Returns void ** *******************************************************************************/ static tBTA_AV_SCB * bta_av_addr_to_scb(BD_ADDR bd_addr) { tBTA_AV_SCB * p_scb = NULL; int xx; for(xx=0; xx<BTA_AV_NUM_STRS; xx++) { if(bta_av_cb.p_scb[xx]) { if(!bdcmp(bd_addr, bta_av_cb.p_scb[xx]->peer_addr)) { p_scb = bta_av_cb.p_scb[xx]; break; } } } return p_scb; }
/******************************************************************************* ** ** Function bta_ag_idx_by_bdaddr ** ** Description Find SCB associated with peer BD address. ** ** ** Returns Index of SCB or zero if none found. ** *******************************************************************************/ UINT16 bta_ag_idx_by_bdaddr(BD_ADDR peer_addr) { tBTA_AG_SCB *p_scb = &bta_ag_cb.scb[0]; UINT16 i; if (peer_addr != NULL) { for (i = 0; i < BTA_AG_NUM_SCB; i++, p_scb++) { if (p_scb->in_use && !bdcmp(peer_addr, p_scb->peer_addr)) { return (i + 1); } } } /* no scb found */ APPL_TRACE_WARNING("No ag scb for peer addr"); return 0; }
/*************************************************************************** * Function handle_rc_connect * * - Argument: tBTA_AV_RC_OPEN RC open data structure * * - Description: RC connection event handler * ***************************************************************************/ static void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open) { BTC_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_open->rc_handle); bt_bdaddr_t rc_addr; if (p_rc_open->status == BTA_AV_SUCCESS) { //check if already some RC is connected if (btc_rc_vb.rc_connected) { BTC_TRACE_ERROR("Got RC OPEN in connected state, Connected RC: %d \ and Current RC: %d", btc_rc_vb.rc_handle, p_rc_open->rc_handle ); if ((btc_rc_vb.rc_handle != p_rc_open->rc_handle) && (bdcmp(btc_rc_vb.rc_addr, p_rc_open->peer_addr))) { BTC_TRACE_DEBUG("Got RC connected for some other handle"); BTA_AvCloseRc(p_rc_open->rc_handle); return; } } memcpy(btc_rc_vb.rc_addr, p_rc_open->peer_addr, sizeof(BD_ADDR)); btc_rc_vb.rc_features = p_rc_open->peer_features; btc_rc_vb.rc_vol_label = MAX_LABEL; btc_rc_vb.rc_volume = MAX_VOLUME; btc_rc_vb.rc_connected = TRUE; btc_rc_vb.rc_handle = p_rc_open->rc_handle; bdcpy(rc_addr.address, btc_rc_vb.rc_addr); esp_avrc_ct_cb_param_t param; memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t)); param.conn_stat.connected = true; memcpy(param.conn_stat.remote_bda, &rc_addr, sizeof(esp_bd_addr_t)); btc_avrc_ct_cb_to_app(ESP_AVRC_CT_CONNECTION_STATE_EVT, ¶m); /* on locally initiated connection we will get remote features as part of connect */ if (p_rc_open->sdp_disc_done == TRUE) { handle_rc_features(); } } else {
/******************************************************************************* ** ** 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; } }
static void bta_dm_pm_ssr(BD_ADDR peer_addr) { tBTA_DM_SSR_SPEC *p_spec, *p_spec_cur; UINT8 i,j; int ssr = BTA_DM_PM_SSR0; /* go through the connected services */ for(i=0; i<bta_dm_conn_srvcs.count ; i++) { if(!bdcmp(bta_dm_conn_srvcs.conn_srvc[i].peer_bdaddr, peer_addr)) { /* p_bta_dm_pm_cfg[0].app_id is the number of entries */ for(j=1; j<=p_bta_dm_pm_cfg[0].app_id; j++) { /* find the associated p_bta_dm_pm_cfg */ if((p_bta_dm_pm_cfg[j].id == bta_dm_conn_srvcs.conn_srvc[i].id) && ((p_bta_dm_pm_cfg[j].app_id == BTA_ALL_APP_ID ) || (p_bta_dm_pm_cfg[j].app_id == bta_dm_conn_srvcs.conn_srvc[i].app_id))) { APPL_TRACE_WARNING("bta_dm_pm_ssr conn_srvc id:%d, app_id:%d", bta_dm_conn_srvcs.conn_srvc[i].id, bta_dm_conn_srvcs.conn_srvc[i].app_id); break; } } /* find the ssr index with the smallest max latency. */ p_spec_cur = &p_bta_dm_ssr_spec[p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr]; p_spec = &p_bta_dm_ssr_spec[ssr]; #if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE) /* HH has the per connection SSR preference, already read the SSR params from BTA HH */ if (p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr == BTA_DM_PM_SSR_HH) { if (bta_hh_read_ssr_param(peer_addr, &p_spec_cur->max_lat, &p_spec_cur->min_rmt_to) == BTA_HH_ERR) continue; APPL_TRACE_WARNING("bta_dm_pm_ssr: Orignal Max Latency = %d, Remote Timeout = %d", p_spec_cur->max_lat, p_spec_cur->min_rmt_to); if (p_spec_cur->max_lat == BTA_HH_SSR_MAX_LATENCY_ZERO) { APPL_TRACE_WARNING("bta_dm_pm_ssr: Max latency is 0, not sending" "SSR command as device is blacklisted"); return; } else if (p_spec_cur->max_lat == BTA_HH_SSR_DISABLE_SSR) { APPL_TRACE_WARNING("bta_dm_pm_ssr: Need to disable SSR" "as device is blacklisted"); BTM_SetSsrParams (peer_addr, 0, 0, 0); return; } else if (p_spec_cur->max_lat > BTA_HH_SSR_MAX_LATENCY_OPTIMAL) { p_spec_cur->max_lat = BTA_HH_SSR_MAX_LATENCY_OPTIMAL; } APPL_TRACE_WARNING("bta_dm_pm_ssr: New Max Latency = %d", p_spec_cur->max_lat); } #endif if (p_spec_cur->max_lat < p_spec->max_lat || (ssr == BTA_DM_PM_SSR0 && p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr != BTA_DM_PM_SSR0)) { ssr = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr; } } } p_spec = &p_bta_dm_ssr_spec[ssr]; APPL_TRACE_WARNING("bta_dm_pm_ssr:%d, lat:%d", ssr, p_spec->max_lat); if(p_spec->max_lat) { /* set the SSR parameters. */ BTM_SetSsrParams (peer_addr, p_spec->max_lat, p_spec->min_rmt_to, p_spec->min_loc_to); } }
/******************************************************************************* ** ** Function bta_dm_pm_set_mode ** ** Description Set the power mode for the device ** ** ** Returns void ** *******************************************************************************/ static void bta_dm_pm_set_mode(BD_ADDR peer_addr, BOOLEAN timed_out ) { tBTA_DM_PM_ACTTION pm_action = BTA_DM_PM_NO_ACTION; UINT16 timeout = 0; UINT8 i,j; tBTA_DM_PM_ACTTION failed_pm = 0; tBTA_DM_PEER_DEVICE *p_peer_device = NULL; tBTA_DM_PM_ACTTION allowed_modes = 0; tBTA_DM_PM_ACTTION pref_modes = 0; tBTA_DM_PM_CFG *p_pm_cfg; tBTA_DM_PM_SPEC *p_pm_spec; tBTA_DM_PM_ACTN *p_act0, *p_act1; tBTA_DM_SRVCS *p_srvcs; if(!bta_dm_cb.device_list.count) return; /* see if any attempt to put device in low power mode failed */ p_peer_device = bta_dm_find_peer_device(peer_addr); /* if no peer device found return */ if (p_peer_device == NULL) return; failed_pm = p_peer_device->pm_mode_failed; for(i=0; i<bta_dm_conn_srvcs.count ; i++) { p_srvcs = &bta_dm_conn_srvcs.conn_srvc[i]; if(!bdcmp(p_srvcs->peer_bdaddr, peer_addr)) { /* p_bta_dm_pm_cfg[0].app_id is the number of entries */ for(j=1; j<=p_bta_dm_pm_cfg[0].app_id; j++) { if((p_bta_dm_pm_cfg[j].id == p_srvcs->id) && ((p_bta_dm_pm_cfg[j].app_id == BTA_ALL_APP_ID ) || (p_bta_dm_pm_cfg[j].app_id == p_srvcs->app_id))) break; } p_pm_cfg = &p_bta_dm_pm_cfg[j]; p_pm_spec = &p_bta_dm_pm_spec[p_pm_cfg->spec_idx]; p_act0 = &p_pm_spec->actn_tbl[p_srvcs->state][0]; p_act1 = &p_pm_spec->actn_tbl[p_srvcs->state][1]; APPL_TRACE_DEBUG("bta_dm_pm_set_mode: srvcsid: %d, state: %d, j: %d", p_srvcs->id, p_srvcs->state, j); allowed_modes |= p_pm_spec->allow_mask; /* PM actions are in the order of strictness */ /* first check if the first preference is ok */ if(!(failed_pm & p_act0->power_mode)) { pref_modes |= p_act0->power_mode; if(p_act0->power_mode > pm_action) { pm_action = p_act0->power_mode; timeout = p_act0->timeout; } } /* if first preference has already failed, try second preference */ else if(!(failed_pm & p_act1->power_mode)) { pref_modes |= p_act1->power_mode; if(p_act1->power_mode > pm_action) { pm_action = p_act1->power_mode; timeout = p_act1->timeout; } } } } if(pm_action & (BTA_DM_PM_PARK | BTA_DM_PM_SNIFF)) { /* some service don't like the mode */ if(!(allowed_modes & pm_action)) { /* select the other mode if its allowed and preferred, otherwise 0 which is BTA_DM_PM_NO_ACTION */ pm_action = (allowed_modes & (BTA_DM_PM_PARK | BTA_DM_PM_SNIFF) & pref_modes); /* no timeout needed if no action is required */ if(pm_action == BTA_DM_PM_NO_ACTION) { timeout = 0; } } } if(!timed_out && timeout) { for(i=0; i<BTA_DM_NUM_PM_TIMER; i++) { if(!bta_dm_cb.pm_timer[i].in_use) { bta_dm_cb.pm_timer[i].in_use = TRUE; bdcpy(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr); bta_dm_cb.pm_timer[i].timer.p_cback = bta_dm_pm_timer_cback; bta_sys_start_timer(&bta_dm_cb.pm_timer[i].timer, 0, timeout); APPL_TRACE_DEBUG("start dm_pm_timer:%d, %d", i, timeout); return; } } /* no more timers */ if(i==BTA_DM_NUM_PM_TIMER) { APPL_TRACE_WARNING("bta_dm_act dm_pm_timer no more"); return; } } if(pm_action == BTA_DM_PM_NO_ACTION) { } else if(pm_action == BTA_DM_PM_PARK) { p_peer_device->pm_mode_attempted = BTA_DM_PM_PARK; bta_dm_pm_park(peer_addr); } else if(pm_action & BTA_DM_PM_SNIFF) { /* dont initiate SNIFF, if link_policy has it disabled */ if (p_peer_device->link_policy & HCI_ENABLE_SNIFF_MODE) { p_peer_device->pm_mode_attempted = BTA_DM_PM_SNIFF; bta_dm_pm_sniff(p_peer_device, (UINT8)(pm_action & 0x0F) ); } else { APPL_TRACE_DEBUG("bta_dm_pm_set_mode: Link policy disallows SNIFF, ignore request"); } } else if(pm_action == BTA_DM_PM_ACTIVE) { bta_dm_pm_active(peer_addr); } }
/******************************************************************************* ** ** Function bta_dm_pm_cback ** ** Description Conn change callback from sys for low power management ** ** ** Returns void ** *******************************************************************************/ static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr) { UINT8 i,j; UINT16 policy_setting; tBTM_STATUS btm_status; tBTM_VERSION_INFO vers; UINT8 *p = NULL; #if (BTM_SSR_INCLUDED == TRUE) int index = BTA_DM_PM_SSR0; #endif tBTA_DM_PEER_DEVICE *p_dev; tACL_CONN *p_dev_rec; APPL_TRACE_DEBUG("bta_dm_pm_cback: st(%d), id(%d), app(%d)", status, id, app_id); btm_status = BTM_ReadLocalVersion (&vers); p_dev = bta_dm_find_peer_device(peer_addr); p_dev_rec = btm_bda_to_acl(peer_addr, BT_TRANSPORT_BR_EDR); /* Disable/Enable sniff policy on the SCO link if sco Up/Down. Will be removed in 2.2*/ if ((p_dev) && ((status == BTA_SYS_SCO_OPEN) || (status == BTA_SYS_SCO_CLOSE)) ) { if ((btm_status == BTM_SUCCESS) && (((vers.manufacturer == LMP_COMPID_BROADCOM) && (vers.hci_version < HCI_PROTO_VERSION_2_0)) || (p_dev_rec && (p_dev_rec->lmp_version < 2)))) { if (p_dev_rec) APPL_TRACE_DEBUG("bta_dm_pm_cback:disable sniff for rmt lmp ver:%d",p_dev_rec->lmp_version); bta_dm_pm_set_sniff_policy(p_dev, (status == BTA_SYS_SCO_OPEN)); } } /* find if there is an power mode entry for the service */ for(i=1; i<=p_bta_dm_pm_cfg[0].app_id; i++) { if((p_bta_dm_pm_cfg[i].id == id) && ((p_bta_dm_pm_cfg[i].app_id == BTA_ALL_APP_ID ) || (p_bta_dm_pm_cfg[i].app_id == app_id ))) break; } /* if no entries are there for the app_id and subystem in p_bta_dm_pm_spec*/ if(i> p_bta_dm_pm_cfg[0].app_id) return; /*p_dev = bta_dm_find_peer_device(peer_addr);*/ #if (BTM_SSR_INCLUDED == TRUE) /* set SSR parameters on SYS CONN OPEN */ if((BTA_SYS_CONN_OPEN == status) && p_dev && (p_dev->info & BTA_DM_DI_USE_SSR)) { index = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].ssr; } #endif /* if no action for the event */ if(p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].actn_tbl[status][0].power_mode == BTA_DM_PM_NO_ACTION) { #if (BTM_SSR_INCLUDED == TRUE) if(BTA_DM_PM_SSR0 == index) /* and do not need to set SSR, return. */ #endif return; } for(j=0; j<bta_dm_conn_srvcs.count ; j++) { /* check if an entry already present */ if((bta_dm_conn_srvcs.conn_srvc[j].id == id) && (bta_dm_conn_srvcs.conn_srvc[j].app_id == app_id ) && !bdcmp(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, peer_addr)) break; } /* if subsystem has no more preference on the power mode remove the cb */ if(p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].actn_tbl[status][0].power_mode == BTA_DM_PM_NO_PREF) { if(j != bta_dm_conn_srvcs.count) { bta_dm_conn_srvcs.count--; APPL_TRACE_DEBUG("Removed power mode entry for service id = %d, count = %d", p_bta_dm_pm_cfg[i].id, bta_dm_conn_srvcs.count); for(; j<bta_dm_conn_srvcs.count ; j++) { memcpy(&bta_dm_conn_srvcs.conn_srvc[j], &bta_dm_conn_srvcs.conn_srvc[j+1], sizeof(bta_dm_conn_srvcs.conn_srvc[j])); } } else { APPL_TRACE_WARNING("bta_dm_act no entry for connected service cbs"); return; } } else if(j == bta_dm_conn_srvcs.count ) { /* check if we have more connected service that cbs */ if(bta_dm_conn_srvcs.count == BTA_DM_NUM_CONN_SRVS) { APPL_TRACE_WARNING("bta_dm_act no more connected service cbs"); return; } /* fill in a new cb */ bta_dm_conn_srvcs.conn_srvc[j].id = id; bta_dm_conn_srvcs.conn_srvc[j].app_id = app_id; bdcpy(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, peer_addr); APPL_TRACE_WARNING("new conn_srvc id:%d, app_id:%d", id, app_id); bta_dm_conn_srvcs.count++; bta_dm_conn_srvcs.conn_srvc[j].state = status; APPL_TRACE_WARNING("new conn_srvc id:%d, app_id:%d count:%d", id, app_id, bta_dm_conn_srvcs.count); } else { /* no service is added or removed. only updating status. */ bta_dm_conn_srvcs.conn_srvc[j].state = status; } /* stop timer */ bta_dm_pm_stop_timer(peer_addr); if(p_dev) { p_dev->pm_mode_attempted = 0; p_dev->pm_mode_failed = 0; } #if (BTM_SSR_INCLUDED == TRUE) if(p_bta_dm_ssr_spec[index].max_lat #if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE) || index == BTA_DM_PM_SSR_HH #endif ) { /* If HID connection open is received and SCO is already active. This will handle the case where HID connects when SCO already active */ if ((status == BTA_SYS_CONN_OPEN) && (id == BTA_ID_HH) && bta_dm_pm_is_sco_active()) { APPL_TRACE_DEBUG("bta_dm_pm_cback: SCO is Active, disabling SSR on HID link") APPL_TRACE_WARNING("HID Dev address: %02x:%02x:%02x:%02x:%02x:%02x", peer_addr[0], peer_addr[1], peer_addr[2], peer_addr[3], peer_addr[4], peer_addr[5]); BTM_SetSsrParams(peer_addr, 0, 0, 0); } else { bta_dm_pm_ssr(peer_addr); } } else { if( ((NULL != (p = BTM_ReadLocalFeatures ())) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) && ((NULL != (p = BTM_ReadRemoteFeatures (peer_addr))) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) && (index == BTA_DM_PM_SSR0) ) { if (status == BTA_SYS_SCO_OPEN) { APPL_TRACE_DEBUG("bta_dm_pm_cback: SCO is open, reset SSR to zero"); BTM_SetSsrParams (peer_addr, 0,0,0 ); } else if (status == BTA_SYS_SCO_CLOSE) { APPL_TRACE_DEBUG("bta_dm_pm_cback: SCO is close, back to old SSR"); bta_dm_pm_ssr(peer_addr); } } } /* If SCO up/down event is received, then enable/disable SSR on active HID link */ if (btm_status == BTM_SUCCESS && (status == BTA_SYS_SCO_OPEN || status == BTA_SYS_SCO_CLOSE)) { BOOLEAN bScoActive = (status == BTA_SYS_SCO_OPEN); APPL_TRACE_DEBUG("bta_dm_pm_cback: bta_dm_pm_hid_check with bScoActive = %d", bScoActive); bta_dm_pm_hid_check(bScoActive); } #endif bta_dm_pm_set_mode(peer_addr, FALSE); }
/******************************************************************************* ** ** Function bta_ag_rfc_acp_open ** ** Description Handle RFCOMM channel open when accepting connection. ** ** ** Returns void ** *******************************************************************************/ void bta_ag_rfc_acp_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) { UINT16 lcid; int i; tBTA_AG_SCB *ag_scb, *other_scb; BD_ADDR dev_addr; int status; /* set role */ p_scb->role = BTA_AG_ACP; APPL_TRACE_IMP ("bta_ag_rfc_acp_open: serv_handle0 = %d serv_handle1 = %d", p_scb->serv_handle[0], p_scb->serv_handle[1]); /* get bd addr of peer */ if (PORT_SUCCESS != (status=PORT_CheckConnection(p_data->rfc.port_handle, dev_addr, &lcid))) { APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open error PORT_CheckConnection returned status %d", status); } /* Collision Handling */ for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++) { if ((ag_scb->in_use) && (ag_scb->colli_tmr_on)) { /* stop collision timer */ ag_scb->colli_tmr_on = FALSE; bta_sys_stop_timer (&ag_scb->colli_timer); if (bdcmp (dev_addr, ag_scb->peer_addr) == 0) { /* If incoming and outgoing device are same, nothing more to do. */ /* Outgoing conn will be aborted because we have successful incoming conn. */ } else { /* Resume outgoing connection. */ other_scb = bta_ag_get_other_idle_scb (p_scb); if (other_scb) { bdcpy(other_scb->peer_addr, ag_scb->peer_addr); other_scb->open_services = ag_scb->open_services; other_scb->cli_sec_mask = ag_scb->cli_sec_mask; bta_ag_resume_open (other_scb); } } break; } } bdcpy (p_scb->peer_addr, dev_addr); /* determine connected service from port handle */ for (i = 0; i < BTA_AG_NUM_IDX; i++) { APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open: i = %d serv_handle = %d port_handle = %d", i, p_scb->serv_handle[i], p_data->rfc.port_handle); if (p_scb->serv_handle[i] == p_data->rfc.port_handle) { p_scb->conn_service = i; p_scb->conn_handle = p_data->rfc.port_handle; break; } } APPL_TRACE_IMP ("bta_ag_rfc_acp_open: conn_service = %d conn_handle = %d", p_scb->conn_service, p_scb->conn_handle); /* close any unopened server */ bta_ag_close_servers(p_scb, (p_scb->reg_services & ~bta_ag_svc_mask[p_scb->conn_service])); /* do service discovery to get features */ bta_ag_do_disc(p_scb, bta_ag_svc_mask[p_scb->conn_service]); /* continue with common open processing */ bta_ag_rfc_open(p_scb, p_data); }
/******************************************************************************* ** ** Function bta_gattc_mark_bg_conn ** ** Description mark background connection status when a bg connection is initiated ** or terminated. ** ** Returns TRUE if success; FALSE otherwise. ** *******************************************************************************/ BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR_PTR remote_bda_ptr, BOOLEAN add, BOOLEAN is_listen) { tBTA_GATTC_BG_TCK *p_bg_tck = &bta_gattc_cb.bg_track[0]; UINT8 i = 0; tBTA_GATTC_CIF_MASK *p_cif_mask; for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++) { if (p_bg_tck->in_use && ((remote_bda_ptr != NULL && bdcmp(p_bg_tck->remote_bda, remote_bda_ptr) == 0) || (remote_bda_ptr == NULL && bdcmp(p_bg_tck->remote_bda, dummy_bda) == 0))) { p_cif_mask = is_listen ? &p_bg_tck->cif_adv_mask : &p_bg_tck->cif_mask; if (add) /* mask on the cif bit */ *p_cif_mask |= (1 <<(client_if - 1)); else { if (client_if != 0) *p_cif_mask &= (~(1 <<(client_if - 1))); else *p_cif_mask = 0; } /* no BG connection for this device, make it available */ if (p_bg_tck->cif_mask == 0 && p_bg_tck->cif_adv_mask == 0) { memset(p_bg_tck, 0, sizeof(tBTA_GATTC_BG_TCK)); } return TRUE; } } if (!add) { if (remote_bda_ptr) { bdstr_t bdstr = {0}; APPL_TRACE_ERROR("%s unable to find the bg connection mask for: %s", __func__, bdaddr_to_string((bt_bdaddr_t *)remote_bda_ptr, bdstr, sizeof(bdstr))); } return FALSE; } else /* adding a new device mask */ { for (i = 0, p_bg_tck = &bta_gattc_cb.bg_track[0]; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++) { if (!p_bg_tck->in_use) { p_bg_tck->in_use = TRUE; if (remote_bda_ptr) bdcpy(p_bg_tck->remote_bda, remote_bda_ptr); else bdcpy(p_bg_tck->remote_bda, dummy_bda); p_cif_mask = is_listen ? &p_bg_tck->cif_adv_mask : &p_bg_tck->cif_mask; *p_cif_mask = (1 <<(client_if - 1)); return TRUE; } } APPL_TRACE_ERROR("no available space to mark the bg connection status"); return FALSE; } }