1 /******************************************************************************
2 *
3 * Copyright 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 #include "main/shim/entry.h"
32 #define LOG_TAG "bt_btm_pm"
33
34 #include <base/strings/stringprintf.h>
35 #include <bluetooth/log.h>
36
37 #include <cstdint>
38 #include <unordered_map>
39
40 #include "device/include/interop.h"
41 #include "hci/controller_interface.h"
42 #include "internal_include/bt_target.h"
43 #include "main/shim/dumpsys.h"
44 #include "main/shim/entry.h"
45 #include "osi/include/stack_power_telemetry.h"
46 #include "stack/btm/btm_int_types.h"
47 #include "stack/include/acl_api.h"
48 #include "stack/include/acl_hci_link_interface.h"
49 #include "stack/include/bt_types.h"
50 #include "stack/include/btm_log_history.h"
51 #include "stack/include/btm_status.h"
52 #include "stack/include/l2cap_hci_link_interface.h"
53 #include "stack/include/sco_hci_link_interface.h"
54 #include "types/raw_address.h"
55
56 using namespace bluetooth;
57
58 extern tBTM_CB btm_cb;
59
60 namespace {
61 uint16_t pm_pend_link = 0;
62
63 std::unordered_map<uint16_t /* handle */, tBTM_PM_MCB> pm_mode_db;
64
btm_pm_get_power_manager_from_address(const RawAddress & bda)65 tBTM_PM_MCB* btm_pm_get_power_manager_from_address(const RawAddress& bda) {
66 for (auto& entry : pm_mode_db) {
67 if (entry.second.bda_ == bda) {
68 return &entry.second;
69 }
70 }
71 return nullptr;
72 }
73
74 tBTM_PM_RCB pm_reg_db; /* per application/module */
75
76 uint8_t pm_pend_id = 0; /* the id pf the module, which has a pending PM cmd */
77
78 constexpr char kBtmLogTag[] = "ACL";
79 } // namespace
80
81 /*****************************************************************************/
82 /* to handle different modes */
83 /*****************************************************************************/
84 #define BTM_PM_NUM_SET_MODES 3 /* only hold, sniff & park */
85
86 #define BTM_PM_GET_MD1 1
87 #define BTM_PM_GET_MD2 2
88 #define BTM_PM_GET_COMP 3
89
90 const uint8_t btm_pm_md_comp_matrix[BTM_PM_NUM_SET_MODES * BTM_PM_NUM_SET_MODES] = {
91 BTM_PM_GET_COMP, BTM_PM_GET_MD2, BTM_PM_GET_MD2,
92
93 BTM_PM_GET_MD1, BTM_PM_GET_COMP, BTM_PM_GET_MD1,
94
95 BTM_PM_GET_MD1, BTM_PM_GET_MD2, BTM_PM_GET_COMP};
96
send_sniff_subrating(uint16_t handle,const RawAddress & addr,uint16_t max_lat,uint16_t min_rmt_to,uint16_t min_loc_to)97 static void send_sniff_subrating(uint16_t handle, const RawAddress& addr, uint16_t max_lat,
98 uint16_t min_rmt_to, uint16_t min_loc_to) {
99 uint16_t new_max_lat = 0;
100 if (interop_match_addr_get_max_lat(INTEROP_UPDATE_HID_SSR_MAX_LAT, &addr, &new_max_lat)) {
101 max_lat = new_max_lat;
102 }
103
104 btsnd_hcic_sniff_sub_rate(handle, max_lat, min_rmt_to, min_loc_to);
105 BTM_LogHistory(kBtmLogTag, addr, "Sniff subrating",
106 base::StringPrintf("max_latency:%.2f peer_timeout:%.2f local_timeout:%.2f",
107 ticks_to_seconds(max_lat), ticks_to_seconds(min_rmt_to),
108 ticks_to_seconds(min_loc_to)));
109 }
110
111 static tBTM_STATUS btm_pm_snd_md_req(uint16_t handle, uint8_t pm_id, int link_ind,
112 const tBTM_PM_PWR_MD* p_mode);
113
114 /*****************************************************************************/
115 /* P U B L I C F U N C T I O N S */
116 /*****************************************************************************/
117 /*******************************************************************************
118 *
119 * Function BTM_PmRegister
120 *
121 * Description register or deregister with power manager
122 *
123 * Returns tBTM_STATUS::BTM_SUCCESS if successful,
124 * tBTM_STATUS::BTM_NO_RESOURCES if no room to hold registration
125 * tBTM_STATUS::BTM_ILLEGAL_VALUE
126 *
127 ******************************************************************************/
BTM_PmRegister(uint8_t mask,uint8_t * p_pm_id,tBTM_PM_STATUS_CBACK * p_cb)128 tBTM_STATUS BTM_PmRegister(uint8_t mask, uint8_t* p_pm_id, tBTM_PM_STATUS_CBACK* p_cb) {
129 /* de-register */
130 if (mask & BTM_PM_DEREG) {
131 if (*p_pm_id >= BTM_MAX_PM_RECORDS) {
132 return tBTM_STATUS::BTM_ILLEGAL_VALUE;
133 }
134 pm_reg_db.mask = BTM_PM_REC_NOT_USED;
135 return tBTM_STATUS::BTM_SUCCESS;
136 }
137
138 if (pm_reg_db.mask == BTM_PM_REC_NOT_USED) {
139 /* if register for notification, should provide callback routine */
140 if (p_cb == NULL) {
141 return tBTM_STATUS::BTM_ILLEGAL_VALUE;
142 }
143 pm_reg_db.cback = p_cb;
144 pm_reg_db.mask = mask;
145 *p_pm_id = 0;
146 return tBTM_STATUS::BTM_SUCCESS;
147 }
148
149 return tBTM_STATUS::BTM_NO_RESOURCES;
150 }
151
BTM_PM_OnConnected(uint16_t handle,const RawAddress & remote_bda)152 void BTM_PM_OnConnected(uint16_t handle, const RawAddress& remote_bda) {
153 if (pm_mode_db.find(handle) != pm_mode_db.end()) {
154 log::error("Overwriting power mode db entry handle:{} peer:{}", handle, remote_bda);
155 }
156 pm_mode_db[handle] = {};
157 pm_mode_db[handle].Init(remote_bda, handle);
158 }
159
BTM_PM_OnDisconnected(uint16_t handle)160 void BTM_PM_OnDisconnected(uint16_t handle) {
161 if (pm_mode_db.find(handle) == pm_mode_db.end()) {
162 log::error("Erasing unknown power mode db entry handle:{}", handle);
163 }
164 pm_mode_db.erase(handle);
165 if (handle == pm_pend_link) {
166 pm_pend_link = 0;
167 }
168 }
169
170 /*******************************************************************************
171 *
172 * Function BTM_SetPowerMode
173 *
174 * Description store the mode in control block or
175 * alter ACL connection behavior.
176 *
177 * Returns tBTM_STATUS::BTM_SUCCESS if successful,
178 * tBTM_STATUS::BTM_UNKNOWN_ADDR if bd addr is not active or bad
179 *
180 ******************************************************************************/
BTM_SetPowerMode(uint8_t pm_id,const RawAddress & remote_bda,const tBTM_PM_PWR_MD * p_mode)181 tBTM_STATUS BTM_SetPowerMode(uint8_t pm_id, const RawAddress& remote_bda,
182 const tBTM_PM_PWR_MD* p_mode) {
183 if (pm_id >= BTM_MAX_PM_RECORDS) {
184 pm_id = BTM_PM_SET_ONLY_ID;
185 }
186
187 if (!p_mode) {
188 log::error("pm_id: {}, p_mode is null for {}", unsigned(pm_id), remote_bda);
189 return tBTM_STATUS::BTM_ILLEGAL_VALUE;
190 }
191
192 // per ACL link
193 auto* p_cb = btm_pm_get_power_manager_from_address(remote_bda);
194 if (p_cb == nullptr) {
195 log::warn("Unable to find power manager for peer: {}", remote_bda);
196 return tBTM_STATUS::BTM_UNKNOWN_ADDR;
197 }
198 uint16_t handle = p_cb->handle_;
199
200 tBTM_PM_MODE mode = p_mode->mode;
201 if (!is_legal_power_mode(mode)) {
202 log::error("Unable to set illegal power mode value:0x{:02x}", mode);
203 return tBTM_STATUS::BTM_ILLEGAL_VALUE;
204 }
205
206 if (p_mode->mode & BTM_PM_MD_FORCE) {
207 log::info("Attempting to force into this power mode");
208 /* take out the force bit */
209 mode &= (~BTM_PM_MD_FORCE);
210 }
211
212 if (mode != BTM_PM_MD_ACTIVE) {
213 auto controller = bluetooth::shim::GetController();
214 if ((mode == BTM_PM_MD_HOLD && !controller->SupportsHoldMode()) ||
215 (mode == BTM_PM_MD_SNIFF && !controller->SupportsSniffMode()) ||
216 (mode == BTM_PM_MD_PARK && !controller->SupportsParkMode()) ||
217 interop_match_addr(INTEROP_DISABLE_SNIFF, &remote_bda)) {
218 log::error("pm_id {} mode {} is not supported for {}", pm_id, mode, remote_bda);
219 return tBTM_STATUS::BTM_MODE_UNSUPPORTED;
220 }
221 }
222
223 if (mode == p_cb->state) {
224 /* already in the requested mode and the current interval has less latency
225 * than the max */
226 if ((mode == BTM_PM_MD_ACTIVE) ||
227 ((p_mode->mode & BTM_PM_MD_FORCE) && (p_mode->max >= p_cb->interval) &&
228 (p_mode->min <= p_cb->interval)) ||
229 ((p_mode->mode & BTM_PM_MD_FORCE) == 0 && (p_mode->max >= p_cb->interval))) {
230 log::debug(
231 "Device is already in requested mode {}, interval: {}, max: {}, min: "
232 "{}",
233 p_mode->mode, p_cb->interval, p_mode->max, p_mode->min);
234 return tBTM_STATUS::BTM_SUCCESS;
235 }
236 }
237
238 /* update mode database */
239 if (((pm_id != BTM_PM_SET_ONLY_ID) && (pm_reg_db.mask & BTM_PM_REG_SET)) ||
240 ((pm_id == BTM_PM_SET_ONLY_ID) && (pm_pend_link != 0))) {
241 /* Make sure mask is set to BTM_PM_REG_SET */
242 pm_reg_db.mask |= BTM_PM_REG_SET;
243 *(&p_cb->req_mode) = *p_mode;
244 p_cb->chg_ind = true;
245 }
246
247 /* if mode == hold or pending, return */
248 if ((p_cb->state == BTM_PM_STS_HOLD) || (p_cb->state == BTM_PM_STS_PENDING) ||
249 (pm_pend_link != 0)) {
250 log::info(
251 "Current power mode is hold or pending status or pending links "
252 "state:{}[{}] pm_pending_link:{}",
253 power_mode_state_text(p_cb->state), p_cb->state, pm_pend_link);
254 /* command pending */
255 if (handle != pm_pend_link) {
256 p_cb->state |= BTM_PM_STORED_MASK;
257 log::info("Setting stored bitmask for peer:{}", remote_bda);
258 }
259 return tBTM_STATUS::BTM_CMD_STORED;
260 }
261
262 log::info("Setting power mode for peer:{} current_mode:{}[{}] new_mode:{}[{}]", remote_bda,
263 power_mode_state_text(p_cb->state), p_cb->state, power_mode_text(p_mode->mode),
264 p_mode->mode);
265
266 return btm_pm_snd_md_req(p_cb->handle_, pm_id, p_cb->handle_, p_mode);
267 }
268
BTM_SetLinkPolicyActiveMode(const RawAddress & remote_bda)269 bool BTM_SetLinkPolicyActiveMode(const RawAddress& remote_bda) {
270 tBTM_PM_PWR_MD settings;
271 memset((void*)&settings, 0, sizeof(settings));
272 settings.mode = BTM_PM_MD_ACTIVE;
273
274 switch (BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, remote_bda, &settings)) {
275 case tBTM_STATUS::BTM_CMD_STORED:
276 case tBTM_STATUS::BTM_SUCCESS:
277 return true;
278 default:
279 return false;
280 }
281 }
282
BTM_ReadPowerMode(const RawAddress & remote_bda,tBTM_PM_MODE * p_mode)283 bool BTM_ReadPowerMode(const RawAddress& remote_bda, tBTM_PM_MODE* p_mode) {
284 if (p_mode == nullptr) {
285 log::error("power mode is nullptr");
286 return false;
287 }
288 tBTM_PM_MCB* p_mcb = btm_pm_get_power_manager_from_address(remote_bda);
289 if (p_mcb == nullptr) {
290 log::warn("Unknown device:{}", remote_bda);
291 return false;
292 }
293 *p_mode = static_cast<tBTM_PM_MODE>(p_mcb->state);
294 return true;
295 }
296
297 /*******************************************************************************
298 *
299 * Function BTM_SetSsrParams
300 *
301 * Description This sends the given SSR parameters for the given ACL
302 * connection if it is in ACTIVE mode.
303 *
304 * Input Param remote_bda - device address of desired ACL connection
305 * max_lat - maximum latency (in 0.625ms)(0-0xFFFE)
306 * min_rmt_to - minimum remote timeout
307 * min_loc_to - minimum local timeout
308 *
309 *
310 * Returns tBTM_STATUS::BTM_SUCCESS if the HCI command is issued successful,
311 * tBTM_STATUS::BTM_UNKNOWN_ADDR if bd addr is not active or bad
312 * tBTM_STATUS::BTM_CMD_STORED if the command is stored
313 *
314 ******************************************************************************/
BTM_SetSsrParams(const RawAddress & remote_bda,uint16_t max_lat,uint16_t min_rmt_to,uint16_t min_loc_to)315 tBTM_STATUS BTM_SetSsrParams(const RawAddress& remote_bda, uint16_t max_lat, uint16_t min_rmt_to,
316 uint16_t min_loc_to) {
317 tBTM_PM_MCB* p_cb = btm_pm_get_power_manager_from_address(remote_bda);
318 if (p_cb == nullptr) {
319 log::warn("Unable to find power manager for peer:{}", remote_bda);
320 return tBTM_STATUS::BTM_UNKNOWN_ADDR;
321 }
322
323 if (!bluetooth::shim::GetController()->SupportsSniffSubrating()) {
324 log::info("No controller support for sniff subrating");
325 return tBTM_STATUS::BTM_SUCCESS;
326 }
327
328 if (p_cb->state == BTM_PM_ST_ACTIVE || p_cb->state == BTM_PM_ST_SNIFF) {
329 log::info(
330 "Set sniff subrating state:{}[{}] max_latency:0x{:04x} "
331 "min_remote_timeout:0x{:04x} min_local_timeout:0x{:04x}",
332 power_mode_state_text(p_cb->state), p_cb->state, max_lat, min_rmt_to, min_loc_to);
333 send_sniff_subrating(p_cb->handle_, remote_bda, max_lat, min_rmt_to, min_loc_to);
334 return tBTM_STATUS::BTM_SUCCESS;
335 }
336 log::info("pm_mode_db state: {}", p_cb->state);
337 p_cb->max_lat = max_lat;
338 p_cb->min_rmt_to = min_rmt_to;
339 p_cb->min_loc_to = min_loc_to;
340 return tBTM_STATUS::BTM_CMD_STORED;
341 }
342
343 /*******************************************************************************
344 *
345 * Function btm_pm_reset
346 *
347 * Description as a part of the BTM reset process.
348 *
349 * Returns void
350 *
351 ******************************************************************************/
btm_pm_reset(void)352 void btm_pm_reset(void) {
353 tBTM_PM_STATUS_CBACK* cb = NULL;
354
355 /* clear the pending request for application */
356 if ((pm_pend_id != BTM_PM_SET_ONLY_ID) && (pm_reg_db.mask & BTM_PM_REG_SET)) {
357 cb = pm_reg_db.cback;
358 }
359
360 pm_reg_db.mask = BTM_PM_REC_NOT_USED;
361
362 if (cb != NULL && pm_pend_link != 0) {
363 const RawAddress raw_address = pm_mode_db[pm_pend_link].bda_;
364 (*cb)(raw_address, BTM_PM_STS_ERROR, static_cast<uint16_t>(tBTM_STATUS::BTM_DEV_RESET),
365 HCI_SUCCESS);
366 }
367 /* no command pending */
368 pm_pend_link = 0;
369 pm_mode_db.clear();
370 pm_pend_id = 0;
371 memset(&pm_reg_db, 0, sizeof(pm_reg_db));
372 log::info("reset pm");
373 }
374
375 /*******************************************************************************
376 *
377 * Function btm_pm_compare_modes
378 * Description get the "more active" mode of the 2
379 * Returns void
380 *
381 ******************************************************************************/
btm_pm_compare_modes(const tBTM_PM_PWR_MD * p_md1,const tBTM_PM_PWR_MD * p_md2,tBTM_PM_PWR_MD * p_res)382 static tBTM_PM_PWR_MD* btm_pm_compare_modes(const tBTM_PM_PWR_MD* p_md1,
383 const tBTM_PM_PWR_MD* p_md2, tBTM_PM_PWR_MD* p_res) {
384 uint8_t res;
385
386 if (p_md1 == NULL) {
387 *p_res = *p_md2;
388 p_res->mode &= ~BTM_PM_MD_FORCE;
389
390 return p_res;
391 }
392
393 if (p_md2->mode == BTM_PM_MD_ACTIVE || p_md1->mode == BTM_PM_MD_ACTIVE) {
394 return NULL;
395 }
396
397 /* check if force bit is involved */
398 if (p_md1->mode & BTM_PM_MD_FORCE) {
399 *p_res = *p_md1;
400 p_res->mode &= ~BTM_PM_MD_FORCE;
401 return p_res;
402 }
403
404 if (p_md2->mode & BTM_PM_MD_FORCE) {
405 *p_res = *p_md2;
406 p_res->mode &= ~BTM_PM_MD_FORCE;
407 return p_res;
408 }
409
410 res = (p_md1->mode - 1) * BTM_PM_NUM_SET_MODES + (p_md2->mode - 1);
411 res = btm_pm_md_comp_matrix[res];
412 switch (res) {
413 case BTM_PM_GET_MD1:
414 *p_res = *p_md1;
415 return p_res;
416
417 case BTM_PM_GET_MD2:
418 *p_res = *p_md2;
419 return p_res;
420
421 case BTM_PM_GET_COMP:
422 p_res->mode = p_md1->mode;
423 /* min of the two */
424 p_res->max = (p_md1->max < p_md2->max) ? (p_md1->max) : (p_md2->max);
425 /* max of the two */
426 p_res->min = (p_md1->min > p_md2->min) ? (p_md1->min) : (p_md2->min);
427
428 /* the intersection is NULL */
429 if (p_res->max < p_res->min) {
430 return NULL;
431 }
432
433 if (p_res->mode == BTM_PM_MD_SNIFF) {
434 /* max of the two */
435 p_res->attempt = (p_md1->attempt > p_md2->attempt) ? (p_md1->attempt) : (p_md2->attempt);
436 p_res->timeout = (p_md1->timeout > p_md2->timeout) ? (p_md1->timeout) : (p_md2->timeout);
437 }
438 return p_res;
439 }
440 return NULL;
441 }
442
443 /*******************************************************************************
444 *
445 * Function btm_pm_get_set_mode
446 * Description get the resulting mode from the registered parties, then compare
447 * it with the requested mode, if the command is from an
448 * unregistered party.
449 *
450 * Returns void
451 *
452 ******************************************************************************/
btm_pm_get_set_mode(uint8_t pm_id,tBTM_PM_MCB * p_cb,const tBTM_PM_PWR_MD * p_mode,tBTM_PM_PWR_MD * p_res)453 static tBTM_PM_MODE btm_pm_get_set_mode(uint8_t pm_id, tBTM_PM_MCB* p_cb,
454 const tBTM_PM_PWR_MD* p_mode, tBTM_PM_PWR_MD* p_res) {
455 tBTM_PM_PWR_MD* p_md = NULL;
456
457 if (p_mode != NULL && p_mode->mode & BTM_PM_MD_FORCE) {
458 *p_res = *p_mode;
459 p_res->mode &= ~BTM_PM_MD_FORCE;
460 return p_res->mode;
461 }
462
463 /* g through all the registered "set" parties */
464 if (pm_reg_db.mask & BTM_PM_REG_SET) {
465 if (p_cb->req_mode.mode == BTM_PM_MD_ACTIVE) {
466 /* if at least one registered (SET) party says ACTIVE, stay active */
467 return BTM_PM_MD_ACTIVE;
468 } else {
469 /* if registered parties give conflicting information, stay active */
470 if ((btm_pm_compare_modes(p_md, &p_cb->req_mode, p_res)) == NULL) {
471 return BTM_PM_MD_ACTIVE;
472 }
473 p_md = p_res;
474 }
475 }
476
477 /* if the resulting mode is NULL(nobody registers SET), use the requested mode
478 */
479 if (p_md == NULL) {
480 if (p_mode) {
481 *p_res = *((tBTM_PM_PWR_MD*)p_mode);
482 } else { /* p_mode is NULL when btm_pm_snd_md_req is called from
483 btm_pm_proc_mode_change */
484 return BTM_PM_MD_ACTIVE;
485 }
486 } else {
487 /* if the command is from unregistered party,
488 compare the resulting mode from registered party*/
489 if ((pm_id == BTM_PM_SET_ONLY_ID) && ((btm_pm_compare_modes(p_mode, p_md, p_res)) == NULL)) {
490 return BTM_PM_MD_ACTIVE;
491 }
492 }
493
494 return p_res->mode;
495 }
496
497 /*******************************************************************************
498 *
499 * Function btm_pm_snd_md_req
500 * Description get the resulting mode and send the resuest to host controller
501 * Returns tBTM_STATUS
502 *, bool *p_chg_ind
503 ******************************************************************************/
btm_pm_snd_md_req(uint16_t handle,uint8_t pm_id,int link_ind,const tBTM_PM_PWR_MD * p_mode)504 static tBTM_STATUS btm_pm_snd_md_req(uint16_t handle, uint8_t pm_id, int link_ind,
505 const tBTM_PM_PWR_MD* p_mode) {
506 log::assert_that(pm_mode_db.count(handle) != 0, "Unable to find active acl for handle {}",
507 handle);
508 tBTM_PM_PWR_MD md_res;
509 tBTM_PM_MODE mode;
510 tBTM_PM_MCB* p_cb = &pm_mode_db[handle];
511 bool chg_ind = false;
512
513 mode = btm_pm_get_set_mode(pm_id, p_cb, p_mode, &md_res);
514 md_res.mode = mode;
515
516 log::verbose("Found controller in mode:{}", power_mode_text(mode));
517
518 if (p_cb->state == mode) {
519 log::info("Link already in requested mode pm_id:{} link_ind:{} mode:{}[{}]", pm_id, link_ind,
520 power_mode_text(mode), mode);
521
522 /* already in the resulting mode */
523 if ((mode == BTM_PM_MD_ACTIVE) ||
524 ((md_res.max >= p_cb->interval) && (md_res.min <= p_cb->interval))) {
525 log::debug("Storing command");
526 return tBTM_STATUS::BTM_CMD_STORED;
527 }
528 log::debug("Need to wake then sleep");
529 chg_ind = true;
530 }
531 p_cb->chg_ind = chg_ind;
532
533 /* cannot go directly from current mode to resulting mode. */
534 if (mode != BTM_PM_MD_ACTIVE && p_cb->state != BTM_PM_MD_ACTIVE) {
535 log::debug("Power mode change delay required");
536 p_cb->chg_ind = true; /* needs to wake, then sleep */
537 }
538
539 if (p_cb->chg_ind) {
540 log::debug("Need to wake first");
541 md_res.mode = BTM_PM_MD_ACTIVE;
542 } else if (BTM_PM_MD_SNIFF == md_res.mode && p_cb->max_lat) {
543 if (bluetooth::shim::GetController()->SupportsSniffSubrating()) {
544 log::debug("Sending sniff subrating to controller");
545 send_sniff_subrating(handle, p_cb->bda_, p_cb->max_lat, p_cb->min_rmt_to, p_cb->min_loc_to);
546 }
547 p_cb->max_lat = 0;
548 }
549 /* Default is failure */
550 pm_pend_link = 0;
551
552 /* send the appropriate HCI command */
553 pm_pend_id = pm_id;
554
555 log::info("Switching from {}[0x{:02x}] to {}[0x{:02x}]", power_mode_state_text(p_cb->state),
556 p_cb->state, power_mode_state_text(md_res.mode), md_res.mode);
557 BTM_LogHistory(kBtmLogTag, p_cb->bda_, "Power mode change",
558 base::StringPrintf("%s[0x%02x] ==> %s[0x%02x]",
559 power_mode_state_text(p_cb->state).c_str(), p_cb->state,
560 power_mode_state_text(md_res.mode).c_str(), md_res.mode));
561
562 switch (md_res.mode) {
563 case BTM_PM_MD_ACTIVE:
564 switch (p_cb->state) {
565 case BTM_PM_MD_SNIFF:
566 btsnd_hcic_exit_sniff_mode(handle);
567 pm_pend_link = handle;
568 break;
569 case BTM_PM_MD_PARK:
570 btsnd_hcic_exit_park_mode(handle);
571 pm_pend_link = handle;
572 break;
573 default:
574 /* Failure pm_pend_link = MAX_L2CAP_LINKS */
575 break;
576 }
577 break;
578
579 case BTM_PM_MD_HOLD:
580 btsnd_hcic_hold_mode(handle, md_res.max, md_res.min);
581 pm_pend_link = handle;
582 break;
583
584 case BTM_PM_MD_SNIFF:
585 btsnd_hcic_sniff_mode(handle, md_res.max, md_res.min, md_res.attempt, md_res.timeout);
586 pm_pend_link = handle;
587 break;
588
589 case BTM_PM_MD_PARK:
590 btsnd_hcic_park_mode(handle, md_res.max, md_res.min);
591 pm_pend_link = handle;
592 break;
593 default:
594 /* Failure pm_pend_link = MAX_L2CAP_LINKS */
595 break;
596 }
597
598 if (pm_pend_link == 0) {
599 /* the command was not sent */
600 log::error("pm_pending_link maxed out");
601 return tBTM_STATUS::BTM_NO_RESOURCES;
602 }
603
604 return tBTM_STATUS::BTM_CMD_STARTED;
605 }
606
btm_pm_continue_pending_mode_changes()607 static void btm_pm_continue_pending_mode_changes() {
608 for (auto& entry : pm_mode_db) {
609 if (entry.second.state & BTM_PM_STORED_MASK) {
610 entry.second.state &= ~BTM_PM_STORED_MASK;
611 log::info("Found another link requiring power mode change:{}", entry.second.bda_);
612 btm_pm_snd_md_req(entry.second.handle_, BTM_PM_SET_ONLY_ID, entry.second.handle_, NULL);
613 return;
614 }
615 }
616 }
617
618 /*******************************************************************************
619 *
620 * Function btm_pm_proc_cmd_status
621 *
622 * Description This function is called when an HCI command status event
623 * occurs for power manager related commands.
624 *
625 * Input Parms status - status of the event (HCI_SUCCESS if no errors)
626 *
627 * Returns none.
628 *
629 ******************************************************************************/
btm_pm_proc_cmd_status(tHCI_STATUS status)630 void btm_pm_proc_cmd_status(tHCI_STATUS status) {
631 if (pm_pend_link == 0) {
632 log::error(
633 "There are no links pending power mode changes; try to find other "
634 "pending changes");
635 btm_pm_continue_pending_mode_changes();
636 return;
637 }
638 if (pm_mode_db.count(pm_pend_link) == 0) {
639 log::error(
640 "Got PM change status for disconnected link {}; forgot to clean up "
641 "pm_pend_link?",
642 pm_pend_link);
643 btm_pm_continue_pending_mode_changes();
644 return;
645 }
646
647 tBTM_PM_MCB* p_cb = &pm_mode_db[pm_pend_link];
648
649 // if the command was not successful. Stay in the same state
650 tBTM_PM_STATUS pm_status = BTM_PM_STS_ERROR;
651
652 if (status == HCI_SUCCESS) {
653 p_cb->state = BTM_PM_ST_PENDING;
654 pm_status = BTM_PM_STS_PENDING;
655 }
656
657 /* notify the caller is appropriate */
658 if ((pm_pend_id != BTM_PM_SET_ONLY_ID) && (pm_reg_db.mask & BTM_PM_REG_SET)) {
659 const RawAddress bd_addr = pm_mode_db[pm_pend_link].bda_;
660 log::verbose("Notifying callback that link power mode is complete peer:{}", bd_addr);
661 (*pm_reg_db.cback)(bd_addr, pm_status, 0, status);
662 }
663
664 log::verbose("Clearing pending power mode link state:{}", power_mode_state_text(p_cb->state));
665 pm_pend_link = 0;
666
667 btm_pm_continue_pending_mode_changes();
668 }
669
670 /*******************************************************************************
671 *
672 * Function btm_process_mode_change
673 *
674 * Description This function is called when an HCI mode change event
675 * occurs.
676 *
677 * Input Parms hci_status - status of the event (HCI_SUCCESS if no errors)
678 * hci_handle - connection handle associated with the change
679 * mode - HCI_MODE_ACTIVE, HCI_MODE_HOLD, HCI_MODE_SNIFF, or
680 * HCI_MODE_PARK
681 * interval - number of baseband slots (meaning depends on
682 * mode)
683 *
684 * Returns none.
685 *
686 ******************************************************************************/
btm_pm_proc_mode_change(tHCI_STATUS hci_status,uint16_t hci_handle,tHCI_MODE hci_mode,uint16_t interval)687 void btm_pm_proc_mode_change(tHCI_STATUS hci_status, uint16_t hci_handle, tHCI_MODE hci_mode,
688 uint16_t interval) {
689 tBTM_PM_STATUS mode = static_cast<tBTM_PM_STATUS>(hci_mode);
690
691 /* update control block */
692 if (pm_mode_db.count(hci_handle) == 0) {
693 log::warn("Unable to find active acl for handle {}", hci_handle);
694 return;
695 }
696 tBTM_PM_MCB* p_cb = &pm_mode_db[hci_handle];
697
698 const tBTM_PM_STATE old_state = p_cb->state;
699 p_cb->state = mode;
700 p_cb->interval = interval;
701
702 log::info("Power mode switched from {}[{}] to {}[{}]", power_mode_state_text(old_state),
703 old_state, power_mode_state_text(p_cb->state), p_cb->state);
704
705 if ((p_cb->state == BTM_PM_ST_ACTIVE) || (p_cb->state == BTM_PM_ST_SNIFF)) {
706 l2c_OnHciModeChangeSendPendingPackets(p_cb->bda_);
707 }
708
709 (mode != BTM_PM_ST_ACTIVE)
710 ? power_telemetry::GetInstance().LogSniffStarted(hci_handle, p_cb->bda_)
711 : power_telemetry::GetInstance().LogSniffStopped(hci_handle, p_cb->bda_);
712
713 /* set req_mode HOLD mode->ACTIVE */
714 if ((mode == BTM_PM_MD_ACTIVE) && (p_cb->req_mode.mode == BTM_PM_MD_HOLD)) {
715 p_cb->req_mode.mode = BTM_PM_MD_ACTIVE;
716 }
717
718 /* new request has been made. - post a message to BTU task */
719 if (old_state & BTM_PM_STORED_MASK) {
720 btm_pm_snd_md_req(hci_handle, BTM_PM_SET_ONLY_ID, hci_handle, NULL);
721 } else {
722 for (auto& entry : pm_mode_db) {
723 if (entry.second.chg_ind) {
724 btm_pm_snd_md_req(entry.second.handle_, BTM_PM_SET_ONLY_ID, entry.second.handle_, NULL);
725 break;
726 }
727 }
728 }
729
730 /* notify registered parties */
731 if (pm_reg_db.mask & BTM_PM_REG_SET) {
732 (*pm_reg_db.cback)(p_cb->bda_, mode, interval, hci_status);
733 }
734 /*check if sco disconnect is waiting for the mode change */
735 btm_sco_disc_chk_pend_for_modechange(hci_handle);
736
737 /* If mode change was because of an active role switch or change link key */
738 btm_cont_rswitch_from_handle(hci_handle);
739 }
740
741 /*******************************************************************************
742 *
743 * Function btm_pm_proc_ssr_evt
744 *
745 * Description This function is called when an HCI sniff subrating event
746 * occurs.
747 *
748 * Returns none.
749 *
750 ******************************************************************************/
process_ssr_event(tHCI_STATUS status,uint16_t handle,uint16_t,uint16_t max_rx_lat)751 static void process_ssr_event(tHCI_STATUS status, uint16_t handle, uint16_t /* max_tx_lat */,
752 uint16_t max_rx_lat) {
753 if (pm_mode_db.count(handle) == 0) {
754 log::warn("Received sniff subrating event with no active ACL");
755 return;
756 }
757 tBTM_PM_MCB* p_cb = &pm_mode_db[handle];
758 auto bd_addr = p_cb->bda_;
759
760 bool use_ssr = true;
761 if (p_cb->interval == max_rx_lat) {
762 log::verbose("Sniff subrating unsupported so dropping to legacy sniff mode");
763 use_ssr = false;
764 } else {
765 log::verbose("Sniff subrating enabled");
766 }
767
768 int cnt = 0;
769 if (pm_reg_db.mask & BTM_PM_REG_SET) {
770 (*pm_reg_db.cback)(bd_addr, BTM_PM_STS_SSR, (use_ssr) ? 1 : 0, status);
771 cnt++;
772 }
773 log::debug(
774 "Notified sniff subrating registered clients cnt:{} peer:{} use_ssr:{} "
775 "status:{}",
776 cnt, bd_addr, use_ssr, hci_error_code_text(status));
777 }
778
btm_pm_on_sniff_subrating(tHCI_STATUS status,uint16_t handle,uint16_t maximum_transmit_latency,uint16_t maximum_receive_latency,uint16_t,uint16_t)779 void btm_pm_on_sniff_subrating(tHCI_STATUS status, uint16_t handle,
780 uint16_t maximum_transmit_latency, uint16_t maximum_receive_latency,
781 uint16_t /* minimum_remote_timeout */,
782 uint16_t /* minimum_local_timeout */) {
783 process_ssr_event(status, handle, maximum_transmit_latency, maximum_receive_latency);
784 }
785
btm_pm_proc_ssr_evt(uint8_t * p,uint16_t)786 void btm_pm_proc_ssr_evt(uint8_t* p, uint16_t /* evt_len */) {
787 uint8_t status;
788 uint16_t handle;
789 uint16_t max_tx_lat;
790 uint16_t max_rx_lat;
791
792 STREAM_TO_UINT8(status, p);
793 STREAM_TO_UINT16(handle, p);
794 STREAM_TO_UINT16(max_tx_lat, p);
795 STREAM_TO_UINT16(max_rx_lat, p);
796
797 process_ssr_event(static_cast<tHCI_STATUS>(status), handle, max_tx_lat, max_rx_lat);
798 }
799
800 /*******************************************************************************
801 *
802 * Function btm_pm_device_in_active_or_sniff_mode
803 *
804 * Description This function is called to check if in active or sniff mode
805 *
806 * Returns true, if in active or sniff mode
807 *
808 ******************************************************************************/
btm_pm_device_in_active_or_sniff_mode(void)809 static bool btm_pm_device_in_active_or_sniff_mode(void) {
810 /* The active state is the highest state-includes connected device and sniff
811 * mode*/
812
813 /* Covers active and sniff modes */
814 if (!pm_mode_db.empty()) {
815 return true;
816 }
817
818 /* Check BLE states */
819 if (!btm_cb.ble_ctr_cb.is_connection_state_idle()) {
820 log::verbose("- BLE state is not idle");
821 return true;
822 }
823
824 return false;
825 }
826
827 /*******************************************************************************
828 *
829 * Function BTM_PM_DeviceInScanState
830 *
831 * Description This function is called to check if in inquiry
832 *
833 * Returns true, if in inquiry
834 *
835 ******************************************************************************/
BTM_PM_DeviceInScanState(void)836 bool BTM_PM_DeviceInScanState(void) {
837 /* Check for inquiry */
838 if ((btm_cb.btm_inq_vars.inq_active & (BTM_GENERAL_INQUIRY | BTM_BLE_GENERAL_INQUIRY)) != 0) {
839 log::verbose("BTM_PM_DeviceInScanState- Inq active");
840 return true;
841 }
842
843 return false;
844 }
845
846 /*******************************************************************************
847 *
848 * Function BTM_PM_ReadControllerState
849 *
850 * Description This function is called to obtain the controller state
851 *
852 * Returns Controller State-BTM_CONTRL_ACTIVE, BTM_CONTRL_SCAN, and
853 * BTM_CONTRL_IDLE
854 *
855 ******************************************************************************/
BTM_PM_ReadControllerState(void)856 tBTM_CONTRL_STATE BTM_PM_ReadControllerState(void) {
857 if (btm_pm_device_in_active_or_sniff_mode()) {
858 return BTM_CONTRL_ACTIVE;
859 } else if (BTM_PM_DeviceInScanState()) {
860 return BTM_CONTRL_SCAN;
861 } else {
862 return BTM_CONTRL_IDLE;
863 }
864 }
865
866 /*******************************************************************************
867 *
868 * Function BTM_PM_ReadSniffLinkCount
869 *
870 * Description Return the number of BT connection in sniff mode
871 *
872 * Returns Number of BT connection in sniff mode
873 *
874 ******************************************************************************/
BTM_PM_ReadSniffLinkCount(void)875 uint8_t BTM_PM_ReadSniffLinkCount(void) {
876 uint8_t count = 0;
877 for (auto& entry : pm_mode_db) {
878 if (entry.second.state == HCI_MODE_SNIFF) {
879 ++count;
880 }
881 }
882 return count;
883 }
884
885 /*******************************************************************************
886 *
887 * Function BTM_PM_ReadBleLinkCount
888 *
889 * Description Return the number of BLE connection
890 *
891 * Returns Number of BLE connection
892 *
893 ******************************************************************************/
BTM_PM_ReadBleLinkCount(void)894 uint8_t BTM_PM_ReadBleLinkCount(void) {
895 return btm_cb.ble_ctr_cb.link_count[HCI_ROLE_CENTRAL] +
896 btm_cb.ble_ctr_cb.link_count[HCI_ROLE_PERIPHERAL];
897 }
898
899 /*******************************************************************************
900 *
901 * Function BTM_PM_ReadBleScanDutyCycle
902 *
903 * Description Returns BLE scan duty cycle which is (window * 100) /
904 *interval
905 *
906 * Returns BLE scan duty cycle
907 *
908 ******************************************************************************/
BTM_PM_ReadBleScanDutyCycle(void)909 uint32_t BTM_PM_ReadBleScanDutyCycle(void) {
910 if (!btm_cb.ble_ctr_cb.is_ble_scan_active()) {
911 return 0;
912 }
913 uint32_t scan_window = btm_cb.ble_ctr_cb.inq_var.scan_window;
914 uint32_t scan_interval = btm_cb.ble_ctr_cb.inq_var.scan_interval;
915 log::debug("LE scan_window:{} scan interval:{}", scan_window, scan_interval);
916 return (scan_window * 100) / scan_interval;
917 }
918
btm_pm_on_mode_change(tHCI_STATUS status,uint16_t handle,tHCI_MODE current_mode,uint16_t interval)919 void btm_pm_on_mode_change(tHCI_STATUS status, uint16_t handle, tHCI_MODE current_mode,
920 uint16_t interval) {
921 btm_sco_chk_pend_unpark(status, handle);
922 btm_pm_proc_mode_change(status, handle, current_mode, interval);
923 }
924