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