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