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