1 /*
2 * Copyright (c) 2020 Demant
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/mayfly.h"
21 #include "util/dbuf.h"
22
23 #include "pdu_df.h"
24 #include "lll/pdu_vendor.h"
25 #include "pdu.h"
26
27 #include "ll.h"
28 #include "ll_settings.h"
29
30 #include "lll.h"
31 #include "lll/lll_df_types.h"
32 #include "lll_conn.h"
33 #include "lll_conn_iso.h"
34
35 #include "ull_tx_queue.h"
36
37 #include "isoal.h"
38 #include "ull_internal.h"
39 #include "ull_iso_types.h"
40 #include "ull_conn_iso_types.h"
41 #include "ull_conn_iso_internal.h"
42
43 #include "ull_conn_types.h"
44 #include "ull_llcp.h"
45 #include "ull_llcp_internal.h"
46 #include "ull_conn_internal.h"
47
48 #include <soc.h>
49 #include "hal/debug.h"
50
51 static struct proc_ctx *lr_dequeue(struct ll_conn *conn);
52
53 /* LLCP Local Request FSM State */
54 enum lr_state {
55 LR_STATE_IDLE,
56 LR_STATE_ACTIVE,
57 LR_STATE_DISCONNECT,
58 LR_STATE_TERMINATE,
59 };
60
61 /* LLCP Local Request FSM Event */
62 enum {
63 /* Procedure run */
64 LR_EVT_RUN,
65
66 /* Procedure completed */
67 LR_EVT_COMPLETE,
68
69 /* Link connected */
70 LR_EVT_CONNECT,
71
72 /* Link disconnected */
73 LR_EVT_DISCONNECT,
74 };
75
llcp_lr_check_done(struct ll_conn * conn,struct proc_ctx * ctx)76 void llcp_lr_check_done(struct ll_conn *conn, struct proc_ctx *ctx)
77 {
78 if (ctx->done) {
79 struct proc_ctx *ctx_header;
80
81 ctx_header = llcp_lr_peek(conn);
82 LL_ASSERT(ctx_header == ctx);
83
84 lr_dequeue(conn);
85
86 llcp_proc_ctx_release(ctx);
87 }
88 }
89
90 /*
91 * LLCP Local Request Shared Data Locking
92 */
93
shared_data_access_lock(void)94 static ALWAYS_INLINE uint32_t shared_data_access_lock(void)
95 {
96 bool enabled;
97
98 if (mayfly_is_running()) {
99 /* We are in Mayfly context, nothing to be done */
100 return false;
101 }
102
103 /* We are in thread context and have to disable TICKER_USER_ID_ULL_HIGH */
104 enabled = mayfly_is_enabled(TICKER_USER_ID_THREAD, TICKER_USER_ID_ULL_HIGH) != 0U;
105 mayfly_enable(TICKER_USER_ID_THREAD, TICKER_USER_ID_ULL_HIGH, 0U);
106
107 return enabled;
108 }
109
shared_data_access_unlock(bool key)110 static ALWAYS_INLINE void shared_data_access_unlock(bool key)
111 {
112 if (key) {
113 /* We are in thread context and have to reenable TICKER_USER_ID_ULL_HIGH */
114 mayfly_enable(TICKER_USER_ID_THREAD, TICKER_USER_ID_ULL_HIGH, 1U);
115 }
116 }
117
118 /*
119 * LLCP Local Request FSM
120 */
121
lr_set_state(struct ll_conn * conn,enum lr_state state)122 static void lr_set_state(struct ll_conn *conn, enum lr_state state)
123 {
124 conn->llcp.local.state = state;
125 }
126
llcp_lr_enqueue(struct ll_conn * conn,struct proc_ctx * ctx)127 void llcp_lr_enqueue(struct ll_conn *conn, struct proc_ctx *ctx)
128 {
129 /* This function is called from both Thread and Mayfly (ISR),
130 * make sure only a single context have access at a time.
131 */
132
133 bool key = shared_data_access_lock();
134
135 sys_slist_append(&conn->llcp.local.pend_proc_list, &ctx->node);
136
137 shared_data_access_unlock(key);
138 }
139
lr_dequeue(struct ll_conn * conn)140 static struct proc_ctx *lr_dequeue(struct ll_conn *conn)
141 {
142 /* This function is called from both Thread and Mayfly (ISR),
143 * make sure only a single context have access at a time.
144 */
145
146 struct proc_ctx *ctx;
147
148 bool key = shared_data_access_lock();
149
150 ctx = (struct proc_ctx *)sys_slist_get(&conn->llcp.local.pend_proc_list);
151
152 shared_data_access_unlock(key);
153
154 return ctx;
155 }
156
llcp_lr_peek(struct ll_conn * conn)157 struct proc_ctx *llcp_lr_peek(struct ll_conn *conn)
158 {
159 /* This function is called from both Thread and Mayfly (ISR),
160 * make sure only a single context have access at a time.
161 */
162 struct proc_ctx *ctx;
163
164 bool key = shared_data_access_lock();
165
166 ctx = (struct proc_ctx *)sys_slist_peek_head(&conn->llcp.local.pend_proc_list);
167
168 shared_data_access_unlock(key);
169
170 return ctx;
171 }
172
llcp_lr_peek_proc(struct ll_conn * conn,uint8_t proc)173 struct proc_ctx *llcp_lr_peek_proc(struct ll_conn *conn, uint8_t proc)
174 {
175 /* This function is called from both Thread and Mayfly (ISR),
176 * make sure only a single context have access at a time.
177 */
178
179 struct proc_ctx *ctx, *tmp;
180
181 bool key = shared_data_access_lock();
182
183 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&conn->llcp.local.pend_proc_list, ctx, tmp, node) {
184 if (ctx->proc == proc) {
185 break;
186 }
187 }
188
189 shared_data_access_unlock(key);
190
191 return ctx;
192 }
193
llcp_lr_ispaused(struct ll_conn * conn)194 bool llcp_lr_ispaused(struct ll_conn *conn)
195 {
196 return conn->llcp.local.pause == 1U;
197 }
198
llcp_lr_pause(struct ll_conn * conn)199 void llcp_lr_pause(struct ll_conn *conn)
200 {
201 conn->llcp.local.pause = 1U;
202 }
203
llcp_lr_resume(struct ll_conn * conn)204 void llcp_lr_resume(struct ll_conn *conn)
205 {
206 conn->llcp.local.pause = 0U;
207 }
208
llcp_lr_prt_restart(struct ll_conn * conn)209 void llcp_lr_prt_restart(struct ll_conn *conn)
210 {
211 conn->llcp.local.prt_expire = conn->llcp.prt_reload;
212 }
213
llcp_lr_prt_restart_with_value(struct ll_conn * conn,uint16_t value)214 void llcp_lr_prt_restart_with_value(struct ll_conn *conn, uint16_t value)
215 {
216 conn->llcp.local.prt_expire = value;
217 }
218
llcp_lr_prt_stop(struct ll_conn * conn)219 void llcp_lr_prt_stop(struct ll_conn *conn)
220 {
221 conn->llcp.local.prt_expire = 0U;
222 }
223
llcp_lr_flush_procedures(struct ll_conn * conn)224 void llcp_lr_flush_procedures(struct ll_conn *conn)
225 {
226 struct proc_ctx *ctx;
227
228 /* Flush all pending procedures */
229 ctx = lr_dequeue(conn);
230 while (ctx) {
231 llcp_nodes_release(conn, ctx);
232 llcp_proc_ctx_release(ctx);
233 ctx = lr_dequeue(conn);
234 }
235 }
236
llcp_lr_rx(struct ll_conn * conn,struct proc_ctx * ctx,memq_link_t * link,struct node_rx_pdu * rx)237 void llcp_lr_rx(struct ll_conn *conn, struct proc_ctx *ctx, memq_link_t *link,
238 struct node_rx_pdu *rx)
239 {
240 /* Store RX node and link */
241 ctx->node_ref.rx = rx;
242 ctx->node_ref.link = link;
243
244 switch (ctx->proc) {
245 #if defined(CONFIG_BT_CTLR_LE_PING)
246 case PROC_LE_PING:
247 llcp_lp_comm_rx(conn, ctx, rx);
248 break;
249 #endif /* CONFIG_BT_CTLR_LE_PING */
250 case PROC_FEATURE_EXCHANGE:
251 llcp_lp_comm_rx(conn, ctx, rx);
252 break;
253 #if defined(CONFIG_BT_CTLR_MIN_USED_CHAN)
254 case PROC_MIN_USED_CHANS:
255 llcp_lp_comm_rx(conn, ctx, rx);
256 break;
257 #endif /* CONFIG_BT_CTLR_MIN_USED_CHAN */
258 case PROC_VERSION_EXCHANGE:
259 llcp_lp_comm_rx(conn, ctx, rx);
260 break;
261 #if defined(CONFIG_BT_CTLR_LE_ENC) && defined(CONFIG_BT_CENTRAL)
262 case PROC_ENCRYPTION_START:
263 case PROC_ENCRYPTION_PAUSE:
264 llcp_lp_enc_rx(conn, ctx, rx);
265 break;
266 #endif /* CONFIG_BT_CTLR_LE_ENC && CONFIG_BT_CENTRAL */
267 #ifdef CONFIG_BT_CTLR_PHY
268 case PROC_PHY_UPDATE:
269 llcp_lp_pu_rx(conn, ctx, rx);
270 break;
271 #endif /* CONFIG_BT_CTLR_PHY */
272 case PROC_CONN_UPDATE:
273 case PROC_CONN_PARAM_REQ:
274 llcp_lp_cu_rx(conn, ctx, rx);
275 break;
276 case PROC_TERMINATE:
277 llcp_lp_comm_rx(conn, ctx, rx);
278 break;
279 #if defined(CONFIG_BT_CENTRAL)
280 case PROC_CHAN_MAP_UPDATE:
281 llcp_lp_chmu_rx(conn, ctx, rx);
282 break;
283 #endif /* CONFIG_BT_CENTRAL */
284 #if defined(CONFIG_BT_CTLR_DATA_LENGTH)
285 case PROC_DATA_LENGTH_UPDATE:
286 llcp_lp_comm_rx(conn, ctx, rx);
287 break;
288 #endif /* CONFIG_BT_CTLR_DATA_LENGTH */
289 #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ)
290 case PROC_CTE_REQ:
291 llcp_lp_comm_rx(conn, ctx, rx);
292 break;
293 #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
294 #if defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
295 case PROC_CIS_TERMINATE:
296 llcp_lp_comm_rx(conn, ctx, rx);
297 break;
298 #endif /* defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) */
299 #if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
300 case PROC_CIS_CREATE:
301 llcp_lp_cc_rx(conn, ctx, rx);
302 break;
303 #endif /* defined(CONFIG_BT_CTLR_CENTRAL_ISO) */
304 #if defined(CONFIG_BT_CTLR_SCA_UPDATE)
305 case PROC_SCA_UPDATE:
306 llcp_lp_comm_rx(conn, ctx, rx);
307 break;
308 #endif /* CONFIG_BT_CTLR_SCA_UPDATE */
309 default:
310 /* Unknown procedure */
311 LL_ASSERT(0);
312 break;
313 }
314
315 llcp_lr_check_done(conn, ctx);
316 }
317
llcp_lr_tx_ack(struct ll_conn * conn,struct proc_ctx * ctx,struct node_tx * tx)318 void llcp_lr_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, struct node_tx *tx)
319 {
320 switch (ctx->proc) {
321 #if defined(CONFIG_BT_CTLR_MIN_USED_CHAN)
322 case PROC_MIN_USED_CHANS:
323 llcp_lp_comm_tx_ack(conn, ctx, tx);
324 break;
325 #endif /* CONFIG_BT_CTLR_MIN_USED_CHAN */
326 case PROC_TERMINATE:
327 llcp_lp_comm_tx_ack(conn, ctx, tx);
328 break;
329 #if defined(CONFIG_BT_CTLR_DATA_LENGTH)
330 case PROC_DATA_LENGTH_UPDATE:
331 llcp_lp_comm_tx_ack(conn, ctx, tx);
332 break;
333 #endif /* CONFIG_BT_CTLR_DATA_LENGTH */
334 #ifdef CONFIG_BT_CTLR_PHY
335 case PROC_PHY_UPDATE:
336 llcp_lp_pu_tx_ack(conn, ctx, tx);
337 break;
338 #endif /* CONFIG_BT_CTLR_PHY */
339 #if defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
340 case PROC_CIS_TERMINATE:
341 llcp_lp_comm_tx_ack(conn, ctx, tx);
342 break;
343 #endif /* defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) */
344 default:
345 break;
346 /* Ignore tx_ack */
347 }
348
349 /* Clear TX node reference */
350 ctx->node_ref.tx_ack = NULL;
351
352 llcp_lr_check_done(conn, ctx);
353 }
354
llcp_lr_tx_ntf(struct ll_conn * conn,struct proc_ctx * ctx)355 void llcp_lr_tx_ntf(struct ll_conn *conn, struct proc_ctx *ctx)
356 {
357 switch (ctx->proc) {
358 #if defined(CONFIG_BT_CTLR_PHY)
359 case PROC_PHY_UPDATE:
360 llcp_lp_pu_tx_ntf(conn, ctx);
361 break;
362 #endif /* CONFIG_BT_CTLR_PHY */
363 default:
364 /* Ignore other procedures */
365 break;
366 }
367
368 llcp_lr_check_done(conn, ctx);
369 }
370
lr_act_run(struct ll_conn * conn)371 static void lr_act_run(struct ll_conn *conn)
372 {
373 struct proc_ctx *ctx;
374
375 ctx = llcp_lr_peek(conn);
376
377 switch (ctx->proc) {
378 #if defined(CONFIG_BT_CTLR_LE_PING)
379 case PROC_LE_PING:
380 llcp_lp_comm_run(conn, ctx, NULL);
381 break;
382 #endif /* CONFIG_BT_CTLR_LE_PING */
383 case PROC_FEATURE_EXCHANGE:
384 llcp_lp_comm_run(conn, ctx, NULL);
385 break;
386 #if defined(CONFIG_BT_CTLR_MIN_USED_CHAN)
387 case PROC_MIN_USED_CHANS:
388 llcp_lp_comm_run(conn, ctx, NULL);
389 break;
390 #endif /* CONFIG_BT_CTLR_MIN_USED_CHAN */
391 case PROC_VERSION_EXCHANGE:
392 llcp_lp_comm_run(conn, ctx, NULL);
393 break;
394 #if defined(CONFIG_BT_CTLR_LE_ENC) && defined(CONFIG_BT_CENTRAL)
395 case PROC_ENCRYPTION_START:
396 case PROC_ENCRYPTION_PAUSE:
397 llcp_lp_enc_run(conn, ctx, NULL);
398 break;
399 #endif /* CONFIG_BT_CTLR_LE_ENC && CONFIG_BT_CENTRAL */
400 #ifdef CONFIG_BT_CTLR_PHY
401 case PROC_PHY_UPDATE:
402 llcp_lp_pu_run(conn, ctx, NULL);
403 break;
404 #endif /* CONFIG_BT_CTLR_PHY */
405 case PROC_CONN_UPDATE:
406 case PROC_CONN_PARAM_REQ:
407 llcp_lp_cu_run(conn, ctx, NULL);
408 break;
409 case PROC_TERMINATE:
410 llcp_lp_comm_run(conn, ctx, NULL);
411 break;
412 #if defined(CONFIG_BT_CENTRAL)
413 case PROC_CHAN_MAP_UPDATE:
414 llcp_lp_chmu_run(conn, ctx, NULL);
415 break;
416 #endif /* CONFIG_BT_CENTRAL */
417 #if defined(CONFIG_BT_CTLR_DATA_LENGTH)
418 case PROC_DATA_LENGTH_UPDATE:
419 llcp_lp_comm_run(conn, ctx, NULL);
420 break;
421 #endif /* CONFIG_BT_CTLR_DATA_LENGTH */
422 #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ)
423 case PROC_CTE_REQ:
424 /* 3rd partam null? */
425 llcp_lp_comm_run(conn, ctx, NULL);
426 break;
427 #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
428 #if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
429 case PROC_CIS_CREATE:
430 llcp_lp_cc_run(conn, ctx, NULL);
431 break;
432 #endif /* CONFIG_BT_CTLR_CENTRAL_ISO */
433 #if defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
434 case PROC_CIS_TERMINATE:
435 llcp_lp_comm_run(conn, ctx, NULL);
436 break;
437 #endif /* defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) */
438 #if defined(CONFIG_BT_CTLR_SCA_UPDATE)
439 case PROC_SCA_UPDATE:
440 llcp_lp_comm_run(conn, ctx, NULL);
441 break;
442 #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
443 default:
444 /* Unknown procedure */
445 LL_ASSERT(0);
446 break;
447 }
448
449 llcp_lr_check_done(conn, ctx);
450 }
451
lr_act_complete(struct ll_conn * conn)452 static void lr_act_complete(struct ll_conn *conn)
453 {
454 struct proc_ctx *ctx;
455
456 ctx = llcp_lr_peek(conn);
457 LL_ASSERT(ctx != NULL);
458
459 /* Stop procedure response timeout timer */
460 llcp_lr_prt_stop(conn);
461
462 /* Mark the procedure as safe to delete */
463 ctx->done = 1U;
464 }
465
lr_act_connect(struct ll_conn * conn)466 static void lr_act_connect(struct ll_conn *conn)
467 {
468 /* Empty on purpose */
469 }
470
lr_act_disconnect(struct ll_conn * conn)471 static void lr_act_disconnect(struct ll_conn *conn)
472 {
473 llcp_lr_flush_procedures(conn);
474 }
475
lr_st_disconnect(struct ll_conn * conn,uint8_t evt,void * param)476 static void lr_st_disconnect(struct ll_conn *conn, uint8_t evt, void *param)
477 {
478 switch (evt) {
479 case LR_EVT_CONNECT:
480 lr_act_connect(conn);
481 lr_set_state(conn, LR_STATE_IDLE);
482 break;
483 default:
484 /* Ignore other evts */
485 break;
486 }
487 }
488
lr_st_idle(struct ll_conn * conn,uint8_t evt,void * param)489 static void lr_st_idle(struct ll_conn *conn, uint8_t evt, void *param)
490 {
491 struct proc_ctx *ctx;
492
493 switch (evt) {
494 case LR_EVT_RUN:
495 ctx = llcp_lr_peek(conn);
496 if (ctx) {
497 /*
498 * since the call to lr_act_run may release the context we need to remember
499 * which procedure we are running
500 */
501 const enum llcp_proc curr_proc = ctx->proc;
502 lr_act_run(conn);
503 if (curr_proc != PROC_TERMINATE) {
504 lr_set_state(conn, LR_STATE_ACTIVE);
505 } else {
506 lr_set_state(conn, LR_STATE_TERMINATE);
507 }
508 }
509 break;
510 case LR_EVT_DISCONNECT:
511 lr_act_disconnect(conn);
512 lr_set_state(conn, LR_STATE_DISCONNECT);
513 break;
514 case LR_EVT_COMPLETE:
515 /* Some procedures like CTE request may be completed without actual run due to
516 * change in conditions while the procedure was waiting in a queue.
517 */
518 lr_act_complete(conn);
519 break;
520 default:
521 /* Ignore other evts */
522 break;
523 }
524 }
525
lr_st_active(struct ll_conn * conn,uint8_t evt,void * param)526 static void lr_st_active(struct ll_conn *conn, uint8_t evt, void *param)
527 {
528 switch (evt) {
529 case LR_EVT_RUN:
530 if (llcp_lr_peek(conn)) {
531 lr_act_run(conn);
532 }
533 break;
534 case LR_EVT_COMPLETE:
535 lr_act_complete(conn);
536 lr_set_state(conn, LR_STATE_IDLE);
537 break;
538 case LR_EVT_DISCONNECT:
539 lr_act_disconnect(conn);
540 lr_set_state(conn, LR_STATE_DISCONNECT);
541 break;
542 default:
543 /* Ignore other evts */
544 break;
545 }
546 }
547
lr_st_terminate(struct ll_conn * conn,uint8_t evt,void * param)548 static void lr_st_terminate(struct ll_conn *conn, uint8_t evt, void *param)
549 {
550 switch (evt) {
551 case LR_EVT_RUN:
552 if (llcp_lr_peek(conn)) {
553 lr_act_run(conn);
554 }
555 break;
556 case LR_EVT_COMPLETE:
557 lr_act_complete(conn);
558 lr_set_state(conn, LR_STATE_IDLE);
559 break;
560 case LR_EVT_DISCONNECT:
561 lr_act_disconnect(conn);
562 lr_set_state(conn, LR_STATE_DISCONNECT);
563 break;
564 default:
565 /* Ignore other evts */
566 break;
567 }
568 }
569
lr_execute_fsm(struct ll_conn * conn,uint8_t evt,void * param)570 static void lr_execute_fsm(struct ll_conn *conn, uint8_t evt, void *param)
571 {
572 switch (conn->llcp.local.state) {
573 case LR_STATE_DISCONNECT:
574 lr_st_disconnect(conn, evt, param);
575 break;
576 case LR_STATE_IDLE:
577 lr_st_idle(conn, evt, param);
578 break;
579 case LR_STATE_ACTIVE:
580 lr_st_active(conn, evt, param);
581 break;
582 case LR_STATE_TERMINATE:
583 lr_st_terminate(conn, evt, param);
584 break;
585 default:
586 /* Unknown state */
587 LL_ASSERT(0);
588 }
589 }
590
llcp_lr_init(struct ll_conn * conn)591 void llcp_lr_init(struct ll_conn *conn)
592 {
593 lr_set_state(conn, LR_STATE_DISCONNECT);
594 conn->llcp.local.prt_expire = 0U;
595 }
596
llcp_lr_run(struct ll_conn * conn)597 void llcp_lr_run(struct ll_conn *conn)
598 {
599 lr_execute_fsm(conn, LR_EVT_RUN, NULL);
600 }
601
llcp_lr_complete(struct ll_conn * conn)602 void llcp_lr_complete(struct ll_conn *conn)
603 {
604 lr_execute_fsm(conn, LR_EVT_COMPLETE, NULL);
605 }
606
llcp_lr_connect(struct ll_conn * conn)607 void llcp_lr_connect(struct ll_conn *conn)
608 {
609 lr_execute_fsm(conn, LR_EVT_CONNECT, NULL);
610 }
611
llcp_lr_disconnect(struct ll_conn * conn)612 void llcp_lr_disconnect(struct ll_conn *conn)
613 {
614 lr_execute_fsm(conn, LR_EVT_DISCONNECT, NULL);
615 }
616
llcp_lr_terminate(struct ll_conn * conn)617 void llcp_lr_terminate(struct ll_conn *conn)
618 {
619
620 llcp_lr_flush_procedures(conn);
621 llcp_lr_prt_stop(conn);
622 llcp_rr_set_incompat(conn, 0U);
623 lr_set_state(conn, LR_STATE_IDLE);
624 }
625
626 #ifdef ZTEST_UNITTEST
627
llcp_lr_is_disconnected(struct ll_conn * conn)628 bool llcp_lr_is_disconnected(struct ll_conn *conn)
629 {
630 return conn->llcp.local.state == LR_STATE_DISCONNECT;
631 }
632
llcp_lr_is_idle(struct ll_conn * conn)633 bool llcp_lr_is_idle(struct ll_conn *conn)
634 {
635 return conn->llcp.local.state == LR_STATE_IDLE;
636 }
637
llcp_lr_dequeue(struct ll_conn * conn)638 struct proc_ctx *llcp_lr_dequeue(struct ll_conn *conn)
639 {
640 return lr_dequeue(conn);
641 }
642
643 #endif
644