60
60
#define BLE_LL_SYNC_SM_FLAG_DISABLED 0x0040
61
61
#define BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED 0x0080
62
62
#define BLE_LL_SYNC_SM_FLAG_HCI_TRUNCATED 0x0100
63
+ #define BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP 0x0200
63
64
64
65
#define BLE_LL_SYNC_CHMAP_LEN 5
65
66
#define BLE_LL_SYNC_ITVL_USECS 1250
@@ -75,6 +76,9 @@ struct ble_ll_sync_sm {
75
76
uint8_t chanmap [BLE_LL_SYNC_CHMAP_LEN ];
76
77
uint8_t num_used_chans ;
77
78
79
+ uint8_t chanmap_new [BLE_LL_SYNC_CHMAP_LEN ];
80
+ uint16_t chanmap_new_instant ;
81
+
78
82
uint8_t chan_index ;
79
83
uint8_t chan_chain ;
80
84
@@ -525,7 +529,8 @@ ble_ll_sync_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr)
525
529
}
526
530
527
531
static int
528
- ble_ll_sync_parse_ext_hdr (struct os_mbuf * om , uint8_t * * aux , int8_t * tx_power )
532
+ ble_ll_sync_parse_ext_hdr (struct os_mbuf * om , uint8_t * * aux , int8_t * tx_power ,
533
+ uint8_t * * acad , uint8_t * acad_len )
529
534
{
530
535
uint8_t * rxbuf = om -> om_data ;
531
536
uint8_t ext_hdr_flags ;
@@ -585,12 +590,17 @@ ble_ll_sync_parse_ext_hdr(struct os_mbuf *om, uint8_t **aux, int8_t *tx_power)
585
590
i += BLE_LL_EXT_ADV_TX_POWER_SIZE ;
586
591
}
587
592
588
- /* TODO Handle ACAD if needed */
589
-
590
593
/* sanity check */
591
594
if (i > ext_hdr_len ) {
592
595
return -1 ;
593
596
}
597
+
598
+ /* ACAD */
599
+ if (ext_hdr_len > (i + 1 )) {
600
+ * acad = ext_hdr + i ;
601
+ * acad_len = ext_hdr_len - i - 1 ;
602
+ }
603
+
594
604
}
595
605
596
606
return pdu_len - ext_hdr_len - 1 ;
@@ -996,14 +1006,81 @@ ble_ll_sync_check_failed(struct ble_ll_sync_sm *sm)
996
1006
ble_ll_sync_est_event_failed (BLE_ERR_CONN_ESTABLISHMENT );
997
1007
}
998
1008
1009
+ static bool
1010
+ ble_ll_sync_check_acad (struct ble_ll_sync_sm * sm ,
1011
+ const uint8_t * acad , uint8_t acad_len )
1012
+ {
1013
+ const struct ble_ll_acad_channel_map_update_ind * chmu ;
1014
+ unsigned int ad_len ;
1015
+ uint8_t ad_type ;
1016
+
1017
+ /* assume no empty fields */
1018
+ while (acad_len > 2 ) {
1019
+ ad_len = acad [0 ];
1020
+ ad_type = acad [1 ];
1021
+
1022
+ /* early termination should not happen in ACAD */
1023
+ if (ad_len == 0 ) {
1024
+ return false;
1025
+ }
1026
+
1027
+ /* check if not passing pass acad data */
1028
+ if (ad_len + 1 > acad_len ) {
1029
+ return false;
1030
+ }
1031
+
1032
+ switch (ad_type ) {
1033
+ case BLE_LL_ACAD_CHANNEL_MAP_UPDATE_IND :
1034
+ chmu = (const void * )& acad [2 ];
1035
+
1036
+ if (ad_len - 1 != sizeof (* chmu )) {
1037
+ return false;
1038
+ }
1039
+
1040
+ /* Channels Mask (37 bits)
1041
+ * TODO should we check this?
1042
+ */
1043
+ sm -> chanmap_new [0 ] = chmu -> map [0 ];
1044
+ sm -> chanmap_new [1 ] = chmu -> map [1 ];
1045
+ sm -> chanmap_new [2 ] = chmu -> map [2 ];
1046
+ sm -> chanmap_new [3 ] = chmu -> map [3 ];
1047
+ sm -> chanmap_new [4 ] = chmu -> map [4 ] & 0x1f ;
1048
+
1049
+ /* drop if channel map is invalid */
1050
+ if (ble_ll_utils_calc_num_used_chans (sm -> chanmap_new ) == 0 ) {
1051
+ return false;
1052
+ }
1053
+
1054
+ sm -> chanmap_new_instant = le16toh (chmu -> instant );
1055
+ sm -> flags |= BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP ;
1056
+ break ;
1057
+ default :
1058
+ break ;
1059
+ }
1060
+
1061
+ acad += ad_len + 1 ;
1062
+ acad_len -= ad_len + 1 ;
1063
+ }
1064
+
1065
+ /* should have no trailing zeros */
1066
+ if (acad_len ) {
1067
+ return false;
1068
+ }
1069
+
1070
+ return true;
1071
+ }
1072
+
999
1073
void
1000
1074
ble_ll_sync_rx_pkt_in (struct os_mbuf * rxpdu , struct ble_mbuf_hdr * hdr )
1001
1075
{
1002
1076
struct ble_ll_sync_sm * sm = hdr -> rxinfo .user_data ;
1003
1077
bool aux_scheduled = false;
1004
1078
int8_t tx_power = 127 ; /* defaults to not available */
1005
1079
uint8_t * aux = NULL ;
1080
+ uint8_t * acad = NULL ;
1081
+ uint8_t acad_len ;
1006
1082
int datalen ;
1083
+ bool reports_enabled ;
1007
1084
1008
1085
BLE_LL_ASSERT (sm );
1009
1086
@@ -1048,36 +1125,43 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
1048
1125
goto end_event ;
1049
1126
}
1050
1127
1051
- if (ble_ll_hci_is_le_event_enabled (BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT ) &&
1052
- !(sm -> flags & BLE_LL_SYNC_SM_FLAG_DISABLED )) {
1053
- /* get ext header data */
1054
- datalen = ble_ll_sync_parse_ext_hdr (rxpdu , & aux , & tx_power );
1055
- if (datalen < 0 ) {
1056
- /* we got bad packet, end event */
1057
- goto end_event ;
1058
- }
1128
+ /* get ext header data */
1129
+ datalen = ble_ll_sync_parse_ext_hdr (rxpdu , & aux , & tx_power , & acad , & acad_len );
1130
+ if (datalen < 0 ) {
1131
+ /* we got bad packet, end event */
1132
+ goto end_event ;
1133
+ }
1059
1134
1135
+ reports_enabled = ble_ll_hci_is_le_event_enabled (BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT ) &&
1136
+ !(sm -> flags & BLE_LL_SYNC_SM_FLAG_DISABLED );
1137
+
1138
+ /* no need to schedule for chain if reporting is disabled */
1139
+ if (reports_enabled ) {
1060
1140
/* if aux is present, we need to schedule ASAP */
1061
1141
if (aux && (ble_ll_sync_schedule_chain (sm , hdr , aux ) == 0 )) {
1062
1142
aux_scheduled = true;
1063
1143
}
1144
+ }
1064
1145
1065
- /* in case data reporting is enabled we need to send sync established here */
1066
- if (sm -> flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING ) {
1067
- ble_ll_sync_established (sm );
1068
- }
1146
+ /* check ACAD, needs to be done before rxpdu is adjusted for ADV data */
1147
+ if (acad && !ble_ll_sync_check_acad (sm , acad , acad_len )) {
1148
+ /* we got bad packet (bad ACAD data), end event */
1149
+ goto end_event ;
1150
+ }
1151
+
1152
+ /* we need to establish link even if reporting was disabled */
1153
+ if (sm -> flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING ) {
1154
+ ble_ll_sync_established (sm );
1155
+ }
1069
1156
1157
+ /* only if reporting is enabled */
1158
+ if (reports_enabled ) {
1070
1159
/* Adjust rxpdu to contain advertising data only */
1071
1160
ble_ll_sync_adjust_ext_hdr (rxpdu );
1072
1161
1073
1162
/* send reports from this PDU */
1074
1163
ble_ll_sync_send_per_adv_rpt (sm , rxpdu , hdr -> rxinfo .rssi , tx_power ,
1075
1164
datalen , aux , aux_scheduled );
1076
- } else {
1077
- /* we need to establish link even if reporting was disabled */
1078
- if (sm -> flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING ) {
1079
- ble_ll_sync_established (sm );
1080
- }
1081
1165
}
1082
1166
1083
1167
/* if chain was scheduled we don't end event yet */
@@ -1131,6 +1215,20 @@ ble_ll_sync_next_event(struct ble_ll_sync_sm *sm, uint32_t cur_ww_adjust)
1131
1215
/* Set event counter to the next event */
1132
1216
sm -> event_cntr += 1 + skip ;
1133
1217
1218
+ /* update channel map if needed */
1219
+ if (sm -> flags & BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP ) {
1220
+ if (((int16_t )(sm -> event_cntr - sm -> chanmap_new_instant )) >= 0 ) {
1221
+ /* map was verified on reception */
1222
+ sm -> chanmap [0 ] = sm -> chanmap_new [0 ];
1223
+ sm -> chanmap [1 ] = sm -> chanmap_new [1 ];
1224
+ sm -> chanmap [2 ] = sm -> chanmap_new [2 ];
1225
+ sm -> chanmap [3 ] = sm -> chanmap_new [3 ];
1226
+ sm -> chanmap [4 ] = sm -> chanmap_new [4 ];
1227
+ sm -> num_used_chans = ble_ll_utils_calc_num_used_chans (sm -> chanmap );
1228
+ sm -> flags &= ~BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP ;
1229
+ }
1230
+ }
1231
+
1134
1232
/* Calculate channel index of next event */
1135
1233
sm -> chan_index = ble_ll_utils_calc_dci_csa2 (sm -> event_cntr , sm -> channel_id ,
1136
1234
sm -> num_used_chans , sm -> chanmap );
0 commit comments