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