/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include
#include
#include
#include "stack/include/btm_status.h"
#include "stack/include/hci_error_code.h"
#include "stack/include/hci_mode.h"
#include "types/raw_address.h"
/* BTM Power manager status codes */
enum : uint8_t {
BTM_PM_STS_ACTIVE = HCI_MODE_ACTIVE, // 0x00
BTM_PM_STS_HOLD = HCI_MODE_HOLD, // 0x01
BTM_PM_STS_SNIFF = HCI_MODE_SNIFF, // 0x02
BTM_PM_STS_PARK = HCI_MODE_PARK, // 0x03
BTM_PM_STS_SSR, /* report the SSR parameters in HCI_SNIFF_SUB_RATE_EVT */
BTM_PM_STS_PENDING, /* when waiting for status from controller */
BTM_PM_STS_ERROR /* when HCI command status returns error */
};
typedef uint8_t tBTM_PM_STATUS;
inline std::string power_mode_status_text(tBTM_PM_STATUS status) {
switch (status) {
case BTM_PM_STS_ACTIVE:
return std::string("active");
case BTM_PM_STS_HOLD:
return std::string("hold");
case BTM_PM_STS_SNIFF:
return std::string("sniff");
case BTM_PM_STS_PARK:
return std::string("park");
case BTM_PM_STS_SSR:
return std::string("sniff_subrating");
case BTM_PM_STS_PENDING:
return std::string("pending");
case BTM_PM_STS_ERROR:
return std::string("error");
default:
return std::string("UNKNOWN");
}
}
/* BTM Power manager modes */
enum : uint8_t {
BTM_PM_MD_ACTIVE = HCI_MODE_ACTIVE, // 0x00
BTM_PM_MD_HOLD = HCI_MODE_HOLD, // 0x01
BTM_PM_MD_SNIFF = HCI_MODE_SNIFF, // 0x02
BTM_PM_MD_PARK = HCI_MODE_PARK, // 0x03
BTM_PM_MD_FORCE = 0x10, /* OR this to force ACL link to a certain mode */
BTM_PM_MD_UNKNOWN = 0xEF,
};
typedef uint8_t tBTM_PM_MODE;
#define HCI_TO_BTM_POWER_MODE(mode) (static_cast(mode))
inline bool is_legal_power_mode(tBTM_PM_MODE mode) {
switch (mode & ~BTM_PM_MD_FORCE) {
case BTM_PM_MD_ACTIVE:
case BTM_PM_MD_HOLD:
case BTM_PM_MD_SNIFF:
case BTM_PM_MD_PARK:
return true;
default:
return false;
}
}
inline std::string power_mode_text(tBTM_PM_MODE mode) {
std::string s = base::StringPrintf((mode & BTM_PM_MD_FORCE) ? "" : "forced:");
switch (mode & ~BTM_PM_MD_FORCE) {
case BTM_PM_MD_ACTIVE:
return s + std::string("active");
case BTM_PM_MD_HOLD:
return s + std::string("hold");
case BTM_PM_MD_SNIFF:
return s + std::string("sniff");
case BTM_PM_MD_PARK:
return s + std::string("park");
default:
return s + std::string("UNKNOWN");
}
}
#define BTM_PM_SET_ONLY_ID 0x80
/* Operation codes */
typedef enum : uint8_t {
/* The module wants to set the desired power mode */
BTM_PM_REG_SET = (1u << 0),
/* The module does not want to involve with PM anymore */
BTM_PM_DEREG = (1u << 2),
} tBTM_PM_REGISTER;
typedef struct {
uint16_t max = 0;
uint16_t min = 0;
uint16_t attempt = 0;
uint16_t timeout = 0;
tBTM_PM_MODE mode = BTM_PM_MD_ACTIVE; // 0
} tBTM_PM_PWR_MD;
typedef void(tBTM_PM_STATUS_CBACK)(const RawAddress& p_bda,
tBTM_PM_STATUS status, uint16_t value,
tHCI_STATUS hci_status);
#define BTM_CONTRL_UNKNOWN 0
/* ACL link on, SCO link ongoing, sniff mode */
#define BTM_CONTRL_ACTIVE 1
/* Scan state - paging/inquiry/trying to connect*/
#define BTM_CONTRL_SCAN 2
/* Idle state - page scan, LE advt, inquiry scan */
#define BTM_CONTRL_IDLE 3
#define BTM_CONTRL_NUM_ACL_CLASSIC_ACTIVE_MASK 0xF
#define BTM_CONTRL_NUM_ACL_CLASSIC_ACTIVE_SHIFT 0
#define BTM_CONTRL_NUM_ACL_CLASSIC_SNIFF_MASK 0xF
#define BTM_CONTRL_NUM_ACL_CLASSIC_SNIFF_SHIFT 4
#define BTM_CONTRL_NUM_ACL_LE_MASK 0xF
#define BTM_CONTRL_NUM_ACL_LE_SHIFT 8
#define BTM_CONTRL_NUM_LE_ADV_MASK 0xF
#define BTM_CONTRL_NUM_LE_ADV_SHIFT 12
#define BTM_CONTRL_LE_SCAN_MODE_IDLE 0
#define BTM_CONTRL_LE_SCAN_MODE_ULTRA_LOW_POWER 1
#define BTM_CONTRL_LE_SCAN_MODE_LOW_POWER 2
#define BTM_CONTRL_LE_SCAN_MODE_BALANCED 3
#define BTM_CONTRL_LE_SCAN_MODE_LOW_LATENCY 4
#define BTM_CONTRL_LE_SCAN_MODE_MASK 0xF
#define BTM_CONTRL_LE_SCAN_MODE_SHIFT 16
#define BTM_CONTRL_INQUIRY_SHIFT 20
#define BTM_CONTRL_INQUIRY (1u << BTM_CONTRL_INQUIRY_SHIFT)
#define BTM_CONTRL_SCO_SHIFT 21
#define BTM_CONTRL_SCO (1u << BTM_CONTRL_SCO_SHIFT)
#define BTM_CONTRL_A2DP_SHIFT 22
#define BTM_CONTRL_A2DP (1u << BTM_CONTRL_A2DP_SHIFT)
#define BTM_CONTRL_LE_AUDIO_SHIFT 23
#define BTM_CONTRL_LE_AUDIO (1u << BTM_CONTRL_LE_AUDIO_SHIFT)
typedef uint32_t tBTM_CONTRL_STATE;
inline void set_num_acl_active_to_ctrl_state(uint32_t num,
tBTM_CONTRL_STATE& ctrl_state) {
if (num > BTM_CONTRL_NUM_ACL_CLASSIC_ACTIVE_MASK) {
num = BTM_CONTRL_NUM_ACL_CLASSIC_ACTIVE_MASK;
}
ctrl_state |= ((num & BTM_CONTRL_NUM_ACL_CLASSIC_ACTIVE_MASK)
<< BTM_CONTRL_NUM_ACL_CLASSIC_ACTIVE_SHIFT);
}
inline void set_num_acl_sniff_to_ctrl_state(uint32_t num,
tBTM_CONTRL_STATE& ctrl_state) {
if (num > BTM_CONTRL_NUM_ACL_CLASSIC_SNIFF_MASK) {
num = BTM_CONTRL_NUM_ACL_CLASSIC_SNIFF_MASK;
}
ctrl_state |= ((num & BTM_CONTRL_NUM_ACL_CLASSIC_SNIFF_MASK)
<< BTM_CONTRL_NUM_ACL_CLASSIC_SNIFF_SHIFT);
}
inline void set_num_acl_le_to_ctrl_state(uint32_t num,
tBTM_CONTRL_STATE& ctrl_state) {
if (num > BTM_CONTRL_NUM_ACL_LE_MASK) {
num = BTM_CONTRL_NUM_ACL_LE_MASK;
}
ctrl_state |=
((num & BTM_CONTRL_NUM_ACL_LE_MASK) << BTM_CONTRL_NUM_ACL_LE_SHIFT);
}
inline void set_num_le_adv_to_ctrl_state(uint32_t num,
tBTM_CONTRL_STATE& ctrl_state) {
if (num > BTM_CONTRL_NUM_LE_ADV_MASK) {
num = BTM_CONTRL_NUM_LE_ADV_MASK;
}
ctrl_state |=
((num & BTM_CONTRL_NUM_LE_ADV_MASK) << BTM_CONTRL_NUM_LE_ADV_SHIFT);
}
inline void set_le_scan_mode_to_ctrl_state(uint32_t duty_cycle,
tBTM_CONTRL_STATE& ctrl_state) {
uint32_t scan_mode;
if (duty_cycle == 0) {
scan_mode = BTM_CONTRL_LE_SCAN_MODE_IDLE;
} else if (duty_cycle <= 5) {
scan_mode = BTM_CONTRL_LE_SCAN_MODE_ULTRA_LOW_POWER;
} else if (duty_cycle <= 10) {
scan_mode = BTM_CONTRL_LE_SCAN_MODE_LOW_POWER;
} else if (duty_cycle <= 25) {
scan_mode = BTM_CONTRL_LE_SCAN_MODE_BALANCED;
} else {
scan_mode = BTM_CONTRL_LE_SCAN_MODE_LOW_LATENCY;
}
ctrl_state |= ((scan_mode & BTM_CONTRL_LE_SCAN_MODE_MASK)
<< BTM_CONTRL_LE_SCAN_MODE_SHIFT);
}
/*******************************************************************************
*
* Function BTM_PmRegister
*
* Description register or deregister with power manager
*
* Returns BTM_SUCCESS if successful,
* BTM_NO_RESOURCES if no room to hold registration
* BTM_ILLEGAL_VALUE
*
******************************************************************************/
tBTM_STATUS BTM_PmRegister(uint8_t mask, uint8_t* p_pm_id,
tBTM_PM_STATUS_CBACK* p_cb);
// Notified by ACL that a new link is connected
void BTM_PM_OnConnected(uint16_t handle, const RawAddress& remote_bda);
// Notified by ACL that a link is disconnected
void BTM_PM_OnDisconnected(uint16_t handle);
/*******************************************************************************
*
* Function BTM_SetPowerMode
*
* Description store the mode in control block or
* alter ACL connection behavior.
*
* Returns BTM_SUCCESS if successful,
* BTM_UNKNOWN_ADDR if bd addr is not active or bad
*
******************************************************************************/
tBTM_STATUS BTM_SetPowerMode(uint8_t pm_id, const RawAddress& remote_bda,
const tBTM_PM_PWR_MD* p_mode);
bool BTM_SetLinkPolicyActiveMode(const RawAddress& remote_bda);
/*******************************************************************************
*
* Function BTM_SetSsrParams
*
* Description This sends the given SSR parameters for the given ACL
* connection if it is in ACTIVE mode.
*
* Input Param remote_bda - device address of desired ACL connection
* max_lat - maximum latency (in 0.625ms)(0-0xFFFE)
* min_rmt_to - minimum remote timeout
* min_loc_to - minimum local timeout
*
*
* Returns BTM_SUCCESS if the HCI command is issued successful,
* BTM_UNKNOWN_ADDR if bd addr is not active or bad
* BTM_CMD_STORED if the command is stored
*
******************************************************************************/
tBTM_STATUS BTM_SetSsrParams(const RawAddress& remote_bda, uint16_t max_lat,
uint16_t min_rmt_to, uint16_t min_loc_to);
/*******************************************************************************
*
* Function BTM_PM_ReadControllerState
*
* Description This function is called to obtain the controller state
*
* Returns Controller state (BTM_CONTRL_ACTIVE, BTM_CONTRL_SCAN, and
* BTM_CONTRL_IDLE)
*
******************************************************************************/
tBTM_CONTRL_STATE BTM_PM_ReadControllerState(void);
/*******************************************************************************
*
* Function BTM_PM_ReadSniffLinkCount
*
* Description Return the number of BT connection in sniff mode
*
* Returns Number of BT connection in sniff mode
*
******************************************************************************/
uint8_t BTM_PM_ReadSniffLinkCount(void);
/*******************************************************************************
*
* Function BTM_PM_ReadBleLinkCount
*
* Description Return the number of BLE connection
*
* Returns Number of BLE connection
*
******************************************************************************/
uint8_t BTM_PM_ReadBleLinkCount(void);
/*******************************************************************************
*
* Function BTM_PM_DeviceInScanState
*
* Description This function is called to check if in inquiry
*
* Returns true, if in inquiry
*
******************************************************************************/
bool BTM_PM_DeviceInScanState(void);
/*******************************************************************************
*
* Function BTM_PM_ReadBleScanDutyCycle
*
* Description Returns BLE scan duty cycle which is (window * 100) /
*interval
*
* Returns BLE scan duty cycle
*
******************************************************************************/
uint32_t BTM_PM_ReadBleScanDutyCycle(void);