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