1 /*
2 * Copyright (c) 2016-2019 Nordic Semiconductor ASA
3 * Copyright (c) 2016 Vinayak Kariappa Chettimada
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <zephyr/kernel.h>
9 #include <soc.h>
10 #include <zephyr/bluetooth/hci_types.h>
11 #include <zephyr/bluetooth/hci_vs.h>
12
13 #include "hal/cpu.h"
14 #include "hal/ccm.h"
15 #include "hal/radio.h"
16
17 #include "util/util.h"
18 #include "util/memq.h"
19 #include "util/mem.h"
20 #include "util/dbuf.h"
21
22 #include "pdu_df.h"
23 #include "lll/pdu_vendor.h"
24 #include "pdu.h"
25
26 #include "lll.h"
27 #include "lll/lll_adv_types.h"
28 #include "lll_adv.h"
29 #include "lll/lll_adv_pdu.h"
30 #include "lll_scan.h"
31 #include "lll/lll_df_types.h"
32 #include "lll_conn.h"
33
34 #include "ll_sw/ull_tx_queue.h"
35
36 #include "ull_adv_types.h"
37 #include "ull_scan_types.h"
38 #include "ull_conn_types.h"
39
40 #include "ull_adv_internal.h"
41 #include "ull_scan_internal.h"
42 #include "ull_conn_internal.h"
43
44 #include "ll.h"
45
ll_tx_pwr_lvl_get(uint8_t handle_type,uint16_t handle,uint8_t type,int8_t * tx_pwr_lvl)46 uint8_t ll_tx_pwr_lvl_get(uint8_t handle_type,
47 uint16_t handle, uint8_t type, int8_t *tx_pwr_lvl)
48 {
49 switch (handle_type) {
50 #if defined(CONFIG_BT_BROADCASTER) &&\
51 defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
52 case (BT_HCI_VS_LL_HANDLE_TYPE_ADV): {
53 struct ll_adv_set *adv;
54
55 #if !defined(CONFIG_BT_CTLR_ADV_EXT)
56 /* Ignore handle if AE not enabled */
57 handle = 0;
58 #endif /* CONFIG_BT_CTLR_ADV_EXT */
59 /* Allow the app to get Tx power
60 * when advertising is off
61 */
62 adv = ull_adv_set_get(handle);
63 if (!adv) {
64 return BT_HCI_ERR_UNKNOWN_CONN_ID;
65 }
66 *tx_pwr_lvl = adv->lll.tx_pwr_lvl;
67 break;
68 }
69 #endif /* CONFIG_BT_BROADCASTER && CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
70 #if defined(CONFIG_BT_OBSERVER) &&\
71 defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
72 case (BT_HCI_VS_LL_HANDLE_TYPE_SCAN): {
73 struct ll_scan_set *scan;
74
75 /* Ignore handle in case of scanner
76 * as for mesh extensions and scanning
77 * sets this control is handled
78 * at a lower-level in the stack.
79 */
80 handle = 0;
81 /* Allow the app to get Tx power
82 * when scanning is off
83 */
84 scan = ull_scan_set_get(handle);
85 if (!scan) {
86 return BT_HCI_ERR_UNKNOWN_CONN_ID;
87 }
88 *tx_pwr_lvl = scan->lll.tx_pwr_lvl;
89 break;
90 }
91 #endif /* CONFIG_BT_OBSERVER && CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL*/
92 #if defined(CONFIG_BT_CONN)
93 case (BT_HCI_VS_LL_HANDLE_TYPE_CONN): {
94 struct ll_conn *conn;
95
96 conn = ll_connected_get(handle);
97 if (!conn) {
98 return BT_HCI_ERR_UNKNOWN_CONN_ID;
99 }
100
101 if (type) {
102 #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
103 /* Level desired is maximum available */
104 *tx_pwr_lvl = lll_radio_tx_pwr_max_get();
105 #else /* !CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
106 /* Return default if not multiple TXP */
107 *tx_pwr_lvl = RADIO_TXP_DEFAULT;
108 #endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
109 } else {
110 #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
111 /* Current level is requested */
112 *tx_pwr_lvl = conn->lll.tx_pwr_lvl;
113 #else /* !CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
114 /* Return default if not multiple TXP */
115 *tx_pwr_lvl = RADIO_TXP_DEFAULT;
116 #endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
117 }
118 break;
119 }
120 #endif /* CONFIG_BT_CONN */
121 default: {
122 return BT_HCI_ERR_UNKNOWN_CMD;
123 }
124 }
125
126 return BT_HCI_ERR_SUCCESS;
127 }
128
129
ll_tx_pwr_lvl_set(uint8_t handle_type,uint16_t handle,int8_t * const tx_pwr_lvl)130 uint8_t ll_tx_pwr_lvl_set(uint8_t handle_type, uint16_t handle,
131 int8_t *const tx_pwr_lvl)
132 {
133 #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
134 if (*tx_pwr_lvl == BT_HCI_VS_LL_TX_POWER_LEVEL_NO_PREF) {
135 /* If no preference selected, then use default Tx power */
136 *tx_pwr_lvl = RADIO_TXP_DEFAULT;
137 }
138
139 /**
140 * Check that desired Tx power matches the achievable transceiver
141 * Tx power capabilities by flooring - if selected power matches than
142 * is used, otherwise next smaller power available is used.
143 */
144 *tx_pwr_lvl = lll_radio_tx_pwr_floor(*tx_pwr_lvl);
145 #endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
146
147 switch (handle_type) {
148 #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
149 #if defined(CONFIG_BT_BROADCASTER)
150 case (BT_HCI_VS_LL_HANDLE_TYPE_ADV): {
151 struct ll_adv_set *adv;
152
153 #if !defined(CONFIG_BT_CTLR_ADV_EXT)
154 /* Ignore handle if AE not enabled */
155 handle = 0;
156 #endif /* CONFIG_BT_CTLR_ADV_EXT */
157 /* Allow the app to set Tx power
158 * prior to advertising
159 */
160 adv = ull_adv_set_get(handle);
161 if (!adv) {
162 return BT_HCI_ERR_UNKNOWN_CONN_ID;
163 }
164 adv->lll.tx_pwr_lvl = *tx_pwr_lvl;
165 break;
166 }
167 #endif /* CONFIG_BT_BROADCASTER */
168 #if defined(CONFIG_BT_OBSERVER)
169 case (BT_HCI_VS_LL_HANDLE_TYPE_SCAN): {
170 struct ll_scan_set *scan;
171
172 /* Ignore handle in case of scanner
173 * as for mesh extensions and scanning
174 * sets this control is handled
175 * at a lower-level in the stack.
176 */
177 handle = 0;
178 /* Allow the app to set Tx power
179 * prior to scanning
180 */
181 scan = ull_scan_set_get(handle);
182 if (!scan) {
183 return BT_HCI_ERR_UNKNOWN_CONN_ID;
184 }
185 scan->lll.tx_pwr_lvl = *tx_pwr_lvl;
186 break;
187 }
188 #endif /* CONFIG_BT_OBSERVER */
189 #if defined(CONFIG_BT_CONN)
190 case (BT_HCI_VS_LL_HANDLE_TYPE_CONN): {
191 struct ll_conn *conn;
192
193 conn = ll_connected_get(handle);
194 if (!conn) {
195 return BT_HCI_ERR_UNKNOWN_CONN_ID;
196 }
197 conn->lll.tx_pwr_lvl = *tx_pwr_lvl;
198 break;
199 }
200 #endif /* CONFIG_BT_CONN */
201 #endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
202 default: {
203 return BT_HCI_ERR_UNKNOWN_CMD;
204 }
205 }
206
207 return BT_HCI_ERR_SUCCESS;
208 }
209
ll_tx_pwr_get(int8_t * min,int8_t * max)210 void ll_tx_pwr_get(int8_t *min, int8_t *max)
211 {
212 #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
213 *min = lll_radio_tx_pwr_min_get();
214 *max = lll_radio_tx_pwr_max_get();
215 #else
216 *min = RADIO_TXP_DEFAULT;
217 *max = RADIO_TXP_DEFAULT;
218 #endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
219 }
220