/******************************************************************************* ** ** Function bta_dm_pm_set_sniff_policy ** ** Description Disables/Enables sniff in link policy for the give device ** ** Returns None ** *******************************************************************************/ static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE *p_dev, BOOLEAN bDisable) { UINT16 policy_setting; if (!p_dev) return; if (bDisable) { policy_setting = bta_dm_cb.cur_policy & (HCI_ENABLE_MASTER_SLAVE_SWITCH | HCI_ENABLE_HOLD_MODE | HCI_ENABLE_PARK_MODE); } else { /* allow sniff after sco is closed */ policy_setting= bta_dm_cb.cur_policy; } /* if disabling SNIFF, make sure link is Active */ if (bDisable) bta_dm_pm_active(p_dev->peer_bdaddr); /* update device record and set link policy */ p_dev->link_policy = policy_setting; BTM_SetLinkPolicy(p_dev->peer_bdaddr, &policy_setting); }
/******************************************************************************* ** ** Function bta_hf_client_start_close ** ** Description Start the process of closing SCO and RFCOMM connection. ** ** ** Returns void ** *******************************************************************************/ void bta_hf_client_start_close(tBTA_HF_CLIENT_DATA *p_data) { /* Take the link out of sniff and set L2C idle time to 0 */ bta_dm_pm_active(bta_hf_client_cb.scb.peer_addr); L2CA_SetIdleTimeoutByBdAddr(bta_hf_client_cb.scb.peer_addr, 0, BT_TRANSPORT_BR_EDR); /* if SCO is open close SCO and wait on RFCOMM close */ if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_OPEN_ST) { bta_hf_client_cb.scb.sco_close_rfc = TRUE; } else { bta_hf_client_rfc_do_close(p_data); } /* always do SCO shutdown to handle all SCO corner cases */ bta_hf_client_sco_shutdown(NULL); }
/******************************************************************************* ** ** Function bta_ag_start_close ** ** Description Start the process of closing SCO and RFCOMM connection. ** ** ** Returns void ** *******************************************************************************/ void bta_ag_start_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) { /* Take the link out of sniff and set L2C idle time to 0 */ bta_dm_pm_active(p_scb->peer_addr); L2CA_SetIdleTimeoutByBdAddr(p_scb->peer_addr, 0); /* if SCO is open close SCO and wait on RFCOMM close */ if (bta_ag_sco_is_open(p_scb)) { p_scb->post_sco = BTA_AG_POST_SCO_CLOSE_RFC; } else { p_scb->post_sco = BTA_AG_POST_SCO_NONE; bta_ag_rfc_do_close(p_scb, p_data); } /* always do SCO shutdown to handle all SCO corner cases */ bta_ag_sco_shutdown(p_scb, p_data); }
/******************************************************************************* ** ** 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); } }