@@ -156,6 +156,19 @@ static void generic_success(struct net_buf *buf, struct net_buf **evt, uint8_t l
156156 ccst -> status = BT_HCI_ERR_SUCCESS ;
157157}
158158
159+ /* Generic command status with success status. */
160+ static void generic_status (struct net_buf * buf , struct net_buf * * evt , uint8_t len , uint16_t opcode )
161+ {
162+ struct bt_hci_evt_cmd_status * cs ;
163+
164+ * evt = bt_buf_get_evt (BT_HCI_EVT_CMD_STATUS , false, K_FOREVER );
165+ evt_create (* evt , BT_HCI_EVT_CMD_STATUS , sizeof (* cs ));
166+ cs = net_buf_add (* evt , sizeof (* cs ));
167+ cs -> status = BT_HCI_ERR_SUCCESS ;
168+ cs -> ncmd = 1U ;
169+ cs -> opcode = sys_cpu_to_le16 (opcode );
170+ }
171+
159172/* Bogus handler for BT_HCI_OP_READ_LOCAL_FEATURES. */
160173static void read_local_features (struct net_buf * buf , struct net_buf * * evt , uint8_t len ,
161174 uint16_t opcode )
@@ -221,6 +234,7 @@ static const struct cmd_handler cmds[] = {
221234 generic_success },
222235 { BT_HCI_OP_LE_SET_EXT_SCAN_PARAM , sizeof (struct bt_hci_evt_cc_status ), generic_success },
223236 { BT_HCI_OP_LE_SET_EXT_SCAN_ENABLE , sizeof (struct bt_hci_evt_cc_status ), generic_success },
237+ { BT_HCI_OP_LE_PER_ADV_CREATE_SYNC , 0 , generic_status },
224238 { BT_HCI_OP_RESET , sizeof (struct bt_hci_evt_cc_status ), generic_success },
225239};
226240
@@ -360,6 +374,83 @@ static void scan_timeout_cb(void)
360374 zassert_unreachable ("Timeout should not happen" );
361375}
362376
377+ #define SYNC_HANDLE 0x0001
378+
379+ /* Send a periodic advertising sync established event for the pending sync. */
380+ static void send_per_adv_sync_established (const bt_addr_le_t * addr , uint8_t sid )
381+ {
382+ struct bt_hci_evt_le_meta_event * meta_evt ;
383+ struct bt_hci_evt_le_per_adv_sync_established * evt ;
384+ struct net_buf * buf ;
385+
386+ buf = bt_buf_get_rx (BT_BUF_EVT , K_FOREVER );
387+ evt_create (buf , BT_HCI_EVT_LE_META_EVENT , sizeof (* meta_evt ) + sizeof (* evt ));
388+ meta_evt = net_buf_add (buf , sizeof (* meta_evt ));
389+ le_meta_evt_create (meta_evt , BT_HCI_EVT_LE_PER_ADV_SYNC_ESTABLISHED );
390+ evt = net_buf_add (buf , sizeof (* evt ));
391+ evt -> status = BT_HCI_ERR_SUCCESS ;
392+ evt -> handle = sys_cpu_to_le16 (SYNC_HANDLE );
393+ evt -> sid = sid ;
394+ bt_addr_le_copy (& evt -> adv_addr , addr );
395+ evt -> phy = BT_HCI_LE_PHY_1M ;
396+ evt -> interval = sys_cpu_to_le16 (0x0100 );
397+ evt -> clock_accuracy = 0 ;
398+
399+ bt_recv_job_submit (buf );
400+ }
401+
402+ /* Send a periodic advertising report carrying data_len bytes of data, whose length
403+ * field claims claimed_len bytes.
404+ */
405+ static void send_per_adv_report (uint8_t data_status , const uint8_t * data , uint8_t data_len ,
406+ uint8_t claimed_len )
407+ {
408+ struct bt_hci_evt_le_meta_event * meta_evt ;
409+ struct bt_hci_evt_le_per_advertising_report * evt ;
410+ struct net_buf * buf ;
411+
412+ buf = bt_buf_get_rx (BT_BUF_EVT , K_FOREVER );
413+ evt_create (buf , BT_HCI_EVT_LE_META_EVENT , sizeof (* meta_evt ) + sizeof (* evt ) + data_len );
414+ meta_evt = net_buf_add (buf , sizeof (* meta_evt ));
415+ le_meta_evt_create (meta_evt , BT_HCI_EVT_LE_PER_ADVERTISING_REPORT );
416+ evt = net_buf_add (buf , sizeof (* evt ));
417+ evt -> handle = sys_cpu_to_le16 (SYNC_HANDLE );
418+ evt -> tx_power = 0 ;
419+ evt -> rssi = 0 ;
420+ evt -> cte_type = BT_HCI_LE_NO_CTE ;
421+ evt -> data_status = data_status ;
422+ evt -> length = claimed_len ;
423+ net_buf_add_mem (buf , data , data_len );
424+
425+ bt_recv_job_submit (buf );
426+ }
427+
428+ static K_SEM_DEFINE (per_adv_synced_sem , 0 , 1 ) ;
429+
430+ static void per_adv_sync_synced_cb (struct bt_le_per_adv_sync * sync ,
431+ struct bt_le_per_adv_sync_synced_info * info )
432+ {
433+ k_sem_give (& per_adv_synced_sem );
434+ }
435+
436+ static void per_adv_sync_term_cb (struct bt_le_per_adv_sync * sync ,
437+ const struct bt_le_per_adv_sync_term_info * info )
438+ {
439+ zassert_unreachable ("Sync should not be terminated" );
440+ }
441+
442+ static void per_adv_sync_recv_cb (struct bt_le_per_adv_sync * sync ,
443+ const struct bt_le_per_adv_sync_recv_info * info ,
444+ struct net_buf_simple * buf )
445+ {
446+ const struct test_adv_report expected = get_expected_report ();
447+
448+ LOG_DBG ("Received periodic adv report with length %u" , buf -> len );
449+
450+ zassert_equal (buf -> len , expected .length , "Lengths should be equal" );
451+ zassert_mem_equal (buf -> data , expected .data , buf -> len , "Data should be equal" );
452+ }
453+
363454static void generate_sequence (uint8_t * dest , uint16_t len , uint8_t range_start , uint8_t range_end )
364455{
365456 uint16_t written = 0 ;
@@ -374,15 +465,19 @@ static void generate_sequence(uint8_t *dest, uint16_t len, uint8_t range_start,
374465 }
375466}
376467
377- ZTEST_SUITE (long_adv_rx_tests , NULL , NULL , NULL , NULL , NULL );
468+ static void * suite_setup (void )
469+ {
470+ zassert_true ((bt_enable (NULL ) == 0 ), "bt_enable failed" );
471+
472+ return NULL ;
473+ }
474+
475+ ZTEST_SUITE (long_adv_rx_tests , NULL , suite_setup , NULL , NULL , NULL );
378476
379477ZTEST (long_adv_rx_tests , test_host_long_adv_recv )
380478{
381479 struct test_adv_report expected_reports [2 ];
382480
383- /* Go! Wait until Bluetooth initialization is done */
384- zassert_true ((bt_enable (NULL ) == 0 ), "bt_enable failed" );
385-
386481 static struct bt_le_scan_cb scan_callbacks = { .recv = scan_recv_cb ,
387482 .timeout = scan_timeout_cb };
388483 bt_le_scan_cb_register (& scan_callbacks );
@@ -510,3 +605,66 @@ ZTEST(long_adv_rx_tests, test_host_long_adv_recv)
510605 send_adv_report (& report_b_2 );
511606 zassert_equal (1 , get_expected_report_fake .call_count );
512607}
608+
609+ ZTEST (long_adv_rx_tests , test_host_per_adv_report_bad_len )
610+ {
611+ static struct bt_le_per_adv_sync_cb sync_callbacks = {
612+ .synced = per_adv_sync_synced_cb ,
613+ .term = per_adv_sync_term_cb ,
614+ .recv = per_adv_sync_recv_cb ,
615+ };
616+ struct bt_le_per_adv_sync_param param = {
617+ .sid = 1 ,
618+ .timeout = BT_GAP_PER_ADV_MIN_TIMEOUT ,
619+ };
620+ struct bt_le_per_adv_sync * sync ;
621+ struct test_adv_report report = { .length = 20 };
622+ uint8_t fragment [10 ];
623+ int err ;
624+
625+ RESET_FAKE (get_expected_report );
626+ FFF_RESET_HISTORY ();
627+
628+ bt_addr_le_create_static (& param .addr );
629+ generate_sequence (fragment , sizeof (fragment ), 'A' , 'Z' );
630+ generate_sequence (report .data , report .length , 'a' , 'z' );
631+
632+ err = bt_le_per_adv_sync_cb_register (& sync_callbacks );
633+ zassert_equal (err , 0 , "bt_le_per_adv_sync_cb_register failed (err %d)" , err );
634+
635+ err = bt_le_per_adv_sync_create (& param , & sync );
636+ zassert_equal (err , 0 , "bt_le_per_adv_sync_create failed (err %d)" , err );
637+
638+ send_per_adv_sync_established (& param .addr , param .sid );
639+ err = k_sem_take (& per_adv_synced_sem , K_SECONDS (1 ));
640+ zassert_equal (err , 0 , "Sync not established (err %d)" , err );
641+
642+ /* A partial fragment claiming more data than the event carries. The report is
643+ * discarded up to and including the next complete fragment, and the one after
644+ * that is delivered intact.
645+ */
646+ SET_RETURN_SEQ (get_expected_report , & report , 1 );
647+ send_per_adv_report (BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL , fragment , sizeof (fragment ),
648+ sizeof (fragment ));
649+ send_per_adv_report (BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL , fragment , sizeof (fragment ),
650+ 4 * sizeof (fragment ));
651+ send_per_adv_report (BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_COMPLETE , report .data , report .length ,
652+ report .length );
653+ send_per_adv_report (BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_COMPLETE , report .data , report .length ,
654+ report .length );
655+ zassert_equal (1 , get_expected_report_fake .call_count );
656+ RESET_FAKE (get_expected_report );
657+ FFF_RESET_HISTORY ();
658+
659+ /* Same with the complete fragment of a reassembled report being the bad one */
660+ SET_RETURN_SEQ (get_expected_report , & report , 1 );
661+ send_per_adv_report (BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL , fragment , sizeof (fragment ),
662+ sizeof (fragment ));
663+ send_per_adv_report (BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_COMPLETE , fragment , sizeof (fragment ),
664+ 4 * sizeof (fragment ));
665+ send_per_adv_report (BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_COMPLETE , report .data , report .length ,
666+ report .length );
667+ send_per_adv_report (BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_COMPLETE , report .data , report .length ,
668+ report .length );
669+ zassert_equal (1 , get_expected_report_fake .call_count );
670+ }
0 commit comments