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