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