Home | History | Annotate | Download | only in btm
      1 /******************************************************************************
      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 
     31 #define LOG_TAG "bt_btm_pm"
     32 
     33 #include <stddef.h>
     34 #include <stdio.h>
     35 #include <stdlib.h>
     36 #include <string.h>
     37 
     38 #include "bt_common.h"
     39 #include "bt_types.h"
     40 #include "bt_utils.h"
     41 #include "btm_api.h"
     42 #include "btm_int.h"
     43 #include "btu.h"
     44 #include "hcidefs.h"
     45 #include "hcimsgs.h"
     46 #include "l2c_int.h"
     47 #include "osi/include/log.h"
     48 #include "osi/include/osi.h"
     49 
     50 /*****************************************************************************/
     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 
     56 /* Usage:  (ptr_features[ offset ] & mask )?true:false */
     57 /* offset to supported feature */
     58 const uint8_t btm_pm_mode_off[BTM_PM_NUM_SET_MODES] = {0, 0, 1};
     59 /* mask to supported feature */
     60 const uint8_t btm_pm_mode_msk[BTM_PM_NUM_SET_MODES] = {0x40, 0x80, 0x01};
     61 
     62 #define BTM_PM_GET_MD1 1
     63 #define BTM_PM_GET_MD2 2
     64 #define BTM_PM_GET_COMP 3
     65 
     66 const uint8_t
     67     btm_pm_md_comp_matrix[BTM_PM_NUM_SET_MODES * BTM_PM_NUM_SET_MODES] = {
     68         BTM_PM_GET_COMP, BTM_PM_GET_MD2,  BTM_PM_GET_MD2,
     69 
     70         BTM_PM_GET_MD1,  BTM_PM_GET_COMP, BTM_PM_GET_MD1,
     71 
     72         BTM_PM_GET_MD1,  BTM_PM_GET_MD2,  BTM_PM_GET_COMP};
     73 
     74 /* function prototype */
     75 static int btm_pm_find_acl_ind(const RawAddress& remote_bda);
     76 static tBTM_STATUS btm_pm_snd_md_req(uint8_t pm_id, int link_ind,
     77                                      tBTM_PM_PWR_MD* p_mode);
     78 static const char* mode_to_string(tBTM_PM_MODE mode);
     79 
     80 #if (BTM_PM_DEBUG == TRUE)
     81 const char* btm_pm_state_str[] = {"pm_active_state", "pm_hold_state",
     82                                   "pm_sniff_state", "pm_park_state",
     83                                   "pm_pend_state"};
     84 
     85 const char* btm_pm_event_str[] = {"pm_set_mode_event", "pm_hci_sts_event",
     86                                   "pm_mod_chg_event", "pm_update_event"};
     87 
     88 const char* btm_pm_action_str[] = {"pm_set_mode_action", "pm_update_db_action",
     89                                    "pm_mod_chg_action", "pm_hci_sts_action",
     90                                    "pm_update_action"};
     91 #endif  // BTM_PM_DEBUG
     92 
     93 /*****************************************************************************/
     94 /*                     P U B L I C  F U N C T I O N S                        */
     95 /*****************************************************************************/
     96 /*******************************************************************************
     97  *
     98  * Function         BTM_PmRegister
     99  *
    100  * Description      register or deregister with power manager
    101  *
    102  * Returns          BTM_SUCCESS if successful,
    103  *                  BTM_NO_RESOURCES if no room to hold registration
    104  *                  BTM_ILLEGAL_VALUE
    105  *
    106  ******************************************************************************/
    107 tBTM_STATUS BTM_PmRegister(uint8_t mask, uint8_t* p_pm_id,
    108                            tBTM_PM_STATUS_CBACK* p_cb) {
    109   int xx;
    110 
    111   /* de-register */
    112   if (mask & BTM_PM_DEREG) {
    113     if (*p_pm_id >= BTM_MAX_PM_RECORDS) return BTM_ILLEGAL_VALUE;
    114     btm_cb.pm_reg_db[*p_pm_id].mask = BTM_PM_REC_NOT_USED;
    115     return BTM_SUCCESS;
    116   }
    117 
    118   for (xx = 0; xx < BTM_MAX_PM_RECORDS; xx++) {
    119     /* find an unused entry */
    120     if (btm_cb.pm_reg_db[xx].mask == BTM_PM_REC_NOT_USED) {
    121       /* if register for notification, should provide callback routine */
    122       if (mask & BTM_PM_REG_NOTIF) {
    123         if (p_cb == NULL) return BTM_ILLEGAL_VALUE;
    124         btm_cb.pm_reg_db[xx].cback = p_cb;
    125       }
    126       btm_cb.pm_reg_db[xx].mask = mask;
    127       *p_pm_id = xx;
    128       return BTM_SUCCESS;
    129     }
    130   }
    131 
    132   return BTM_NO_RESOURCES;
    133 }
    134 
    135 /*******************************************************************************
    136  *
    137  * Function         BTM_SetPowerMode
    138  *
    139  * Description      store the mode in control block or
    140  *                  alter ACL connection behavior.
    141  *
    142  * Returns          BTM_SUCCESS if successful,
    143  *                  BTM_UNKNOWN_ADDR if bd addr is not active or bad
    144  *
    145  ******************************************************************************/
    146 tBTM_STATUS BTM_SetPowerMode(uint8_t pm_id, const RawAddress& remote_bda,
    147                              tBTM_PM_PWR_MD* p_mode) {
    148   uint8_t* p_features;
    149   int ind, acl_ind;
    150   tBTM_PM_MCB* p_cb = NULL; /* per ACL link */
    151   tBTM_PM_MODE mode;
    152   int temp_pm_id;
    153 
    154   if (pm_id >= BTM_MAX_PM_RECORDS) pm_id = BTM_PM_SET_ONLY_ID;
    155 
    156   if (p_mode == NULL) return BTM_ILLEGAL_VALUE;
    157 
    158   VLOG(2) << __func__ << " pm_id " << pm_id << " BDA: " << remote_bda
    159           << " mode:0x" << std::hex << p_mode->mode;
    160 
    161   /* take out the force bit */
    162   mode = p_mode->mode & ~BTM_PM_MD_FORCE;
    163 
    164   acl_ind = btm_pm_find_acl_ind(remote_bda);
    165   if (acl_ind == MAX_L2CAP_LINKS) return (BTM_UNKNOWN_ADDR);
    166 
    167   p_cb = &(btm_cb.pm_mode_db[acl_ind]);
    168 
    169   if (mode != BTM_PM_MD_ACTIVE) {
    170     /* check if the requested mode is supported */
    171     ind = mode - BTM_PM_MD_HOLD; /* make it base 0 */
    172     p_features = BTM_ReadLocalFeatures();
    173     if (!(p_features[btm_pm_mode_off[ind]] & btm_pm_mode_msk[ind]))
    174       return BTM_MODE_UNSUPPORTED;
    175   }
    176 
    177   if (mode == p_cb->state) /* the requested mode is current mode */
    178   {
    179     /* already in the requested mode and the current interval has less latency
    180      * than the max */
    181     if ((mode == BTM_PM_MD_ACTIVE) ||
    182         ((p_mode->mode & BTM_PM_MD_FORCE) && (p_mode->max >= p_cb->interval) &&
    183          (p_mode->min <= p_cb->interval)) ||
    184         ((p_mode->mode & BTM_PM_MD_FORCE) == 0 &&
    185          (p_mode->max >= p_cb->interval))) {
    186       BTM_TRACE_DEBUG("BTM_SetPowerMode: mode:0x%x interval %d max:%d, min:%d",
    187                       p_mode->mode, p_cb->interval, p_mode->max, p_mode->min);
    188       return BTM_SUCCESS;
    189     }
    190   }
    191 
    192   temp_pm_id = pm_id;
    193   if (pm_id == BTM_PM_SET_ONLY_ID) temp_pm_id = BTM_MAX_PM_RECORDS;
    194 
    195   /* update mode database */
    196   if (((pm_id != BTM_PM_SET_ONLY_ID) &&
    197        (btm_cb.pm_reg_db[pm_id].mask & BTM_PM_REG_SET)) ||
    198       ((pm_id == BTM_PM_SET_ONLY_ID) &&
    199        (btm_cb.pm_pend_link != MAX_L2CAP_LINKS))) {
    200 #if (BTM_PM_DEBUG == TRUE)
    201     BTM_TRACE_DEBUG("BTM_SetPowerMode: Saving cmd acl_ind %d temp_pm_id %d",
    202                     acl_ind, temp_pm_id);
    203 #endif  // BTM_PM_DEBUG
    204     /* Make sure mask is set to BTM_PM_REG_SET */
    205     btm_cb.pm_reg_db[temp_pm_id].mask |= BTM_PM_REG_SET;
    206     *(&p_cb->req_mode[temp_pm_id]) = *((tBTM_PM_PWR_MD*)p_mode);
    207     p_cb->chg_ind = true;
    208   }
    209 
    210 #if (BTM_PM_DEBUG == TRUE)
    211   BTM_TRACE_DEBUG("btm_pm state:0x%x, pm_pend_link: %d", p_cb->state,
    212                   btm_cb.pm_pend_link);
    213 #endif  // BTM_PM_DEBUG
    214   /* if mode == hold or pending, return */
    215   if ((p_cb->state == BTM_PM_STS_HOLD) || (p_cb->state == BTM_PM_STS_PENDING) ||
    216       (btm_cb.pm_pend_link != MAX_L2CAP_LINKS)) /* command pending */
    217   {
    218     if (acl_ind != btm_cb.pm_pend_link) {
    219       /* set the stored mask */
    220       p_cb->state |= BTM_PM_STORED_MASK;
    221       BTM_TRACE_DEBUG("btm_pm state stored:%d", acl_ind);
    222     }
    223     return BTM_CMD_STORED;
    224   }
    225 
    226   return btm_pm_snd_md_req(pm_id, acl_ind, p_mode);
    227 }
    228 
    229 /*******************************************************************************
    230  *
    231  * Function         BTM_ReadPowerMode
    232  *
    233  * Description      This returns the current mode for a specific
    234  *                  ACL connection.
    235  *
    236  * Input Param      remote_bda - device address of desired ACL connection
    237  *
    238  * Output Param     p_mode - address where the current mode is copied into.
    239  *                          BTM_ACL_MODE_NORMAL
    240  *                          BTM_ACL_MODE_HOLD
    241  *                          BTM_ACL_MODE_SNIFF
    242  *                          BTM_ACL_MODE_PARK
    243  *                          (valid only if return code is BTM_SUCCESS)
    244  *
    245  * Returns          BTM_SUCCESS if successful,
    246  *                  BTM_UNKNOWN_ADDR if bd addr is not active or bad
    247  *
    248  ******************************************************************************/
    249 tBTM_STATUS BTM_ReadPowerMode(const RawAddress& remote_bda,
    250                               tBTM_PM_MODE* p_mode) {
    251   int acl_ind;
    252 
    253   acl_ind = btm_pm_find_acl_ind(remote_bda);
    254   if (acl_ind == MAX_L2CAP_LINKS) return (BTM_UNKNOWN_ADDR);
    255 
    256   *p_mode = btm_cb.pm_mode_db[acl_ind].state;
    257   return BTM_SUCCESS;
    258 }
    259 
    260 /*******************************************************************************
    261  *
    262  * Function         btm_read_power_mode_state
    263  *
    264  * Description      This returns the current pm state for a specific
    265  *                  ACL connection.
    266  *
    267  * Input Param      remote_bda - device address of desired ACL connection
    268  *
    269  * Output Param     pmState - address where the current pm state is copied.
    270  *                          BTM_PM_ST_ACTIVE
    271  *                          BTM_PM_ST_HOLD
    272  *                          BTM_PM_ST_SNIFF
    273  *                          BTM_PM_ST_PARK
    274  *                          BTM_PM_ST_PENDING
    275  *                          (valid only if return code is BTM_SUCCESS)
    276  *
    277  * Returns          BTM_SUCCESS if successful,
    278  *                  BTM_UNKNOWN_ADDR if bd addr is not active or bad
    279  *
    280  ******************************************************************************/
    281 tBTM_STATUS btm_read_power_mode_state(const RawAddress& remote_bda,
    282                                       tBTM_PM_STATE* pmState) {
    283   int acl_ind = btm_pm_find_acl_ind(remote_bda);
    284 
    285   if (acl_ind == MAX_L2CAP_LINKS) return (BTM_UNKNOWN_ADDR);
    286 
    287   *pmState = btm_cb.pm_mode_db[acl_ind].state;
    288   return BTM_SUCCESS;
    289 }
    290 
    291 /*******************************************************************************
    292  *
    293  * Function         BTM_SetSsrParams
    294  *
    295  * Description      This sends the given SSR parameters for the given ACL
    296  *                  connection if it is in ACTIVE mode.
    297  *
    298  * Input Param      remote_bda - device address of desired ACL connection
    299  *                  max_lat    - maximum latency (in 0.625ms)(0-0xFFFE)
    300  *                  min_rmt_to - minimum remote timeout
    301  *                  min_loc_to - minimum local timeout
    302  *
    303  *
    304  * Returns          BTM_SUCCESS if the HCI command is issued successful,
    305  *                  BTM_UNKNOWN_ADDR if bd addr is not active or bad
    306  *                  BTM_CMD_STORED if the command is stored
    307  *
    308  ******************************************************************************/
    309 tBTM_STATUS BTM_SetSsrParams(const RawAddress& remote_bda, uint16_t max_lat,
    310                              uint16_t min_rmt_to, uint16_t min_loc_to) {
    311 #if (BTM_SSR_INCLUDED == TRUE)
    312   int acl_ind;
    313   tBTM_PM_MCB* p_cb;
    314 
    315   acl_ind = btm_pm_find_acl_ind(remote_bda);
    316   if (acl_ind == MAX_L2CAP_LINKS) return (BTM_UNKNOWN_ADDR);
    317 
    318   if (BTM_PM_STS_ACTIVE == btm_cb.pm_mode_db[acl_ind].state ||
    319       BTM_PM_STS_SNIFF == btm_cb.pm_mode_db[acl_ind].state) {
    320     btsnd_hcic_sniff_sub_rate(btm_cb.acl_db[acl_ind].hci_handle, max_lat,
    321                               min_rmt_to, min_loc_to);
    322     return BTM_SUCCESS;
    323   }
    324   p_cb = &btm_cb.pm_mode_db[acl_ind];
    325   p_cb->max_lat = max_lat;
    326   p_cb->min_rmt_to = min_rmt_to;
    327   p_cb->min_loc_to = min_loc_to;
    328   return BTM_CMD_STORED;
    329 #else
    330   return BTM_ILLEGAL_ACTION;
    331 #endif  // BTM_SSR_INCLUDED
    332 }
    333 
    334 /*******************************************************************************
    335  *
    336  * Function         btm_pm_reset
    337  *
    338  * Description      as a part of the BTM reset process.
    339  *
    340  * Returns          void
    341  *
    342  ******************************************************************************/
    343 void btm_pm_reset(void) {
    344   int xx;
    345   tBTM_PM_STATUS_CBACK* cb = NULL;
    346 
    347   /* clear the pending request for application */
    348   if ((btm_cb.pm_pend_id != BTM_PM_SET_ONLY_ID) &&
    349       (btm_cb.pm_reg_db[btm_cb.pm_pend_id].mask & BTM_PM_REG_NOTIF)) {
    350     cb = btm_cb.pm_reg_db[btm_cb.pm_pend_id].cback;
    351   }
    352 
    353   /* clear the register record */
    354   for (xx = 0; xx < BTM_MAX_PM_RECORDS; xx++) {
    355     btm_cb.pm_reg_db[xx].mask = BTM_PM_REC_NOT_USED;
    356   }
    357 
    358   if (cb != NULL && btm_cb.pm_pend_link < MAX_L2CAP_LINKS)
    359     (*cb)(btm_cb.acl_db[btm_cb.pm_pend_link].remote_addr, BTM_PM_STS_ERROR,
    360           BTM_DEV_RESET, 0);
    361 
    362   /* no command pending */
    363   btm_cb.pm_pend_link = MAX_L2CAP_LINKS;
    364 }
    365 
    366 /*******************************************************************************
    367  *
    368  * Function         btm_pm_sm_alloc
    369  *
    370  * Description      This function initializes the control block of an ACL link.
    371  *                  It is called when an ACL connection is created.
    372  *
    373  * Returns          void
    374  *
    375  ******************************************************************************/
    376 void btm_pm_sm_alloc(uint8_t ind) {
    377   tBTM_PM_MCB* p_db = &btm_cb.pm_mode_db[ind]; /* per ACL link */
    378   memset(p_db, 0, sizeof(tBTM_PM_MCB));
    379   p_db->state = BTM_PM_ST_ACTIVE;
    380 #if (BTM_PM_DEBUG == TRUE)
    381   BTM_TRACE_DEBUG("btm_pm_sm_alloc ind:%d st:%d", ind, p_db->state);
    382 #endif  // BTM_PM_DEBUG
    383 }
    384 
    385 /*******************************************************************************
    386  *
    387  * Function         btm_pm_find_acl_ind
    388  *
    389  * Description      This function initializes the control block of an ACL link.
    390  *                  It is called when an ACL connection is created.
    391  *
    392  * Returns          void
    393  *
    394  ******************************************************************************/
    395 static int btm_pm_find_acl_ind(const RawAddress& remote_bda) {
    396   tACL_CONN* p = &btm_cb.acl_db[0];
    397   uint8_t xx;
    398 
    399   for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p++) {
    400     if (p->in_use && p->remote_addr == remote_bda &&
    401         p->transport == BT_TRANSPORT_BR_EDR) {
    402 #if (BTM_PM_DEBUG == TRUE)
    403       BTM_TRACE_DEBUG("btm_pm_find_acl_ind ind:%d, st:%d", xx,
    404                       btm_cb.pm_mode_db[xx].state);
    405 #endif  // BTM_PM_DEBUG
    406       break;
    407     }
    408   }
    409   return xx;
    410 }
    411 
    412 /*******************************************************************************
    413  *
    414  * Function     btm_pm_compare_modes
    415  * Description  get the "more active" mode of the 2
    416  * Returns      void
    417  *
    418  ******************************************************************************/
    419 static tBTM_PM_PWR_MD* btm_pm_compare_modes(tBTM_PM_PWR_MD* p_md1,
    420                                             tBTM_PM_PWR_MD* p_md2,
    421                                             tBTM_PM_PWR_MD* p_res) {
    422   uint8_t res;
    423 
    424   if (p_md1 == NULL) {
    425     *p_res = *p_md2;
    426     p_res->mode &= ~BTM_PM_MD_FORCE;
    427 
    428     return p_md2;
    429   }
    430 
    431   if (p_md2->mode == BTM_PM_MD_ACTIVE || p_md1->mode == BTM_PM_MD_ACTIVE) {
    432     return NULL;
    433   }
    434 
    435   /* check if force bit is involved */
    436   if (p_md1->mode & BTM_PM_MD_FORCE) {
    437     *p_res = *p_md1;
    438     p_res->mode &= ~BTM_PM_MD_FORCE;
    439     return p_res;
    440   }
    441 
    442   if (p_md2->mode & BTM_PM_MD_FORCE) {
    443     *p_res = *p_md2;
    444     p_res->mode &= ~BTM_PM_MD_FORCE;
    445     return p_res;
    446   }
    447 
    448   res = (p_md1->mode - 1) * BTM_PM_NUM_SET_MODES + (p_md2->mode - 1);
    449   res = btm_pm_md_comp_matrix[res];
    450   switch (res) {
    451     case BTM_PM_GET_MD1:
    452       *p_res = *p_md1;
    453       return p_md1;
    454 
    455     case BTM_PM_GET_MD2:
    456       *p_res = *p_md2;
    457       return p_md2;
    458 
    459     case BTM_PM_GET_COMP:
    460       p_res->mode = p_md1->mode;
    461       /* min of the two */
    462       p_res->max = (p_md1->max < p_md2->max) ? (p_md1->max) : (p_md2->max);
    463       /* max of the two */
    464       p_res->min = (p_md1->min > p_md2->min) ? (p_md1->min) : (p_md2->min);
    465 
    466       /* the intersection is NULL */
    467       if (p_res->max < p_res->min) return NULL;
    468 
    469       if (p_res->mode == BTM_PM_MD_SNIFF) {
    470         /* max of the two */
    471         p_res->attempt = (p_md1->attempt > p_md2->attempt) ? (p_md1->attempt)
    472                                                            : (p_md2->attempt);
    473         p_res->timeout = (p_md1->timeout > p_md2->timeout) ? (p_md1->timeout)
    474                                                            : (p_md2->timeout);
    475       }
    476       return p_res;
    477   }
    478   return NULL;
    479 }
    480 
    481 /*******************************************************************************
    482  *
    483  * Function     btm_pm_get_set_mode
    484  * Description  get the resulting mode from the registered parties, then compare
    485  *              it with the requested mode, if the command is from an
    486  *              unregistered party.
    487  *
    488  * Returns      void
    489  *
    490  ******************************************************************************/
    491 static tBTM_PM_MODE btm_pm_get_set_mode(uint8_t pm_id, tBTM_PM_MCB* p_cb,
    492                                         tBTM_PM_PWR_MD* p_mode,
    493                                         tBTM_PM_PWR_MD* p_res) {
    494   int xx, loop_max;
    495   tBTM_PM_PWR_MD* p_md = NULL;
    496 
    497   if (p_mode != NULL && p_mode->mode & BTM_PM_MD_FORCE) {
    498     *p_res = *p_mode;
    499     p_res->mode &= ~BTM_PM_MD_FORCE;
    500     return p_res->mode;
    501   }
    502 
    503   if (!p_mode)
    504     loop_max = BTM_MAX_PM_RECORDS + 1;
    505   else
    506     loop_max = BTM_MAX_PM_RECORDS;
    507 
    508   for (xx = 0; xx < loop_max; xx++) {
    509     /* g through all the registered "set" parties */
    510     if (btm_cb.pm_reg_db[xx].mask & BTM_PM_REG_SET) {
    511       if (p_cb->req_mode[xx].mode == BTM_PM_MD_ACTIVE) {
    512         /* if at least one registered (SET) party says ACTIVE, stay active */
    513         return BTM_PM_MD_ACTIVE;
    514       } else {
    515         /* if registered parties give conflicting information, stay active */
    516         if ((btm_pm_compare_modes(p_md, &p_cb->req_mode[xx], p_res)) == NULL)
    517           return BTM_PM_MD_ACTIVE;
    518         p_md = p_res;
    519       }
    520     }
    521   }
    522 
    523   /* if the resulting mode is NULL(nobody registers SET), use the requested mode
    524    */
    525   if (p_md == NULL) {
    526     if (p_mode)
    527       *p_res = *((tBTM_PM_PWR_MD*)p_mode);
    528     else /* p_mode is NULL when btm_pm_snd_md_req is called from
    529             btm_pm_proc_mode_change */
    530       return BTM_PM_MD_ACTIVE;
    531   } else {
    532     /* if the command is from unregistered party,
    533        compare the resulting mode from registered party*/
    534     if ((pm_id == BTM_PM_SET_ONLY_ID) &&
    535         ((btm_pm_compare_modes(p_mode, p_md, p_res)) == NULL))
    536       return BTM_PM_MD_ACTIVE;
    537   }
    538 
    539   return p_res->mode;
    540 }
    541 
    542 /*******************************************************************************
    543  *
    544  * Function     btm_pm_snd_md_req
    545  * Description  get the resulting mode and send the resuest to host controller
    546  * Returns      tBTM_STATUS
    547  *, bool    *p_chg_ind
    548  ******************************************************************************/
    549 static tBTM_STATUS btm_pm_snd_md_req(uint8_t pm_id, int link_ind,
    550                                      tBTM_PM_PWR_MD* p_mode) {
    551   tBTM_PM_PWR_MD md_res;
    552   tBTM_PM_MODE mode;
    553   tBTM_PM_MCB* p_cb = &btm_cb.pm_mode_db[link_ind];
    554   bool chg_ind = false;
    555 
    556   mode = btm_pm_get_set_mode(pm_id, p_cb, p_mode, &md_res);
    557   md_res.mode = mode;
    558 
    559 #if (BTM_PM_DEBUG == TRUE)
    560   BTM_TRACE_DEBUG("btm_pm_snd_md_req link_ind:%d, mode: %d", link_ind, mode);
    561 #endif  // BTM_PM_DEBUG
    562 
    563   if (p_cb->state == mode) {
    564     /* already in the resulting mode */
    565     if ((mode == BTM_PM_MD_ACTIVE) ||
    566         ((md_res.max >= p_cb->interval) && (md_res.min <= p_cb->interval)))
    567       return BTM_CMD_STORED;
    568     /* Otherwise, needs to wake, then sleep */
    569     chg_ind = true;
    570   }
    571   p_cb->chg_ind = chg_ind;
    572 
    573   /* cannot go directly from current mode to resulting mode. */
    574   if (mode != BTM_PM_MD_ACTIVE && p_cb->state != BTM_PM_MD_ACTIVE)
    575     p_cb->chg_ind = true; /* needs to wake, then sleep */
    576 
    577   if (p_cb->chg_ind == true) /* needs to wake first */
    578     md_res.mode = BTM_PM_MD_ACTIVE;
    579 #if (BTM_SSR_INCLUDED == TRUE)
    580   else if (BTM_PM_MD_SNIFF == md_res.mode && p_cb->max_lat) {
    581     btsnd_hcic_sniff_sub_rate(btm_cb.acl_db[link_ind].hci_handle, p_cb->max_lat,
    582                               p_cb->min_rmt_to, p_cb->min_loc_to);
    583     p_cb->max_lat = 0;
    584   }
    585 #endif  // BTM_SSR_INCLUDED
    586   /* Default is failure */
    587   btm_cb.pm_pend_link = MAX_L2CAP_LINKS;
    588 
    589   /* send the appropriate HCI command */
    590   btm_cb.pm_pend_id = pm_id;
    591 
    592 #if (BTM_PM_DEBUG == TRUE)
    593   BTM_TRACE_DEBUG("btm_pm_snd_md_req state:0x%x, link_ind: %d", p_cb->state,
    594                   link_ind);
    595 #endif  // BTM_PM_DEBUG
    596 
    597   BTM_TRACE_DEBUG("%s switching from %s to %s.", __func__,
    598                   mode_to_string(p_cb->state), mode_to_string(md_res.mode));
    599   switch (md_res.mode) {
    600     case BTM_PM_MD_ACTIVE:
    601       switch (p_cb->state) {
    602         case BTM_PM_MD_SNIFF:
    603           btsnd_hcic_exit_sniff_mode(btm_cb.acl_db[link_ind].hci_handle);
    604           btm_cb.pm_pend_link = link_ind;
    605           break;
    606         case BTM_PM_MD_PARK:
    607           btsnd_hcic_exit_park_mode(btm_cb.acl_db[link_ind].hci_handle);
    608           btm_cb.pm_pend_link = link_ind;
    609           break;
    610         default:
    611           /* Failure btm_cb.pm_pend_link = MAX_L2CAP_LINKS */
    612           break;
    613       }
    614       break;
    615 
    616     case BTM_PM_MD_HOLD:
    617       btsnd_hcic_hold_mode(btm_cb.acl_db[link_ind].hci_handle, md_res.max,
    618                            md_res.min);
    619       btm_cb.pm_pend_link = link_ind;
    620       break;
    621 
    622     case BTM_PM_MD_SNIFF:
    623       btsnd_hcic_sniff_mode(btm_cb.acl_db[link_ind].hci_handle, md_res.max,
    624                             md_res.min, md_res.attempt, md_res.timeout);
    625       btm_cb.pm_pend_link = link_ind;
    626       break;
    627 
    628     case BTM_PM_MD_PARK:
    629       btsnd_hcic_park_mode(btm_cb.acl_db[link_ind].hci_handle, md_res.max,
    630                            md_res.min);
    631       btm_cb.pm_pend_link = link_ind;
    632       break;
    633     default:
    634       /* Failure btm_cb.pm_pend_link = MAX_L2CAP_LINKS */
    635       break;
    636   }
    637 
    638   if (btm_cb.pm_pend_link == MAX_L2CAP_LINKS) {
    639 /* the command was not sent */
    640 #if (BTM_PM_DEBUG == TRUE)
    641     BTM_TRACE_DEBUG("pm_pend_link: %d", btm_cb.pm_pend_link);
    642 #endif  // BTM_PM_DEBUG
    643     return (BTM_NO_RESOURCES);
    644   }
    645 
    646   return BTM_CMD_STARTED;
    647 }
    648 
    649 /*******************************************************************************
    650  *
    651  * Function         btm_pm_check_stored
    652  *
    653  * Description      This function is called when an HCI command status event
    654  *                  occurs to check if there's any PM command issued while
    655  *                  waiting for HCI command status.
    656  *
    657  * Returns          none.
    658  *
    659  ******************************************************************************/
    660 static void btm_pm_check_stored(void) {
    661   int xx;
    662   for (xx = 0; xx < MAX_L2CAP_LINKS; xx++) {
    663     if (btm_cb.pm_mode_db[xx].state & BTM_PM_STORED_MASK) {
    664       btm_cb.pm_mode_db[xx].state &= ~BTM_PM_STORED_MASK;
    665       BTM_TRACE_DEBUG("btm_pm_check_stored :%d", xx);
    666       btm_pm_snd_md_req(BTM_PM_SET_ONLY_ID, xx, NULL);
    667       break;
    668     }
    669   }
    670 }
    671 
    672 /*******************************************************************************
    673  *
    674  * Function         btm_pm_proc_cmd_status
    675  *
    676  * Description      This function is called when an HCI command status event
    677  *                  occurs for power manager related commands.
    678  *
    679  * Input Parms      status - status of the event (HCI_SUCCESS if no errors)
    680  *
    681  * Returns          none.
    682  *
    683  ******************************************************************************/
    684 void btm_pm_proc_cmd_status(uint8_t status) {
    685   tBTM_PM_MCB* p_cb;
    686   tBTM_PM_STATUS pm_status;
    687 
    688   if (btm_cb.pm_pend_link >= MAX_L2CAP_LINKS) return;
    689 
    690   p_cb = &btm_cb.pm_mode_db[btm_cb.pm_pend_link];
    691 
    692   if (status == HCI_SUCCESS) {
    693     p_cb->state = BTM_PM_ST_PENDING;
    694     pm_status = BTM_PM_STS_PENDING;
    695 #if (BTM_PM_DEBUG == TRUE)
    696     BTM_TRACE_DEBUG("btm_pm_proc_cmd_status new state:0x%x", p_cb->state);
    697 #endif   // BTM_PM_DEBUG
    698   } else /* the command was not successfull. Stay in the same state */
    699   {
    700     pm_status = BTM_PM_STS_ERROR;
    701   }
    702 
    703   /* notify the caller is appropriate */
    704   if ((btm_cb.pm_pend_id != BTM_PM_SET_ONLY_ID) &&
    705       (btm_cb.pm_reg_db[btm_cb.pm_pend_id].mask & BTM_PM_REG_NOTIF)) {
    706     (*btm_cb.pm_reg_db[btm_cb.pm_pend_id].cback)(
    707         btm_cb.acl_db[btm_cb.pm_pend_link].remote_addr, pm_status, 0, status);
    708   }
    709 
    710 /* no pending cmd now */
    711 #if (BTM_PM_DEBUG == TRUE)
    712   BTM_TRACE_DEBUG(
    713       "btm_pm_proc_cmd_status state:0x%x, pm_pend_link: %d(new: %d)",
    714       p_cb->state, btm_cb.pm_pend_link, MAX_L2CAP_LINKS);
    715 #endif  // BTM_PM_DEBUG
    716   btm_cb.pm_pend_link = MAX_L2CAP_LINKS;
    717 
    718   btm_pm_check_stored();
    719 }
    720 
    721 /*******************************************************************************
    722  *
    723  * Function         btm_process_mode_change
    724  *
    725  * Description      This function is called when an HCI mode change event
    726  *                  occurs.
    727  *
    728  * Input Parms      hci_status - status of the event (HCI_SUCCESS if no errors)
    729  *                  hci_handle - connection handle associated with the change
    730  *                  mode - HCI_MODE_ACTIVE, HCI_MODE_HOLD, HCI_MODE_SNIFF, or
    731  *                         HCI_MODE_PARK
    732  *                  interval - number of baseband slots (meaning depends on
    733  *                                                       mode)
    734  *
    735  * Returns          none.
    736  *
    737  ******************************************************************************/
    738 void btm_pm_proc_mode_change(uint8_t hci_status, uint16_t hci_handle,
    739                              uint8_t mode, uint16_t interval) {
    740   tACL_CONN* p;
    741   tBTM_PM_MCB* p_cb = NULL;
    742   int xx, yy, zz;
    743   tBTM_PM_STATE old_state;
    744   tL2C_LCB* p_lcb;
    745 
    746   /* get the index to acl_db */
    747   xx = btm_handle_to_acl_index(hci_handle);
    748   if (xx >= MAX_L2CAP_LINKS) return;
    749 
    750   p = &btm_cb.acl_db[xx];
    751 
    752   /* update control block */
    753   p_cb = &(btm_cb.pm_mode_db[xx]);
    754   old_state = p_cb->state;
    755   p_cb->state = mode;
    756   p_cb->interval = interval;
    757 
    758   BTM_TRACE_DEBUG("%s switched from %s to %s.", __func__,
    759                   mode_to_string(old_state), mode_to_string(p_cb->state));
    760 
    761   p_lcb = l2cu_find_lcb_by_bd_addr(p->remote_addr, BT_TRANSPORT_BR_EDR);
    762   if (p_lcb != NULL) {
    763     if ((p_cb->state == BTM_PM_ST_ACTIVE) || (p_cb->state == BTM_PM_ST_SNIFF)) {
    764       /* There might be any pending packets due to SNIFF or PENDING state */
    765       /* Trigger L2C to start transmission of the pending packets. */
    766       BTM_TRACE_DEBUG(
    767           "btm mode change to active; check l2c_link for outgoing packets");
    768       l2c_link_check_send_pkts(p_lcb, NULL, NULL);
    769     }
    770   }
    771 
    772   /* notify registered parties */
    773   for (yy = 0; yy <= BTM_MAX_PM_RECORDS; yy++) {
    774     /* set req_mode  HOLD mode->ACTIVE */
    775     if ((mode == BTM_PM_MD_ACTIVE) &&
    776         (p_cb->req_mode[yy].mode == BTM_PM_MD_HOLD))
    777       p_cb->req_mode[yy].mode = BTM_PM_MD_ACTIVE;
    778   }
    779 
    780   /* new request has been made. - post a message to BTU task */
    781   if (old_state & BTM_PM_STORED_MASK) {
    782 #if (BTM_PM_DEBUG == TRUE)
    783     BTM_TRACE_DEBUG("btm_pm_proc_mode_change: Sending stored req:%d", xx);
    784 #endif  // BTM_PM_DEBUG
    785     btm_pm_snd_md_req(BTM_PM_SET_ONLY_ID, xx, NULL);
    786   } else {
    787     for (zz = 0; zz < MAX_L2CAP_LINKS; zz++) {
    788       if (btm_cb.pm_mode_db[zz].chg_ind == true) {
    789 #if (BTM_PM_DEBUG == TRUE)
    790         BTM_TRACE_DEBUG("btm_pm_proc_mode_change: Sending PM req :%d", zz);
    791 #endif  // BTM_PM_DEBUG
    792         btm_pm_snd_md_req(BTM_PM_SET_ONLY_ID, zz, NULL);
    793         break;
    794       }
    795     }
    796   }
    797 
    798   /* notify registered parties */
    799   for (yy = 0; yy < BTM_MAX_PM_RECORDS; yy++) {
    800     if (btm_cb.pm_reg_db[yy].mask & BTM_PM_REG_NOTIF) {
    801       (*btm_cb.pm_reg_db[yy].cback)(p->remote_addr, mode, interval, hci_status);
    802     }
    803   }
    804 #if (BTM_SCO_INCLUDED == TRUE)
    805   /*check if sco disconnect  is waiting for the mode change */
    806   btm_sco_disc_chk_pend_for_modechange(hci_handle);
    807 #endif
    808 
    809   /* If mode change was because of an active role switch or change link key */
    810   btm_cont_rswitch(p, btm_find_dev(p->remote_addr), hci_status);
    811 }
    812 
    813 /*******************************************************************************
    814  *
    815  * Function         btm_pm_proc_ssr_evt
    816  *
    817  * Description      This function is called when an HCI sniff subrating event
    818  *                  occurs.
    819  *
    820  * Returns          none.
    821  *
    822  ******************************************************************************/
    823 #if (BTM_SSR_INCLUDED == TRUE)
    824 void btm_pm_proc_ssr_evt(uint8_t* p, UNUSED_ATTR uint16_t evt_len) {
    825   uint8_t status;
    826   uint16_t handle;
    827   uint16_t max_rx_lat;
    828   int xx, yy;
    829   tBTM_PM_MCB* p_cb;
    830   tACL_CONN* p_acl = NULL;
    831   uint16_t use_ssr = true;
    832 
    833   STREAM_TO_UINT8(status, p);
    834 
    835   STREAM_TO_UINT16(handle, p);
    836   /* get the index to acl_db */
    837   xx = btm_handle_to_acl_index(handle);
    838   if (xx >= MAX_L2CAP_LINKS) return;
    839 
    840   p += 2;
    841   STREAM_TO_UINT16(max_rx_lat, p);
    842   p_cb = &(btm_cb.pm_mode_db[xx]);
    843 
    844   p_acl = &btm_cb.acl_db[xx];
    845   if (p_cb->interval == max_rx_lat) {
    846     /* using legacy sniff */
    847     use_ssr = false;
    848   }
    849 
    850   /* notify registered parties */
    851   for (yy = 0; yy < BTM_MAX_PM_RECORDS; yy++) {
    852     if (btm_cb.pm_reg_db[yy].mask & BTM_PM_REG_NOTIF) {
    853       if (p_acl) {
    854         (*btm_cb.pm_reg_db[yy].cback)(p_acl->remote_addr, BTM_PM_STS_SSR,
    855                                       use_ssr, status);
    856       }
    857     }
    858   }
    859 }
    860 #endif  // BTM_SSR_INCLUDED
    861 
    862 /*******************************************************************************
    863  *
    864  * Function         btm_pm_device_in_active_or_sniff_mode
    865  *
    866  * Description      This function is called to check if in active or sniff mode
    867  *
    868  * Returns          true, if in active or sniff mode
    869  *
    870  ******************************************************************************/
    871 bool btm_pm_device_in_active_or_sniff_mode(void) {
    872   /* The active state is the highest state-includes connected device and sniff
    873    * mode*/
    874 
    875   /* Covers active and sniff modes */
    876   if (BTM_GetNumAclLinks() > 0) {
    877     BTM_TRACE_DEBUG("%s - ACL links: %d", __func__, BTM_GetNumAclLinks());
    878     return true;
    879   }
    880 
    881   /* Check BLE states */
    882   if (btm_ble_get_conn_st() != BLE_CONN_IDLE) {
    883     BTM_TRACE_DEBUG("%s - BLE state: %x", __func__, btm_ble_get_conn_st());
    884     return true;
    885   }
    886 
    887   return false;
    888 }
    889 
    890 /*******************************************************************************
    891  *
    892  * Function         btm_pm_device_in_scan_state
    893  *
    894  * Description      This function is called to check if in paging, inquiry or
    895  *                  connecting mode
    896  *
    897  * Returns          true, if in paging, inquiry or connecting mode
    898  *
    899  ******************************************************************************/
    900 bool btm_pm_device_in_scan_state(void) {
    901   /* Scan state-paging, inquiry, and trying to connect */
    902 
    903   /* Check for paging */
    904   if (btm_cb.is_paging || (!fixed_queue_is_empty(btm_cb.page_queue)) ||
    905       BTM_BL_PAGING_STARTED == btm_cb.busy_level) {
    906     BTM_TRACE_DEBUG("btm_pm_device_in_scan_state- paging");
    907     return true;
    908   }
    909 
    910   /* Check for inquiry */
    911   if ((btm_cb.btm_inq_vars.inq_active &
    912        (BTM_BR_INQ_ACTIVE_MASK | BTM_BLE_INQ_ACTIVE_MASK)) != 0) {
    913     BTM_TRACE_DEBUG("btm_pm_device_in_scan_state- Inq active");
    914     return true;
    915   }
    916 
    917   return false;
    918 }
    919 
    920 /*******************************************************************************
    921  *
    922  * Function         BTM_PM_ReadControllerState
    923  *
    924  * Description      This function is called to obtain the controller state
    925  *
    926  * Returns          Controller State-BTM_CONTRL_ACTIVE, BTM_CONTRL_SCAN, and
    927  *                  BTM_CONTRL_IDLE
    928  *
    929  ******************************************************************************/
    930 tBTM_CONTRL_STATE BTM_PM_ReadControllerState(void) {
    931   if (true == btm_pm_device_in_active_or_sniff_mode())
    932     return BTM_CONTRL_ACTIVE;
    933   else if (true == btm_pm_device_in_scan_state())
    934     return BTM_CONTRL_SCAN;
    935   else
    936     return BTM_CONTRL_IDLE;
    937 }
    938 
    939 static const char* mode_to_string(tBTM_PM_MODE mode) {
    940   switch (mode) {
    941     case BTM_PM_MD_ACTIVE:
    942       return "ACTIVE";
    943     case BTM_PM_MD_SNIFF:
    944       return "SNIFF";
    945     case BTM_PM_MD_PARK:
    946       return "PARK";
    947     case BTM_PM_MD_HOLD:
    948       return "HOLD";
    949     default:
    950       return "UNKNOWN";
    951   }
    952 }
    953