blob: 8896a0facfd1000243777c20dc6063892dbccdff [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
2 *
3 * Copyright (C) 2000-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 functions that manages ACL link modes.
22 * This includes operations such as active, hold,
23 * park and sniff modes.
24 *
25 * This module contains both internal and external (API)
26 * functions. External (API) functions are distinguishable
27 * by their names beginning with uppercase BTM.
28 *
29 *****************************************************************************/
30
Chris Mantonf8027002015-03-12 09:22:48 -070031#define LOG_TAG "bt_btm_pm"
Sharvil Nanavati5cf03362014-11-14 17:04:46 -080032
Marie Janssen49a86702015-07-08 11:48:57 -070033#include <stddef.h>
34#include <stdio.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080035#include <stdlib.h>
36#include <string.h>
Sharvil Nanavati44802762014-12-23 23:08:58 -080037
The Android Open Source Project5738f832012-12-12 16:00:35 -080038#include "bt_types.h"
Marie Janssen49a86702015-07-08 11:48:57 -070039#include "bt_utils.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080040#include "btm_api.h"
41#include "btm_int.h"
Marie Janssen49a86702015-07-08 11:48:57 -070042#include "btu.h"
Pavlin Radoslavov258c2532015-09-27 20:59:05 -070043#include "bt_common.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080044#include "hcidefs.h"
Marie Janssen49a86702015-07-08 11:48:57 -070045#include "hcimsgs.h"
46#include "l2c_int.h"
Sharvil Nanavati44802762014-12-23 23:08:58 -080047#include "osi/include/log.h"
Myles Watsond7ffd642016-10-27 10:27:36 -070048#include "osi/include/osi.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080049
The Android Open Source Project5738f832012-12-12 16:00:35 -080050/*****************************************************************************/
51/* to handle different modes */
52/*****************************************************************************/
53#define BTM_PM_STORED_MASK 0x80 /* set this mask if the command is stored */
54#define BTM_PM_NUM_SET_MODES 3 /* only hold, sniff & park */
55
Marie Janssend19e0782016-07-15 12:48:27 -070056/* Usage: (ptr_features[ offset ] & mask )?true:false */
The Android Open Source Project5738f832012-12-12 16:00:35 -080057/* offset to supported feature */
Marie Janssend19e0782016-07-15 12:48:27 -070058const uint8_t btm_pm_mode_off[BTM_PM_NUM_SET_MODES] = {0, 0, 1};
The Android Open Source Project5738f832012-12-12 16:00:35 -080059/* mask to supported feature */
Marie Janssend19e0782016-07-15 12:48:27 -070060const uint8_t btm_pm_mode_msk[BTM_PM_NUM_SET_MODES] = {0x40, 0x80, 0x01};
The Android Open Source Project5738f832012-12-12 16:00:35 -080061
62#define BTM_PM_GET_MD1 1
63#define BTM_PM_GET_MD2 2
64#define BTM_PM_GET_COMP 3
65
Marie Janssend19e0782016-07-15 12:48:27 -070066const uint8_t btm_pm_md_comp_matrix[BTM_PM_NUM_SET_MODES*BTM_PM_NUM_SET_MODES] =
The Android Open Source Project5738f832012-12-12 16:00:35 -080067{
68 BTM_PM_GET_COMP,
69 BTM_PM_GET_MD2,
70 BTM_PM_GET_MD2,
71
72 BTM_PM_GET_MD1,
73 BTM_PM_GET_COMP,
74 BTM_PM_GET_MD1,
75
76 BTM_PM_GET_MD1,
77 BTM_PM_GET_MD2,
78 BTM_PM_GET_COMP
79};
80
81/* function prototype */
82static int btm_pm_find_acl_ind(BD_ADDR remote_bda);
Marie Janssend19e0782016-07-15 12:48:27 -070083static tBTM_STATUS btm_pm_snd_md_req( uint8_t pm_id, int link_ind, tBTM_PM_PWR_MD *p_mode );
Sharvil Nanavati5cf03362014-11-14 17:04:46 -080084static const char *mode_to_string(tBTM_PM_MODE mode);
The Android Open Source Project5738f832012-12-12 16:00:35 -080085
86/*
87#ifdef BTM_PM_DEBUG
88#undef BTM_PM_DEBUG
Marie Janssend19e0782016-07-15 12:48:27 -070089#define BTM_PM_DEBUG true
The Android Open Source Project5738f832012-12-12 16:00:35 -080090#endif
91*/
92
Marie Janssend19e0782016-07-15 12:48:27 -070093#if (BTM_PM_DEBUG == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -080094const char * btm_pm_state_str[] =
95{
96 "pm_active_state",
97 "pm_hold_state",
98 "pm_sniff_state",
99 "pm_park_state",
100 "pm_pend_state"
101};
102
103const char * btm_pm_event_str[] =
104{
105 "pm_set_mode_event",
106 "pm_hci_sts_event",
107 "pm_mod_chg_event",
108 "pm_update_event"
109};
110
111const char * btm_pm_action_str[] =
112{
113 "pm_set_mode_action",
114 "pm_update_db_action",
115 "pm_mod_chg_action",
116 "pm_hci_sts_action",
117 "pm_update_action"
118};
Chris Mantone7ef4652014-10-15 16:31:49 -0700119#endif // BTM_PM_DEBUG
The Android Open Source Project5738f832012-12-12 16:00:35 -0800120
121/*****************************************************************************/
122/* P U B L I C F U N C T I O N S */
123/*****************************************************************************/
124/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800125 *
126 * Function BTM_PmRegister
127 *
128 * Description register or deregister with power manager
129 *
130 * Returns BTM_SUCCESS if successful,
131 * BTM_NO_RESOURCES if no room to hold registration
132 * BTM_ILLEGAL_VALUE
133 *
134 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700135tBTM_STATUS BTM_PmRegister (uint8_t mask, uint8_t *p_pm_id, tBTM_PM_STATUS_CBACK *p_cb)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800136{
137 int xx;
138
139 /* de-register */
140 if(mask & BTM_PM_DEREG)
141 {
142 if(*p_pm_id >= BTM_MAX_PM_RECORDS)
143 return BTM_ILLEGAL_VALUE;
144 btm_cb.pm_reg_db[*p_pm_id].mask = BTM_PM_REC_NOT_USED;
145 return BTM_SUCCESS;
146 }
147
148 for(xx=0; xx<BTM_MAX_PM_RECORDS; xx++)
149 {
150 /* find an unused entry */
151 if(btm_cb.pm_reg_db[xx].mask == BTM_PM_REC_NOT_USED)
152 {
153 /* if register for notification, should provide callback routine */
154 if(mask & BTM_PM_REG_NOTIF)
155 {
156 if(p_cb == NULL)
157 return BTM_ILLEGAL_VALUE;
158 btm_cb.pm_reg_db[xx].cback = p_cb;
159 }
160 btm_cb.pm_reg_db[xx].mask = mask;
161 *p_pm_id = xx;
162 return BTM_SUCCESS;
163 }
164 }
165
166 return BTM_NO_RESOURCES;
167}
168
169/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800170 *
171 * Function BTM_SetPowerMode
172 *
173 * Description store the mode in control block or
174 * alter ACL connection behavior.
175 *
176 * Returns BTM_SUCCESS if successful,
177 * BTM_UNKNOWN_ADDR if bd addr is not active or bad
178 *
179 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700180tBTM_STATUS BTM_SetPowerMode (uint8_t pm_id, BD_ADDR remote_bda, tBTM_PM_PWR_MD *p_mode)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800181{
Marie Janssend19e0782016-07-15 12:48:27 -0700182 uint8_t *p_features;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800183 int ind, acl_ind;
184 tBTM_PM_MCB *p_cb = NULL; /* per ACL link */
185 tBTM_PM_MODE mode;
186 int temp_pm_id;
187
The Android Open Source Project5738f832012-12-12 16:00:35 -0800188 if(pm_id >= BTM_MAX_PM_RECORDS)
189 pm_id = BTM_PM_SET_ONLY_ID;
190
191 if(p_mode == NULL)
192 return BTM_ILLEGAL_VALUE;
193
Sharvil Nanavati5344d6d2014-05-04 00:46:57 -0700194 BTM_TRACE_API( "BTM_SetPowerMode: pm_id %d BDA: %08x mode:0x%x", pm_id,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800195 (remote_bda[2]<<24)+(remote_bda[3]<<16)+(remote_bda[4]<<8)+remote_bda[5], p_mode->mode);
196
197 /* take out the force bit */
198 mode = p_mode->mode & ~BTM_PM_MD_FORCE;
199
200 acl_ind = btm_pm_find_acl_ind(remote_bda);
201 if(acl_ind == MAX_L2CAP_LINKS)
202 return (BTM_UNKNOWN_ADDR);
203
204 p_cb = &(btm_cb.pm_mode_db[acl_ind]);
205
206 if(mode != BTM_PM_MD_ACTIVE)
207 {
208 /* check if the requested mode is supported */
209 ind = mode - BTM_PM_MD_HOLD; /* make it base 0 */
210 p_features = BTM_ReadLocalFeatures();
211 if( !(p_features[ btm_pm_mode_off[ind] ] & btm_pm_mode_msk[ind] ) )
212 return BTM_MODE_UNSUPPORTED;
213 }
214
215 if(mode == p_cb->state) /* the requested mode is current mode */
216 {
217 /* already in the requested mode and the current interval has less latency than the max */
218 if( (mode == BTM_PM_MD_ACTIVE) ||
219 ((p_mode->mode & BTM_PM_MD_FORCE) && (p_mode->max >= p_cb->interval) && (p_mode->min <= p_cb->interval)) ||
220 ((p_mode->mode & BTM_PM_MD_FORCE)==0 && (p_mode->max >= p_cb->interval)) )
221 {
Sharvil Nanavati5344d6d2014-05-04 00:46:57 -0700222 BTM_TRACE_DEBUG( "BTM_SetPowerMode: mode:0x%x interval %d max:%d, min:%d", p_mode->mode, p_cb->interval, p_mode->max, p_mode->min);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800223 return BTM_SUCCESS;
224 }
225 }
226
227 temp_pm_id = pm_id;
228 if(pm_id == BTM_PM_SET_ONLY_ID)
229 temp_pm_id = BTM_MAX_PM_RECORDS;
230
231 /* update mode database */
232 if( ((pm_id != BTM_PM_SET_ONLY_ID) &&
233 (btm_cb.pm_reg_db[pm_id].mask & BTM_PM_REG_SET))
234 || ((pm_id == BTM_PM_SET_ONLY_ID) && (btm_cb.pm_pend_link != MAX_L2CAP_LINKS)) )
235 {
Marie Janssend19e0782016-07-15 12:48:27 -0700236#if (BTM_PM_DEBUG == TRUE)
Sharvil Nanavati5344d6d2014-05-04 00:46:57 -0700237 BTM_TRACE_DEBUG( "BTM_SetPowerMode: Saving cmd acl_ind %d temp_pm_id %d", acl_ind,temp_pm_id);
Chris Mantone7ef4652014-10-15 16:31:49 -0700238#endif // BTM_PM_DEBUG
The Android Open Source Project5738f832012-12-12 16:00:35 -0800239 /* Make sure mask is set to BTM_PM_REG_SET */
240 btm_cb.pm_reg_db[temp_pm_id].mask |= BTM_PM_REG_SET;
241 *(&p_cb->req_mode[temp_pm_id]) = *((tBTM_PM_PWR_MD *)p_mode);
Marie Janssend19e0782016-07-15 12:48:27 -0700242 p_cb->chg_ind = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800243 }
244
Marie Janssend19e0782016-07-15 12:48:27 -0700245#if (BTM_PM_DEBUG == TRUE)
Sharvil Nanavati5344d6d2014-05-04 00:46:57 -0700246 BTM_TRACE_DEBUG( "btm_pm state:0x%x, pm_pend_link: %d", p_cb->state, btm_cb.pm_pend_link);
Chris Mantone7ef4652014-10-15 16:31:49 -0700247#endif // BTM_PM_DEBUG
The Android Open Source Project5738f832012-12-12 16:00:35 -0800248 /* if mode == hold or pending, return */
249 if( (p_cb->state == BTM_PM_STS_HOLD) ||
250 (p_cb->state == BTM_PM_STS_PENDING) ||
251 (btm_cb.pm_pend_link != MAX_L2CAP_LINKS) ) /* command pending */
252 {
253 if(acl_ind != btm_cb.pm_pend_link)
254 {
255 /* set the stored mask */
256 p_cb->state |= BTM_PM_STORED_MASK;
Sharvil Nanavati5344d6d2014-05-04 00:46:57 -0700257 BTM_TRACE_DEBUG( "btm_pm state stored:%d",acl_ind);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800258 }
259 return BTM_CMD_STORED;
260 }
261
The Android Open Source Project5738f832012-12-12 16:00:35 -0800262 return btm_pm_snd_md_req(pm_id, acl_ind, p_mode);
263}
264
265/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800266 *
267 * Function BTM_ReadPowerMode
268 *
269 * Description This returns the current mode for a specific
270 * ACL connection.
271 *
272 * Input Param remote_bda - device address of desired ACL connection
273 *
274 * Output Param p_mode - address where the current mode is copied into.
275 * BTM_ACL_MODE_NORMAL
276 * BTM_ACL_MODE_HOLD
277 * BTM_ACL_MODE_SNIFF
278 * BTM_ACL_MODE_PARK
279 * (valid only if return code is BTM_SUCCESS)
280 *
281 * Returns BTM_SUCCESS if successful,
282 * BTM_UNKNOWN_ADDR if bd addr is not active or bad
283 *
284 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800285tBTM_STATUS BTM_ReadPowerMode (BD_ADDR remote_bda, tBTM_PM_MODE *p_mode)
286{
287 int acl_ind;
288
Marie Janssenf33b6f42016-11-22 15:01:42 -0800289 acl_ind = btm_pm_find_acl_ind(remote_bda);
290 if(acl_ind == MAX_L2CAP_LINKS)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800291 return (BTM_UNKNOWN_ADDR);
292
293 *p_mode = btm_cb.pm_mode_db[acl_ind].state;
294 return BTM_SUCCESS;
295}
296
297/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800298 *
299 * Function btm_read_power_mode_state
300 *
301 * Description This returns the current pm state for a specific
302 * ACL connection.
303 *
304 * Input Param remote_bda - device address of desired ACL connection
305 *
306 * Output Param pmState - address where the current pm state is copied into.
307 * BTM_PM_ST_ACTIVE
308 * BTM_PM_ST_HOLD
309 * BTM_PM_ST_SNIFF
310 * BTM_PM_ST_PARK
311 * BTM_PM_ST_PENDING
312 * (valid only if return code is BTM_SUCCESS)
313 *
314 * Returns BTM_SUCCESS if successful,
315 * BTM_UNKNOWN_ADDR if bd addr is not active or bad
316 *
317 ******************************************************************************/
Mallikarjuna GB9ab2a9d2015-05-30 23:33:58 +0530318tBTM_STATUS btm_read_power_mode_state (BD_ADDR remote_bda, tBTM_PM_STATE *pmState)
319{
320 int acl_ind = btm_pm_find_acl_ind(remote_bda);
321
322 if( acl_ind == MAX_L2CAP_LINKS)
323 return (BTM_UNKNOWN_ADDR);
324
325 *pmState = btm_cb.pm_mode_db[acl_ind].state;
326 return BTM_SUCCESS;
327}
328
329/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800330 *
331 * Function BTM_SetSsrParams
332 *
333 * Description This sends the given SSR parameters for the given ACL
334 * connection if it is in ACTIVE mode.
335 *
336 * Input Param remote_bda - device address of desired ACL connection
337 * max_lat - maximum latency (in 0.625ms)(0-0xFFFE)
338 * min_rmt_to - minimum remote timeout
339 * min_loc_to - minimum local timeout
340 *
341 *
342 * Returns BTM_SUCCESS if the HCI command is issued successful,
343 * BTM_UNKNOWN_ADDR if bd addr is not active or bad
344 * BTM_CMD_STORED if the command is stored
345 *
346 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700347tBTM_STATUS BTM_SetSsrParams (BD_ADDR remote_bda, uint16_t max_lat,
348 uint16_t min_rmt_to, uint16_t min_loc_to)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800349{
350#if (BTM_SSR_INCLUDED == TRUE)
351 int acl_ind;
352 tBTM_PM_MCB *p_cb;
353
Marie Janssenf33b6f42016-11-22 15:01:42 -0800354 acl_ind = btm_pm_find_acl_ind(remote_bda);
355 if(acl_ind == MAX_L2CAP_LINKS)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800356 return (BTM_UNKNOWN_ADDR);
357
358 if(BTM_PM_STS_ACTIVE == btm_cb.pm_mode_db[acl_ind].state ||
359 BTM_PM_STS_SNIFF == btm_cb.pm_mode_db[acl_ind].state)
360 {
Jakub Pawlowskib6ab9b32016-10-10 09:35:13 -0700361 btsnd_hcic_sniff_sub_rate(btm_cb.acl_db[acl_ind].hci_handle, max_lat,
362 min_rmt_to, min_loc_to);
363 return BTM_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800364 }
365 p_cb = &btm_cb.pm_mode_db[acl_ind];
366 p_cb->max_lat = max_lat;
367 p_cb->min_rmt_to = min_rmt_to;
368 p_cb->min_loc_to = min_loc_to;
369 return BTM_CMD_STORED;
370#else
371 return BTM_ILLEGAL_ACTION;
Chris Mantone7ef4652014-10-15 16:31:49 -0700372#endif // BTM_SSR_INCLUDED
The Android Open Source Project5738f832012-12-12 16:00:35 -0800373}
374
375/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800376 *
377 * Function btm_pm_reset
378 *
379 * Description as a part of the BTM reset process.
380 *
381 * Returns void
382 *
383 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800384void btm_pm_reset(void)
385{
386 int xx;
387 tBTM_PM_STATUS_CBACK *cb = NULL;
388
389 /* clear the pending request for application */
390 if( (btm_cb.pm_pend_id != BTM_PM_SET_ONLY_ID) &&
391 (btm_cb.pm_reg_db[btm_cb.pm_pend_id].mask & BTM_PM_REG_NOTIF) )
392 {
393 cb = btm_cb.pm_reg_db[btm_cb.pm_pend_id].cback;
394 }
395
The Android Open Source Project5738f832012-12-12 16:00:35 -0800396 /* clear the register record */
397 for(xx=0; xx<BTM_MAX_PM_RECORDS; xx++)
398 {
399 btm_cb.pm_reg_db[xx].mask = BTM_PM_REC_NOT_USED;
400 }
401
Kim Schulz2a2701c2013-09-16 15:59:33 +0200402 if(cb != NULL && btm_cb.pm_pend_link < MAX_L2CAP_LINKS)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800403 (*cb)(btm_cb.acl_db[btm_cb.pm_pend_link].remote_addr, BTM_PM_STS_ERROR, BTM_DEV_RESET, 0);
Kim Schulz2a2701c2013-09-16 15:59:33 +0200404
405 /* no command pending */
406 btm_cb.pm_pend_link = MAX_L2CAP_LINKS;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800407}
408
409/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800410 *
411 * Function btm_pm_sm_alloc
412 *
413 * Description This function initializes the control block of an ACL link.
414 * It is called when an ACL connection is created.
415 *
416 * Returns void
417 *
418 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700419void btm_pm_sm_alloc(uint8_t ind)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800420{
421 tBTM_PM_MCB *p_db = &btm_cb.pm_mode_db[ind]; /* per ACL link */
422 memset (p_db, 0, sizeof(tBTM_PM_MCB));
423 p_db->state = BTM_PM_ST_ACTIVE;
Marie Janssend19e0782016-07-15 12:48:27 -0700424#if (BTM_PM_DEBUG == TRUE)
Sharvil Nanavati5344d6d2014-05-04 00:46:57 -0700425 BTM_TRACE_DEBUG( "btm_pm_sm_alloc ind:%d st:%d", ind, p_db->state);
Chris Mantone7ef4652014-10-15 16:31:49 -0700426#endif // BTM_PM_DEBUG
The Android Open Source Project5738f832012-12-12 16:00:35 -0800427}
428
429/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800430 *
431 * Function btm_pm_find_acl_ind
432 *
433 * Description This function initializes the control block of an ACL link.
434 * It is called when an ACL connection is created.
435 *
436 * Returns void
437 *
438 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800439static int btm_pm_find_acl_ind(BD_ADDR remote_bda)
440{
441 tACL_CONN *p = &btm_cb.acl_db[0];
Marie Janssend19e0782016-07-15 12:48:27 -0700442 uint8_t xx;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800443
444 for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p++)
445 {
Myles Watson84baa7f2016-11-14 12:05:37 -0800446 if ((p->in_use) && (!memcmp (p->remote_addr, remote_bda, BD_ADDR_LEN)) &&
447 p->transport == BT_TRANSPORT_BR_EDR)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800448 {
Marie Janssend19e0782016-07-15 12:48:27 -0700449#if (BTM_PM_DEBUG == TRUE)
Sharvil Nanavati5344d6d2014-05-04 00:46:57 -0700450 BTM_TRACE_DEBUG( "btm_pm_find_acl_ind ind:%d, st:%d", xx, btm_cb.pm_mode_db[xx].state);
Chris Mantone7ef4652014-10-15 16:31:49 -0700451#endif // BTM_PM_DEBUG
The Android Open Source Project5738f832012-12-12 16:00:35 -0800452 break;
453 }
454 }
455 return xx;
456}
457
458/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800459 *
460 * Function btm_pm_compare_modes
461 * Description get the "more active" mode of the 2
462 * Returns void
463 *
464 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800465static tBTM_PM_PWR_MD * btm_pm_compare_modes(tBTM_PM_PWR_MD *p_md1, tBTM_PM_PWR_MD *p_md2, tBTM_PM_PWR_MD *p_res)
466{
Marie Janssend19e0782016-07-15 12:48:27 -0700467 uint8_t res;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800468
469 if(p_md1 == NULL)
470 {
471 *p_res = *p_md2;
472 p_res->mode &= ~BTM_PM_MD_FORCE;
473
474 return p_md2;
475 }
476
477 if(p_md2->mode == BTM_PM_MD_ACTIVE || p_md1->mode == BTM_PM_MD_ACTIVE)
478 {
479 return NULL;
480 }
481
482 /* check if force bit is involved */
483 if(p_md1->mode & BTM_PM_MD_FORCE)
484 {
485 *p_res = *p_md1;
486 p_res->mode &= ~BTM_PM_MD_FORCE;
487 return p_res;
488 }
489
490 if(p_md2->mode & BTM_PM_MD_FORCE)
491 {
492 *p_res = *p_md2;
493 p_res->mode &= ~BTM_PM_MD_FORCE;
494 return p_res;
495 }
496
497 res = (p_md1->mode - 1) * BTM_PM_NUM_SET_MODES + (p_md2->mode - 1);
498 res = btm_pm_md_comp_matrix[res];
499 switch(res)
500 {
501 case BTM_PM_GET_MD1:
502 *p_res = *p_md1;
503 return p_md1;
504
505 case BTM_PM_GET_MD2:
506 *p_res = *p_md2;
507 return p_md2;
508
509 case BTM_PM_GET_COMP:
510 p_res->mode = p_md1->mode;
511 /* min of the two */
512 p_res->max = (p_md1->max < p_md2->max)? (p_md1->max) : (p_md2->max);
513 /* max of the two */
514 p_res->min = (p_md1->min > p_md2->min)? (p_md1->min) : (p_md2->min);
515
516 /* the intersection is NULL */
517 if( p_res->max < p_res->min)
518 return NULL;
519
520 if(p_res->mode == BTM_PM_MD_SNIFF)
521 {
522 /* max of the two */
523 p_res->attempt = (p_md1->attempt > p_md2->attempt)? (p_md1->attempt) : (p_md2->attempt);
524 p_res->timeout = (p_md1->timeout > p_md2->timeout)? (p_md1->timeout) : (p_md2->timeout);
525 }
526 return p_res;
527 }
528 return NULL;
529}
530
531/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800532 *
533 * Function btm_pm_get_set_mode
534 * Description get the resulting mode from the registered parties, then compare it
535 * with the requested mode, if the command is from an unregistered party.
536 * Returns void
537 *
538 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700539static tBTM_PM_MODE btm_pm_get_set_mode(uint8_t pm_id, tBTM_PM_MCB *p_cb, tBTM_PM_PWR_MD *p_mode, tBTM_PM_PWR_MD *p_res)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800540{
541 int xx, loop_max;
542 tBTM_PM_PWR_MD *p_md = NULL;
543
544 if(p_mode != NULL && p_mode->mode & BTM_PM_MD_FORCE)
545 {
546 *p_res = *p_mode;
547 p_res->mode &= ~BTM_PM_MD_FORCE;
548 return p_res->mode;
549 }
550
551 if(!p_mode)
552 loop_max = BTM_MAX_PM_RECORDS+1;
553 else
554 loop_max = BTM_MAX_PM_RECORDS;
555
556 for( xx=0; xx<loop_max; xx++)
557 {
558 /* g through all the registered "set" parties */
559 if(btm_cb.pm_reg_db[xx].mask & BTM_PM_REG_SET)
560 {
561 if(p_cb->req_mode[xx].mode == BTM_PM_MD_ACTIVE)
562 {
563 /* if at least one registered (SET) party says ACTIVE, stay active */
564 return BTM_PM_MD_ACTIVE;
565 }
566 else
567 {
568 /* if registered parties give conflicting information, stay active */
569 if( (btm_pm_compare_modes(p_md, &p_cb->req_mode[xx], p_res)) == NULL)
570 return BTM_PM_MD_ACTIVE;
571 p_md = p_res;
572 }
573 }
574 }
575
576 /* if the resulting mode is NULL(nobody registers SET), use the requested mode */
577 if(p_md == NULL)
578 {
579 if(p_mode)
580 *p_res = *((tBTM_PM_PWR_MD *)p_mode);
581 else /* p_mode is NULL when btm_pm_snd_md_req is called from btm_pm_proc_mode_change */
582 return BTM_PM_MD_ACTIVE;
583 }
584 else
585 {
586 /* if the command is from unregistered party,
587 compare the resulting mode from registered party*/
588 if( (pm_id == BTM_PM_SET_ONLY_ID) &&
589 ((btm_pm_compare_modes(p_mode, p_md, p_res)) == NULL) )
590 return BTM_PM_MD_ACTIVE;
591 }
592
593 return p_res->mode;
594}
595
596/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800597 *
598 * Function btm_pm_snd_md_req
599 * Description get the resulting mode and send the resuest to host controller
600 * Returns tBTM_STATUS
601 *, bool *p_chg_ind
602 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700603static tBTM_STATUS btm_pm_snd_md_req(uint8_t pm_id, int link_ind, tBTM_PM_PWR_MD *p_mode)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800604{
605 tBTM_PM_PWR_MD md_res;
606 tBTM_PM_MODE mode;
607 tBTM_PM_MCB *p_cb = &btm_cb.pm_mode_db[link_ind];
Marie Janssend19e0782016-07-15 12:48:27 -0700608 bool chg_ind = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800609
610 mode = btm_pm_get_set_mode(pm_id, p_cb, p_mode, &md_res);
611 md_res.mode = mode;
612
Marie Janssend19e0782016-07-15 12:48:27 -0700613#if (BTM_PM_DEBUG == TRUE)
Sharvil Nanavati5344d6d2014-05-04 00:46:57 -0700614 BTM_TRACE_DEBUG( "btm_pm_snd_md_req link_ind:%d, mode: %d",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800615 link_ind, mode);
Chris Mantone7ef4652014-10-15 16:31:49 -0700616#endif // BTM_PM_DEBUG
The Android Open Source Project5738f832012-12-12 16:00:35 -0800617
618 if( p_cb->state == mode)
619 {
620 /* already in the resulting mode */
621 if( (mode == BTM_PM_MD_ACTIVE) ||
622 ((md_res.max >= p_cb->interval) && (md_res.min <= p_cb->interval)) )
623 return BTM_CMD_STORED;
624 /* Otherwise, needs to wake, then sleep */
Marie Janssend19e0782016-07-15 12:48:27 -0700625 chg_ind = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800626 }
627 p_cb->chg_ind = chg_ind;
628
629 /* cannot go directly from current mode to resulting mode. */
630 if( mode != BTM_PM_MD_ACTIVE && p_cb->state != BTM_PM_MD_ACTIVE)
Marie Janssend19e0782016-07-15 12:48:27 -0700631 p_cb->chg_ind = true; /* needs to wake, then sleep */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800632
Marie Janssend19e0782016-07-15 12:48:27 -0700633 if(p_cb->chg_ind == true) /* needs to wake first */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800634 md_res.mode = BTM_PM_MD_ACTIVE;
635#if (BTM_SSR_INCLUDED == TRUE)
636 else if(BTM_PM_MD_SNIFF == md_res.mode && p_cb->max_lat)
637 {
638 btsnd_hcic_sniff_sub_rate(btm_cb.acl_db[link_ind].hci_handle, p_cb->max_lat,
639 p_cb->min_rmt_to, p_cb->min_loc_to);
640 p_cb->max_lat = 0;
641 }
Chris Mantone7ef4652014-10-15 16:31:49 -0700642#endif // BTM_SSR_INCLUDED
The Android Open Source Project5738f832012-12-12 16:00:35 -0800643 /* Default is failure */
644 btm_cb.pm_pend_link = MAX_L2CAP_LINKS;
645
646 /* send the appropriate HCI command */
647 btm_cb.pm_pend_id = pm_id;
648
Marie Janssend19e0782016-07-15 12:48:27 -0700649#if (BTM_PM_DEBUG == TRUE)
Sharvil Nanavati5344d6d2014-05-04 00:46:57 -0700650 BTM_TRACE_DEBUG("btm_pm_snd_md_req state:0x%x, link_ind: %d", p_cb->state, link_ind);
Chris Mantone7ef4652014-10-15 16:31:49 -0700651#endif // BTM_PM_DEBUG
Sharvil Nanavati5cf03362014-11-14 17:04:46 -0800652
Pavlin Radoslavov2313c242015-08-06 19:38:32 -0700653 BTM_TRACE_DEBUG("%s switching from %s to %s.", __func__,
654 mode_to_string(p_cb->state), mode_to_string(md_res.mode));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800655 switch(md_res.mode)
656 {
657 case BTM_PM_MD_ACTIVE:
658 switch(p_cb->state)
659 {
660 case BTM_PM_MD_SNIFF:
Jakub Pawlowskib6ab9b32016-10-10 09:35:13 -0700661 btsnd_hcic_exit_sniff_mode(btm_cb.acl_db[link_ind].hci_handle);
662 btm_cb.pm_pend_link = link_ind;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800663 break;
664 case BTM_PM_MD_PARK:
Jakub Pawlowskib6ab9b32016-10-10 09:35:13 -0700665 btsnd_hcic_exit_park_mode(btm_cb.acl_db[link_ind].hci_handle);
666 btm_cb.pm_pend_link = link_ind;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800667 break;
668 default:
669 /* Failure btm_cb.pm_pend_link = MAX_L2CAP_LINKS */
670 break;
671 }
672 break;
673
674 case BTM_PM_MD_HOLD:
Jakub Pawlowskib6ab9b32016-10-10 09:35:13 -0700675 btsnd_hcic_hold_mode(btm_cb.acl_db[link_ind].hci_handle,
676 md_res.max, md_res.min);
677 btm_cb.pm_pend_link = link_ind;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800678 break;
679
680 case BTM_PM_MD_SNIFF:
Jakub Pawlowskib6ab9b32016-10-10 09:35:13 -0700681 btsnd_hcic_sniff_mode(btm_cb.acl_db[link_ind].hci_handle,
682 md_res.max, md_res.min, md_res.attempt,
683 md_res.timeout);
684 btm_cb.pm_pend_link = link_ind;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800685 break;
686
687 case BTM_PM_MD_PARK:
Jakub Pawlowskib6ab9b32016-10-10 09:35:13 -0700688 btsnd_hcic_park_mode(btm_cb.acl_db[link_ind].hci_handle,
689 md_res.max, md_res.min);
690 btm_cb.pm_pend_link = link_ind;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800691 break;
692 default:
693 /* Failure btm_cb.pm_pend_link = MAX_L2CAP_LINKS */
694 break;
695 }
696
697 if(btm_cb.pm_pend_link == MAX_L2CAP_LINKS)
698 {
699 /* the command was not sent */
Marie Janssend19e0782016-07-15 12:48:27 -0700700#if (BTM_PM_DEBUG == TRUE)
Sharvil Nanavati5344d6d2014-05-04 00:46:57 -0700701 BTM_TRACE_DEBUG( "pm_pend_link: %d",btm_cb.pm_pend_link);
Chris Mantone7ef4652014-10-15 16:31:49 -0700702#endif // BTM_PM_DEBUG
The Android Open Source Project5738f832012-12-12 16:00:35 -0800703 return (BTM_NO_RESOURCES);
704 }
705
706 return BTM_CMD_STARTED;
707}
708
709/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800710 *
711 * Function btm_pm_check_stored
712 *
713 * Description This function is called when an HCI command status event occurs
714 * to check if there's any PM command issued while waiting for
715 * HCI command status.
716 *
717 * Returns none.
718 *
719 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800720static void btm_pm_check_stored(void)
721{
722 int xx;
723 for(xx=0; xx<MAX_L2CAP_LINKS; xx++)
724 {
725 if(btm_cb.pm_mode_db[xx].state & BTM_PM_STORED_MASK)
726 {
727 btm_cb.pm_mode_db[xx].state &= ~BTM_PM_STORED_MASK;
Sharvil Nanavati5344d6d2014-05-04 00:46:57 -0700728 BTM_TRACE_DEBUG( "btm_pm_check_stored :%d", xx);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800729 btm_pm_snd_md_req(BTM_PM_SET_ONLY_ID, xx, NULL);
730 break;
731 }
732 }
733}
734
The Android Open Source Project5738f832012-12-12 16:00:35 -0800735/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800736 *
737 * Function btm_pm_proc_cmd_status
738 *
739 * Description This function is called when an HCI command status event occurs
740 * for power manager related commands.
741 *
742 * Input Parms status - status of the event (HCI_SUCCESS if no errors)
743 *
744 * Returns none.
745 *
746 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700747void btm_pm_proc_cmd_status(uint8_t status)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800748{
749 tBTM_PM_MCB *p_cb;
750 tBTM_PM_STATUS pm_status;
751
752 if(btm_cb.pm_pend_link >= MAX_L2CAP_LINKS)
753 return;
754
755 p_cb = &btm_cb.pm_mode_db[btm_cb.pm_pend_link];
756
757 if(status == HCI_SUCCESS)
758 {
759 p_cb->state = BTM_PM_ST_PENDING;
760 pm_status = BTM_PM_STS_PENDING;
Marie Janssend19e0782016-07-15 12:48:27 -0700761#if (BTM_PM_DEBUG == TRUE)
Sharvil Nanavati5344d6d2014-05-04 00:46:57 -0700762 BTM_TRACE_DEBUG( "btm_pm_proc_cmd_status new state:0x%x", p_cb->state);
Chris Mantone7ef4652014-10-15 16:31:49 -0700763#endif // BTM_PM_DEBUG
The Android Open Source Project5738f832012-12-12 16:00:35 -0800764 }
765 else /* the command was not successfull. Stay in the same state */
766 {
767 pm_status = BTM_PM_STS_ERROR;
768 }
769
770 /* notify the caller is appropriate */
771 if( (btm_cb.pm_pend_id != BTM_PM_SET_ONLY_ID) &&
772 (btm_cb.pm_reg_db[btm_cb.pm_pend_id].mask & BTM_PM_REG_NOTIF) )
773 {
774 (*btm_cb.pm_reg_db[btm_cb.pm_pend_id].cback)(btm_cb.acl_db[btm_cb.pm_pend_link].remote_addr, pm_status, 0, status);
775 }
776
777 /* no pending cmd now */
Marie Janssend19e0782016-07-15 12:48:27 -0700778#if (BTM_PM_DEBUG == TRUE)
Sharvil Nanavati5344d6d2014-05-04 00:46:57 -0700779 BTM_TRACE_DEBUG( "btm_pm_proc_cmd_status state:0x%x, pm_pend_link: %d(new: %d)",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800780 p_cb->state, btm_cb.pm_pend_link, MAX_L2CAP_LINKS);
Chris Mantone7ef4652014-10-15 16:31:49 -0700781#endif // BTM_PM_DEBUG
The Android Open Source Project5738f832012-12-12 16:00:35 -0800782 btm_cb.pm_pend_link = MAX_L2CAP_LINKS;
783
784 btm_pm_check_stored();
785}
786
787/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800788 *
789 * Function btm_process_mode_change
790 *
791 * Description This function is called when an HCI mode change event occurs.
792 *
793 * Input Parms hci_status - status of the event (HCI_SUCCESS if no errors)
794 * hci_handle - connection handle associated with the change
795 * mode - HCI_MODE_ACTIVE, HCI_MODE_HOLD, HCI_MODE_SNIFF, or HCI_MODE_PARK
796 * interval - number of baseband slots (meaning depends on mode)
797 *
798 * Returns none.
799 *
800 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700801void btm_pm_proc_mode_change (uint8_t hci_status, uint16_t hci_handle, uint8_t mode, uint16_t interval)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800802{
803 tACL_CONN *p;
804 tBTM_PM_MCB *p_cb = NULL;
805 int xx, yy, zz;
806 tBTM_PM_STATE old_state;
807 tL2C_LCB *p_lcb;
808
809 /* get the index to acl_db */
Marie Janssenf33b6f42016-11-22 15:01:42 -0800810 xx = btm_handle_to_acl_index(hci_handle);
811 if (xx >= MAX_L2CAP_LINKS)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800812 return;
813
814 p = &btm_cb.acl_db[xx];
815
The Android Open Source Project5738f832012-12-12 16:00:35 -0800816 /* update control block */
817 p_cb = &(btm_cb.pm_mode_db[xx]);
818 old_state = p_cb->state;
819 p_cb->state = mode;
820 p_cb->interval = interval;
Zach Johnson90fe9b02015-01-28 11:16:15 -0800821
Pavlin Radoslavov2313c242015-08-06 19:38:32 -0700822 BTM_TRACE_DEBUG("%s switched from %s to %s.", __func__,
823 mode_to_string(old_state), mode_to_string(p_cb->state));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800824
Marie Janssenf33b6f42016-11-22 15:01:42 -0800825 p_lcb = l2cu_find_lcb_by_bd_addr(p->remote_addr, BT_TRANSPORT_BR_EDR);
826 if (p_lcb != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800827 {
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -0700828 if ((p_cb->state == BTM_PM_ST_ACTIVE) || (p_cb->state == BTM_PM_ST_SNIFF))
829 {
830 /* There might be any pending packets due to SNIFF or PENDING state */
831 /* Trigger L2C to start transmission of the pending packets. */
Sharvil Nanavati5344d6d2014-05-04 00:46:57 -0700832 BTM_TRACE_DEBUG("btm mode change to active; check l2c_link for outgoing packets");
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -0700833 l2c_link_check_send_pkts(p_lcb, NULL, NULL);
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -0700834 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800835 }
836
837 /* notify registered parties */
838 for(yy=0; yy<=BTM_MAX_PM_RECORDS; yy++)
839 {
840 /* set req_mode HOLD mode->ACTIVE */
841 if( (mode == BTM_PM_MD_ACTIVE) && (p_cb->req_mode[yy].mode == BTM_PM_MD_HOLD) )
842 p_cb->req_mode[yy].mode = BTM_PM_MD_ACTIVE;
843 }
844
845 /* new request has been made. - post a message to BTU task */
846 if(old_state & BTM_PM_STORED_MASK)
847 {
Marie Janssend19e0782016-07-15 12:48:27 -0700848#if (BTM_PM_DEBUG == TRUE)
Sharvil Nanavati5344d6d2014-05-04 00:46:57 -0700849 BTM_TRACE_DEBUG( "btm_pm_proc_mode_change: Sending stored req:%d", xx);
Chris Mantone7ef4652014-10-15 16:31:49 -0700850#endif // BTM_PM_DEBUG
The Android Open Source Project5738f832012-12-12 16:00:35 -0800851 btm_pm_snd_md_req(BTM_PM_SET_ONLY_ID, xx, NULL);
852 }
853 else
854 {
855 for(zz=0; zz<MAX_L2CAP_LINKS; zz++)
856 {
Marie Janssend19e0782016-07-15 12:48:27 -0700857 if(btm_cb.pm_mode_db[zz].chg_ind == true)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800858 {
Marie Janssend19e0782016-07-15 12:48:27 -0700859#if (BTM_PM_DEBUG == TRUE)
Sharvil Nanavati5344d6d2014-05-04 00:46:57 -0700860 BTM_TRACE_DEBUG( "btm_pm_proc_mode_change: Sending PM req :%d", zz);
Chris Mantone7ef4652014-10-15 16:31:49 -0700861#endif // BTM_PM_DEBUG
The Android Open Source Project5738f832012-12-12 16:00:35 -0800862 btm_pm_snd_md_req(BTM_PM_SET_ONLY_ID, zz, NULL);
863 break;
864 }
865 }
866 }
867
The Android Open Source Project5738f832012-12-12 16:00:35 -0800868 /* notify registered parties */
869 for(yy=0; yy<BTM_MAX_PM_RECORDS; yy++)
870 {
871 if(btm_cb.pm_reg_db[yy].mask & BTM_PM_REG_NOTIF)
872 {
873 (*btm_cb.pm_reg_db[yy].cback)( p->remote_addr, mode, interval, hci_status);
874 }
875 }
Marie Janssend19e0782016-07-15 12:48:27 -0700876#if (BTM_SCO_INCLUDED == TRUE)
Mallikarjuna GB9ab2a9d2015-05-30 23:33:58 +0530877 /*check if sco disconnect is waiting for the mode change */
878 btm_sco_disc_chk_pend_for_modechange(hci_handle);
879#endif
The Android Open Source Project5738f832012-12-12 16:00:35 -0800880
881 /* If mode change was because of an active role switch or change link key */
Zach Johnsone7faae62014-10-27 17:23:49 -0700882 btm_cont_rswitch(p, btm_find_dev(p->remote_addr), hci_status);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800883}
884
885/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800886 *
887 * Function btm_pm_proc_ssr_evt
888 *
889 * Description This function is called when an HCI sniff subrating event occurs.
890 *
891 * Returns none.
892 *
893 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800894#if (BTM_SSR_INCLUDED == TRUE)
Myles Watsond35a6482016-10-27 08:52:16 -0700895void btm_pm_proc_ssr_evt (uint8_t *p,
896 UNUSED_ATTR uint16_t evt_len)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800897{
Marie Janssend19e0782016-07-15 12:48:27 -0700898 uint8_t status;
899 uint16_t handle;
900 uint16_t max_rx_lat;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800901 int xx, yy;
902 tBTM_PM_MCB *p_cb;
903 tACL_CONN *p_acl=NULL;
Marie Janssend19e0782016-07-15 12:48:27 -0700904 uint16_t use_ssr = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800905
906 STREAM_TO_UINT8 (status, p);
907
908 STREAM_TO_UINT16 (handle, p);
909 /* get the index to acl_db */
Marie Janssenf33b6f42016-11-22 15:01:42 -0800910 xx = btm_handle_to_acl_index(handle);
911 if (xx >= MAX_L2CAP_LINKS)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800912 return;
913
Sharvil Nanavatif1c764f2015-02-23 17:31:48 -0800914 p += 2;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800915 STREAM_TO_UINT16 (max_rx_lat, p);
916 p_cb = &(btm_cb.pm_mode_db[xx]);
917
918 p_acl = &btm_cb.acl_db[xx];
919 if(p_cb->interval == max_rx_lat)
920 {
921 /* using legacy sniff */
Marie Janssend19e0782016-07-15 12:48:27 -0700922 use_ssr = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800923 }
924
925 /* notify registered parties */
926 for(yy=0; yy<BTM_MAX_PM_RECORDS; yy++)
927 {
928 if(btm_cb.pm_reg_db[yy].mask & BTM_PM_REG_NOTIF)
929 {
930 if( p_acl)
931 {
932 (*btm_cb.pm_reg_db[yy].cback)( p_acl->remote_addr, BTM_PM_STS_SSR, use_ssr, status);
933 }
934 }
935 }
936}
Chris Mantone7ef4652014-10-15 16:31:49 -0700937#endif // BTM_SSR_INCLUDED
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -0700938
Satya Callojie5ba8842014-07-03 17:18:02 -0700939/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800940 *
941 * Function btm_pm_device_in_active_or_sniff_mode
942 *
943 * Description This function is called to check if in active or sniff mode
944 *
945 * Returns true, if in active or sniff mode
946 *
947 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700948bool btm_pm_device_in_active_or_sniff_mode(void)
Satya Callojie5ba8842014-07-03 17:18:02 -0700949{
950 /* The active state is the highest state-includes connected device and sniff mode*/
951
952 /* Covers active and sniff modes */
Andre Eisenbachf4c4b782015-03-19 15:15:05 -0700953 if (BTM_GetNumAclLinks() > 0)
Satya Callojie5ba8842014-07-03 17:18:02 -0700954 {
Andre Eisenbachf4c4b782015-03-19 15:15:05 -0700955 BTM_TRACE_DEBUG("%s - ACL links: %d", __func__, BTM_GetNumAclLinks());
Marie Janssend19e0782016-07-15 12:48:27 -0700956 return true;
Satya Callojie5ba8842014-07-03 17:18:02 -0700957 }
958
959 /* Check BLE states */
960 if (btm_ble_get_conn_st() != BLE_CONN_IDLE)
961 {
Andre Eisenbachf4c4b782015-03-19 15:15:05 -0700962 BTM_TRACE_DEBUG("%s - BLE state: %x", __func__, btm_ble_get_conn_st());
Marie Janssend19e0782016-07-15 12:48:27 -0700963 return true;
Satya Callojie5ba8842014-07-03 17:18:02 -0700964 }
965
Marie Janssend19e0782016-07-15 12:48:27 -0700966 return false;
Satya Callojie5ba8842014-07-03 17:18:02 -0700967}
968
969/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800970 *
971 * Function btm_pm_device_in_scan_state
972 *
973 * Description This function is called to check if in paging, inquiry or connecting mode
974 *
975 * Returns true, if in paging, inquiry or connecting mode
976 *
977 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700978bool btm_pm_device_in_scan_state(void)
Satya Callojie5ba8842014-07-03 17:18:02 -0700979{
980 /* Scan state-paging, inquiry, and trying to connect */
981
982 /* Check for paging */
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700983 if (btm_cb.is_paging || (!fixed_queue_is_empty(btm_cb.page_queue)) ||
Satya Callojie5ba8842014-07-03 17:18:02 -0700984 BTM_BL_PAGING_STARTED == btm_cb.busy_level)
985 {
986 BTM_TRACE_DEBUG("btm_pm_device_in_scan_state- paging");
Marie Janssend19e0782016-07-15 12:48:27 -0700987 return true;
Satya Callojie5ba8842014-07-03 17:18:02 -0700988 }
989
990 /* Check for inquiry */
991 if ((btm_cb.btm_inq_vars.inq_active & (BTM_BR_INQ_ACTIVE_MASK | BTM_BLE_INQ_ACTIVE_MASK)) != 0)
992 {
993 BTM_TRACE_DEBUG("btm_pm_device_in_scan_state- Inq active");
Marie Janssend19e0782016-07-15 12:48:27 -0700994 return true;
Satya Callojie5ba8842014-07-03 17:18:02 -0700995 }
996
Marie Janssend19e0782016-07-15 12:48:27 -0700997 return false;
Satya Callojie5ba8842014-07-03 17:18:02 -0700998}
999
1000/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001001 *
1002 * Function BTM_PM_ReadControllerState
1003 *
1004 * Description This function is called to obtain the controller state
1005 *
1006 * Returns Controller State-BTM_CONTRL_ACTIVE, BTM_CONTRL_SCAN, and BTM_CONTRL_IDLE
1007 *
1008 ******************************************************************************/
Satya Callojie5ba8842014-07-03 17:18:02 -07001009tBTM_CONTRL_STATE BTM_PM_ReadControllerState(void)
1010{
Marie Janssend19e0782016-07-15 12:48:27 -07001011 if (true == btm_pm_device_in_active_or_sniff_mode())
Satya Callojie5ba8842014-07-03 17:18:02 -07001012 return BTM_CONTRL_ACTIVE;
1013 else
Marie Janssend19e0782016-07-15 12:48:27 -07001014 if (true == btm_pm_device_in_scan_state())
Satya Callojie5ba8842014-07-03 17:18:02 -07001015 return BTM_CONTRL_SCAN;
1016 else
1017 return BTM_CONTRL_IDLE;
1018}
Sharvil Nanavati5cf03362014-11-14 17:04:46 -08001019
1020static const char *mode_to_string(tBTM_PM_MODE mode) {
1021 switch (mode) {
1022 case BTM_PM_MD_ACTIVE: return "ACTIVE";
1023 case BTM_PM_MD_SNIFF: return "SNIFF";
1024 case BTM_PM_MD_PARK: return "PARK";
1025 case BTM_PM_MD_HOLD: return "HOLD";
1026 default: return "UNKNOWN";
1027 }
1028}