1 /*
2  * Copyright (c) 2018-2021 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /* The Aux Offset shall be at least the length of the packet plus T_MAFS */
8 #define PDU_ADV_AUX_OFFSET_MIN_US 300
9 
10 #if defined(CONFIG_BT_CTLR_ADV_PDU_LINK)
11 #define PDU_ADV_MEM_SIZE       MROUND(PDU_AC_LL_HEADER_SIZE + \
12 				      PDU_AC_PAYLOAD_SIZE_MAX + \
13 				      sizeof(uintptr_t))
14 #define PDU_ADV_NEXT_PTR(p)    *(struct pdu_adv **)((uint8_t *)(p) + \
15 						    PDU_ADV_MEM_SIZE - \
16 						    sizeof(uintptr_t))
17 #else
18 #define PDU_ADV_MEM_SIZE       MROUND(PDU_AC_LL_HEADER_SIZE + \
19 				      PDU_AC_PAYLOAD_SIZE_MAX)
20 #endif
21 
22 int lll_adv_data_init(struct lll_adv_pdu *pdu);
23 int lll_adv_data_reset(struct lll_adv_pdu *pdu);
24 int lll_adv_data_dequeue(struct lll_adv_pdu *pdu);
25 int lll_adv_data_release(struct lll_adv_pdu *pdu);
26 
lll_adv_pdu_enqueue(struct lll_adv_pdu * pdu,uint8_t idx)27 static inline void lll_adv_pdu_enqueue(struct lll_adv_pdu *pdu, uint8_t idx)
28 {
29 	pdu->last = idx;
30 }
31 
32 struct pdu_adv *lll_adv_pdu_alloc(struct lll_adv_pdu *pdu, uint8_t *idx);
33 struct pdu_adv *lll_adv_pdu_alloc_pdu_adv(void);
34 
lll_adv_data_alloc(struct lll_adv * lll,uint8_t * idx)35 static inline struct pdu_adv *lll_adv_data_alloc(struct lll_adv *lll,
36 						 uint8_t *idx)
37 {
38 	return lll_adv_pdu_alloc(&lll->adv_data, idx);
39 }
40 
lll_adv_data_enqueue(struct lll_adv * lll,uint8_t idx)41 static inline void lll_adv_data_enqueue(struct lll_adv *lll, uint8_t idx)
42 {
43 	lll_adv_pdu_enqueue(&lll->adv_data, idx);
44 }
45 
lll_adv_data_peek(struct lll_adv * lll)46 static inline struct pdu_adv *lll_adv_data_peek(struct lll_adv *lll)
47 {
48 	return (void *)lll->adv_data.pdu[lll->adv_data.last];
49 }
50 
lll_adv_data_curr_get(struct lll_adv * lll)51 static inline struct pdu_adv *lll_adv_data_curr_get(struct lll_adv *lll)
52 {
53 	return (void *)lll->adv_data.pdu[lll->adv_data.first];
54 }
55 
lll_adv_scan_rsp_alloc(struct lll_adv * lll,uint8_t * idx)56 static inline struct pdu_adv *lll_adv_scan_rsp_alloc(struct lll_adv *lll,
57 						     uint8_t *idx)
58 {
59 	return lll_adv_pdu_alloc(&lll->scan_rsp, idx);
60 }
61 
lll_adv_scan_rsp_enqueue(struct lll_adv * lll,uint8_t idx)62 static inline void lll_adv_scan_rsp_enqueue(struct lll_adv *lll, uint8_t idx)
63 {
64 	lll_adv_pdu_enqueue(&lll->scan_rsp, idx);
65 }
66 
lll_adv_scan_rsp_peek(const struct lll_adv * lll)67 static inline struct pdu_adv *lll_adv_scan_rsp_peek(const struct lll_adv *lll)
68 {
69 	return (void *)lll->scan_rsp.pdu[lll->scan_rsp.last];
70 }
71 
72 static inline struct pdu_adv *
lll_adv_pdu_latest_peek(const struct lll_adv_pdu * const pdu)73 lll_adv_pdu_latest_peek(const struct lll_adv_pdu *const pdu)
74 {
75 	uint8_t first;
76 
77 	first = pdu->first;
78 	if (first != pdu->last) {
79 		first += 1U;
80 		if (first == DOUBLE_BUFFER_SIZE) {
81 			first = 0U;
82 		}
83 	}
84 
85 	return (void *)pdu->pdu[first];
86 }
87 
88 static inline struct pdu_adv *
lll_adv_data_latest_peek(const struct lll_adv * const lll)89 lll_adv_data_latest_peek(const struct lll_adv *const lll)
90 {
91 	return lll_adv_pdu_latest_peek(&lll->adv_data);
92 }
93 
94 #if defined(CONFIG_BT_CTLR_ADV_EXT)
lll_adv_aux_data_init(struct lll_adv_pdu * pdu)95 static inline int lll_adv_aux_data_init(struct lll_adv_pdu *pdu)
96 {
97 	return lll_adv_data_init(pdu);
98 }
99 
lll_adv_aux_data_alloc(struct lll_adv_aux * lll,uint8_t * idx)100 static inline struct pdu_adv *lll_adv_aux_data_alloc(struct lll_adv_aux *lll,
101 						     uint8_t *idx)
102 {
103 	return lll_adv_pdu_alloc(&lll->data, idx);
104 }
105 
lll_adv_aux_data_enqueue(struct lll_adv_aux * lll,uint8_t idx)106 static inline void lll_adv_aux_data_enqueue(struct lll_adv_aux *lll,
107 					    uint8_t idx)
108 {
109 	lll_adv_pdu_enqueue(&lll->data, idx);
110 }
111 
112 static inline struct pdu_adv *
lll_adv_aux_data_peek(const struct lll_adv_aux * const lll)113 	lll_adv_aux_data_peek(const struct lll_adv_aux *const lll)
114 {
115 	return (void *)lll->data.pdu[lll->data.last];
116 }
117 
118 static inline struct pdu_adv *
lll_adv_aux_data_latest_peek(const struct lll_adv_aux * const lll)119 lll_adv_aux_data_latest_peek(const struct lll_adv_aux *const lll)
120 {
121 	return lll_adv_pdu_latest_peek(&lll->data);
122 }
123 
lll_adv_aux_data_curr_get(struct lll_adv_aux * lll)124 static inline struct pdu_adv *lll_adv_aux_data_curr_get(struct lll_adv_aux *lll)
125 {
126 	return (void *)lll->data.pdu[lll->data.first];
127 }
128 
lll_adv_aux_scan_rsp_alloc(struct lll_adv * lll,uint8_t * idx)129 static inline struct pdu_adv *lll_adv_aux_scan_rsp_alloc(struct lll_adv *lll,
130 							 uint8_t *idx)
131 {
132 	return lll_adv_pdu_alloc(&lll->scan_rsp, idx);
133 }
134 
135 
136 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
137 int lll_adv_and_extra_data_release(struct lll_adv_pdu *pdu);
138 
139 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK)
140 void lll_adv_sync_pdu_b2b_update(struct lll_adv_sync *lll, uint8_t idx);
141 #endif
142 
lll_adv_sync_data_init(struct lll_adv_pdu * pdu)143 static inline int lll_adv_sync_data_init(struct lll_adv_pdu *pdu)
144 {
145 	return lll_adv_data_init(pdu);
146 }
147 
148 struct pdu_adv *lll_adv_pdu_and_extra_data_alloc(struct lll_adv_pdu *pdu,
149 						 void **extra_data,
150 						 uint8_t *idx);
151 
lll_adv_sync_data_alloc(struct lll_adv_sync * lll,void ** extra_data,uint8_t * idx)152 static inline struct pdu_adv *lll_adv_sync_data_alloc(struct lll_adv_sync *lll,
153 						      void **extra_data,
154 						      uint8_t *idx)
155 {
156 #if defined(CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY)
157 	return lll_adv_pdu_and_extra_data_alloc(&lll->data, extra_data, idx);
158 #else
159 	return lll_adv_pdu_alloc(&lll->data, idx);
160 #endif /* CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY */
161 }
162 
lll_adv_sync_data_release(struct lll_adv_sync * lll)163 static inline void lll_adv_sync_data_release(struct lll_adv_sync *lll)
164 {
165 #if defined(CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY)
166 	lll_adv_and_extra_data_release(&lll->data);
167 #else
168 	lll_adv_data_release(&lll->data);
169 #endif /* CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY */
170 }
171 
lll_adv_sync_data_enqueue(struct lll_adv_sync * lll,uint8_t idx)172 static inline void lll_adv_sync_data_enqueue(struct lll_adv_sync *lll,
173 					     uint8_t idx)
174 {
175 	lll_adv_pdu_enqueue(&lll->data, idx);
176 }
177 
178 static inline struct pdu_adv *
lll_adv_sync_data_peek(const struct lll_adv_sync * lll,void ** extra_data)179 lll_adv_sync_data_peek(const struct lll_adv_sync *lll, void **extra_data)
180 {
181 	uint8_t last = lll->data.last;
182 
183 #if defined(CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY)
184 	if (extra_data) {
185 		*extra_data = lll->data.extra_data[last];
186 	}
187 #endif /* CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY */
188 
189 	return (void *)lll->data.pdu[last];
190 }
191 
192 static inline struct pdu_adv *
lll_adv_sync_data_latest_peek(const struct lll_adv_sync * const lll)193 lll_adv_sync_data_latest_peek(const struct lll_adv_sync *const lll)
194 {
195 	return lll_adv_pdu_latest_peek(&lll->data);
196 }
197 
lll_adv_sync_data_curr_get(struct lll_adv_sync * lll)198 static inline struct pdu_adv *lll_adv_sync_data_curr_get(struct lll_adv_sync *lll)
199 {
200 	return (void *)lll->data.pdu[lll->data.first];
201 }
202 
203 #if defined(CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY)
lll_adv_sync_extra_data_peek(struct lll_adv_sync * lll)204 static inline void *lll_adv_sync_extra_data_peek(struct lll_adv_sync *lll)
205 {
206 	return lll->data.extra_data[lll->data.last];
207 }
208 
lll_adv_sync_extra_data_curr_get(struct lll_adv_sync * lll)209 static inline void *lll_adv_sync_extra_data_curr_get(struct lll_adv_sync *lll)
210 {
211 	return lll->data.extra_data[lll->data.first];
212 }
213 #endif /* CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY */
214 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
215 #endif /* CONFIG_BT_CTLR_ADV_EXT */
216 
217 #if defined(CONFIG_BT_CTLR_ADV_PDU_LINK)
218 /* Release PDU and all linked PDUs, shall only be called from ULL */
219 void lll_adv_pdu_linked_release_all(struct pdu_adv *pdu_first);
220 
lll_adv_pdu_linked_next_get(const struct pdu_adv * pdu)221 static inline struct pdu_adv *lll_adv_pdu_linked_next_get(const struct pdu_adv *pdu)
222 {
223 	return PDU_ADV_NEXT_PTR(pdu);
224 }
225 
lll_adv_pdu_linked_last_get(struct pdu_adv * pdu)226 static inline struct pdu_adv *lll_adv_pdu_linked_last_get(struct pdu_adv *pdu)
227 {
228 	while (PDU_ADV_NEXT_PTR(pdu)) {
229 		pdu = PDU_ADV_NEXT_PTR(pdu);
230 	}
231 	return pdu;
232 }
233 
lll_adv_pdu_linked_append(struct pdu_adv * pdu,struct pdu_adv * prev)234 static inline void lll_adv_pdu_linked_append(struct pdu_adv *pdu,
235 					     struct pdu_adv *prev)
236 {
237 	PDU_ADV_NEXT_PTR(prev) = pdu;
238 }
239 
lll_adv_pdu_linked_append_end(struct pdu_adv * pdu,struct pdu_adv * first)240 static inline void lll_adv_pdu_linked_append_end(struct pdu_adv *pdu,
241 						 struct pdu_adv *first)
242 {
243 	struct pdu_adv *last;
244 
245 	last = lll_adv_pdu_linked_last_get(first);
246 	lll_adv_pdu_linked_append(pdu, last);
247 }
248 #endif
249