1 /*
2 * Copyright 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #pragma once
18
19 #include <cstdint>
20 #include <string>
21
22 #include "stack/include/btm_status.h"
23 #include "stack/include/hci_error_code.h"
24 #include "stack/include/hci_mode.h"
25 #include "types/raw_address.h"
26
27 /* BTM Power manager status codes */
28 enum : uint8_t {
29 BTM_PM_STS_ACTIVE = HCI_MODE_ACTIVE, // 0x00
30 BTM_PM_STS_HOLD = HCI_MODE_HOLD, // 0x01
31 BTM_PM_STS_SNIFF = HCI_MODE_SNIFF, // 0x02
32 BTM_PM_STS_PARK = HCI_MODE_PARK, // 0x03
33 BTM_PM_STS_SSR, /* report the SSR parameters in HCI_SNIFF_SUB_RATE_EVT */
34 BTM_PM_STS_PENDING, /* when waiting for status from controller */
35 BTM_PM_STS_ERROR /* when HCI command status returns error */
36 };
37 typedef uint8_t tBTM_PM_STATUS;
38
power_mode_status_text(tBTM_PM_STATUS status)39 inline std::string power_mode_status_text(tBTM_PM_STATUS status) {
40 switch (status) {
41 case BTM_PM_STS_ACTIVE:
42 return std::string("active");
43 case BTM_PM_STS_HOLD:
44 return std::string("hold");
45 case BTM_PM_STS_SNIFF:
46 return std::string("sniff");
47 case BTM_PM_STS_PARK:
48 return std::string("park");
49 case BTM_PM_STS_SSR:
50 return std::string("sniff_subrating");
51 case BTM_PM_STS_PENDING:
52 return std::string("pending");
53 case BTM_PM_STS_ERROR:
54 return std::string("error");
55 default:
56 return std::string("UNKNOWN");
57 }
58 }
59
60 /* BTM Power manager modes */
61 enum : uint8_t {
62 BTM_PM_MD_ACTIVE = HCI_MODE_ACTIVE, // 0x00
63 BTM_PM_MD_HOLD = HCI_MODE_HOLD, // 0x01
64 BTM_PM_MD_SNIFF = HCI_MODE_SNIFF, // 0x02
65 BTM_PM_MD_PARK = HCI_MODE_PARK, // 0x03
66 BTM_PM_MD_FORCE = 0x10, /* OR this to force ACL link to a certain mode */
67 BTM_PM_MD_UNKNOWN = 0xEF,
68 };
69
70 typedef uint8_t tBTM_PM_MODE;
71 #define HCI_TO_BTM_POWER_MODE(mode) (static_cast<tBTM_PM_MODE>(mode))
72
is_legal_power_mode(tBTM_PM_MODE mode)73 inline bool is_legal_power_mode(tBTM_PM_MODE mode) {
74 switch (mode & ~BTM_PM_MD_FORCE) {
75 case BTM_PM_MD_ACTIVE:
76 case BTM_PM_MD_HOLD:
77 case BTM_PM_MD_SNIFF:
78 case BTM_PM_MD_PARK:
79 return true;
80 default:
81 return false;
82 }
83 }
84
power_mode_text(tBTM_PM_MODE mode)85 inline std::string power_mode_text(tBTM_PM_MODE mode) {
86 std::string s = (mode & BTM_PM_MD_FORCE) ? "" : "forced:";
87 switch (mode & ~BTM_PM_MD_FORCE) {
88 case BTM_PM_MD_ACTIVE:
89 return s + std::string("active");
90 case BTM_PM_MD_HOLD:
91 return s + std::string("hold");
92 case BTM_PM_MD_SNIFF:
93 return s + std::string("sniff");
94 case BTM_PM_MD_PARK:
95 return s + std::string("park");
96 default:
97 return s + std::string("UNKNOWN");
98 }
99 }
100
101 #define BTM_PM_SET_ONLY_ID 0x80
102
103 /* Operation codes */
104 typedef enum : uint8_t {
105 /* The module wants to set the desired power mode */
106 BTM_PM_REG_SET = (1u << 0),
107 /* The module does not want to involve with PM anymore */
108 BTM_PM_DEREG = (1u << 2),
109 } tBTM_PM_REGISTER;
110
111 typedef struct {
112 uint16_t max = 0;
113 uint16_t min = 0;
114 uint16_t attempt = 0;
115 uint16_t timeout = 0;
116 tBTM_PM_MODE mode = BTM_PM_MD_ACTIVE; // 0
117 } tBTM_PM_PWR_MD;
118
119 typedef void(tBTM_PM_STATUS_CBACK)(const RawAddress& p_bda, tBTM_PM_STATUS status, uint16_t value,
120 tHCI_STATUS hci_status);
121
122 #define BTM_CONTRL_UNKNOWN 0
123 /* ACL link on, SCO link ongoing, sniff mode */
124 #define BTM_CONTRL_ACTIVE 1
125 /* Scan state - paging/inquiry/trying to connect*/
126 #define BTM_CONTRL_SCAN 2
127 /* Idle state - page scan, LE advt, inquiry scan */
128 #define BTM_CONTRL_IDLE 3
129
130 #define BTM_CONTRL_NUM_ACL_CLASSIC_ACTIVE_MASK 0xF
131 #define BTM_CONTRL_NUM_ACL_CLASSIC_ACTIVE_SHIFT 0
132 #define BTM_CONTRL_NUM_ACL_CLASSIC_SNIFF_MASK 0xF
133 #define BTM_CONTRL_NUM_ACL_CLASSIC_SNIFF_SHIFT 4
134 #define BTM_CONTRL_NUM_ACL_LE_MASK 0xF
135 #define BTM_CONTRL_NUM_ACL_LE_SHIFT 8
136 #define BTM_CONTRL_NUM_LE_ADV_MASK 0xF
137 #define BTM_CONTRL_NUM_LE_ADV_SHIFT 12
138
139 #define BTM_CONTRL_LE_SCAN_MODE_IDLE 0
140 #define BTM_CONTRL_LE_SCAN_MODE_ULTRA_LOW_POWER 1
141 #define BTM_CONTRL_LE_SCAN_MODE_LOW_POWER 2
142 #define BTM_CONTRL_LE_SCAN_MODE_BALANCED 3
143 #define BTM_CONTRL_LE_SCAN_MODE_LOW_LATENCY 4
144 #define BTM_CONTRL_LE_SCAN_MODE_MASK 0xF
145 #define BTM_CONTRL_LE_SCAN_MODE_SHIFT 16
146
147 #define BTM_CONTRL_INQUIRY_SHIFT 20
148 #define BTM_CONTRL_INQUIRY (1u << BTM_CONTRL_INQUIRY_SHIFT)
149 #define BTM_CONTRL_SCO_SHIFT 21
150 #define BTM_CONTRL_SCO (1u << BTM_CONTRL_SCO_SHIFT)
151 #define BTM_CONTRL_A2DP_SHIFT 22
152 #define BTM_CONTRL_A2DP (1u << BTM_CONTRL_A2DP_SHIFT)
153 #define BTM_CONTRL_LE_AUDIO_SHIFT 23
154 #define BTM_CONTRL_LE_AUDIO (1u << BTM_CONTRL_LE_AUDIO_SHIFT)
155
156 typedef uint32_t tBTM_CONTRL_STATE;
157
set_num_acl_active_to_ctrl_state(uint32_t num,tBTM_CONTRL_STATE & ctrl_state)158 inline void set_num_acl_active_to_ctrl_state(uint32_t num, tBTM_CONTRL_STATE& ctrl_state) {
159 if (num > BTM_CONTRL_NUM_ACL_CLASSIC_ACTIVE_MASK) {
160 num = BTM_CONTRL_NUM_ACL_CLASSIC_ACTIVE_MASK;
161 }
162 ctrl_state |= ((num & BTM_CONTRL_NUM_ACL_CLASSIC_ACTIVE_MASK)
163 << BTM_CONTRL_NUM_ACL_CLASSIC_ACTIVE_SHIFT);
164 }
165
set_num_acl_sniff_to_ctrl_state(uint32_t num,tBTM_CONTRL_STATE & ctrl_state)166 inline void set_num_acl_sniff_to_ctrl_state(uint32_t num, tBTM_CONTRL_STATE& ctrl_state) {
167 if (num > BTM_CONTRL_NUM_ACL_CLASSIC_SNIFF_MASK) {
168 num = BTM_CONTRL_NUM_ACL_CLASSIC_SNIFF_MASK;
169 }
170 ctrl_state |=
171 ((num & BTM_CONTRL_NUM_ACL_CLASSIC_SNIFF_MASK) << BTM_CONTRL_NUM_ACL_CLASSIC_SNIFF_SHIFT);
172 }
173
set_num_acl_le_to_ctrl_state(uint32_t num,tBTM_CONTRL_STATE & ctrl_state)174 inline void set_num_acl_le_to_ctrl_state(uint32_t num, tBTM_CONTRL_STATE& ctrl_state) {
175 if (num > BTM_CONTRL_NUM_ACL_LE_MASK) {
176 num = BTM_CONTRL_NUM_ACL_LE_MASK;
177 }
178 ctrl_state |= ((num & BTM_CONTRL_NUM_ACL_LE_MASK) << BTM_CONTRL_NUM_ACL_LE_SHIFT);
179 }
180
set_num_le_adv_to_ctrl_state(uint32_t num,tBTM_CONTRL_STATE & ctrl_state)181 inline void set_num_le_adv_to_ctrl_state(uint32_t num, tBTM_CONTRL_STATE& ctrl_state) {
182 if (num > BTM_CONTRL_NUM_LE_ADV_MASK) {
183 num = BTM_CONTRL_NUM_LE_ADV_MASK;
184 }
185 ctrl_state |= ((num & BTM_CONTRL_NUM_LE_ADV_MASK) << BTM_CONTRL_NUM_LE_ADV_SHIFT);
186 }
187
set_le_scan_mode_to_ctrl_state(uint32_t duty_cycle,tBTM_CONTRL_STATE & ctrl_state)188 inline void set_le_scan_mode_to_ctrl_state(uint32_t duty_cycle, tBTM_CONTRL_STATE& ctrl_state) {
189 uint32_t scan_mode;
190 if (duty_cycle == 0) {
191 scan_mode = BTM_CONTRL_LE_SCAN_MODE_IDLE;
192 } else if (duty_cycle <= 5) {
193 scan_mode = BTM_CONTRL_LE_SCAN_MODE_ULTRA_LOW_POWER;
194 } else if (duty_cycle <= 10) {
195 scan_mode = BTM_CONTRL_LE_SCAN_MODE_LOW_POWER;
196 } else if (duty_cycle <= 25) {
197 scan_mode = BTM_CONTRL_LE_SCAN_MODE_BALANCED;
198 } else {
199 scan_mode = BTM_CONTRL_LE_SCAN_MODE_LOW_LATENCY;
200 }
201 ctrl_state |= ((scan_mode & BTM_CONTRL_LE_SCAN_MODE_MASK) << BTM_CONTRL_LE_SCAN_MODE_SHIFT);
202 }
203
204 /*******************************************************************************
205 *
206 * Function BTM_PmRegister
207 *
208 * Description register or deregister with power manager
209 *
210 * Returns tBTM_STATUS::BTM_SUCCESS if successful,
211 * tBTM_STATUS::BTM_NO_RESOURCES if no room to hold registration
212 * tBTM_STATUS::BTM_ILLEGAL_VALUE
213 *
214 ******************************************************************************/
215 tBTM_STATUS BTM_PmRegister(uint8_t mask, uint8_t* p_pm_id, tBTM_PM_STATUS_CBACK* p_cb);
216
217 // Notified by ACL that a new link is connected
218 void BTM_PM_OnConnected(uint16_t handle, const RawAddress& remote_bda);
219
220 // Notified by ACL that a link is disconnected
221 void BTM_PM_OnDisconnected(uint16_t handle);
222
223 /*******************************************************************************
224 *
225 * Function BTM_SetPowerMode
226 *
227 * Description store the mode in control block or
228 * alter ACL connection behavior.
229 *
230 * Returns tBTM_STATUS::BTM_SUCCESS if successful,
231 * tBTM_STATUS::BTM_UNKNOWN_ADDR if bd addr is not active or bad
232 *
233 ******************************************************************************/
234 tBTM_STATUS BTM_SetPowerMode(uint8_t pm_id, const RawAddress& remote_bda,
235 const tBTM_PM_PWR_MD* p_mode);
236 bool BTM_SetLinkPolicyActiveMode(const RawAddress& remote_bda);
237
238 /*******************************************************************************
239 *
240 * Function BTM_SetSsrParams
241 *
242 * Description This sends the given SSR parameters for the given ACL
243 * connection if it is in ACTIVE mode.
244 *
245 * Input Param remote_bda - device address of desired ACL connection
246 * max_lat - maximum latency (in 0.625ms)(0-0xFFFE)
247 * min_rmt_to - minimum remote timeout
248 * min_loc_to - minimum local timeout
249 *
250 *
251 * Returns tBTM_STATUS::BTM_SUCCESS if the HCI command is issued successful,
252 * tBTM_STATUS::BTM_UNKNOWN_ADDR if bd addr is not active or bad
253 * tBTM_STATUS::BTM_CMD_STORED if the command is stored
254 *
255 ******************************************************************************/
256 tBTM_STATUS BTM_SetSsrParams(const RawAddress& remote_bda, uint16_t max_lat, uint16_t min_rmt_to,
257 uint16_t min_loc_to);
258
259 /*******************************************************************************
260 *
261 * Function BTM_PM_ReadControllerState
262 *
263 * Description This function is called to obtain the controller state
264 *
265 * Returns Controller state (BTM_CONTRL_ACTIVE, BTM_CONTRL_SCAN, and
266 * BTM_CONTRL_IDLE)
267 *
268 ******************************************************************************/
269 tBTM_CONTRL_STATE BTM_PM_ReadControllerState(void);
270
271 /*******************************************************************************
272 *
273 * Function BTM_PM_ReadSniffLinkCount
274 *
275 * Description Return the number of BT connection in sniff mode
276 *
277 * Returns Number of BT connection in sniff mode
278 *
279 ******************************************************************************/
280 uint8_t BTM_PM_ReadSniffLinkCount(void);
281
282 /*******************************************************************************
283 *
284 * Function BTM_PM_ReadBleLinkCount
285 *
286 * Description Return the number of BLE connection
287 *
288 * Returns Number of BLE connection
289 *
290 ******************************************************************************/
291 uint8_t BTM_PM_ReadBleLinkCount(void);
292
293 /*******************************************************************************
294 *
295 * Function BTM_PM_DeviceInScanState
296 *
297 * Description This function is called to check if in inquiry
298 *
299 * Returns true, if in inquiry
300 *
301 ******************************************************************************/
302 bool BTM_PM_DeviceInScanState(void);
303
304 /*******************************************************************************
305 *
306 * Function BTM_PM_ReadBleScanDutyCycle
307 *
308 * Description Returns BLE scan duty cycle which is (window * 100) /
309 *interval
310 *
311 * Returns BLE scan duty cycle
312 *
313 ******************************************************************************/
314 uint32_t BTM_PM_ReadBleScanDutyCycle(void);
315