1 /* USER CODE BEGIN Header */
2 /**
3 ******************************************************************************
4 * @file aci_adv_nwk.c
5 * @author MCD Application Team
6 * @brief Adaptation layer from stack native advertising interface
7 * to network interface.
8 ******************************************************************************
9 * @attention
10 *
11 * Copyright (c) 2024 STMicroelectronics.
12 * All rights reserved.
13 *
14 * This software is licensed under terms that can be found in the LICENSE file
15 * in the root directory of this software component.
16 * If no LICENSE file comes with this software, it is provided AS-IS.
17 *
18 ******************************************************************************
19 */
20 /* USER CODE END Header */
21
22 #include <string.h>
23 #include "aci_adv_nwk.h"
24 #include "app_common.h"
25 #include "adv_buff_alloc.h"
26 #include "adv_buff_alloc_tiny.h"
27 #include "pawr_buff_alloc.h"
28 #include "ble.h"
29
30 #define LEGACY_ADV_HANDLE 0xFE
31 #define MEM_ALLOC_OVERHEAD 8
32 #define MAX_ADV_DATA_LENGTH MIN(CFG_BLE_GATT_ADV_NWK_BUFFER_SIZE - CFG_BLE_ATT_QUEUED_WRITE_SIZE - MEM_ALLOC_OVERHEAD, 1650)
33
34 /** @name Operation codes for setting advertising data
35 * @{
36 */
37 #define INTERMEDIATE_FRAGMENT 0
38 #define FIRST_FRAGMENT 1
39 #define LAST_FRAGMENT 2
40 #define COMPLETE_DATA 3
41 #define UNCHANGED_DATA 4
42 /**
43 * @}
44 */
45
46 /** @name Options for layer parameter of set_legacy_adv_scan_data
47 * @{
48 */
49 #define LL 0
50 #define GAP 1
51 /**
52 * @}
53 */
54
55 #if (CFG_BLE_CONTROLLER_EXT_ADV_SCAN_ENABLED == 0)
56
57 static tBleStatus allocate_and_set_data_legacy(uint8_t Advertising_Handle, uint8_t Operation,
58 uint8_t Data_Length, uint8_t *Data, uint8_t adv_scan_resp, uint8_t layer);
59
60 static tBleStatus set_legacy_data_ptr(uint16_t Data_Length, uint8_t *Data, uint8_t adv_scan_resp, uint8_t layer);
61
aci_adv_nwk_init(void)62 void aci_adv_nwk_init(void)
63 {
64 adv_tiny_buff_init();
65 }
66
allocate_and_set_data(uint8_t Advertising_Handle,uint8_t Operation,uint8_t Data_Length,uint8_t * Data,uint8_t adv_scan_resp,uint8_t layer)67 static tBleStatus allocate_and_set_data(uint8_t Advertising_Handle, uint8_t Operation, uint8_t Data_Length, uint8_t *Data, uint8_t adv_scan_resp, uint8_t layer)
68 {
69 return allocate_and_set_data_legacy(Advertising_Handle, Operation, Data_Length, Data, adv_scan_resp, layer);
70 }
71
72 /* Event raised by the stack when a new data pointer becomes active.
73 The function will free the the memory pointed by the old pointer.
74 */
aci_hal_adv_scan_resp_data_update_event_preprocess(void * old_pointer,void * new_pointer)75 int aci_hal_adv_scan_resp_data_update_event_preprocess(void *old_pointer, void *new_pointer)
76 {
77 if (new_pointer != old_pointer)
78 {
79 adv_tiny_buff_free(old_pointer);
80 }
81
82 return 1;
83 }
84
85 // Advertising_Handle is actually not used
allocate_and_set_data_legacy(uint8_t Advertising_Handle,uint8_t Operation,uint8_t Data_Length,uint8_t * Data,uint8_t adv_scan_resp,uint8_t layer)86 static tBleStatus allocate_and_set_data_legacy(uint8_t Advertising_Handle, uint8_t Operation, uint8_t Data_Length, uint8_t *Data, uint8_t adv_scan_resp, uint8_t layer)
87 {
88 tBleStatus ret;
89 uint8_t *adv_buffer;
90
91 if(Operation != COMPLETE_DATA || Data_Length > 31)
92 return BLE_ERROR_INVALID_HCI_CMD_PARAMS;
93
94 adv_buffer = adv_tiny_buff_alloc();
95
96 if(adv_buffer == NULL)
97 return BLE_ERROR_CONTROLLER_BUSY;
98
99 memcpy(adv_buffer, Data, Data_Length);
100
101 ret = set_legacy_data_ptr(Data_Length, adv_buffer, adv_scan_resp, layer);
102
103 if(ret)
104 {
105 adv_tiny_buff_free(adv_buffer);
106 }
107
108 return ret;
109 }
110
set_legacy_data_ptr(uint16_t Data_Length,uint8_t * Data,uint8_t adv_scan_resp,uint8_t layer)111 static tBleStatus set_legacy_data_ptr(uint16_t Data_Length, uint8_t *Data, uint8_t adv_scan_resp, uint8_t layer)
112 {
113 if(adv_scan_resp == ADV_DATA){
114 // Advertising Data
115 #if (BLESTACK_CONTROLLER_ONLY == 0)
116 if(layer == GAP)
117 return aci_gap_set_advertising_data(0, COMPLETE_DATA, Data_Length, Data);
118 else
119 #endif
120 return ll_set_legacy_advertising_data_ptr(Data_Length, Data);
121 }
122 else{
123 // Scan Response
124 #if (BLESTACK_CONTROLLER_ONLY == 0)
125 if(layer == GAP)
126 return aci_gap_set_scan_response_data(0, Data_Length, Data);
127 else
128 #endif
129 return ll_set_legacy_scan_reponse_data_ptr(Data_Length, Data);
130 }
131 }
132
aci_gap_set_advertising_enable_preprocess(uint8_t Enable,uint8_t Number_of_Sets,Advertising_Set_Parameters_t Advertising_Set_Parameters[])133 tBleStatus aci_gap_set_advertising_enable_preprocess(uint8_t Enable,
134 uint8_t Number_of_Sets,
135 Advertising_Set_Parameters_t Advertising_Set_Parameters[])
136 {
137 return BLE_STATUS_SUCCESS;
138 }
139
140 #else /* (CFG_BLE_CONTROLLER_EXT_ADV_SCAN_ENABLED == 1) */
141
hci_le_read_maximum_advertising_data_length(uint16_t * Maximum_Advertising_Data_Length)142 tBleStatus hci_le_read_maximum_advertising_data_length(uint16_t *Maximum_Advertising_Data_Length)
143 {
144 *Maximum_Advertising_Data_Length = MAX_ADV_DATA_LENGTH;
145
146 return BLE_STATUS_SUCCESS;
147 }
148
149 static tBleStatus allocate_and_set_data_ext(uint8_t Advertising_Handle,
150 uint8_t Operation, uint8_t Data_Length, uint8_t *Data, uint8_t data_type, uint8_t layer);
151
aci_adv_nwk_init(void)152 void aci_adv_nwk_init(void)
153 {
154 adv_buff_init();
155 #if (CFG_BLE_CONTROLLER_PERIODIC_ADV_WR_ENABLED == 1)
156 pawr_buff_init();
157 #endif
158 }
159
allocate_and_set_data(uint8_t Advertising_Handle,uint8_t Operation,uint8_t Data_Length,uint8_t * Data,uint8_t data_type,uint8_t layer)160 static tBleStatus allocate_and_set_data(uint8_t Advertising_Handle, uint8_t Operation, uint8_t Data_Length, uint8_t *Data, uint8_t data_type, uint8_t layer)
161 {
162 return allocate_and_set_data_ext(Advertising_Handle, Operation, Data_Length, Data, data_type, layer);
163 }
164
hci_le_set_extended_advertising_data(uint8_t Advertising_Handle,uint8_t Operation,uint8_t Fragment_Preference,uint8_t Advertising_Data_Length,uint8_t * Advertising_Data)165 tBleStatus hci_le_set_extended_advertising_data(uint8_t Advertising_Handle, uint8_t Operation,
166 uint8_t Fragment_Preference,
167 uint8_t Advertising_Data_Length, uint8_t *Advertising_Data)
168 {
169 return allocate_and_set_data(Advertising_Handle,
170 Operation, Advertising_Data_Length, Advertising_Data, ADV_DATA, LL);
171
172 }
173
hci_le_set_extended_scan_response_data(uint8_t Advertising_Handle,uint8_t Operation,uint8_t Fragment_Preference,uint8_t Scan_Response_Data_Length,uint8_t * Scan_Response_Data)174 tBleStatus hci_le_set_extended_scan_response_data(uint8_t Advertising_Handle, uint8_t Operation,
175 uint8_t Fragment_Preference,
176 uint8_t Scan_Response_Data_Length, uint8_t *Scan_Response_Data)
177 {
178 return allocate_and_set_data(Advertising_Handle,
179 Operation, Scan_Response_Data_Length, Scan_Response_Data, SCAN_RESP_DATA, LL);
180 }
181
182 #if (CFG_BLE_CONTROLLER_PERIODIC_ADV_ENABLED == 1)
hci_le_set_periodic_advertising_data(uint8_t Advertising_Handle,uint8_t Operation,uint8_t Advertising_Data_Length,uint8_t * Advertising_Data)183 tBleStatus hci_le_set_periodic_advertising_data(uint8_t Advertising_Handle, uint8_t Operation,
184 uint8_t Advertising_Data_Length, uint8_t *Advertising_Data)
185 {
186 return allocate_and_set_data(Advertising_Handle,
187 Operation, Advertising_Data_Length, Advertising_Data, PERIODIC_ADV_DATA, LL);
188 }
189
190 #if (CFG_BLE_CONTROLLER_PERIODIC_ADV_WR_ENABLED == 1)
191
hci_le_set_periodic_advertising_subevent_data(uint8_t Advertising_Handle,uint8_t Num_Subevents,Subevent_Data_Parameters_t Subevent_Data_Parameters[])192 tBleStatus hci_le_set_periodic_advertising_subevent_data(uint8_t Advertising_Handle,
193 uint8_t Num_Subevents,
194 Subevent_Data_Parameters_t Subevent_Data_Parameters[])
195 {
196 tBleStatus ret;
197 uint8_t i;
198 void * p;
199 Subevent_Data_Ptr_Parameters_t Subevent_Data_Ptr_Parameters[CFG_BLE_PAWR_SUBEVENT_DATA_COUNT_MAX] = {0};
200 uint16_t adv_event_prop;
201 uint8_t adv_enabled, periodic_adv_configured, periodic_adv_enabled;
202
203 if (Advertising_Handle > 0xEF)
204 {
205 return BLE_ERROR_INVALID_HCI_CMD_PARAMS;
206 }
207
208 /* Check if advertising set exists, so that error 0x42 will be returned. */
209 ret = ll_get_advertising_info(Advertising_Handle, &adv_enabled, &periodic_adv_configured, &periodic_adv_enabled, &adv_event_prop);
210 if(ret!=0)
211 {
212 return BLE_ERROR_UNKNOWN_ADVERTISING_IDENTIFIER;
213 }
214
215 if(pawr_buff_subevent_num_available() < Num_Subevents)
216 {
217 /* This happens is host has given more data than what requested by the Controller. */
218 return BLE_ERROR_COMMAND_DISALLOWED;
219 }
220
221 for(i = 0; i < Num_Subevents; i++)
222 {
223 if(Subevent_Data_Parameters[i].Subevent_Data_Length > MAX_PAWR_SUBEVENT_DATA_SIZE)
224 {
225 /* This should never happen as long as MAX_PAWR_SUBEVENT_DATA_SIZE >= 249. */
226 ret = BLE_ERROR_MEMORY_CAPACITY_EXCEEDED;
227 goto fail;
228 }
229
230 p = pawr_buff_subevent_alloc();
231
232 if(p != NULL)
233 {
234 Subevent_Data_Ptr_Parameters[i].Subevent = Subevent_Data_Parameters[i].Subevent;
235 Subevent_Data_Ptr_Parameters[i].Response_Slot_Start = Subevent_Data_Parameters[i].Response_Slot_Start;
236 Subevent_Data_Ptr_Parameters[i].Response_Slot_Count = Subevent_Data_Parameters[i].Response_Slot_Count;
237 Subevent_Data_Ptr_Parameters[i].Subevent_Data_Length = Subevent_Data_Parameters[i].Subevent_Data_Length;
238 memcpy(p, Subevent_Data_Parameters[i].Subevent_Data, Subevent_Data_Parameters[i].Subevent_Data_Length);
239 Subevent_Data_Ptr_Parameters[i].Subevent_Data = p;
240 }
241 else
242 {
243 /* This should never happen since we checked num of available buffers before. */
244 goto fail;
245 }
246 }
247
248 ret = ll_set_periodic_advertising_subevent_data_ptr(Advertising_Handle,
249 Num_Subevents,
250 Subevent_Data_Ptr_Parameters);
251
252 if(ret == BLE_STATUS_SUCCESS)
253 return ret;
254
255 fail:
256
257 /* Free allocated buffers */
258 for(i = 0; i < Num_Subevents; i++)
259 {
260 pawr_buff_free(Subevent_Data_Ptr_Parameters[i].Subevent_Data, HAL_PAWR_DATA_TYPE_SUBEVENT);
261 }
262 return ret;
263 }
264
hci_le_set_periodic_advertising_response_data(uint16_t Sync_Handle,uint16_t Request_Event,uint8_t Request_Subevent,uint8_t Response_Subevent,uint8_t Response_Slot,uint8_t Response_Data_Length,uint8_t Response_Data[])265 tBleStatus hci_le_set_periodic_advertising_response_data(uint16_t Sync_Handle,
266 uint16_t Request_Event,
267 uint8_t Request_Subevent,
268 uint8_t Response_Subevent,
269 uint8_t Response_Slot,
270 uint8_t Response_Data_Length,
271 uint8_t Response_Data[])
272 {
273 tBleStatus ret;
274 void * p;
275
276 if(Response_Data_Length > MAX_PAWR_RESPONSE_DATA_SIZE)
277 {
278 /* This should never happen as long as MAX_PAWR_RESPONSE_DATA_SIZE >= 247. */
279 return BLE_ERROR_MEMORY_CAPACITY_EXCEEDED;
280 }
281
282 p = pawr_buff_resp_alloc();
283
284 if(p == NULL)
285 {
286 return BLE_ERROR_MEMORY_CAPACITY_EXCEEDED;
287 }
288
289 memcpy(p, Response_Data, Response_Data_Length);
290
291 ret = ll_set_periodic_advertising_response_data_ptr(Sync_Handle, Request_Event,
292 Request_Subevent, Response_Subevent,
293 Response_Slot, Response_Data_Length,
294 p);
295
296 if(ret != BLE_STATUS_SUCCESS)
297 {
298 pawr_buff_free(p, HAL_PAWR_DATA_TYPE_RESPONSE);
299 }
300
301 return ret;
302 }
303
304 #endif /* (CFG_BLE_CONTROLLER_PERIODIC_ADV_WR_ENABLED == 1) */
305 #endif /* (CFG_BLE_CONTROLLER_PERIODIC_ADV_ENABLED == 1) */
306
aci_hal_adv_scan_resp_data_update_event_preprocess(void * old_pointer,void * new_pointer)307 int aci_hal_adv_scan_resp_data_update_event_preprocess(void *old_pointer, void *new_pointer)
308 {
309 if (new_pointer != old_pointer)
310 {
311 adv_buff_free_old(old_pointer);
312 }
313
314 /* Do not forward the event. */
315 return 1;
316 }
317
318 #if (CFG_BLE_CONTROLLER_PERIODIC_ADV_WR_ENABLED == 1)
aci_hal_pawr_data_free_event_preprocess(void * buffer,uint8_t type)319 int aci_hal_pawr_data_free_event_preprocess(void *buffer, uint8_t type)
320 {
321 pawr_buff_free(buffer, type);
322
323 /* Do not forward the event. */
324 return 1;
325 }
326 #endif
327
adv_data_check_param(uint8_t Advertising_Handle,uint8_t Operation,uint8_t Advertising_Data_Length,uint8_t * adv_enabled)328 static uint8_t adv_data_check_param(uint8_t Advertising_Handle, uint8_t Operation, uint8_t Advertising_Data_Length, uint8_t *adv_enabled)
329 {
330 uint16_t adv_event_prop;
331 uint8_t ret;
332 uint8_t periodic_adv_configured;
333 uint8_t periodic_adv_enabled;
334
335 if(Advertising_Handle == LEGACY_ADV_HANDLE){
336
337 *adv_enabled = TRUE;
338
339 if(Operation != COMPLETE_DATA || Advertising_Data_Length > 31)
340 return BLE_ERROR_INVALID_HCI_CMD_PARAMS;
341
342 return BLE_STATUS_SUCCESS;
343 }
344
345 if(Advertising_Handle > 0xEF || Operation > UNCHANGED_DATA)
346 return BLE_ERROR_INVALID_HCI_CMD_PARAMS;
347
348 ret = ll_get_advertising_info(Advertising_Handle, adv_enabled, &periodic_adv_configured, &periodic_adv_enabled, &adv_event_prop);
349
350 /* "If the advertising set corresponding to the Advertising_Handle parameter does
351 not exist, then the Controller shall return the error code Unknown Advertising
352 Identifier (0x42)." */
353 if(ret!=0) // Advertising set does not exist.
354 return BLE_ERROR_UNKNOWN_ADVERTISING_IDENTIFIER;
355
356 /* "If the advertising set specifies a type that does not support advertising data, the
357 Controller shall return the error code Invalid HCI Command Parameters (0x12)." */
358 if((adv_event_prop & HCI_ADV_EVENT_PROP_LEGACY && adv_event_prop & HCI_ADV_EVENT_PROP_DIRECTED) || // Legacy, directed advertising
359 (adv_event_prop & HCI_ADV_EVENT_PROP_SCANNABLE && !(adv_event_prop & HCI_ADV_EVENT_PROP_LEGACY))) // Scannable, non-legacy
360 return BLE_ERROR_INVALID_HCI_CMD_PARAMS;
361
362 /* "If the advertising set uses legacy advertising PDUs that support advertising
363 data and either Operation is not 0x03 or the Advertising_Data_Length
364 parameter exceeds 31 octets, the Controller shall return the error code Invalid
365 HCI Command Parameters (0x12)." */
366 if(adv_event_prop & HCI_ADV_EVENT_PROP_LEGACY && (Operation != COMPLETE_DATA || Advertising_Data_Length > 31)) // Legacy advertising
367 return BLE_ERROR_INVALID_HCI_CMD_PARAMS;
368
369 /* "If Operation is not 0x03 or 0x04 and Advertising_Data_Length is zero, the
370 Controller shall return the error code Invalid HCI Command Parameters (0x12)." */
371 if(Operation != COMPLETE_DATA && Operation != UNCHANGED_DATA && Advertising_Data_Length == 0)
372 return BLE_ERROR_INVALID_HCI_CMD_PARAMS;
373
374 /* "If advertising is currently enabled for the specified advertising set and
375 Operation does not have the value 0x03 or 0x04, the Controller shall return the
376 error code Command Disallowed (0x0C)." */
377 if(*adv_enabled && Operation != COMPLETE_DATA && Operation != UNCHANGED_DATA)
378 return BLE_ERROR_COMMAND_DISALLOWED;
379
380 return BLE_STATUS_SUCCESS;
381 }
382
scan_resp_data_check_param(uint8_t Advertising_Handle,uint8_t Operation,uint8_t Scan_Resp_Data_Length,uint8_t * adv_enabled)383 static uint8_t scan_resp_data_check_param(uint8_t Advertising_Handle, uint8_t Operation, uint8_t Scan_Resp_Data_Length, uint8_t *adv_enabled)
384 {
385 uint16_t adv_event_prop;
386 uint8_t ret;
387 uint8_t periodic_adv_configured;
388 uint8_t periodic_adv_enabled;
389
390 if(Advertising_Handle == LEGACY_ADV_HANDLE){
391
392 /* Assume advertising is always enabled, even if this is not true.
393 In this way the old buffer cannot be freed even if the advertising is not enabled. */
394 *adv_enabled = TRUE;
395
396 if(Operation != COMPLETE_DATA || Scan_Resp_Data_Length > 31)
397 return BLE_ERROR_INVALID_HCI_CMD_PARAMS;
398
399 return BLE_STATUS_SUCCESS;
400 }
401
402 if(Operation > COMPLETE_DATA)
403 return BLE_ERROR_INVALID_HCI_CMD_PARAMS;
404
405 ret = ll_get_advertising_info(Advertising_Handle, adv_enabled, &periodic_adv_configured, &periodic_adv_enabled, &adv_event_prop);
406
407 /* "If the advertising set corresponding to the Advertising_Handle parameter does
408 not exist, then the Controller shall return the error code Unknown Advertising
409 Identifier (0x42)." */
410 if(ret!=0) // Advertising set does not exist.
411 return BLE_ERROR_UNKNOWN_ADVERTISING_IDENTIFIER;
412
413 /* "If the advertising set is non-scannable and the Host uses this command other
414 than to discard existing data, the Controller shall return the error code Invalid
415 HCI Command Parameters (0x12)." */
416 if((!(adv_event_prop & HCI_ADV_EVENT_PROP_SCANNABLE) && Scan_Resp_Data_Length != 0))
417 return BLE_ERROR_INVALID_HCI_CMD_PARAMS;
418
419 /* If the advertising set uses scannable legacy advertising PDUs and either
420 Operation is not 0x03 or the Scan_Response_Data_Length parameter exceeds
421 31 octets, the Controller shall return the error code Invalid HCI Command
422 Parameters (0x12). */
423 if(adv_event_prop & HCI_ADV_EVENT_PROP_LEGACY && adv_event_prop & HCI_ADV_EVENT_PROP_SCANNABLE
424 && (Operation != COMPLETE_DATA || Scan_Resp_Data_Length > 31))
425 return BLE_ERROR_INVALID_HCI_CMD_PARAMS;
426
427 /* "If Operation is not 0x03 and Scan_Response_Data_Length is zero, the
428 Controller shall return the error code Invalid HCl Command Parameters (0x12)." */
429 if(Operation != COMPLETE_DATA && Scan_Resp_Data_Length == 0)
430 return BLE_ERROR_INVALID_HCI_CMD_PARAMS;
431
432 /* "If advertising is currently enabled for the specified advertising set and
433 Operation does not have the value 0x03, the Controller shall return the error
434 code Command Disallowed (0x0C)." */
435 if(*adv_enabled && Operation != COMPLETE_DATA)
436 return BLE_ERROR_COMMAND_DISALLOWED;
437
438 return BLE_STATUS_SUCCESS;
439 }
440
441 #if (CFG_BLE_CONTROLLER_PERIODIC_ADV_ENABLED == 1)
periodic_adv_data_check_param(uint8_t Advertising_Handle,uint8_t Operation,uint8_t Advertising_Data_Length,uint8_t * adv_enabled,uint8_t * periodic_adv_enabled)442 static uint8_t periodic_adv_data_check_param(uint8_t Advertising_Handle, uint8_t Operation, uint8_t Advertising_Data_Length, uint8_t *adv_enabled, uint8_t *periodic_adv_enabled)
443 {
444 uint16_t adv_event_prop;
445 uint8_t periodic_adv_configured;
446 uint8_t ret;
447
448 if(Operation > UNCHANGED_DATA)
449 return BLE_ERROR_INVALID_HCI_CMD_PARAMS;
450
451 ret = ll_get_advertising_info(Advertising_Handle, adv_enabled, &periodic_adv_configured, periodic_adv_enabled, &adv_event_prop);
452
453 /* "If the advertising set corresponding to the Advertising_Handle parameter does
454 not exist, then the Controller shall return the error code Unknown Advertising
455 Identifier (0x42)." */
456 if(ret!=0) // Advertising set does not exist.
457 return BLE_ERROR_UNKNOWN_ADVERTISING_IDENTIFIER;
458
459 /* "If the advertising set has not been configured for periodic advertising,
460 then the Controller shall return the error code Command Disallowed (0x0C)." */
461 if(!periodic_adv_configured)
462 return BLE_ERROR_COMMAND_DISALLOWED;
463
464 if(Advertising_Data_Length > 252)
465 return BLE_ERROR_INVALID_HCI_CMD_PARAMS;
466
467 if ((Operation != COMPLETE_DATA) && (Operation != UNCHANGED_DATA))
468 {
469 /* "If periodic advertising is currently enabled for the specified advertising set and
470 Operation does not have the value 0x03 or 0x04, then the Controller shall
471 return the error code Command Disallowed (0x0C)." */
472 if(*periodic_adv_enabled)
473 return BLE_ERROR_COMMAND_DISALLOWED;
474
475 if(Advertising_Data_Length == 0U)
476 return BLE_ERROR_INVALID_HCI_CMD_PARAMS;
477 }
478
479 return BLE_STATUS_SUCCESS;
480 }
481 #endif
482
set_data_ptr(uint8_t Advertising_Handle,uint8_t Operation,uint16_t Data_Length,uint8_t * Data,uint8_t data_type,uint8_t gap)483 static tBleStatus set_data_ptr(uint8_t Advertising_Handle,
484 uint8_t Operation, uint16_t Data_Length, uint8_t *Data, uint8_t data_type, uint8_t gap)
485 {
486 if(data_type == ADV_DATA)
487 {
488 // Advertising Data
489 #if (BLESTACK_CONTROLLER_ONLY == 0)
490 if(gap)
491 {
492 return aci_gap_set_advertising_data(Advertising_Handle, Operation,
493 Data_Length, Data);
494 }
495 else
496 #endif
497 {
498 if(Advertising_Handle == LEGACY_ADV_HANDLE)
499 {
500 return ll_set_legacy_advertising_data_ptr(Data_Length, Data);
501 }
502 else
503 {
504 return ll_set_advertising_data_ptr(Advertising_Handle, Operation, Data_Length, Data);
505 }
506 }
507 }
508 else if (data_type == SCAN_RESP_DATA)
509 {
510 // Scan Response
511 #if (BLESTACK_CONTROLLER_ONLY == 0)
512 if(gap)
513 {
514 return aci_gap_set_scan_response_data(Advertising_Handle,
515 Data_Length, Data);
516 }
517 else
518 #endif
519 {
520 if(Advertising_Handle == LEGACY_ADV_HANDLE)
521 {
522 return ll_set_legacy_scan_reponse_data_ptr(Data_Length, Data);
523 }
524 else
525 {
526 return ll_set_scan_reponse_data_ptr(Advertising_Handle, Data_Length, Data);
527 }
528 }
529 }
530 #if (CFG_BLE_CONTROLLER_PERIODIC_ADV_ENABLED == 1)
531 else
532 { /* data_type == PERIODIC_ADV_DATA */
533 return ll_set_periodic_advertising_data_ptr(Advertising_Handle, Operation, Data_Length, Data);
534 }
535 #else
536 return BLE_ERROR_UNKNOWN_HCI_COMMAND;
537 #endif
538 }
539
allocate_and_set_data_ext(uint8_t Advertising_Handle,uint8_t Operation,uint8_t Data_Length,uint8_t * Data,uint8_t data_type,uint8_t layer)540 static tBleStatus allocate_and_set_data_ext(uint8_t Advertising_Handle,
541 uint8_t Operation, uint8_t Data_Length, uint8_t *Data, uint8_t data_type, uint8_t layer)
542 {
543 uint8_t *buffer;
544 uint16_t buff_len;
545 uint8_t adv_enabled;
546 #if CONTROLLER_PERIODIC_ADV_ENABLED
547 uint8_t periodic_adv_enabled;
548 #endif
549 uint8_t status = BLE_ERROR_UNKNOWN_HCI_COMMAND;
550 uint16_t old_buff_len;
551 uint8_t extend = FALSE;
552
553 if(Advertising_Handle == LEGACY_ADV_HANDLE && layer != LL){
554 return BLE_ERROR_INVALID_HCI_CMD_PARAMS; // This should not happen
555 }
556
557 if(data_type == ADV_DATA){
558 status = adv_data_check_param(Advertising_Handle, Operation, Data_Length, &adv_enabled);
559 }
560 else if(data_type == SCAN_RESP_DATA){
561 status = scan_resp_data_check_param(Advertising_Handle, Operation, Data_Length, &adv_enabled);
562 }
563 #if (CFG_BLE_CONTROLLER_PERIODIC_ADV_ENABLED == 1)
564 else { /* PERIODIC_ADV_DATA */
565 status = periodic_adv_data_check_param(Advertising_Handle, Operation, Data_Length, &adv_enabled, &periodic_adv_enabled);
566 }
567 #endif
568
569 if(status)
570 return status;
571
572 /* Allocate the buffer */
573 switch(Operation){
574
575 case UNCHANGED_DATA:
576 return set_data_ptr(Advertising_Handle, Operation, Data_Length, Data, data_type, layer);
577
578 case FIRST_FRAGMENT:
579 case COMPLETE_DATA:
580 extend = FALSE;
581 adv_buff_free_next(Advertising_Handle, data_type);
582 break;
583
584 case INTERMEDIATE_FRAGMENT:
585 case LAST_FRAGMENT:
586 extend = TRUE;
587 break;
588
589 }
590
591 buffer = adv_buff_alloc(Advertising_Handle, Data_Length, extend, &old_buff_len, data_type);
592 if((buffer == NULL && Data_Length != 0) || (old_buff_len + Data_Length > MAX_ADV_DATA_LENGTH)){
593 // Tell the stack that current advertising data has to be cancelled.
594 set_data_ptr(Advertising_Handle, COMPLETE_DATA, 0, NULL, data_type, layer);
595 adv_buff_deactivate_current(Advertising_Handle, data_type);
596 adv_buff_free_next(Advertising_Handle, data_type);
597
598 return BLE_ERROR_MEMORY_CAPACITY_EXCEEDED;
599 }
600
601 memcpy(buffer + old_buff_len, Data, Data_Length);
602
603 buff_len = old_buff_len + Data_Length;
604
605 if(Operation == LAST_FRAGMENT || Operation == COMPLETE_DATA){
606 status = set_data_ptr(Advertising_Handle, COMPLETE_DATA, buff_len, buffer, data_type, layer);
607 if(status == BLE_STATUS_SUCCESS){
608 adv_buff_deactivate_current(Advertising_Handle, data_type);
609 adv_buff_activate_next(Advertising_Handle, data_type);
610 }
611 else{
612 // Free what has been allocated so far for this advertising handle
613 adv_buff_free_next(Advertising_Handle, data_type);
614 }
615 }
616 else if(Operation == FIRST_FRAGMENT){
617 // Discard any existing partial or complete advertising data.
618 set_data_ptr(Advertising_Handle, COMPLETE_DATA, 0, NULL, data_type, layer);
619 adv_buff_deactivate_current(Advertising_Handle, data_type);
620 }
621
622 return status;
623 }
624
625 #if (CFG_BLE_CONTROLLER_PERIODIC_ADV_ENABLED == 1)
hci_le_set_periodic_advertising_enable_preprocess(uint8_t Enable,uint8_t Advertising_Handle)626 tBleStatus hci_le_set_periodic_advertising_enable_preprocess(uint8_t Enable,
627 uint8_t Advertising_Handle)
628 {
629 /* If bit 0 of Enable in the HCI_LE_Set_Periodic_Advertising_Enable command is set to 1
630 (periodic advertising is enabled) and the advertising set contains partial periodic
631 advertising data, the Status value in the response to the command shall be
632 Command Disallowed (0x0C). */
633 if(((Enable & 0x01U) == 0x01U) && (new_buff_pending(Advertising_Handle, PERIODIC_ADV_DATA) == TRUE))
634 return BLE_ERROR_COMMAND_DISALLOWED;
635
636 return BLE_STATUS_SUCCESS;
637 }
638 #endif
639
hci_le_set_extended_advertising_enable_preprocess(uint8_t Enable,uint8_t Number_of_Sets,Advertising_Set_Parameters_t Advertising_Set_Parameters[])640 tBleStatus hci_le_set_extended_advertising_enable_preprocess(uint8_t Enable,
641 uint8_t Number_of_Sets,
642 Advertising_Set_Parameters_t Advertising_Set_Parameters[])
643 {
644 /* The remainder of this section only applies if Enable is set to 0x01.
645 If the advertising data or scan response data in the advertising set is not
646 complete, the Controller shall return the error code Command Disallowed
647 (0x0C). */
648 if(Enable == 0x01){
649
650 for(int i = 0; i < Number_of_Sets; i++){
651 if(new_buff_pending(Advertising_Set_Parameters[i].Advertising_Handle, ADV_DATA) == TRUE ||
652 new_buff_pending(Advertising_Set_Parameters[i].Advertising_Handle, SCAN_RESP_DATA) == TRUE)
653 return BLE_ERROR_COMMAND_DISALLOWED;
654 }
655
656 }
657
658 return BLE_STATUS_SUCCESS;
659 }
660
aci_gap_set_advertising_enable_preprocess(uint8_t Enable,uint8_t Number_of_Sets,Advertising_Set_Parameters_t Advertising_Set_Parameters[])661 tBleStatus aci_gap_set_advertising_enable_preprocess(uint8_t Enable,
662 uint8_t Number_of_Sets,
663 Advertising_Set_Parameters_t Advertising_Set_Parameters[])
664 {
665 return hci_le_set_extended_advertising_enable_preprocess(Enable, Number_of_Sets, Advertising_Set_Parameters);
666 }
667
668 #endif /* CFG_BLE_CONTROLLER_EXT_ADV_SCAN_ENABLED == 0 */
669
hci_le_set_advertising_data(uint8_t Advertising_Data_Length,uint8_t Advertising_Data[31])670 tBleStatus hci_le_set_advertising_data(uint8_t Advertising_Data_Length,
671 uint8_t Advertising_Data[31])
672 {
673 return allocate_and_set_data(LEGACY_ADV_HANDLE, COMPLETE_DATA, Advertising_Data_Length, Advertising_Data, ADV_DATA, LL);
674 }
675
hci_le_set_scan_response_data(uint8_t Scan_Response_Data_Length,uint8_t Scan_Response_Data[31])676 tBleStatus hci_le_set_scan_response_data(uint8_t Scan_Response_Data_Length,
677 uint8_t Scan_Response_Data[31])
678 {
679 return allocate_and_set_data(LEGACY_ADV_HANDLE, COMPLETE_DATA, Scan_Response_Data_Length, Scan_Response_Data, SCAN_RESP_DATA, LL);
680 }
681
aci_gap_set_advertising_data_nwk(uint8_t Advertising_Handle,uint8_t Operation,uint8_t Advertising_Data_Length,uint8_t * Advertising_Data)682 tBleStatus aci_gap_set_advertising_data_nwk(uint8_t Advertising_Handle,
683 uint8_t Operation, uint8_t Advertising_Data_Length, uint8_t *Advertising_Data)
684 {
685 return allocate_and_set_data(Advertising_Handle,
686 Operation, Advertising_Data_Length, Advertising_Data, ADV_DATA, GAP);
687 }
688
aci_gap_set_scan_response_data_nwk(uint8_t Advertising_Handle,uint8_t Operation,uint8_t Scan_Response_Data_Length,uint8_t * Scan_Response_Data)689 tBleStatus aci_gap_set_scan_response_data_nwk(uint8_t Advertising_Handle,
690 uint8_t Operation, uint8_t Scan_Response_Data_Length, uint8_t *Scan_Response_Data)
691 {
692 return allocate_and_set_data(Advertising_Handle,
693 Operation, Scan_Response_Data_Length, Scan_Response_Data, SCAN_RESP_DATA, GAP);
694 }
695
696 /* --------------------- E A D --------------------- */
697
698 #if (BLESTACK_CONTROLLER_ONLY == 0)
699
700 extern void char_copy(volatile uint8_t *from, volatile uint8_t *q, size_t n);
701
702 #define ACI_EAD_PAYLOAD_CLEAR_DATA_LEN_MAX (241U)
703 #define ACI_EAD_PAYLOAD_ENCRY_DATA_LEN_MAX (254U)
704 /* the overhead for Encrypted data is given by the leading Randomizer field (5 octets)
705 * and by the trailing MIC field (4 octes) */
706 #define ACI_EAD_PAYLOAD_OVERHEAD_SIZE (9U)
707
aci_gap_encrypt_adv_data_nwk(uint8_t session_key[16],uint8_t iv[8],uint8_t adv_payload_data_clear_len,uint8_t adv_payload_data_clear[],uint8_t * adv_payload_data_encrypted_len,uint8_t adv_payload_data_encrypted[])708 tBleStatus aci_gap_encrypt_adv_data_nwk(uint8_t session_key[16],
709 uint8_t iv[8],
710 uint8_t adv_payload_data_clear_len,
711 uint8_t adv_payload_data_clear[],
712 uint8_t *adv_payload_data_encrypted_len,
713 uint8_t adv_payload_data_encrypted[])
714 {
715 uint8_t Status;
716
717 /* Check that length of adv_payload_data_clear (declared in adv_payload_data_clear_len)
718 * does not exceed 241 octets, that is an upper bound deriving from the maximum allowed length
719 * of adv_payload_data_encrypted that will be returned into the HCI_Command_Complete event -
720 * that has an overhead of 3+2 octets - thus with a remaining net data payload of 255 - (3+2) = 250 octets;
721 * hence, considering that adv_payload_data_encrypted will carry also 2 extra fields
722 * accounting for total 5+4=9 octets, then the maximum allowed length for adv_payload_data_clear is
723 * 255 - (3+2) - (5+4) = 241 octets.
724 */
725 if ((adv_payload_data_clear_len == 0) ||
726 (adv_payload_data_clear_len > ACI_EAD_PAYLOAD_CLEAR_DATA_LEN_MAX))
727 {
728 return BLE_ERROR_INVALID_HCI_CMD_PARAMS;
729 }
730
731 uint32_t clear_data_aligned[((ACI_EAD_PAYLOAD_CLEAR_DATA_LEN_MAX - 1) / sizeof(uint32_t))+1] = { 0U };
732 char_copy((uint8_t *)adv_payload_data_clear, (uint8_t *)clear_data_aligned, adv_payload_data_clear_len);
733
734 Status = aci_gap_encrypt_adv_data(session_key /* 16 */,
735 iv /* 8 */,
736 adv_payload_data_clear_len,
737 clear_data_aligned,
738 adv_payload_data_encrypted);
739
740 if (Status == BLE_STATUS_SUCCESS)
741 {
742 /* the size of returned field adv_payload_data_encrypted is 9 octets longer
743 * w.r.t. adv_payload_data_clear since it contains 2 more fields:
744 * - the Randomizer (5 octets in front of payload), and
745 * - the MIC (4 octets appended as a footer).
746 */
747 *adv_payload_data_encrypted_len = adv_payload_data_clear_len + 9U;
748 }
749 else
750 {
751 *adv_payload_data_encrypted_len = 0U;
752 }
753
754 return Status;
755 }
756
aci_gap_decrypt_adv_data_nwk(uint8_t session_key[16],uint8_t iv[8],uint8_t adv_payload_data_encrypted_len,uint8_t adv_payload_data_encrypted[],uint8_t * adv_payload_data_clear_len,uint8_t adv_payload_data_clear[])757 tBleStatus aci_gap_decrypt_adv_data_nwk(uint8_t session_key[16],
758 uint8_t iv[8],
759 uint8_t adv_payload_data_encrypted_len,
760 uint8_t adv_payload_data_encrypted[],
761 uint8_t *adv_payload_data_clear_len,
762 uint8_t adv_payload_data_clear[])
763 {
764 uint8_t Status;
765
766 /* Check that length of adv_payload_data_encrypted (declared in adv_payload_data_encrypted_len)
767 * does not exceed 254 octets, that is an upper bound deriving from the Core Spec v.5.x, Part C, Sec. 11,
768 * where the Length field in the ADV header has a size of 1 octet.
769 */
770 if (adv_payload_data_encrypted_len > ACI_EAD_PAYLOAD_ENCRY_DATA_LEN_MAX)
771 {
772 return BLE_ERROR_INVALID_HCI_CMD_PARAMS;
773 }
774
775 uint32_t clear_data_aligned[((ACI_EAD_PAYLOAD_ENCRY_DATA_LEN_MAX - ACI_EAD_PAYLOAD_OVERHEAD_SIZE -1) / sizeof(uint32_t))+1] = { 0U };
776
777 Status = aci_gap_decrypt_adv_data(session_key,
778 iv,
779 adv_payload_data_encrypted_len,
780 adv_payload_data_encrypted,
781 clear_data_aligned);
782
783 if (Status == BLE_STATUS_SUCCESS)
784 {
785 /* returned adv_payload_data_clear is 9 octets shorter w.r.t. adv_payload_data_encrypted
786 * since it doesn't contain the 2 extra fields attached to encryped data, i.e.:
787 * - the Randomizer (5 octets in front of payload), and
788 * - the MIC (4 octets appended as a footer).
789 */
790 *adv_payload_data_clear_len = adv_payload_data_encrypted_len - ACI_EAD_PAYLOAD_OVERHEAD_SIZE;
791 char_copy((uint8_t *)clear_data_aligned, (uint8_t *)adv_payload_data_clear, (*adv_payload_data_clear_len));
792 }
793 else
794 {
795 *adv_payload_data_clear_len = 0U;
796 }
797
798 return Status;
799 }
800
801 #endif
802
803 /******************* (C) COPYRIGHT 2020 STMicroelectronics *****END OF FILE****/
804