1 /*
2 * Copyright (c) 2020 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8
9 #include <zephyr/sys/byteorder.h>
10 #include <zephyr/sys/slist.h>
11 #include <zephyr/sys/util.h>
12
13 #include <zephyr/bluetooth/hci_types.h>
14
15 #include "hal/ccm.h"
16
17 #include "util/util.h"
18 #include "util/mem.h"
19 #include "util/memq.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 "ll.h"
27 #include "ll_settings.h"
28
29 #include "lll.h"
30 #include "lll/lll_df_types.h"
31 #include "lll_conn.h"
32 #include "lll_conn_iso.h"
33
34 #include "ull_tx_queue.h"
35
36 #include "isoal.h"
37 #include "ull_iso_types.h"
38 #include "ull_conn_iso_types.h"
39 #include "ull_conn_iso_internal.h"
40
41 #include "ull_conn_types.h"
42 #include "ull_llcp.h"
43 #include "ull_llcp_internal.h"
44 #include "ull_conn_internal.h"
45
46 #include <soc.h>
47 #include "hal/debug.h"
48
49 /* Hardcoded instant delta +6 */
50 #define CHMU_INSTANT_DELTA 6U
51
52 /* LLCP Local Procedure Channel Map Update FSM states */
53 enum {
54 LP_CHMU_STATE_IDLE = LLCP_STATE_IDLE,
55 LP_CHMU_STATE_WAIT_TX_CHAN_MAP_IND,
56 LP_CHMU_STATE_WAIT_INSTANT,
57 };
58
59 /* LLCP Local Procedure Channel Map Update FSM events */
60 enum {
61 /* Procedure run */
62 LP_CHMU_EVT_RUN,
63 };
64
65 /* LLCP Remote Procedure Channel Map Update FSM states */
66 enum {
67 RP_CHMU_STATE_IDLE = LLCP_STATE_IDLE,
68 RP_CHMU_STATE_WAIT_RX_CHAN_MAP_IND,
69 RP_CHMU_STATE_WAIT_INSTANT,
70 };
71
72 /* LLCP Remote Procedure Channel Map Update FSM events */
73 enum {
74 /* Procedure run */
75 RP_CHMU_EVT_RUN,
76
77 /* Indication received */
78 RP_CHMU_EVT_RX_CHAN_MAP_IND,
79 };
80
81 #if defined(CONFIG_BT_CENTRAL)
82 /*
83 * LLCP Local Procedure Channel Map Update FSM
84 */
lp_chmu_tx(struct ll_conn * conn,struct proc_ctx * ctx)85 static void lp_chmu_tx(struct ll_conn *conn, struct proc_ctx *ctx)
86 {
87 struct node_tx *tx;
88 struct pdu_data *pdu;
89
90 /* Allocate tx node */
91 tx = llcp_tx_alloc(conn, ctx);
92 LL_ASSERT(tx);
93
94 pdu = (struct pdu_data *)tx->pdu;
95
96 /* Encode LL Control PDU */
97 llcp_pdu_encode_chan_map_update_ind(ctx, pdu);
98
99 ctx->tx_opcode = pdu->llctrl.opcode;
100
101 /* Enqueue LL Control PDU towards LLL */
102 llcp_tx_enqueue(conn, tx);
103 }
104
lp_chmu_complete(struct ll_conn * conn,struct proc_ctx * ctx,uint8_t evt,void * param)105 static void lp_chmu_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param)
106 {
107 ull_conn_chan_map_set(conn, ctx->data.chmu.chm);
108 llcp_lr_complete(conn);
109 ctx->state = LP_CHMU_STATE_IDLE;
110 }
111
lp_chmu_send_channel_map_update_ind(struct ll_conn * conn,struct proc_ctx * ctx,uint8_t evt,void * param)112 static void lp_chmu_send_channel_map_update_ind(struct ll_conn *conn, struct proc_ctx *ctx,
113 uint8_t evt, void *param)
114 {
115 if (llcp_lr_ispaused(conn) || llcp_rr_get_collision(conn) ||
116 !llcp_tx_alloc_peek(conn, ctx)) {
117 ctx->state = LP_CHMU_STATE_WAIT_TX_CHAN_MAP_IND;
118 } else {
119 llcp_rr_set_incompat(conn, INCOMPAT_RESOLVABLE);
120
121 ctx->data.chmu.instant = ull_conn_event_counter(conn) + conn->lll.latency +
122 CHMU_INSTANT_DELTA;
123
124 lp_chmu_tx(conn, ctx);
125
126 ctx->state = LP_CHMU_STATE_WAIT_INSTANT;
127 }
128 }
129
lp_chmu_st_wait_tx_chan_map_ind(struct ll_conn * conn,struct proc_ctx * ctx,uint8_t evt,void * param)130 static void lp_chmu_st_wait_tx_chan_map_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
131 void *param)
132 {
133 switch (evt) {
134 case LP_CHMU_EVT_RUN:
135 lp_chmu_send_channel_map_update_ind(conn, ctx, evt, param);
136 break;
137 default:
138 /* Ignore other evts */
139 break;
140 }
141 }
142
lp_chmu_check_instant(struct ll_conn * conn,struct proc_ctx * ctx,uint8_t evt,void * param)143 static void lp_chmu_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
144 void *param)
145 {
146 uint16_t event_counter = ull_conn_event_counter_at_prepare(conn);
147
148 if (is_instant_reached_or_passed(ctx->data.chmu.instant, event_counter)) {
149 llcp_rr_set_incompat(conn, INCOMPAT_NO_COLLISION);
150 lp_chmu_complete(conn, ctx, evt, param);
151 }
152 }
153
lp_chmu_st_wait_instant(struct ll_conn * conn,struct proc_ctx * ctx,uint8_t evt,void * param)154 static void lp_chmu_st_wait_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
155 void *param)
156 {
157 switch (evt) {
158 case LP_CHMU_EVT_RUN:
159 lp_chmu_check_instant(conn, ctx, evt, param);
160 break;
161 default:
162 /* Ignore other evts */
163 break;
164 }
165 }
166
lp_chmu_execute_fsm(struct ll_conn * conn,struct proc_ctx * ctx,uint8_t evt,void * param)167 static void lp_chmu_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
168 void *param)
169 {
170 switch (ctx->state) {
171 case LP_CHMU_STATE_IDLE:
172 /* Empty/fallthrough on purpose as idle state handling is equivalent to
173 * 'wait for tx state' - simply to attempt TX'ing chan map ind
174 */
175 case LP_CHMU_STATE_WAIT_TX_CHAN_MAP_IND:
176 lp_chmu_st_wait_tx_chan_map_ind(conn, ctx, evt, param);
177 break;
178 case LP_CHMU_STATE_WAIT_INSTANT:
179 lp_chmu_st_wait_instant(conn, ctx, evt, param);
180 break;
181 default:
182 /* Unknown state */
183 LL_ASSERT(0);
184 }
185 }
186
llcp_lp_chmu_rx(struct ll_conn * conn,struct proc_ctx * ctx,struct node_rx_pdu * rx)187 void llcp_lp_chmu_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx)
188 {
189 struct pdu_data *pdu = (struct pdu_data *)rx->pdu;
190
191 switch (pdu->llctrl.opcode) {
192 default:
193 /* Invalid behaviour */
194 /* Invalid PDU received so terminate connection */
195 conn->llcp_terminate.reason_final = BT_HCI_ERR_LMP_PDU_NOT_ALLOWED;
196 llcp_lr_complete(conn);
197 ctx->state = LP_CHMU_STATE_IDLE;
198 break;
199 }
200 }
201
llcp_lp_chmu_run(struct ll_conn * conn,struct proc_ctx * ctx,void * param)202 void llcp_lp_chmu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param)
203 {
204 lp_chmu_execute_fsm(conn, ctx, LP_CHMU_EVT_RUN, param);
205 }
206
llcp_lp_chmu_awaiting_instant(struct proc_ctx * ctx)207 bool llcp_lp_chmu_awaiting_instant(struct proc_ctx *ctx)
208 {
209 return (ctx->state == LP_CHMU_STATE_WAIT_INSTANT);
210 }
211 #endif /* CONFIG_BT_CENTRAL */
212
213 #if defined(CONFIG_BT_PERIPHERAL)
214 /*
215 * LLCP Remote Procedure Channel Map Update FSM
216 */
rp_chmu_complete(struct ll_conn * conn,struct proc_ctx * ctx,uint8_t evt,void * param)217 static void rp_chmu_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param)
218 {
219 ull_conn_chan_map_set(conn, ctx->data.chmu.chm);
220 llcp_rr_complete(conn);
221 ctx->state = RP_CHMU_STATE_IDLE;
222 }
223
rp_chmu_st_idle(struct ll_conn * conn,struct proc_ctx * ctx,uint8_t evt,void * param)224 static void rp_chmu_st_idle(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param)
225 {
226 switch (evt) {
227 case RP_CHMU_EVT_RUN:
228 ctx->state = RP_CHMU_STATE_WAIT_RX_CHAN_MAP_IND;
229 break;
230 default:
231 /* Ignore other evts */
232 break;
233 }
234 }
235
rp_chmu_st_wait_rx_channel_map_update_ind(struct ll_conn * conn,struct proc_ctx * ctx,uint8_t evt,void * param)236 static void rp_chmu_st_wait_rx_channel_map_update_ind(struct ll_conn *conn, struct proc_ctx *ctx,
237 uint8_t evt, void *param)
238 {
239 switch (evt) {
240 case RP_CHMU_EVT_RX_CHAN_MAP_IND:
241 llcp_pdu_decode_chan_map_update_ind(ctx, param);
242 if (is_instant_not_passed(ctx->data.chmu.instant,
243 ull_conn_event_counter(conn))) {
244
245 ctx->state = RP_CHMU_STATE_WAIT_INSTANT;
246 } else {
247 conn->llcp_terminate.reason_final = BT_HCI_ERR_INSTANT_PASSED;
248 llcp_rr_complete(conn);
249 ctx->state = RP_CHMU_STATE_IDLE;
250 }
251 break;
252 default:
253 /* Ignore other evts */
254 break;
255 }
256 }
257
rp_chmu_check_instant(struct ll_conn * conn,struct proc_ctx * ctx,uint8_t evt,void * param)258 static void rp_chmu_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
259 void *param)
260 {
261 uint16_t event_counter = ull_conn_event_counter_at_prepare(conn);
262
263 if (((event_counter - ctx->data.chmu.instant) & 0xFFFF) <= 0x7FFF) {
264 rp_chmu_complete(conn, ctx, evt, param);
265 }
266 }
267
rp_chmu_st_wait_instant(struct ll_conn * conn,struct proc_ctx * ctx,uint8_t evt,void * param)268 static void rp_chmu_st_wait_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
269 void *param)
270 {
271 switch (evt) {
272 case RP_CHMU_EVT_RUN:
273 rp_chmu_check_instant(conn, ctx, evt, param);
274 break;
275 default:
276 /* Ignore other evts */
277 break;
278 }
279 }
280
rp_chmu_execute_fsm(struct ll_conn * conn,struct proc_ctx * ctx,uint8_t evt,void * param)281 static void rp_chmu_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
282 void *param)
283 {
284 switch (ctx->state) {
285 case RP_CHMU_STATE_IDLE:
286 rp_chmu_st_idle(conn, ctx, evt, param);
287 break;
288 case RP_CHMU_STATE_WAIT_RX_CHAN_MAP_IND:
289 rp_chmu_st_wait_rx_channel_map_update_ind(conn, ctx, evt, param);
290 break;
291 case RP_CHMU_STATE_WAIT_INSTANT:
292 rp_chmu_st_wait_instant(conn, ctx, evt, param);
293 break;
294 default:
295 /* Unknown state */
296 LL_ASSERT(0);
297 }
298 }
299
llcp_rp_chmu_rx(struct ll_conn * conn,struct proc_ctx * ctx,struct node_rx_pdu * rx)300 void llcp_rp_chmu_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx)
301 {
302 struct pdu_data *pdu = (struct pdu_data *)rx->pdu;
303
304 switch (pdu->llctrl.opcode) {
305 case PDU_DATA_LLCTRL_TYPE_CHAN_MAP_IND:
306 rp_chmu_execute_fsm(conn, ctx, RP_CHMU_EVT_RX_CHAN_MAP_IND, pdu);
307 break;
308 default:
309 /* Invalid behaviour */
310 /* Invalid PDU received so terminate connection */
311 conn->llcp_terminate.reason_final = BT_HCI_ERR_LMP_PDU_NOT_ALLOWED;
312 llcp_rr_complete(conn);
313 ctx->state = RP_CHMU_STATE_IDLE;
314 break;
315 }
316 }
317
llcp_rp_chmu_run(struct ll_conn * conn,struct proc_ctx * ctx,void * param)318 void llcp_rp_chmu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param)
319 {
320 rp_chmu_execute_fsm(conn, ctx, RP_CHMU_EVT_RUN, param);
321 }
322
llcp_rp_chmu_awaiting_instant(struct proc_ctx * ctx)323 bool llcp_rp_chmu_awaiting_instant(struct proc_ctx *ctx)
324 {
325 return (ctx->state == RP_CHMU_STATE_WAIT_INSTANT);
326 }
327 #endif /* CONFIG_BT_PERIPHERAL */
328