1 /****************************************************************************** 2 * 3 * Copyright (C) 2003-2012 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 /****************************************************************************** 20 * 21 * This file contains the action functions for device manager state 22 * machine. 23 * 24 ******************************************************************************/ 25 26 #include <assert.h> 27 #include <string.h> 28 29 #include "gki.h" 30 #include "bta_sys.h" 31 #include "bta_api.h" 32 #include "bta_dm_int.h" 33 #include "btm_api.h" 34 35 36 static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr); 37 static void bta_dm_pm_set_mode(BD_ADDR peer_addr, tBTA_DM_PM_ACTION pm_mode, 38 tBTA_DM_PM_REQ pm_req); 39 static void bta_dm_pm_timer_cback(void *p_tle); 40 static void bta_dm_pm_btm_cback(BD_ADDR bd_addr, tBTM_PM_STATUS status, UINT16 value, UINT8 hci_status); 41 static BOOLEAN bta_dm_pm_park(BD_ADDR peer_addr); 42 static BOOLEAN bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE *p_peer_dev, UINT8 index); 43 static BOOLEAN bta_dm_pm_is_sco_active (); 44 static void bta_dm_pm_hid_check(BOOLEAN bScoActive); 45 static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE *p_dev, BOOLEAN bDisable); 46 static void bta_dm_pm_stop_timer_by_index(tBTA_PM_TIMER *p_timer, 47 UINT8 timer_idx); 48 49 #if (BTM_SSR_INCLUDED == TRUE) 50 #if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE) 51 #include "../hh/bta_hh_int.h" 52 /* BTA_DM_PM_SSR1 will be dedicated for HH SSR setting entry, no other profile can use it */ 53 #define BTA_DM_PM_SSR_HH BTA_DM_PM_SSR1 54 #endif 55 static void bta_dm_pm_ssr(BD_ADDR peer_addr); 56 #endif 57 58 tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs; 59 60 61 /******************************************************************************* 62 ** 63 ** Function bta_dm_init_pm 64 ** 65 ** Description Initializes the BT low power manager 66 ** 67 ** 68 ** Returns void 69 ** 70 *******************************************************************************/ 71 void bta_dm_init_pm(void) 72 { 73 memset(&bta_dm_conn_srvcs, 0x00, sizeof(bta_dm_conn_srvcs)); 74 75 /* if there are no power manger entries, so not register */ 76 if(p_bta_dm_pm_cfg[0].app_id != 0) 77 { 78 bta_sys_pm_register((tBTA_SYS_CONN_CBACK*)bta_dm_pm_cback); 79 80 BTM_PmRegister((BTM_PM_REG_SET | BTM_PM_REG_NOTIF), &bta_dm_cb.pm_id, 81 bta_dm_pm_btm_cback); 82 } 83 84 /* Need to initialize all PM timer service IDs */ 85 for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++) 86 { 87 for (int j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++) 88 bta_dm_cb.pm_timer[i].srvc_id[j] = BTA_ID_MAX; 89 } 90 } 91 92 93 /******************************************************************************* 94 ** 95 ** Function bta_dm_disable_pm 96 ** 97 ** Description Disable PM 98 ** 99 ** 100 ** Returns void 101 ** 102 *******************************************************************************/ 103 void bta_dm_disable_pm(void) 104 { 105 BTM_PmRegister( BTM_PM_DEREG, &bta_dm_cb.pm_id, NULL); 106 107 /* 108 * Deregister the PM callback from the system handling to prevent 109 * re-enabling the PM timers after this call if the callback is invoked. 110 */ 111 bta_sys_pm_register((tBTA_SYS_CONN_CBACK*)NULL); 112 113 /* Need to stop all active timers. */ 114 for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++) 115 { 116 for (int j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++) 117 { 118 bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], j); 119 bta_dm_cb.pm_timer[i].pm_action[j] = BTA_DM_PM_NO_ACTION; 120 } 121 } 122 } 123 124 /******************************************************************************* 125 ** 126 ** Function bta_dm_get_av_count 127 ** 128 ** Description Get the number of connected AV 129 ** 130 ** 131 ** Returns number of av connections 132 ** 133 *******************************************************************************/ 134 UINT8 bta_dm_get_av_count(void) 135 { 136 UINT8 count = 0; 137 for (int i = 0; i < bta_dm_conn_srvcs.count; i++) 138 { 139 if (bta_dm_conn_srvcs.conn_srvc[i].id == BTA_ID_AV) 140 ++count; 141 } 142 return count; 143 } 144 145 /******************************************************************************* 146 ** 147 ** Function bta_dm_pm_stop_timer 148 ** 149 ** Description stop a PM timer 150 ** 151 ** 152 ** Returns void 153 ** 154 *******************************************************************************/ 155 static void bta_dm_pm_stop_timer(BD_ADDR peer_addr) 156 { 157 APPL_TRACE_DEBUG("%s: ", __func__); 158 159 for(int i=0; i<BTA_DM_NUM_PM_TIMER; i++) 160 { 161 if (bta_dm_cb.pm_timer[i].in_use && !bdcmp(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr)) 162 { 163 for (int j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++) 164 { 165 bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], j); 166 /* 167 * TODO: For now, stopping the timer does not reset 168 * pm_action[j]. 169 * The reason is because some of the internal logic that 170 * (re)assigns the pm_action[] values is taking into account 171 * the older value; e.g., see the pm_action[] assignment in 172 * function bta_dm_pm_start_timer(). 173 * Such subtlety in the execution logic is error prone, and 174 * should be eliminiated in the future. 175 */ 176 } 177 break; 178 } 179 } 180 } 181 182 /******************************************************************************* 183 ** 184 ** Function bta_pm_action_to_timer_idx 185 ** 186 ** Description convert power mode into timer index for each connected device 187 ** 188 ** 189 ** Returns index of the power mode delay timer 190 ** 191 *******************************************************************************/ 192 static UINT8 bta_pm_action_to_timer_idx(UINT8 pm_action) 193 { 194 if (pm_action == BTA_DM_PM_SUSPEND) 195 return BTA_DM_PM_SUSPEND_TIMER_IDX; 196 else if (pm_action == BTA_DM_PM_PARK) 197 return BTA_DM_PM_PARK_TIMER_IDX; 198 else if ((pm_action & BTA_DM_PM_SNIFF) == BTA_DM_PM_SNIFF) 199 return BTA_DM_PM_SNIFF_TIMER_IDX; 200 201 /* Active, no preference, no action and retry */ 202 return BTA_DM_PM_MODE_TIMER_MAX; 203 } 204 205 /******************************************************************************* 206 ** 207 ** Function bta_dm_pm_stop_timer_by_mode 208 ** 209 ** Description stop a PM timer 210 ** 211 ** 212 ** Returns void 213 ** 214 *******************************************************************************/ 215 static void bta_dm_pm_stop_timer_by_mode(BD_ADDR peer_addr, UINT8 power_mode) 216 { 217 const UINT8 timer_idx = bta_pm_action_to_timer_idx(power_mode); 218 if (timer_idx == BTA_DM_PM_MODE_TIMER_MAX) 219 return; 220 221 for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++) 222 { 223 if (bta_dm_cb.pm_timer[i].in_use && !bdcmp(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr)) 224 { 225 if (bta_dm_cb.pm_timer[i].srvc_id[timer_idx] != BTA_ID_MAX) 226 { 227 bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], timer_idx); 228 /* 229 * TODO: Intentionally setting pm_action[timer_idx]. 230 * This assignment should be eliminated in the future - see the 231 * pm_action[] related comment inside function 232 * bta_dm_pm_stop_timer(). 233 */ 234 bta_dm_cb.pm_timer[i].pm_action[timer_idx] = power_mode; 235 } 236 break; 237 } 238 } 239 } 240 241 /******************************************************************************* 242 ** 243 ** Function bta_dm_pm_stop_timer_by_srvc_id 244 ** 245 ** Description stop all timer started by the service ID. 246 ** 247 ** 248 ** Returns index of the power mode delay timer 249 ** 250 *******************************************************************************/ 251 static void bta_dm_pm_stop_timer_by_srvc_id(BD_ADDR peer_addr, UINT8 srvc_id) 252 { 253 for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++) 254 { 255 if (bta_dm_cb.pm_timer[i].in_use && !bdcmp(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr)) 256 { 257 for (int j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++) 258 { 259 if (bta_dm_cb.pm_timer[i].srvc_id[j] == srvc_id) 260 { 261 bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], j); 262 bta_dm_cb.pm_timer[i].pm_action[j] = BTA_DM_PM_NO_ACTION; 263 break; 264 } 265 } 266 } 267 } 268 } 269 270 /******************************************************************************* 271 ** 272 ** Function bta_dm_pm_start_timer 273 ** 274 ** Description start a PM timer 275 ** 276 ** 277 ** Returns void 278 ** 279 *******************************************************************************/ 280 static void bta_dm_pm_start_timer(tBTA_PM_TIMER *p_timer, UINT8 timer_idx, 281 INT32 timeout, UINT8 srvc_id, UINT8 pm_action) 282 { 283 p_timer->in_use = TRUE; 284 p_timer->timer[timer_idx].p_cback = bta_dm_pm_timer_cback; 285 286 if (p_timer->srvc_id[timer_idx] == BTA_ID_MAX) 287 p_timer->active++; 288 289 if (p_timer->pm_action[timer_idx] < pm_action) 290 p_timer->pm_action[timer_idx] = pm_action; 291 292 p_timer->srvc_id[timer_idx] = srvc_id; 293 294 bta_sys_start_timer(&p_timer->timer[timer_idx], 0, timeout); 295 } 296 297 /******************************************************************************* 298 ** 299 ** Function bta_dm_pm_stop_timer_by_index 300 ** 301 ** Description stop a PM timer 302 ** 303 ** 304 ** Returns void 305 ** 306 *******************************************************************************/ 307 static void bta_dm_pm_stop_timer_by_index(tBTA_PM_TIMER *p_timer, 308 UINT8 timer_idx) 309 { 310 if ((p_timer == NULL) || (timer_idx >= BTA_DM_PM_MODE_TIMER_MAX)) 311 return; 312 313 if (p_timer->srvc_id[timer_idx] == BTA_ID_MAX) 314 return; /* The timer was not scheduled */ 315 316 assert(p_timer->in_use && (p_timer->active > 0)); 317 318 bta_sys_stop_timer(&p_timer->timer[timer_idx]); 319 p_timer->srvc_id[timer_idx] = BTA_ID_MAX; 320 /* NOTE: pm_action[timer_idx] intentionally not reset */ 321 322 p_timer->active--; 323 if (p_timer->active == 0) 324 p_timer->in_use = FALSE; 325 } 326 327 UINT32 bta_dm_pm_get_remaining_ticks (TIMER_LIST_ENT *p_target_tle) 328 { 329 return bta_sys_get_remaining_ticks(p_target_tle); 330 } 331 332 /******************************************************************************* 333 ** 334 ** Function bta_dm_pm_cback 335 ** 336 ** Description Conn change callback from sys for low power management 337 ** 338 ** 339 ** Returns void 340 ** 341 *******************************************************************************/ 342 static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr) 343 { 344 345 UINT8 i,j; 346 UINT16 policy_setting; 347 UINT8 *p = NULL; 348 tBTA_DM_PEER_DEVICE *p_dev; 349 350 #if (BTM_SSR_INCLUDED == TRUE) 351 int index = BTA_DM_PM_SSR0; 352 #endif 353 354 APPL_TRACE_DEBUG("bta_dm_pm_cback: st(%d), id(%d), app(%d)", status, id, app_id); 355 356 p_dev = bta_dm_find_peer_device(peer_addr); 357 358 /* find if there is an power mode entry for the service */ 359 for(i=1; i<=p_bta_dm_pm_cfg[0].app_id; i++) 360 { 361 362 if((p_bta_dm_pm_cfg[i].id == id) 363 && ((p_bta_dm_pm_cfg[i].app_id == BTA_ALL_APP_ID ) || (p_bta_dm_pm_cfg[i].app_id == app_id ))) 364 break; 365 366 } 367 368 /* if no entries are there for the app_id and subsystem in p_bta_dm_pm_spec*/ 369 if(i> p_bta_dm_pm_cfg[0].app_id) 370 return; 371 372 bta_dm_pm_stop_timer_by_srvc_id(peer_addr, id); 373 /*p_dev = bta_dm_find_peer_device(peer_addr);*/ 374 375 #if (BTM_SSR_INCLUDED == TRUE) 376 /* set SSR parameters on SYS CONN OPEN */ 377 if((BTA_SYS_CONN_OPEN == status) && p_dev && (p_dev->info & BTA_DM_DI_USE_SSR)) 378 { 379 index = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].ssr; 380 } 381 #endif 382 383 /* if no action for the event */ 384 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) 385 { 386 #if (BTM_SSR_INCLUDED == TRUE) 387 if(BTA_DM_PM_SSR0 == index) /* and do not need to set SSR, return. */ 388 #endif 389 return; 390 } 391 392 for(j=0; j<bta_dm_conn_srvcs.count ; j++) 393 { 394 /* check if an entry already present */ 395 if((bta_dm_conn_srvcs.conn_srvc[j].id == id) 396 && (bta_dm_conn_srvcs.conn_srvc[j].app_id == app_id ) 397 && !bdcmp(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, peer_addr)) 398 { 399 bta_dm_conn_srvcs.conn_srvc[j].new_request = TRUE; 400 break; 401 } 402 403 } 404 405 /* if subsystem has no more preference on the power mode remove 406 the cb */ 407 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) 408 { 409 if(j != bta_dm_conn_srvcs.count) 410 { 411 bta_dm_conn_srvcs.count--; 412 413 for(; j<bta_dm_conn_srvcs.count ; j++) 414 { 415 416 memcpy(&bta_dm_conn_srvcs.conn_srvc[j], &bta_dm_conn_srvcs.conn_srvc[j+1], sizeof(bta_dm_conn_srvcs.conn_srvc[j])); 417 418 } 419 } 420 else 421 { 422 APPL_TRACE_WARNING("bta_dm_act no entry for connected service cbs"); 423 return; 424 } 425 } 426 else if(j == bta_dm_conn_srvcs.count ) 427 { 428 /* check if we have more connected service that cbs */ 429 if(bta_dm_conn_srvcs.count == BTA_DM_NUM_CONN_SRVS) 430 { 431 APPL_TRACE_WARNING("bta_dm_act no more connected service cbs"); 432 return; 433 } 434 435 /* fill in a new cb */ 436 bta_dm_conn_srvcs.conn_srvc[j].id = id; 437 bta_dm_conn_srvcs.conn_srvc[j].app_id = app_id; 438 bta_dm_conn_srvcs.conn_srvc[j].new_request = TRUE; 439 bdcpy(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, peer_addr); 440 441 APPL_TRACE_WARNING("new conn_srvc id:%d, app_id:%d", id, app_id); 442 443 bta_dm_conn_srvcs.count++; 444 bta_dm_conn_srvcs.conn_srvc[j].state = status; 445 } 446 else 447 { 448 /* no service is added or removed. only updating status. */ 449 bta_dm_conn_srvcs.conn_srvc[j].state = status; 450 } 451 452 /* stop timer */ 453 bta_dm_pm_stop_timer(peer_addr); 454 455 if(p_dev) 456 { 457 p_dev->pm_mode_attempted = 0; 458 p_dev->pm_mode_failed = 0; 459 } 460 461 #if (BTM_SSR_INCLUDED == TRUE) 462 if(p_bta_dm_ssr_spec[index].max_lat 463 #if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE) 464 || index == BTA_DM_PM_SSR_HH 465 #endif 466 ) 467 { 468 bta_dm_pm_ssr(peer_addr); 469 } 470 else 471 { 472 if( ((NULL != (p = BTM_ReadLocalFeatures ())) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) && 473 ((NULL != (p = BTM_ReadRemoteFeatures (peer_addr))) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) && 474 (index == BTA_DM_PM_SSR0)) 475 { 476 if (status == BTA_SYS_SCO_OPEN) 477 { 478 APPL_TRACE_DEBUG("%s: SCO inactive, reset SSR to zero", __func__); 479 BTM_SetSsrParams (peer_addr, 0,0,0 ); 480 } 481 else if (status == BTA_SYS_SCO_CLOSE) 482 { 483 APPL_TRACE_DEBUG("%s: SCO active, back to old SSR", __func__); 484 bta_dm_pm_ssr(peer_addr); 485 } 486 } 487 } 488 #endif 489 490 bta_dm_pm_set_mode(peer_addr, BTA_DM_PM_NO_ACTION, BTA_DM_PM_NEW_REQ); 491 492 /* perform the HID link workaround if needed 493 ** 1. If SCO up/down event is received OR 494 ** 2. If HID connection open is received and SCO is already active. 495 ** This will handle the case where HID connects when SCO already active 496 */ 497 if ( BTM_IsDeviceUp() && 498 ( ((status == BTA_SYS_SCO_OPEN) || (status == BTA_SYS_SCO_CLOSE)) || 499 ((status == BTA_SYS_CONN_OPEN) && (id == BTA_ID_HH) && bta_dm_pm_is_sco_active()) ) ) 500 { 501 BOOLEAN bScoActive; 502 if (status == BTA_SYS_CONN_OPEN) 503 bScoActive = TRUE; 504 else 505 bScoActive = (status == BTA_SYS_SCO_OPEN); 506 507 bta_dm_pm_hid_check(bScoActive); 508 } 509 510 } 511 512 513 /******************************************************************************* 514 ** 515 ** Function bta_dm_pm_set_mode 516 ** 517 ** Description Set the power mode for the device 518 ** 519 ** 520 ** Returns void 521 ** 522 *******************************************************************************/ 523 524 static void bta_dm_pm_set_mode(BD_ADDR peer_addr, tBTA_DM_PM_ACTION pm_request, 525 tBTA_DM_PM_REQ pm_req ) 526 { 527 528 tBTA_DM_PM_ACTION pm_action = BTA_DM_PM_NO_ACTION; 529 UINT16 timeout = 0; 530 UINT8 i,j; 531 tBTA_DM_PM_ACTION failed_pm = 0; 532 tBTA_DM_PEER_DEVICE *p_peer_device = NULL; 533 tBTA_DM_PM_ACTION allowed_modes = 0; 534 tBTA_DM_PM_ACTION pref_modes = 0; 535 tBTA_DM_PM_CFG *p_pm_cfg; 536 tBTA_DM_PM_SPEC *p_pm_spec; 537 tBTA_DM_PM_ACTN *p_act0, *p_act1; 538 tBTA_DM_SRVCS *p_srvcs = NULL; 539 BOOLEAN timer_started = FALSE; 540 UINT8 timer_idx, available_timer = BTA_DM_PM_MODE_TIMER_MAX; 541 UINT32 remaining_ticks = 0; 542 543 if(!bta_dm_cb.device_list.count) 544 return; 545 546 /* see if any attempt to put device in low power mode failed */ 547 p_peer_device = bta_dm_find_peer_device(peer_addr); 548 /* if no peer device found return */ 549 if (p_peer_device == NULL) 550 return; 551 552 failed_pm = p_peer_device->pm_mode_failed; 553 554 for(i=0; i<bta_dm_conn_srvcs.count ; i++) 555 { 556 557 p_srvcs = &bta_dm_conn_srvcs.conn_srvc[i]; 558 if(!bdcmp(p_srvcs->peer_bdaddr, peer_addr)) 559 { 560 561 /* p_bta_dm_pm_cfg[0].app_id is the number of entries */ 562 for(j=1; j<=p_bta_dm_pm_cfg[0].app_id; j++) 563 { 564 if((p_bta_dm_pm_cfg[j].id == p_srvcs->id) 565 && ((p_bta_dm_pm_cfg[j].app_id == BTA_ALL_APP_ID ) || 566 (p_bta_dm_pm_cfg[j].app_id == p_srvcs->app_id))) 567 break; 568 } 569 570 p_pm_cfg = &p_bta_dm_pm_cfg[j]; 571 p_pm_spec = &p_bta_dm_pm_spec[p_pm_cfg->spec_idx]; 572 p_act0 = &p_pm_spec->actn_tbl[p_srvcs->state][0]; 573 p_act1 = &p_pm_spec->actn_tbl[p_srvcs->state][1]; 574 575 APPL_TRACE_DEBUG("bta_dm_pm_set_mode: srvcsid: %d, state: %d, j: %d", p_srvcs->id, p_srvcs->state, j); 576 allowed_modes |= p_pm_spec->allow_mask; 577 578 /* PM actions are in the order of strictness */ 579 580 /* first check if the first preference is ok */ 581 if(!(failed_pm & p_act0->power_mode)) 582 { 583 pref_modes |= p_act0->power_mode; 584 585 if(p_act0->power_mode >= pm_action) 586 { 587 pm_action = p_act0->power_mode; 588 589 if (pm_req != BTA_DM_PM_NEW_REQ || p_srvcs->new_request) 590 { 591 p_srvcs->new_request = FALSE; 592 timeout = p_act0->timeout; 593 } 594 } 595 } 596 /* if first preference has already failed, try second preference */ 597 else if(!(failed_pm & p_act1->power_mode)) 598 { 599 pref_modes |= p_act1->power_mode; 600 601 if(p_act1->power_mode > pm_action) 602 { 603 pm_action = p_act1->power_mode; 604 timeout = p_act1->timeout; 605 } 606 } 607 } 608 } 609 610 if(pm_action & (BTA_DM_PM_PARK | BTA_DM_PM_SNIFF)) 611 { 612 /* some service don't like the mode */ 613 if(!(allowed_modes & pm_action)) 614 { 615 616 /* select the other mode if its allowed and preferred, otherwise 0 which is BTA_DM_PM_NO_ACTION */ 617 pm_action = (allowed_modes & (BTA_DM_PM_PARK | BTA_DM_PM_SNIFF) & pref_modes); 618 619 /* no timeout needed if no action is required */ 620 if(pm_action == BTA_DM_PM_NO_ACTION) 621 { 622 timeout = 0; 623 } 624 625 } 626 } 627 /* if need to start a timer */ 628 if((pm_req != BTA_DM_PM_EXECUTE) && timeout) 629 { 630 for(i=0; i<BTA_DM_NUM_PM_TIMER; i++) 631 { 632 if(bta_dm_cb.pm_timer[i].in_use && bdcmp(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr) == 0) 633 { 634 if ((timer_idx = bta_pm_action_to_timer_idx(pm_action)) != BTA_DM_PM_MODE_TIMER_MAX) 635 { 636 remaining_ticks = bta_dm_pm_get_remaining_ticks(&bta_dm_cb.pm_timer[i].timer[timer_idx]); 637 if (remaining_ticks < timeout) 638 { 639 /* Cancel and restart the timer */ 640 /* 641 * TODO: The value of pm_action[timer_idx] is 642 * conditionally updated between the two function 643 * calls below when the timer is restarted. 644 * This logic is error-prone and should be eliminated 645 * in the future. 646 */ 647 bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], 648 timer_idx); 649 bta_dm_pm_start_timer(&bta_dm_cb.pm_timer[i], timer_idx, timeout, p_srvcs->id, pm_action); 650 } 651 timer_started = TRUE; 652 } 653 break; 654 } 655 else if (!bta_dm_cb.pm_timer[i].in_use) 656 { 657 APPL_TRACE_DEBUG("%s dm_pm_timer:%d, %d", __func__, i, timeout); 658 if (available_timer == BTA_DM_PM_MODE_TIMER_MAX) 659 available_timer = i; 660 } 661 } 662 /* new power mode for a new active connection */ 663 if (!timer_started) 664 { 665 if( available_timer != BTA_DM_PM_MODE_TIMER_MAX) 666 { 667 bdcpy(bta_dm_cb.pm_timer[available_timer].peer_bdaddr, peer_addr); 668 if ((timer_idx = bta_pm_action_to_timer_idx(pm_action)) != BTA_DM_PM_MODE_TIMER_MAX) 669 { 670 bta_dm_pm_start_timer(&bta_dm_cb.pm_timer[available_timer], timer_idx, timeout, p_srvcs->id, pm_action); 671 timer_started = TRUE; 672 } 673 } 674 /* no more timers */ 675 else 676 { 677 APPL_TRACE_WARNING("bta_dm_act dm_pm_timer no more"); 678 } 679 } 680 return; 681 } 682 /* if pending power mode timer expires, and currecnt link is in a 683 lower power mode than current profile requirement, igonre it */ 684 if (pm_req == BTA_DM_PM_EXECUTE && pm_request < pm_action) 685 { 686 APPL_TRACE_ERROR("Ignore the power mode request: %d", pm_request) 687 return; 688 } 689 if(pm_action == BTA_DM_PM_PARK) 690 { 691 p_peer_device->pm_mode_attempted = BTA_DM_PM_PARK; 692 bta_dm_pm_park(peer_addr); 693 } 694 else if(pm_action & BTA_DM_PM_SNIFF) 695 { 696 /* dont initiate SNIFF, if link_policy has it disabled */ 697 if (p_peer_device->link_policy & HCI_ENABLE_SNIFF_MODE) 698 { 699 p_peer_device->pm_mode_attempted = BTA_DM_PM_SNIFF; 700 bta_dm_pm_sniff(p_peer_device, (UINT8)(pm_action & 0x0F) ); 701 } 702 else 703 { 704 APPL_TRACE_DEBUG("bta_dm_pm_set_mode: Link policy disallows SNIFF, ignore request"); 705 } 706 } 707 else if(pm_action == BTA_DM_PM_ACTIVE) 708 { 709 bta_dm_pm_active(peer_addr); 710 } 711 } 712 /******************************************************************************* 713 ** 714 ** Function bta_ag_pm_park 715 ** 716 ** Description Switch to park mode. 717 ** 718 ** 719 ** Returns TRUE if park attempted, FALSE otherwise. 720 ** 721 *******************************************************************************/ 722 static BOOLEAN bta_dm_pm_park(BD_ADDR peer_addr) 723 { 724 725 tBTM_PM_MODE mode = BTM_PM_STS_ACTIVE; 726 727 /* if not in park mode, switch to park */ 728 BTM_ReadPowerMode(peer_addr, &mode); 729 730 if(mode != BTM_PM_MD_PARK) 731 { 732 BTM_SetPowerMode (bta_dm_cb.pm_id, peer_addr, &p_bta_dm_pm_md[BTA_DM_PM_PARK_IDX]); 733 } 734 return TRUE; 735 736 } 737 738 /******************************************************************************* 739 ** 740 ** Function bta_ag_pm_sniff 741 ** 742 ** Description Switch to sniff mode. 743 ** 744 ** 745 ** Returns TRUE if sniff attempted, FALSE otherwise. 746 ** 747 *******************************************************************************/ 748 static BOOLEAN bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE *p_peer_dev, UINT8 index) 749 { 750 tBTM_PM_MODE mode = BTM_PM_STS_ACTIVE; 751 tBTM_PM_PWR_MD pwr_md; 752 tBTM_STATUS status; 753 #if (BTM_SSR_INCLUDED == TRUE) 754 UINT8 *p_rem_feat = NULL; 755 #endif 756 757 BTM_ReadPowerMode(p_peer_dev->peer_bdaddr, &mode); 758 p_rem_feat = BTM_ReadRemoteFeatures (p_peer_dev->peer_bdaddr); 759 #if (BTM_SSR_INCLUDED == TRUE) 760 APPL_TRACE_DEBUG("bta_dm_pm_sniff cur:%d, idx:%d, info:x%x", mode, index, p_peer_dev->info); 761 if (mode != BTM_PM_MD_SNIFF || 762 (HCI_SNIFF_SUB_RATE_SUPPORTED(BTM_ReadLocalFeatures ()) && p_rem_feat && 763 HCI_SNIFF_SUB_RATE_SUPPORTED(p_rem_feat) && 764 !(p_peer_dev->info & BTA_DM_DI_USE_SSR))) 765 #else 766 APPL_TRACE_DEBUG("bta_dm_pm_sniff cur:%d, idx:%d", mode, index); 767 if(mode != BTM_PM_MD_SNIFF) 768 #endif 769 { 770 #if (BTM_SSR_INCLUDED == TRUE) 771 /* Dont initiate Sniff if controller has alreay accepted 772 * remote sniff params. This avoid sniff loop issue with 773 * some agrresive headsets who use sniff latencies more than 774 * DUT supported range of Sniff intervals.*/ 775 if ((mode == BTM_PM_MD_SNIFF) && (p_peer_dev->info & BTA_DM_DI_ACP_SNIFF)) 776 { 777 APPL_TRACE_DEBUG("%s: already in remote initiate sniff", __func__); 778 return TRUE; 779 } 780 #endif 781 /* if the current mode is not sniff, issue the sniff command. 782 * If sniff, but SSR is not used in this link, still issue the command */ 783 memcpy(&pwr_md, &p_bta_dm_pm_md[index], sizeof (tBTM_PM_PWR_MD)); 784 if (p_peer_dev->info & BTA_DM_DI_INT_SNIFF) 785 { 786 pwr_md.mode |= BTM_PM_MD_FORCE; 787 } 788 status = BTM_SetPowerMode (bta_dm_cb.pm_id, p_peer_dev->peer_bdaddr, &pwr_md); 789 if (status == BTM_CMD_STORED|| status == BTM_CMD_STARTED) 790 { 791 p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF); 792 p_peer_dev->info |= BTA_DM_DI_SET_SNIFF; 793 } 794 else if (status == BTM_SUCCESS) 795 { 796 APPL_TRACE_DEBUG("bta_dm_pm_sniff BTM_SetPowerMode() returns BTM_SUCCESS"); 797 p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF|BTA_DM_DI_SET_SNIFF); 798 } 799 else /* error */ 800 { 801 APPL_TRACE_ERROR("bta_dm_pm_sniff BTM_SetPowerMode() returns ERROR status=%d", status); 802 p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF|BTA_DM_DI_SET_SNIFF); 803 } 804 } 805 return TRUE; 806 807 } 808 /******************************************************************************* 809 ** 810 ** Function bta_dm_pm_ssr 811 ** 812 ** Description checks and sends SSR parameters 813 ** 814 ** Returns void 815 ** 816 *******************************************************************************/ 817 #if (BTM_SSR_INCLUDED == TRUE) 818 static void bta_dm_pm_ssr(BD_ADDR peer_addr) 819 { 820 tBTA_DM_SSR_SPEC *p_spec, *p_spec_cur; 821 UINT8 i,j; 822 int ssr = BTA_DM_PM_SSR0; 823 824 /* go through the connected services */ 825 for(i=0; i<bta_dm_conn_srvcs.count ; i++) 826 { 827 if(!bdcmp(bta_dm_conn_srvcs.conn_srvc[i].peer_bdaddr, peer_addr)) 828 { 829 /* p_bta_dm_pm_cfg[0].app_id is the number of entries */ 830 for(j=1; j<=p_bta_dm_pm_cfg[0].app_id; j++) 831 { 832 /* find the associated p_bta_dm_pm_cfg */ 833 if((p_bta_dm_pm_cfg[j].id == bta_dm_conn_srvcs.conn_srvc[i].id) 834 && ((p_bta_dm_pm_cfg[j].app_id == BTA_ALL_APP_ID ) 835 || (p_bta_dm_pm_cfg[j].app_id == bta_dm_conn_srvcs.conn_srvc[i].app_id))) 836 { 837 APPL_TRACE_WARNING("bta_dm_pm_ssr conn_srvc id:%d, app_id:%d", 838 bta_dm_conn_srvcs.conn_srvc[i].id, bta_dm_conn_srvcs.conn_srvc[i].app_id); 839 break; 840 } 841 } 842 843 /* find the ssr index with the smallest max latency. */ 844 p_spec_cur = &p_bta_dm_ssr_spec[p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr]; 845 p_spec = &p_bta_dm_ssr_spec[ssr]; 846 847 #if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE) 848 /* HH has the per connection SSR preference, already read the SSR params from BTA HH */ 849 if (p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr == BTA_DM_PM_SSR_HH) 850 { 851 if (bta_hh_read_ssr_param(peer_addr, &p_spec_cur->max_lat, &p_spec_cur->min_rmt_to) == BTA_HH_ERR) 852 continue; 853 } 854 #endif 855 if (p_spec_cur->max_lat < p_spec->max_lat || 856 (ssr == BTA_DM_PM_SSR0 && p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr != BTA_DM_PM_SSR0)) 857 { 858 ssr = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr; 859 } 860 861 } 862 } 863 864 p_spec = &p_bta_dm_ssr_spec[ssr]; 865 APPL_TRACE_WARNING("bta_dm_pm_ssr:%d, lat:%d", ssr, p_spec->max_lat); 866 if(p_spec->max_lat) 867 { 868 /* set the SSR parameters. */ 869 BTM_SetSsrParams (peer_addr, p_spec->max_lat, 870 p_spec->min_rmt_to, p_spec->min_loc_to); 871 } 872 } 873 #endif 874 /******************************************************************************* 875 ** 876 ** Function bta_dm_pm_active 877 ** 878 ** Description Brings connection to active mode 879 ** 880 ** 881 ** Returns void 882 ** 883 *******************************************************************************/ 884 void bta_dm_pm_active(BD_ADDR peer_addr) 885 { 886 tBTM_PM_PWR_MD pm; 887 888 memset( (void*)&pm, 0, sizeof(pm)); 889 890 /* switch to active mode */ 891 pm.mode = BTM_PM_MD_ACTIVE; 892 BTM_SetPowerMode (bta_dm_cb.pm_id, peer_addr, &pm); 893 894 895 } 896 897 898 /******************************************************************************* 899 ** 900 ** Function bta_dm_pm_btm_cback 901 ** 902 ** Description BTM power manager callback. 903 ** 904 ** 905 ** Returns void 906 ** 907 *******************************************************************************/ 908 static void bta_dm_pm_btm_cback(BD_ADDR bd_addr, tBTM_PM_STATUS status, UINT16 value, UINT8 hci_status) 909 { 910 tBTA_DM_PM_BTM_STATUS *p_buf; 911 912 if ((p_buf = (tBTA_DM_PM_BTM_STATUS *) GKI_getbuf(sizeof(tBTA_DM_PM_BTM_STATUS))) != NULL) 913 { 914 p_buf->hdr.event = BTA_DM_PM_BTM_STATUS_EVT; 915 p_buf->status = status; 916 p_buf->value = value; 917 p_buf->hci_status = hci_status; 918 bdcpy(p_buf->bd_addr, bd_addr); 919 bta_sys_sendmsg(p_buf); 920 } 921 } 922 923 /******************************************************************************* 924 ** 925 ** Function bta_dm_pm_timer_cback 926 ** 927 ** Description Power management timer callback. 928 ** 929 ** 930 ** Returns void 931 ** 932 *******************************************************************************/ 933 static void bta_dm_pm_timer_cback(void *p_tle) 934 { 935 UINT8 i, j; 936 937 for (i=0; i<BTA_DM_NUM_PM_TIMER; i++) 938 { 939 APPL_TRACE_DEBUG("dm_pm_timer[%d] in use? %d", i, bta_dm_cb.pm_timer[i].in_use); 940 if (bta_dm_cb.pm_timer[i].in_use) 941 { 942 for (j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++) 943 { 944 if(&bta_dm_cb.pm_timer[i].timer[j] == (TIMER_LIST_ENT*) p_tle) 945 { 946 bta_dm_cb.pm_timer[i].active --; 947 bta_dm_cb.pm_timer[i].srvc_id[j] = BTA_ID_MAX; 948 APPL_TRACE_DEBUG("dm_pm_timer[%d] expires, timer_idx=%d", i, j); 949 break; 950 } 951 } 952 if (bta_dm_cb.pm_timer[i].active == 0) 953 bta_dm_cb.pm_timer[i].in_use = FALSE; 954 if (j < BTA_DM_PM_MODE_TIMER_MAX) 955 break; 956 } 957 } 958 959 /* no more timers */ 960 if (i==BTA_DM_NUM_PM_TIMER) 961 return; 962 963 tBTA_DM_PM_TIMER *p_buf = (tBTA_DM_PM_TIMER *) GKI_getbuf(sizeof(tBTA_DM_PM_TIMER)); 964 if (p_buf != NULL) 965 { 966 p_buf->hdr.event = BTA_DM_PM_TIMER_EVT; 967 p_buf->pm_request = bta_dm_cb.pm_timer[i].pm_action[j]; 968 bdcpy(p_buf->bd_addr, bta_dm_cb.pm_timer[i].peer_bdaddr); 969 bta_sys_sendmsg(p_buf); 970 } 971 } 972 973 /******************************************************************************* 974 ** 975 ** Function bta_dm_pm_btm_status 976 ** 977 ** Description Process pm status event from btm 978 ** 979 ** 980 ** Returns void 981 ** 982 *******************************************************************************/ 983 void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data) 984 { 985 APPL_TRACE_DEBUG("%s status: %d", __func__, p_data->pm_status.status); 986 987 tBTA_DM_PEER_DEVICE *p_dev = bta_dm_find_peer_device(p_data->pm_status.bd_addr); 988 if (NULL == p_dev) 989 return; 990 991 tBTA_DM_DEV_INFO info = p_dev->info; 992 /* check new mode */ 993 switch (p_data->pm_status.status) 994 { 995 case BTM_PM_STS_ACTIVE: 996 /* if our sniff or park attempt failed 997 we should not try it again*/ 998 if (p_data->pm_status.hci_status != 0) 999 { 1000 APPL_TRACE_ERROR("%s hci_status=%d", __func__, p_data->pm_status.hci_status); 1001 p_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF|BTA_DM_DI_SET_SNIFF); 1002 1003 if(p_dev->pm_mode_attempted &(BTA_DM_PM_PARK | BTA_DM_PM_SNIFF)) 1004 { 1005 p_dev->pm_mode_failed 1006 |= ((BTA_DM_PM_PARK | BTA_DM_PM_SNIFF) & p_dev->pm_mode_attempted); 1007 bta_dm_pm_stop_timer_by_mode(p_data->pm_status.bd_addr, p_dev->pm_mode_attempted); 1008 bta_dm_pm_set_mode(p_data->pm_status.bd_addr, BTA_DM_PM_NO_ACTION, BTA_DM_PM_RESTART); 1009 } 1010 } 1011 else 1012 { 1013 #if (BTM_SSR_INCLUDED == TRUE) 1014 if(p_dev->prev_low) 1015 { 1016 /* need to send the SSR paramaters to controller again */ 1017 bta_dm_pm_ssr(p_dev->peer_bdaddr); 1018 } 1019 p_dev->prev_low = BTM_PM_STS_ACTIVE; 1020 #endif 1021 /* link to active mode, need to restart the timer for next low power mode if needed */ 1022 bta_dm_pm_stop_timer(p_data->pm_status.bd_addr); 1023 bta_dm_pm_set_mode(p_data->pm_status.bd_addr, BTA_DM_PM_NO_ACTION, BTA_DM_PM_RESTART); 1024 } 1025 break; 1026 1027 #if (BTM_SSR_INCLUDED == TRUE) 1028 case BTM_PM_STS_PARK: 1029 case BTM_PM_STS_HOLD: 1030 /* save the previous low power mode - for SSR. 1031 * SSR parameters are sent to controller on "conn open". 1032 * the numbers stay good until park/hold/detach */ 1033 if(p_dev->info & BTA_DM_DI_USE_SSR) 1034 p_dev->prev_low = p_data->pm_status.status; 1035 break; 1036 1037 case BTM_PM_STS_SSR: 1038 if(p_data->pm_status.value) 1039 p_dev->info |= BTA_DM_DI_USE_SSR; 1040 else 1041 p_dev->info &= ~BTA_DM_DI_USE_SSR; 1042 break; 1043 #endif 1044 case BTM_PM_STS_SNIFF: 1045 if (p_data->pm_status.hci_status == 0) 1046 { 1047 /* Stop PM timer now if already active for 1048 * particular device since link is already 1049 * put in sniff mode by remote device, and 1050 * PM timer sole purpose is to put the link 1051 * in sniff mode from host side. 1052 */ 1053 bta_dm_pm_stop_timer(p_data->pm_status.bd_addr); 1054 } 1055 else 1056 { 1057 p_dev->info &= ~(BTA_DM_DI_SET_SNIFF | BTA_DM_DI_INT_SNIFF | BTA_DM_DI_ACP_SNIFF); 1058 if (info & BTA_DM_DI_SET_SNIFF) 1059 p_dev->info |= BTA_DM_DI_INT_SNIFF; 1060 else 1061 p_dev->info |= BTA_DM_DI_ACP_SNIFF; 1062 } 1063 break; 1064 1065 case BTM_PM_STS_ERROR: 1066 p_dev->info &= ~BTA_DM_DI_SET_SNIFF; 1067 break; 1068 1069 default: 1070 break; 1071 } 1072 1073 1074 1075 } 1076 1077 /******************************************************************************* 1078 ** 1079 ** Function bta_dm_pm_timer 1080 ** 1081 ** Description Process pm timer event from btm 1082 ** 1083 ** 1084 ** Returns void 1085 ** 1086 *******************************************************************************/ 1087 void bta_dm_pm_timer(tBTA_DM_MSG *p_data) 1088 { 1089 APPL_TRACE_EVENT("%s", __func__); 1090 bta_dm_pm_set_mode(p_data->pm_timer.bd_addr, p_data->pm_timer.pm_request, BTA_DM_PM_EXECUTE); 1091 } 1092 1093 /******************************************************************************* 1094 ** 1095 ** Function bta_dm_find_peer_device 1096 ** 1097 ** Description Given an address, find the associated control block. 1098 ** 1099 ** Returns tBTA_DM_PEER_DEVICE 1100 ** 1101 *******************************************************************************/ 1102 tBTA_DM_PEER_DEVICE * bta_dm_find_peer_device(BD_ADDR peer_addr) 1103 { 1104 tBTA_DM_PEER_DEVICE *p_dev = NULL; 1105 1106 for (int i=0; i<bta_dm_cb.device_list.count; i++) 1107 { 1108 if(!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, peer_addr)) 1109 { 1110 p_dev = &bta_dm_cb.device_list.peer_device[i]; 1111 break; 1112 } 1113 1114 } 1115 return p_dev; 1116 } 1117 1118 /******************************************************************************* 1119 ** 1120 ** Function bta_dm_is_sco_active 1121 ** 1122 ** Description Loop through connected services for HFP+State=SCO 1123 ** 1124 ** Returns BOOLEAN. TRUE if SCO active, else FALSE 1125 ** 1126 *******************************************************************************/ 1127 static BOOLEAN bta_dm_pm_is_sco_active () 1128 { 1129 int j; 1130 BOOLEAN bScoActive = FALSE; 1131 1132 for(j=0; j<bta_dm_conn_srvcs.count ; j++) 1133 { 1134 /* check if an entry already present */ 1135 if ( (bta_dm_conn_srvcs.conn_srvc[j].id == BTA_ID_AG ) && (bta_dm_conn_srvcs.conn_srvc[j].state == BTA_SYS_SCO_OPEN) ) 1136 { 1137 bScoActive = TRUE; 1138 break; 1139 } 1140 } 1141 1142 APPL_TRACE_DEBUG("bta_dm_is_sco_active: SCO active: %d", bScoActive); 1143 return bScoActive; 1144 } 1145 1146 1147 /******************************************************************************* 1148 ** 1149 ** Function bta_dm_pm_hid_check 1150 ** 1151 ** Description Disables/Enables sniff in link policy based on SCO Up/Down 1152 ** 1153 ** Returns None 1154 ** 1155 *******************************************************************************/ 1156 1157 static void bta_dm_pm_hid_check(BOOLEAN bScoActive) 1158 { 1159 int j; 1160 1161 /* if HID is active, disable the link policy */ 1162 for(j=0; j<bta_dm_conn_srvcs.count ; j++) 1163 { 1164 /* check if an entry already present */ 1165 if(bta_dm_conn_srvcs.conn_srvc[j].id == BTA_ID_HH ) 1166 { 1167 APPL_TRACE_DEBUG ("SCO status change(Active: %d), modify HID link policy. state: %d", 1168 bScoActive, bta_dm_conn_srvcs.conn_srvc[j].state); 1169 bta_dm_pm_set_sniff_policy( bta_dm_find_peer_device(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr), bScoActive); 1170 1171 /* if we had disabled link policy, seems like the hid device stop retrying SNIFF after a few tries. force sniff if needed */ 1172 if (!bScoActive) 1173 bta_dm_pm_set_mode(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, BTA_DM_PM_NO_ACTION, 1174 BTA_DM_PM_RESTART); 1175 } 1176 } 1177 1178 } 1179 1180 /******************************************************************************* 1181 ** 1182 ** Function bta_dm_pm_set_sniff_policy 1183 ** 1184 ** Description Disables/Enables sniff in link policy for the give device 1185 ** 1186 ** Returns None 1187 ** 1188 *******************************************************************************/ 1189 static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE *p_dev, BOOLEAN bDisable) 1190 { 1191 UINT16 policy_setting; 1192 1193 if (!p_dev) 1194 return; 1195 1196 if (bDisable) 1197 { 1198 policy_setting = bta_dm_cb.cur_policy & 1199 (HCI_ENABLE_MASTER_SLAVE_SWITCH | 1200 HCI_ENABLE_HOLD_MODE | 1201 HCI_ENABLE_PARK_MODE); 1202 1203 } 1204 else 1205 { 1206 /* allow sniff after sco is closed */ 1207 policy_setting= bta_dm_cb.cur_policy; 1208 } 1209 1210 /* if disabling SNIFF, make sure link is Active */ 1211 if (bDisable) 1212 bta_dm_pm_active(p_dev->peer_bdaddr); 1213 1214 /* update device record and set link policy */ 1215 p_dev->link_policy = policy_setting; 1216 BTM_SetLinkPolicy(p_dev->peer_bdaddr, &policy_setting); 1217 1218 } 1219 1220 #if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE)) 1221 /******************************************************************************* 1222 ** 1223 ** Function bta_dm_pm_obtain_controller_state 1224 ** 1225 ** Description This function obtains the consolidated controller power state 1226 ** 1227 ** Parameters: 1228 ** 1229 *******************************************************************************/ 1230 tBTA_DM_CONTRL_STATE bta_dm_pm_obtain_controller_state(void) 1231 { 1232 /* Did not use counts as it is not sure, how accurate the count values are in 1233 ** bta_dm_cb.device_list.count > 0 || bta_dm_cb.device_list.le_count > 0 */ 1234 1235 tBTA_DM_CONTRL_STATE cur_state = BTA_DM_CONTRL_UNKNOWN; 1236 cur_state = BTM_PM_ReadControllerState(); 1237 1238 APPL_TRACE_DEBUG("bta_dm_pm_obtain_controller_state: %d", cur_state); 1239 return cur_state; 1240 } 1241 #endif 1242