From 8afb1c5bac06ee90ff6f43adc51088239d5834b8 Mon Sep 17 00:00:00 2001 From: Chris Swinchatt Date: Mon, 19 Jul 2021 13:02:47 +0100 Subject: [PATCH] Update Cordio host & controller stack to 21.04 --- .../include/ble/driver/CordioHCIDriver.h | 10 +- .../libraries/TARGET_CORDIO_LL/CHANGES.md | 131 ++++ .../stack/controller/include/ble/bb_ble_api.h | 27 +- .../controller/include/ble/bb_ble_api_op.h | 92 ++- .../include/ble/bb_ble_api_pdufilt.h | 6 +- .../stack/controller/include/ble/lhci_api.h | 1 + .../stack/controller/include/ble/ll_api.h | 321 +++++--- .../controller/include/ble/ll_init_api.h | 2 +- .../controller/include/ble/sch_api_ble.h | 4 +- .../stack/controller/include/common/bb_api.h | 6 +- .../stack/controller/include/common/cfg_mac.h | 6 - .../controller/include/common/cfg_mac_ble.h | 17 +- .../stack/controller/include/common/chci_tr.h | 9 - .../stack/controller/include/common/sch_api.h | 7 +- .../sources/ble/bb/bb_ble_adv_master.c | 47 +- .../sources/ble/bb/bb_ble_adv_master_ae.c | 185 +++-- .../sources/ble/bb/bb_ble_adv_slave.c | 2 +- .../sources/ble/bb/bb_ble_adv_slave_ae.c | 1 - .../sources/ble/bb/bb_ble_bis_slave.c | 19 +- .../controller/sources/ble/bb/bb_ble_cis.c | 8 +- .../sources/ble/bb/bb_ble_cis_master.c | 30 +- .../sources/ble/bb/bb_ble_cis_slave.c | 59 +- .../controller/sources/ble/bb/bb_ble_int.h | 4 - .../ble/include/lctr_api_adv_master_ae.h | 12 +- .../ble/include/lctr_api_adv_slave_ae.h | 2 +- .../sources/ble/include/lctr_api_conn.h | 44 +- .../sources/ble/include/lctr_api_iso.h | 1 + .../sources/ble/include/lmgr_api_conn.h | 10 +- .../stack/controller/sources/ble/init/init.c | 19 +- .../controller/sources/ble/init/init_ctr.c | 13 +- .../sources/ble/lctr/lctr_act_adv_master_ae.c | 1 + .../sources/ble/lctr/lctr_act_adv_slave_ae.c | 26 +- .../sources/ble/lctr/lctr_act_bis_master.c | 75 +- .../sources/ble/lctr/lctr_act_cis.c | 129 +++- .../sources/ble/lctr/lctr_act_cis_master.c | 22 +- .../sources/ble/lctr/lctr_act_cis_slave.c | 16 +- .../sources/ble/lctr/lctr_act_conn.c | 282 ++++++- .../sources/ble/lctr/lctr_act_conn_past.c | 2 +- .../sources/ble/lctr/lctr_act_enc.c | 7 +- .../controller/sources/ble/lctr/lctr_act_pc.c | 146 ++-- .../sources/ble/lctr/lctr_act_phy.c | 5 +- .../controller/sources/ble/lctr/lctr_int.h | 24 +- .../sources/ble/lctr/lctr_int_adv_master_ae.h | 9 +- .../sources/ble/lctr/lctr_int_adv_slave.h | 3 +- .../sources/ble/lctr/lctr_int_adv_slave_ae.h | 8 +- .../sources/ble/lctr/lctr_int_bis.h | 80 +- .../sources/ble/lctr/lctr_int_bis_master.h | 3 +- .../sources/ble/lctr/lctr_int_cis.h | 59 +- .../sources/ble/lctr/lctr_int_cis_master.h | 1 + .../sources/ble/lctr/lctr_int_cis_slave.h | 3 +- .../sources/ble/lctr/lctr_int_conn.h | 146 +++- .../sources/ble/lctr/lctr_int_iso.h | 95 ++- .../controller/sources/ble/lctr/lctr_int_pc.h | 20 +- .../sources/ble/lctr/lctr_int_slave_phy.h | 4 +- .../sources/ble/lctr/lctr_isr_adv_master_ae.c | 330 +++++--- .../sources/ble/lctr/lctr_isr_adv_slave_ae.c | 63 +- .../sources/ble/lctr/lctr_isr_bis_master.c | 729 ++++++++++++------ .../sources/ble/lctr/lctr_isr_bis_slave.c | 80 +- .../sources/ble/lctr/lctr_isr_cis.c | 42 +- .../sources/ble/lctr/lctr_isr_cis_master.c | 358 ++++++--- .../sources/ble/lctr/lctr_isr_cis_slave.c | 348 ++++++--- .../sources/ble/lctr/lctr_isr_conn.c | 9 +- .../sources/ble/lctr/lctr_isr_conn_master.c | 93 ++- .../sources/ble/lctr/lctr_isr_conn_slave.c | 184 ++++- .../controller/sources/ble/lctr/lctr_main.c | 49 ++ .../sources/ble/lctr/lctr_main_adv_master.c | 16 +- .../ble/lctr/lctr_main_adv_master_ae.c | 58 +- .../sources/ble/lctr/lctr_main_adv_slave.c | 16 +- .../sources/ble/lctr/lctr_main_adv_slave_ae.c | 131 ++-- .../sources/ble/lctr/lctr_main_bis.c | 258 +++---- .../sources/ble/lctr/lctr_main_bis_master.c | 64 +- .../sources/ble/lctr/lctr_main_bis_slave.c | 87 ++- .../sources/ble/lctr/lctr_main_cis.c | 272 +++++-- .../sources/ble/lctr/lctr_main_cis_master.c | 135 +++- .../sources/ble/lctr/lctr_main_cis_slave.c | 45 +- .../sources/ble/lctr/lctr_main_conn.c | 228 +++++- .../sources/ble/lctr/lctr_main_conn_data.c | 2 + .../sources/ble/lctr/lctr_main_conn_master.c | 69 +- .../sources/ble/lctr/lctr_main_conn_slave.c | 12 +- .../sources/ble/lctr/lctr_main_enc_master.c | 6 +- .../sources/ble/lctr/lctr_main_enc_slave.c | 6 +- .../sources/ble/lctr/lctr_main_init_master.c | 3 + .../ble/lctr/lctr_main_init_master_ae.c | 4 + .../sources/ble/lctr/lctr_main_iso.c | 358 ++++++--- .../sources/ble/lctr/lctr_main_iso_data.c | 336 ++++++-- .../sources/ble/lctr/lctr_main_pc.c | 10 +- .../sources/ble/lctr/lctr_main_sc.c | 159 ++-- .../sources/ble/lctr/lctr_main_slave_phy.c | 4 +- .../sources/ble/lctr/lctr_pdu_adv_slave_ae.c | 14 +- .../sources/ble/lctr/lctr_pdu_conn.c | 200 ++++- .../sources/ble/lctr/lctr_pdu_conn.h | 130 ++-- .../sources/ble/lctr/lctr_pdu_iso.c | 41 +- .../sources/ble/lctr/lctr_pdu_iso.h | 4 +- .../sources/ble/lctr/lctr_sm_adv_slave_ae.c | 2 +- .../controller/sources/ble/lctr/lctr_sm_cis.c | 3 +- .../ble/lctr/lctr_sm_llcp_cis_master.c | 7 +- .../sources/ble/lctr/lctr_sm_llcp_conn.c | 67 +- .../ble/lctr/lctr_sm_llcp_conn_master.c | 21 +- .../ble/lctr/lctr_sm_llcp_conn_slave.c | 21 +- .../sources/ble/lctr/lctr_sm_llcp_enc_slave.c | 6 +- .../sources/ble/lctr/lctr_sm_llcp_pc.c | 244 ++++-- .../sources/ble/lctr/lctr_sm_llcp_slave_phy.c | 42 +- .../controller/sources/ble/lhci/lhci_cmd.c | 18 + .../sources/ble/lhci/lhci_cmd_cis_master.c | 21 +- .../sources/ble/lhci/lhci_cmd_iso.c | 337 +++++++- .../controller/sources/ble/lhci/lhci_cmd_vs.c | 59 +- .../sources/ble/lhci/lhci_cmd_vs_iso.c | 9 +- .../sources/ble/lhci/lhci_evt_bis_master.c | 16 +- .../sources/ble/lhci/lhci_evt_cis_master.c | 37 +- .../sources/ble/lhci/lhci_evt_cis_slave.c | 51 +- .../sources/ble/lhci/lhci_evt_conn.c | 4 +- .../sources/ble/lhci/lhci_evt_enc_slave.c | 34 +- .../controller/sources/ble/lhci/lhci_evt_pc.c | 6 +- .../controller/sources/ble/lhci/lhci_int.h | 34 +- .../controller/sources/ble/lhci/lhci_main.c | 32 +- .../stack/controller/sources/ble/ll/ll_init.c | 98 +-- .../controller/sources/ble/ll/ll_init_iso.c | 1 + .../controller/sources/ble/ll/ll_init_pc.c | 1 - .../stack/controller/sources/ble/ll/ll_main.c | 21 +- .../sources/ble/ll/ll_main_adv_master_ae.c | 18 +- .../sources/ble/ll/ll_main_adv_slave_ae.c | 2 +- .../sources/ble/ll/ll_main_cis_master.c | 64 +- .../controller/sources/ble/ll/ll_main_conn.c | 6 +- .../sources/ble/ll/ll_main_conn_master_ae.c | 14 +- .../sources/ble/ll/ll_main_conn_slave.c | 14 +- .../controller/sources/ble/ll/ll_main_dtm.c | 14 +- .../controller/sources/ble/ll/ll_main_iso.c | 18 + .../controller/sources/ble/ll/ll_main_past.c | 6 +- .../controller/sources/ble/lmgr/lmgr_main.c | 43 +- .../sources/ble/lmgr/lmgr_main_conn.c | 6 + .../controller/sources/ble/sch/sch_ble.c | 5 - .../controller/sources/ble/sch/sch_int_rm.h | 4 +- .../stack/controller/sources/ble/sch/sch_rm.c | 136 ++-- .../controller/sources/common/bb/bb_main.c | 15 +- .../controller/sources/common/chci/chci_tr.c | 29 +- .../controller/sources/common/sch/sch_int.h | 72 +- .../controller/sources/common/sch/sch_list.c | 493 ++++-------- .../controller/sources/common/sch/sch_main.c | 685 +++++++++------- .../components/boards/arduino_primo.h | 2 +- .../nordic-bsp/components/boards/boards.c | 2 +- .../nordic-bsp/components/boards/boards.h | 13 +- .../nordic-bsp/components/boards/nrf6310.h | 2 +- .../nordic-bsp/components/boards/pca10000.h | 2 +- .../nordic-bsp/components/boards/pca10001.h | 2 +- .../nordic-bsp/components/boards/pca10003.h | 2 +- .../nordic-bsp/components/boards/pca10028.h | 2 +- .../nordic-bsp/components/boards/pca10031.h | 2 +- .../nordic-bsp/components/boards/pca10036.h | 2 +- .../nordic-bsp/components/boards/pca10040.h | 2 +- .../nordic-bsp/components/boards/pca10056.h | 2 +- .../nordic-bsp/components/boards/pca10059.h | 2 +- .../nordic-bsp/components/boards/pca10100.h | 2 +- .../nordic-bsp/components/boards/pca20006.h | 2 +- .../nordic-bsp/components/boards/pca20020.h | 2 +- .../nordic-bsp/components/boards/wt51822.h | 2 +- .../libraries/cordio_stack/CHANGES.md | 82 ++ .../cordio_stack/ble-host/CMakeLists.txt | 1 + .../cordio_stack/ble-host/include/att_api.h | 21 +- .../cordio_stack/ble-host/include/att_defs.h | 4 - .../cordio_stack/ble-host/include/att_uuid.h | 87 ++- .../cordio_stack/ble-host/include/dm_api.h | 177 ++++- .../cordio_stack/ble-host/include/eatt_api.h | 9 + .../cordio_stack/ble-host/include/hci_api.h | 25 +- .../cordio_stack/ble-host/include/hci_core.h | 50 +- .../ble-host/include/hci_core_iso.h | 397 ++++++++++ .../cordio_stack/ble-host/include/hci_tr.h | 2 +- .../ble-host/sources/hci/common/hci_core.c | 265 ++++--- .../sources/hci/dual_chip/hci_cmd_bis.c | 4 +- .../sources/hci/dual_chip/hci_cmd_cis.c | 10 +- .../sources/hci/dual_chip/hci_cmd_cte.c | 2 +- .../sources/hci/dual_chip/hci_core_ps.c | 49 +- .../sources/hci/dual_chip/hci_core_ps.h | 4 +- .../ble-host/sources/hci/dual_chip/hci_evt.c | 276 +++++-- .../sources/sec/common/sec_ecc_debug.c | 2 +- .../ble-host/sources/stack/att/att_eatt.c | 89 ++- .../ble-host/sources/stack/att/att_eatt.h | 1 + .../ble-host/sources/stack/att/att_main.c | 76 +- .../ble-host/sources/stack/att/att_main.h | 4 + .../ble-host/sources/stack/att/att_uuid.c | 39 +- .../ble-host/sources/stack/att/attc_eatt.c | 48 +- .../ble-host/sources/stack/att/attc_main.c | 20 +- .../ble-host/sources/stack/att/attc_proc.c | 6 +- .../ble-host/sources/stack/att/attc_sign.c | 4 +- .../ble-host/sources/stack/att/atts_ccc.c | 30 +- .../ble-host/sources/stack/att/atts_csf.c | 5 +- .../ble-host/sources/stack/att/atts_eatt.c | 134 +++- .../ble-host/sources/stack/att/atts_ind.c | 23 +- .../ble-host/sources/stack/att/atts_main.c | 42 +- .../ble-host/sources/stack/att/atts_main.h | 2 +- .../ble-host/sources/stack/att/atts_proc.c | 8 +- .../ble-host/sources/stack/att/atts_read.c | 12 +- .../ble-host/sources/stack/att/atts_sign.c | 116 ++- .../ble-host/sources/stack/att/atts_write.c | 24 +- .../ble-host/sources/stack/cfg/cfg_stack.c | 3 +- .../ble-host/sources/stack/cfg/cfg_stack.h | 6 +- .../ble-host/sources/stack/dm/dm_adv.c | 4 +- .../ble-host/sources/stack/dm/dm_adv_ae.c | 2 +- .../ble-host/sources/stack/dm/dm_adv_leg.c | 10 +- .../ble-host/sources/stack/dm/dm_bis_master.c | 28 +- .../ble-host/sources/stack/dm/dm_bis_slave.c | 5 +- .../ble-host/sources/stack/dm/dm_cis.c | 48 +- .../ble-host/sources/stack/dm/dm_cis.h | 2 +- .../ble-host/sources/stack/dm/dm_cis_master.c | 24 +- .../ble-host/sources/stack/dm/dm_conn_cte.c | 34 +- .../ble-host/sources/stack/dm/dm_iso.c | 486 +++++++++--- .../ble-host/sources/stack/dm/dm_main.c | 10 +- .../ble-host/sources/stack/dm/dm_past.c | 8 +- .../ble-host/sources/stack/dm/dm_scan.h | 4 +- .../ble-host/sources/stack/dm/dm_sec.c | 32 +- .../ble-host/sources/stack/dm/dm_sec.h | 10 +- .../ble-host/sources/stack/dm/dm_sync_ae.c | 48 +- .../ble-host/sources/stack/hci/hci_main.c | 7 +- .../ble-host/sources/stack/l2c/l2c_coc.c | 22 +- .../ble-host/sources/stack/smp/smp_act.c | 4 +- .../ble-host/sources/stack/smp/smp_main.h | 3 +- .../ble-host/sources/stack/smp/smp_sc_act.c | 72 +- .../ble-host/sources/stack/smp/smp_sc_main.c | 7 +- .../ble-host/sources/stack/smp/smp_sc_main.h | 4 +- .../ble-host/sources/stack/smp/smpi_act.c | 3 + .../ble-host/sources/stack/smp/smpi_sc_act.c | 49 +- .../ble-host/sources/stack/smp/smpr_act.c | 3 + .../ble-host/sources/stack/smp/smpr_sc_act.c | 16 +- .../cordio_stack/platform/include/pal_bb.h | 19 +- .../platform/include/pal_bb_ble.h | 56 +- .../platform/include/pal_bb_ble_tester.h | 2 +- .../cordio_stack/platform/include/pal_btn.h | 3 +- .../cordio_stack/platform/include/pal_cfg.h | 6 +- .../cordio_stack/platform/include/pal_codec.h | 97 ++- .../platform/include/pal_crypto.h | 2 - .../cordio_stack/platform/include/pal_flash.h | 38 +- .../cordio_stack/platform/include/pal_frc.h | 55 ++ .../cordio_stack/platform/include/pal_i2s.h | 1 + .../platform/include/pal_io_exp.h | 46 +- .../cordio_stack/platform/include/pal_ipc.h | 70 ++ .../cordio_stack/platform/include/pal_led.h | 4 +- .../cordio_stack/platform/include/pal_radio.h | 9 - .../platform/include/pal_radio2.h | 26 +- .../cordio_stack/platform/include/pal_rtc.h | 19 +- .../cordio_stack/platform/include/pal_sys.h | 19 +- .../cordio_stack/platform/include/pal_timer.h | 24 +- .../cordio_stack/wsf/include/hci_defs.h | 121 ++- .../cordio_stack/wsf/include/ll_defs.h | 57 +- .../cordio_stack/wsf/include/util/bstream.h | 4 +- .../cordio_stack/wsf/include/wsf_buf.h | 9 + .../cordio_stack/wsf/include/wsf_cs.h | 42 +- .../cordio_stack/wsf/include/wsf_efs.h | 27 +- .../cordio_stack/wsf/include/wsf_msg.h | 9 +- .../cordio_stack/wsf/include/wsf_os.h | 39 +- .../cordio_stack/wsf/include/wsf_timer.h | 17 +- .../cordio_stack/wsf/include/wsf_trace.h | 124 +-- .../cordio_stack/wsf/include/wsf_types.h | 12 + .../wsf/sources/port/baremetal/wsf_assert.c | 12 +- .../wsf/sources/port/baremetal/wsf_buf.c | 21 + .../wsf/sources/port/baremetal/wsf_bufio.c | 4 +- .../wsf/sources/port/baremetal/wsf_detoken.c | 8 +- .../wsf/sources/port/baremetal/wsf_efs.c | 46 +- .../wsf/sources/port/baremetal/wsf_heap.c | 6 +- .../wsf/sources/port/baremetal/wsf_msg.c | 11 +- .../wsf/sources/port/baremetal/wsf_queue.c | 6 +- .../wsf/sources/port/baremetal/wsf_timer.c | 287 +------ .../wsf/sources/port/baremetal/wsf_trace.c | 2 + .../libraries/cordio_updates/.gitignore | 1 + .../libraries/cordio_updates/ReadMe.md | 49 ++ .../libraries/cordio_updates/restructure.py | 93 +++ .../libraries/cordio_updates/summary.py | 104 +++ .../libraries/cordio_updates/update-cordio | 422 ++++++++++ .../cordio/source/BLEInstanceBaseImpl.cpp | 3 + .../source/cordio/source/PalGapImpl.cpp | 3 +- .../source/cordio/stack_adaptation/hci_tr.c | 77 +- .../source/cordio/stack_adaptation/hci_vs.c | 18 +- .../cordio/stack_adaptation/mbed_wsf_trace.h | 30 +- .../pal_mbed_os_adaptation.cpp | 22 +- .../source/cordio/stack_adaptation/wsf_os.c | 7 +- .../TARGET_NRF5x/CMakeLists.txt | 1 + .../TARGET_NRF5x/NRFCordioHCIDriver.cpp | 56 +- .../TARGET_NRF5x/NRFCordioHCIDriver.h | 6 +- .../TARGET_NRF5x/mbed_lib.json | 9 +- .../stack/include/mbed_nrf5x_adaptation.h | 34 + .../TARGET_NRF5x/stack/sources/pal_bb.c | 53 +- .../TARGET_NRF5x/stack/sources/pal_bb_ble.c | 649 ++++++++++------ .../stack/sources/pal_bb_ble_rf.c | 6 +- .../TARGET_NRF5x/stack/sources/pal_cfg.c | 108 ++- .../TARGET_NRF5x/stack/sources/pal_crypto.c | 34 +- .../TARGET_NRF5x/stack/sources/pal_frc.c | 207 +++++ .../TARGET_NRF5x/stack/sources/pal_timer.c | 167 ++-- .../TARGET_NRF5x/TARGET_NRF52/common_rtc.c | 15 +- .../TARGET_NRF5x/TARGET_NRF52/common_rtc.h | 9 +- 287 files changed, 11587 insertions(+), 5155 deletions(-) create mode 100644 connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/CHANGES.md create mode 100644 connectivity/FEATURE_BLE/libraries/cordio_stack/CHANGES.md create mode 100644 connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/hci_core_iso.h create mode 100644 connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_frc.h create mode 100644 connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_ipc.h create mode 100644 connectivity/FEATURE_BLE/libraries/cordio_updates/.gitignore create mode 100644 connectivity/FEATURE_BLE/libraries/cordio_updates/ReadMe.md create mode 100755 connectivity/FEATURE_BLE/libraries/cordio_updates/restructure.py create mode 100755 connectivity/FEATURE_BLE/libraries/cordio_updates/summary.py create mode 100755 connectivity/FEATURE_BLE/libraries/cordio_updates/update-cordio create mode 100644 connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/include/mbed_nrf5x_adaptation.h create mode 100644 connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_frc.c diff --git a/connectivity/FEATURE_BLE/include/ble/driver/CordioHCIDriver.h b/connectivity/FEATURE_BLE/include/ble/driver/CordioHCIDriver.h index a32d1607be..5ac217bd3c 100644 --- a/connectivity/FEATURE_BLE/include/ble/driver/CordioHCIDriver.h +++ b/connectivity/FEATURE_BLE/include/ble/driver/CordioHCIDriver.h @@ -24,6 +24,7 @@ #include "ble/common/BLETypes.h" #include "ble/driver/CordioHCITransportDriver.h" #include "ble/common/blecommon.h" +#include "hal/ticker_api.h" // FIXME: make this invisible! #include "wsf_buf.h" @@ -145,7 +146,14 @@ public: * * Any call to write signals to the driver that the host stack is active. */ - virtual void on_host_stack_inactivity(); + virtual void on_host_stack_inactivity(); + + /** + * React to host stack preparing to enter deep sleep. + * + * \param[in] wakeTimeMs The amount of time in which to wake. + */ + virtual void on_deep_sleep(timestamp_t wakeTimeMs) {} /* BLE Tester commands */ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/CHANGES.md b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/CHANGES.md new file mode 100644 index 0000000000..45b465f901 --- /dev/null +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/CHANGES.md @@ -0,0 +1,131 @@ +Change Log +r21.04 + +Improvements: + +FW-3921 Deprecate power management API +FW-3996 Improve interoperability with connection establishment when LL_OP_MODE_FLAG_ENA_FEAT_LLCP_STARTUP is enabled +FW-4045 Relocate CIS Audio codec decode to end of CIS ISO event +FW-4047 CIS Should change RTE parameters if it cannot honor host-requested value + +Defects fixed: + +FW-3851 HCI_LE_CIS_Established event has MAX_PDUs fields zero on both Master and Slave +FW-3879 Incorrect AuxOffsetPtr value with large skip values +FW-3890 Master may not synchronize with PAST +FW-3981 HCI_LE_Setup_ISO_Data_Path for a BIS may incorrectly return success when clearing +FW-3982 HCI_LE_Read_Remote_Features may return bits not in controller-to-controller mask +FW-3986 HCI_Disconnect for CIS should return HCI_ERR_LOCAL_TERMINATED +FW-3987 CIS ISO test Rx mode incorrectly counts successful packets +FW-3989 Framed CIS test Rx mode will hang when receiving a data packet +FW-3995 HCI_LE_Read_Remote_Features with LL_OP_MODE_FLAG_ENA_FEAT_LLCP_STARTUP enabled may be disallowed +FW-3997 HCI_LE_Set_Address_Resolution_Enable set to FALSE may prevents controller from generating RPA for peer +FW-3998 HCI_LE_Set_Address_Resolution_Enable set to FALSE may incorrectly continue to resolve RPA packets +FW-3999 HCI_LE_ISO_Receive_Test for BIS does not receive when datapath is disabled +FW-4004 HCI_LE_Transmit_Power_Reporting not generated when delta is 0 +FW-4005 Flushing of a PDU when a framed assembly has not started will discard the next valid PDU +FW-4020 Allow payload with SYNC_INFO when synchronizing with Periodic Advertiser +FW-4021 Periodic Synchronizer may use incorrect Aux Offset +FW-4028 IAL BIS case times out before able to complete test procedure +FW-4035 LL initialization directives are multiply defined +FW-4039 LL_FEAT_ISO_SYNC feature bit not set +FW-4042 CIS has MIC failure if two data packets are sent in same ISO event +FW-4044 Peripheral CIS is not able to be schedule after a connection update +FW-4046 CIS acknowledgement scheme does not work correctly +FW-4048 Peripheral CIS may not advance payloads even after central acknowledges them + +Known limitations: + +FW-3789 ISO timestamps and packet counters may not be aligned in certain scenarios +FW-3886 DLE max packet time should cap at 1M PHY when LE Coded PHY is disabled +FW-4063 HCI_LE_Advertising_Set_Terminated may report incorrect Num_Completed_Extended_Advertising_Events with ExtAdv using LE Coded PHY + +r21.02 + +Improvements: + +FW-3988 LeSetCigParams defensive coding for zero-division + +Known limitations: + +FW-3981 HCI_LE_Setup_ISO_Data_Path for a BIS may incorrectly return success when clearing +FW-3982 HCI_LE_Read_Remote_Features may return bits not in controller-to-controller mask +FW-3986 HCI_Disconnect for CIS should return HCI_ERR_LOCAL_TERMINATED +FW-3789 ISO timestamps and packet counters may not be aligned in certain scenarios +FW-3851 HCI_LE_CIS_Established event has MAX_PDUs fields zero on both Master and Slave +FW-3879 Incorrect AuxOffsetPtr value with large skip values +FW-3886 DLE max packet time should cap at 1M PHY when LE Coded PHY is disabled +FW-3890 Master may not synchronize with PAST +FW-3987 CIS ISO test Rx mode incorrectly counts successful packets +FW-3989 Framed CIS test Rx mode will hang when receiving a data packet +FW-3995 HCI_LE_Read_Remote_Features with LL_OP_MODE_FLAG_ENA_FEAT_LLCP_STARTUP enabled may be disallowed +FW-3997 HCI_LE_Set_Address_Resolution_Enable set to FALSE may prevents controller from generating RPA for peer +FW-3998 HCI_LE_Set_Address_Resolution_Enable set to FALSE may incorrectly continue to resolve RPA packets +FW-3999 HCI_LE_ISO_Receive_Test for BIS does not receive when datapath is disabled +FW-4004 HCI_LE_Transmit_Power_Reporting not generated when delta is 0 +FW-4005 Flushing of a PDU when a framed assembly has not started will discard the next valid PDU + +r20.12 + +Improvements: + +FW-3385 Non-blocking scheme for PAL flash +FW-3728 Packetcraft Audio Cape for PCA10056 +FW-3838 Token monitor utility script +FW-3848 CIS and BIS recombination of SDUs +FW-3862 BV32 codec integrated on nRF52840 +FW-3864 Write flash between radio events on nRF52840 +FW-3865 Nordic secure bootloader updates firmware from internal flash +FW-3876 Tester should have a way to sequentially queue ISO Packets +FW-3899 Controller should queue up disconnect commands for multiple CIS +FW-3905 Change BIS datapath to use generic functions +FW-3907 ITM SWO trace diagnostics +FW-3931 Power control monitor improvements +FW-3943 Sydney erratta: CIS RTE max removed (0x0F -> 0xFF) +FW-3949 LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2 force CIS to use Coded PHY S2 option + +Defects fixed: + +FW-3263 Scanner may not filter AdvReport events when Filter Policy is 0x02 and RPA is used +FW-3781 Some broadcaster BIS PTO combinations may fail +FW-3821 BIS broadcaster may corrupt transmitted ISO SDUs +FW-3822 HCI_LE_BIG_Create_Sync does not filter on BIS[i] +FW-3831 HCI_GetVersion does not report build number +FW-3837 Incorrect BIS length will prevent adjacent BIS from receive +FW-3839 CIS interleaved uses incorrect channels on subevent 3+ +FW-3841 Timer may expire early +FW-3845 CIS and ACL are using wrong channel parameters +FW-3846 BIS encryption may use incorrect packet counter +FW-3849 Command complete for setting CIG params will always return CIG=0 +FW-3850 Disconnecting ACL with CIS does not return a terminated event for CIS +FW-3856 BIS should send lost packet SDUs to the host if no PDU is received +FW-3857 BIS Framed PDUs are not sent in consecutive subevents +FW-3858 Unframed BIS may send duplicate Data PDUs when BN > 1 +FW-3868 LE_REMOVE_CIG command doesn't have CIG ID field. +FW-3869 Radio scheduler may operate on list out of order +FW-3870 PHY incorrect when using CIS encryption that differs in PHY with ACL +FW-3872 Removing CIS output data path returns command disallowed +FW-3873 Closing and re-opening the same CIS will not properly establish the second CIS +FW-3875 Controller will not send LLCP anymore if receiving UNKNOWN_RSP for a power control LLCP +FW-3877 LhciRegisterSendTrCompleteHandler() callback does not persist after HCI_Reset +FW-3878 Inline decryption does not filter encrypted packets that are NACK'ed +FW-3881 CIS may attempt transmission after a failed receive +FW-3882 CIS may receive on incorrect PHY when encrypted +FW-3883 CIS rx timeout will cause the whole ISO event to be canceled +FW-3884 CIS Slave encryption will not transmit correctly when bn StoM>0 and NSE>1 +FW-3894 CIS Slave will not respond to ACL events if CIS is disconnected +FW-3895 CIS will not pass up lost or invalid SDUs to host +FW-3896 MIC failure upon establishing 2 CIS +FW-3906 Radio scheduler may overlap reservations +FW-3908 Periodic Advertising may not send SyncInfo when restarting +FW-3937 CIS MIC error returns two discconnection events +FW-3941 Advertising while scanning may skip first advertising event +FW-3942 CIS may duplicate packets when using codec datapath + +Known limitations: + +FW-3789 ISO timestamps and packet counters may not be aligned in certain scenarios +FW-3851 HCI_LE_CIS_Established event has MAX_PDUs fields zero on both Master and Slave +FW-3879 Incorrect AuxOffsetPtr value with large skip values +FW-3886 DLE max packet time should cap at 1M PHY when LE Coded PHY is disabled +FW-3890 Master may not synchronize with PAST diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api.h index a9011674c9..cb1d54ad83 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api.h @@ -350,6 +350,24 @@ void BbBleGetPerScanStats(BbBlePerScanPktStats_t *pStats); /*************************************************************************************************/ void BbBleGetConnStats(BbBleDataPktStats_t *pStats); +/*************************************************************************************************/ +/*! + * \brief Get CIS packet statistics. + * + * \param pStats CIS data statistics. + */ +/*************************************************************************************************/ +void BbBleGetCisStats(BbBleDataPktStats_t *pStats); + +/*************************************************************************************************/ +/*! + * \brief Get BIS packet statistics. + * + * \param pStats BIS data statistics. + */ +/*************************************************************************************************/ +void BbBleGetBisStats(BbBleDataPktStats_t *pStats); + /*************************************************************************************************/ /*! * \brief Get test mode packet statistics. @@ -404,15 +422,6 @@ void BbBleBisMasterInit(void); /*************************************************************************************************/ void BbBleBisSlaveInit(void); -/*************************************************************************************************/ -/*! - * \brief Get CIS packet statistics. - * - * \param pStats CIS data statistics. - */ -/*************************************************************************************************/ -void BbBleGetCisStats(BbBleDataPktStats_t *pStats); - /*! \} */ /* BB_API_BLE */ #ifdef __cplusplus diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_op.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_op.h index 1f0c57907f..b423ee0b90 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_op.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_op.h @@ -6,7 +6,7 @@ * * Copyright (c) 2016-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -99,6 +99,15 @@ typedef void (*BbBleTxAdvSetup_t)(BbOpDesc_t *pBod, uint32_t advTxTime); /*! \brief Chain indication PDU transmit setup call signature. */ typedef uint32_t (*BbBleTxAuxSetup_t)(BbOpDesc_t *pBod, bool_t isChainInd); +/*! \brief Aux Rx setup call signature. Returns TRUE if Scan was programmed. */ +typedef bool_t (*BbBleRxAuxSetup_t)(BbOpDesc_t *pBod, uint32_t refTime, uint32_t remScanDur); + +/*! \brief Aux Tx complete call signature. Returns TRUE if BOD is complete. */ +typedef bool_t (*BbBleAuxTxComp_t)(BbOpDesc_t *pBod, uint8_t status); + +/*! \brief Aux Rx complete call signature. Returns TRUE if BOD is complete. */ +typedef bool_t (*BbBleAuxRxComp_t)(BbOpDesc_t * const pCur, uint8_t status, int8_t rssi, uint32_t crc, uint32_t timestamp, uint8_t rxPhyOptions); + /*! \brief Returns TRUE if an scan request/response required. */ typedef bool_t (*BbBleAdvComp_t)(BbOpDesc_t *pBod, const uint8_t *pBuf); @@ -152,6 +161,13 @@ typedef struct BbBleAdvComp_t txReqCback; /*!< Scan request completion callback. */ BbBleAdvComp_t rxRspCback; /*!< Scan response completion callback. */ + /* Aux Scan BOD link */ + BbOpDesc_t *auxScanBod; /*!< Pointer to the Aux Scan BOD */ + BbBleRxAuxSetup_t auxScanCheckCback; /*!< Setup an Aux Scan that needs to be programmed ASAP. */ + BbBleAuxTxComp_t auxScanTxCompCback; /*!< Aux Scan Tx complete. */ + BbBleAuxRxComp_t auxScanRxCompCback; /*!< Aux Scan Rx complete. */ + bool_t auxScanOpRunning; /*!< Informs if an Aux Scan operation is running in the context of the Ext Scan BOD. */ + uint8_t txReqLen; /*!< Scan request buffer length. */ uint8_t scanChMap; /*!< Scan channel map. */ @@ -202,6 +218,7 @@ typedef struct uint8_t *pTxAuxReqBuf; /*!< Scan request buffer. */ BbBleAdvComp_t rxAuxAdvCback; /*!< Advertising completion callback. */ + BbBleAdvPost_t rxAuxAdvPostCback; /*!< Advertising completion post callback. */ BbBleAdvComp_t rxAuxRspCback; /*!< Scan response completion callback. */ BbBleRxChain_t rxAuxChainCback; /*!< Chain completion callback. */ BbBleRxChainPost_t rxAuxChainPostCback;/*!< Chain completion post callback. */ @@ -291,13 +308,14 @@ typedef struct /*! \brief CIS master event operation data (\ref BB_BLE_OP_MST_CIS_EVENT). */ typedef struct { - BbBleCisCheckContOp_t checkContOpCback; /*!< Check whether to continue current operation callback. */ - BbBleExec_t execCback; /*!< Execute callback. */ - BbBleExec_t contExecCback; /*!< Continue execute callback. */ - BbBleCisPostExec_t postSubEvtCback; /*!< Post subevent callback. */ - BbBleCancel_t cancelCback; /*!< Cancel callback. */ - BbBleTxDataComp_t txDataCback; /*!< Transmit completion callback. */ - BbBleCisRxDataComp_t rxDataCback; /*!< Receive completion callback. */ + BbBleCisCheckContOp_t checkContOpCback; /*!< Check whether to continue current operation callback. */ + BbBleCisCheckContOp_t checkContOpPostCback; /*!< Check whether to continue current operation callback. */ + BbBleExec_t execCback; /*!< Execute callback. */ + BbBleExec_t contExecCback; /*!< Continue execute callback. */ + BbBleCisPostExec_t postSubEvtCback; /*!< Post subevent callback. */ + BbBleCancel_t cancelCback; /*!< Cancel callback. */ + BbBleTxDataComp_t txDataCback; /*!< Transmit completion callback. */ + BbBleCisRxDataComp_t rxDataCback; /*!< Receive completion callback. */ /* Return parameters. */ int8_t rssi; /*!< RSSI of the last received packet. */ uint8_t rxPhyOptions; /*!< Rx PHY options. */ @@ -306,13 +324,14 @@ typedef struct /*! \brief CIS slave event operation data (\ref BB_BLE_OP_SLV_CIS_EVENT). */ typedef struct { - BbBleCisCheckContOp_t checkContOpCback; /*!< Check whether to continue current operation callback. */ - BbBleExec_t execCback; /*!< Execute callback. */ - BbBleExec_t contExecCback; /*!< Continue execute callback. */ - BbBleCisPostExec_t postSubEvtCback; /*!< Post subevent callback. */ - BbBleCancel_t cancelCback; /*!< Cancel callback. */ - BbBleTxDataComp_t txDataCback; /*!< Transmit completion callback. */ - BbBleRxDataComp_t rxDataCback; /*!< Receive completion callback. */ + BbBleCisCheckContOp_t checkContOpCback; /*!< Check whether to continue current operation callback. */ + BbBleCisCheckContOp_t checkContOpPostCback; /*!< Check whether to continue current operation callback. */ + BbBleExec_t execCback; /*!< Execute callback. */ + BbBleExec_t contExecCback; /*!< Continue execute callback. */ + BbBleCisPostExec_t postSubEvtCback; /*!< Post subevent callback. */ + BbBleCancel_t cancelCback; /*!< Cancel callback. */ + BbBleTxDataComp_t txDataCback; /*!< Transmit completion callback. */ + BbBleRxDataComp_t rxDataCback; /*!< Receive completion callback. */ /* Return parameters. */ bool_t isFirstTs; /*!< True for the first timestamp. */ @@ -490,6 +509,49 @@ void BbBleBisRxData(uint8_t *pBuf, uint16_t len, uint32_t nextPduTime, PalBbBleC /*************************************************************************************************/ void BbBleBisRxDataReAcq(uint32_t syncTime, PalBbBleChan_t *pChan); +/*************************************************************************************************/ +/*! + * \brief Execute auxiliary scanning master BOD. + * + * \param pBod Pointer to the BOD to execute. + * \param pBle BLE operation parameters. + */ +/*************************************************************************************************/ +void BbMstExecuteLinkedAuxScanOp(BbOpDesc_t *pBod, BbBleData_t *pBle); + +/*************************************************************************************************/ +/*! + * \brief Tx completion for auxiliary scanning master operation. + * + * \param status Completion status. + * \param pBod Pointer to the BOD + * + * Setup for next action in the operation or complete the operation. + * + * \return TRUE if BOD is complete, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t BbMstAuxScanTxCompHandler(BbOpDesc_t * const pBod, uint8_t status); + +/*************************************************************************************************/ +/*! + * \brief Rx completion for auxiliary scanning master operation. + * + * \param pCur Pointer to the BOD + * \param status Reception status. + * \param rssi RSSI value. + * \param crc CRC value. + * \param timestamp Start of packet timestamp in microseconds. + * \param rxPhyOptions Rx PHY options. + * + * Setup for next action in the operation or complete the operation. + * + * \return TRUE if BOD is complete, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t BbMstAuxScanRxCompHandler(BbOpDesc_t * const pCur, uint8_t status, int8_t rssi, uint32_t crc, + uint32_t timestamp, uint8_t rxPhyOptions); + /*! \} */ /* BB_API_BLE */ #ifdef __cplusplus diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_pdufilt.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_pdufilt.h index 7b1cdd93b9..15c9d873e4 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_pdufilt.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_pdufilt.h @@ -6,7 +6,7 @@ * * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,6 +44,10 @@ extern "C" { /*! \brief Set a flag. */ #define BB_BLE_PDU_FILT_SET_FLAG(pFilt, flag) (pFilt)->flags |= BB_BLE_PDU_FILT_FLAG_##flag; +/*! \brief Clear a flag. */ +#define BB_BLE_PDU_FILT_CLR_FLAG(pFilt, flag) (pFilt)->flags &= ~(BB_BLE_PDU_FILT_FLAG_##flag); + + /*! \brief PDU filtering flags. */ enum { diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/lhci_api.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/lhci_api.h index 72eb718416..10a4d05e14 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/lhci_api.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/lhci_api.h @@ -76,6 +76,7 @@ void LhciBisSlaveInit(void); void LhciBisMasterInit(void); void LhciIsoInit(void); void LhciPowerControlInit(void); +void LhciEnhConnUpdateInit(void); void LhciVsExtInit(lhciCmdHandler_t decodeCmd); void LhciHandlerInit(wsfHandlerId_t handlerId); void LhciHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/ll_api.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/ll_api.h index c677bd4e00..dc7e627da0 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/ll_api.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/ll_api.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,7 @@ extern "C" { #endif /*! \brief Version number. */ -#define LL_VER_NUM 1366 +#define LL_VER_NUM 21015 /************************************************************************************************** Data Types @@ -164,6 +164,11 @@ typedef struct bool_t phyCodedSup; /*!< Coded PHY supported. */ bool_t stableModIdxTxSup; /*!< Tx stable modulation index supported. */ bool_t stableModIdxRxSup; /*!< Rx stable modulation index supported. */ + /* Power control */ + int8_t pcHighThreshold; /*!< High RSSI threshold for power monitoring. */ + int8_t pcLowThreshold; /*!< Low RSSI threshold for power monitoring. */ + /* Channel classification reporting. */ + uint8_t chClassIntSpacing; /*!< Interval spacing of channel classification reporting. */ } LlRtCfg_t; /*! \} */ /* LL_API_INIT */ @@ -253,15 +258,23 @@ typedef struct #define LL_FEAT_CIS_MASTER_ROLE (UINT64_C(1) << 28) /*!< Connected Isochronous Stream Master Role supported. */ #define LL_FEAT_CIS_SLAVE_ROLE (UINT64_C(1) << 29) /*!< Connected Isochronous Stream Slave Role supported. */ #define LL_FEAT_ISO_BROADCASTER (UINT64_C(1) << 30) /*!< Isochronous Broadcaster Role supported. */ -#define LL_FEAT_ISO_SYNC (UINT64_C(1) << 31) /*!< Isochronous Synchronizer Role supported. */ +#define LL_FEAT_ISO_SYNC (UINT64_C(1) << 31) /*!< Isochronous Synchronized Receiver Role supported. */ #define LL_FEAT_ISO_HOST_SUPPORT (UINT64_C(1) << 32) /*!< Host support for ISO Channels. */ #define LL_FEAT_POWER_CONTROL_REQUEST (UINT64_C(1) << 33) /*!< Power control requests supported. */ #define LL_FEAT_POWER_CHANGE_IND (UINT64_C(1) << 34) /*!< Power control power change indication supported. */ #define LL_FEAT_PATH_LOSS_MONITOR (UINT64_C(1) << 35) /*!< Path loss monitoring supported. */ +/* --- Core Spec Sydney --- */ +#define LL_FEAT_PER_ADV_ADI_SUP (UINT64_C(1) << 36) /*!< Periodic advertising ADI field supported. */ +#define LL_FEAT_CONN_SUBRATE (UINT64_C(1) << 37) /*!< Connection subrating supported. */ +#define LL_FEAT_CONN_SUBRATE_HOST_SUPPORT (UINT64_C(1) << 38) /*!< Host support for connection subrating. */ +#define LL_FEAT_CHANNEL_CLASSIFICATION (UINT64_C(1) << 39) /*!< Channel classification supported. */ +/* Bits 56 - 62 are RFU for testing. */ -#define LL_HOST_CONTROLLED_FEAT LL_FEAT_ISO_HOST_SUPPORT /*!< Feature bits controlled by the host. */ +/*! \brief Feature bits controlled by the host. */ +#define LL_HOST_CONTROLLED_FEAT (LL_FEAT_ISO_HOST_SUPPORT | LL_FEAT_CONN_SUBRATE_HOST_SUPPORT) -#define LL_FEAT_ALL_MASK (UINT64_C(0x0000000FFF01FFFF)) /*!< All feature mask, need to be updated when new features are added. */ +/*! \brief All feature mask. */ +#define LL_FEAT_ALL_MASK (UINT64_C(0x000000FFFFFFFFFF)) /*! \brief This parameter identifies the device role. */ typedef enum @@ -289,14 +302,19 @@ enum LL_OP_MODE_FLAG_ENA_MST_CIS_NULL_PDU = (1 << 12), /*!< Enable CIS master sends additional NULL PDU for acknowledge scheme. */ LL_OP_MODE_FLAG_ENA_SLV_AUX_IND_ADVA = (1 << 13), /*!< AdvA will be included in AUX_ADV_IND instead of ADV_EXT_IND. */ LL_OP_MODE_FLAG_ENA_ADV_CHAN_RAND = (1 << 14), /*!< Enable advertising channel randomization. */ - LL_OP_MODE_DISABLE_POWER_MONITOR = (1 << 15), /*!< Disable power monitoring. */ + LL_OP_MODE_FLAG_DIS_POWER_MONITOR = (1 << 15), /*!< Disable power monitoring. */ + LL_OP_MODE_FLAG_ENA_BIS_RECV_DUP = (1 << 16), /*!< Enable BIS receive duplicates. */ + LL_OP_MODE_FLAG_ENA_ISO_LOST_NOTIFY = (1 << 17), /*!< Enable HCI ISO lost SDU notification. */ + LL_OP_MODE_FLAG_ENA_CH_RPT_LLCP_AFTER_FEAT = (1 << 18), /*!< Perform channel report LLCP after feature exchange. */ + LL_OP_MODE_FLAG_IGNORE_CRC_ERR_TS = (1 << 19), /*!< Ignore timestamp of Rx packet with CRC error. */ + LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2 = (1 << 20), /*!< Force CIS to use Coded PHY with S2 option. */ /* diagnostics only */ - LL_OP_MODE_FLAG_ENA_ADV_DLY = (1 << 16), /*!< Enable advertising delay. */ - LL_OP_MODE_FLAG_ENA_SCAN_BACKOFF = (1 << 17), /*!< Enable scan backoff. */ - LL_OP_MODE_FLAG_ENA_WW = (1 << 18), /*!< Enable window widening. */ - LL_OP_MODE_FLAG_ENA_SLV_LATENCY = (1 << 19), /*!< Enable slave latency. */ - LL_OP_MODE_FLAG_ENA_LLCP_TIMER = (1 << 20), /*!< Enable LLCP timer. */ - LL_OP_MODE_FLAG_IGNORE_CRC_ERR_TS = (1 << 21) /*!< Ignore timestamp of RX packet with CRC error. */ + LL_OP_MODE_FLAG_ENA_ADV_DLY = (1 << 24), /*!< Enable advertising delay. */ + LL_OP_MODE_FLAG_ENA_SCAN_BACKOFF = (1 << 25), /*!< Enable scan backoff. */ + LL_OP_MODE_FLAG_ENA_WW = (1 << 26), /*!< Enable window widening. */ + LL_OP_MODE_FLAG_ENA_SLV_LATENCY = (1 << 27), /*!< Enable slave latency. */ + LL_OP_MODE_FLAG_ENA_LLCP_TIMER = (1 << 28), /*!< Enable LLCP timer. */ + LL_OP_MODE_FLAG_ENA_SUBRATE_CE = (1 << 29) /*!< Enable subrating connection events. */ }; /*! \} */ /* LL_API_DEVICE */ @@ -485,7 +503,14 @@ enum }; /*! \brief Periodic advertising create sync options valid bits. */ -#define LL_PER_ADV_CREATE_SYNC_OPTIONS_BITS 0x03 +#define LL_PER_ADV_CREATE_SYNC_OPTIONS_BITS 0x07 + +/*! \brief Periodic advertising enable bits. */ +enum +{ + LL_PER_ADV_ENABLE_ADV_ENABLE_BIT = (1 << 0), /*!< Enable bit for periodic advertising enable command. */ + LL_PER_ADV_ENABLE_ADI_ENABLE_BIT = (1 << 1) /*!< Enable bit for periodic advertising ADI inclusion. */ +}; /*! \brief Periodic advertising create sync command. */ typedef struct @@ -732,8 +757,8 @@ typedef enum /*! \brief ISO data path. */ typedef enum { - LL_ISO_DATA_PATH_HCI = 0x00, - LL_ISO_DATA_PATH_VS = 0x01, /*!< Vendor Specific. */ + LL_ISO_DATA_PATH_HCI = 0x00, /*!< HCI data path. */ + LL_ISO_DATA_PATH_VS = 0x01, /*!< Vendor Specific data path. */ LL_ISO_DATA_PATH_TOTAL, /*!< Total number of data path methods. */ @@ -747,6 +772,15 @@ enum LL_ISO_DATA_PATH_OUTPUT_BIT = (1 << 1) /*!< Data path output bit. */ }; +/*! \brief LE setup ISO Data Path command. */ +typedef struct +{ + LlIsoDataPathDir_t dpDir:8; /*!< Data path direction. */ + uint8_t dpId; /*!< Data path ID. */ + uint8_t vsCfgLen; /*!< Length of \a pVsCfg. */ + const uint8_t *pVsCfg; /*!< VS configuration buffer. */ +} LlIsoConfigDataPath_t; + /*! \brief LE setup ISO Data Path command. */ typedef struct { @@ -756,18 +790,19 @@ typedef struct uint8_t codecFormat; /*!< Codec Format. */ uint16_t codecCompId; /*!< Codec Company ID. */ uint16_t codecId; /*!< Codec ID. */ - uint32_t ctrDly; /*!< Codec ID. */ + uint32_t ctrDly; /*!< Controller delay. */ uint8_t codecConfigLen; /*!< Codec configuration length. */ - uint8_t *pCodecConfig; /*!< Codec configuration. */ + const uint8_t *pCodecConfig; /*!< Codec configuration. */ } LlIsoSetupDataPath_t; -/*! \brief BIG Create BIG message. */ +/*! \brief BIG Create BIG command. */ typedef struct { uint8_t bigHandle; /*!< Used to identify the BIG. */ uint8_t advHandle; /*!< Used to identify the periodic advertising train. */ uint8_t numBis; /*!< Total number of BISes in the BIG. */ uint32_t sduInterUsec; /*!< Interval, in microseconds, of BIG SDUs. */ + uint8_t bcstCode[LL_BC_LEN];/*!< Session key used to encrypt and decrypt BIS payloads. */ uint16_t maxSdu; /*!< Maximum size of an SDU. */ uint16_t mtlMs; /*!< Maximum time in milliseconds. */ uint8_t rtn; /*!< Retransmitted number. */ @@ -775,16 +810,16 @@ typedef struct uint8_t packing; /*!< Sequential or Interleaved packing. */ LlFraming_t framing:8; /*!< Unframed or Framed. */ uint8_t encrypt; /*!< Unencrypted or Encrypted. */ - uint8_t bcstCode[LL_BC_LEN];/*!< Session key used to encrypt and decrypt BIS payloads. */ } LlCreateBig_t; -/*! \brief BIG Create BIG Test message. */ +/*! \brief BIG Create BIG Test command. */ typedef struct { uint8_t bigHandle; /*!< Used to identify the BIG. */ uint8_t advHandle; /*!< Used to identify the periodic advertising train. */ uint8_t numBis; /*!< Total number of BISes in the BIG. */ uint32_t sduInterUsec; /*!< Interval in microseconds of BIG SDUs. */ + uint8_t bcstCode[LL_BC_LEN];/*!< Code used to derive the session key. */ uint16_t isoInter; /*!< Duration of an isochronous interval for BIG PDUs in 1.25ms unit. */ uint8_t nse; /*!< Total number of subevents in each interval of each BIS in the BIG. */ uint16_t maxSdu; /*!< Maximum size of a SDU. */ @@ -796,10 +831,9 @@ typedef struct uint8_t irc; /*!< Number of times the scheduled payload(s) are transmitted in a given event. */ uint8_t pto; /*!< Offset used for pre-transmissions. */ uint8_t encrypt; /*!< Unencrypted or Encrypted. */ - uint8_t bcstCode[LL_BC_LEN];/*!< Code used to derive the session key. */ } LlCreateBigTest_t; -/*! \brief BIG Create Sync message. */ +/*! \brief BIG Create Sync command. */ typedef struct { uint8_t bigHandle; /*!< Used to identify the BIG. */ @@ -814,6 +848,21 @@ typedef struct /*! \} */ /* LL_API_ISO */ +/*! \addtogroup LL_API_ECU + * \{ */ + +/*! \brief Subrate parameter. */ +typedef struct +{ + uint16_t srMin; /*!< Subrate minimum value. */ + uint16_t srMax; /*!< Subrate maximum value. */ + uint16_t maxLatency; /*!< Maximum latency. */ + uint16_t contNum; /*!< Continuation number. */ + uint16_t svt; /*!< Supervision timeout in 10ms units. */ +} LlSubrateParam_t; + +/*! \} */ /* LL_API_ECU */ + /*! \addtogroup LL_API_ENCRYPT * \{ */ @@ -903,7 +952,6 @@ typedef struct uint32_t duplicatePkt; /*!< Retransmitted CIS data PDUs. */ } LlIsoLinkQual_t; - /*! \} */ /* LL_API_TEST */ /*! \addtogroup LL_API_EVENT @@ -966,7 +1014,9 @@ enum LL_TX_POWER_REPORTING_IND, /*!< LL txPower change report received. */ LL_PATH_LOSS_REPORTING_IND, /*!< Path loss reporting event. */ LL_ISO_EVT_CMPL_IND, /*!< ISO Event complete event. */ - LL_BIG_INFO_ADV_REPORT_IND /*!< BIG Info advertising report event. */ + LL_BIG_INFO_ADV_REPORT_IND, /*!< BIG Info advertising report event. */ + /* --- Core Spec Sydney --- */ + LL_SUBRATE_CHANGE_IND /*!< Enhanced connection update complete. */ }; /*! \brief Advertising report indication */ @@ -1069,6 +1119,7 @@ typedef struct uint8_t status; /*!< Status. */ uint16_t handle; /*!< Connection handle. */ bool_t enabled; /*!< Encryption enabled. */ + uint8_t encKeySize; /*!< Encryption key size. */ } LlEncChangeInd_t; /*! \brief Key refresh indication */ @@ -1456,7 +1507,19 @@ typedef struct uint16_t connHandle; /*!< Connection handle. */ uint8_t curPathLoss; /*!< Current path loss. */ uint8_t zoneEntered; /*!< Zone entered. */ -} LlPathLossThresholdEvt_t; +} LlPathLossThresholdInd_t; + +/*! \brief Subrate change event. */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t status; /*!< Status. */ + uint16_t handle; /*!< Connection handle. */ + uint16_t srFactor; /*!< Subrate factor. */ + uint16_t perLatency; /*!< Peripheral latency. */ + uint16_t contNum; /*!< Continuation number. */ + uint16_t svt; /*!< Supervision timeout in 10ms units. */ +} LlSubrateChangeInd_t; /*! \brief Union of all event types */ typedef union @@ -1507,9 +1570,11 @@ typedef union LlBigSyncLostInd_t bigSyncLostInd; /*!< LE BIG sync lost. */ LlPeerScaCnf_t peerScaCnf; /*!< LE request peer SCA complete. */ LlPowerReportInd_t powerRptInd; /*!< LE transmit power reporting indication. */ - LlIsoEventCmplInd_t isoEvtCmplInd; /*!< VS ISO Event complete. */ + LlIsoEventCmplInd_t isoEvtCmplInd; /*!< ISO Event complete. */ LlBigInfoAdvRptInd_t bigInfoInd; /*!< LE Big Info indication. */ - LlPathLossThresholdEvt_t pathLossEvt; /*!< LE Path loss threshold reporting event. */ + LlPathLossThresholdInd_t pathLossInd; /*!< LE Path loss threshold reporting indication. */ + /* --- Core Spec Sydney --- */ + LlSubrateChangeInd_t subrateChangeInd; /*!< Subrate change event. */ } LlEvt_t; /*! \brief Event callback */ @@ -3841,27 +3906,31 @@ void LlGetPerScanContextSize(uint8_t *pMaxPerScan, uint16_t *pPerScanCtxSize); /*************************************************************************************************/ /*! - * \brief Get CIG context size. + * \brief Get CIS context size. * * \param pMaxCig Buffer to return the maximum number of CIG. * \param pCigCtxSize Buffer to return the size in bytes of the CIG context. - * - * Return the connection context sizes. - */ -/*************************************************************************************************/ -void LlGetCigContextSize(uint8_t *pMaxCig, uint16_t *pCigCtxSize); - -/*************************************************************************************************/ -/*! - * \brief Get CIS context size. - * * \param pMaxCis Buffer to return the maximum number of CIS. * \param pCisCtxSize Buffer to return the size in bytes of the CIS context. * * Return the connection context sizes. */ /*************************************************************************************************/ -void LlGetCisContextSize(uint8_t *pMaxCis, uint16_t *pCisCtxSize); +void LlGetCisContextSize(uint8_t *pMaxCig, uint16_t *pCigCtxSize, uint8_t *pMaxCis, uint16_t *pCisCtxSize); + +/*************************************************************************************************/ +/*! + * \brief Get BIS context size. + * + * \param pMaxBig Buffer to return the maximum number of BIG. + * \param pBigCtxSize Buffer to return the size in bytes of the BIG context. + * \param pMaxBis Buffer to return the maximum number of BIS. + * \param pBisCtxSize Buffer to return the size in bytes of the BIS context. + * + * Return the connection context sizes. + */ +/*************************************************************************************************/ +void LlGetBisContextSize(uint8_t *pMaxBig, uint16_t *pBigCtxSize, uint8_t *pMaxBis, uint16_t *pBisCtxSize); /*************************************************************************************************/ /*! @@ -3874,9 +3943,67 @@ uint16_t LlStatsGetHandlerWatermarkUsec(void); /*! \} */ /* LL_API_DIAG */ -/*! \addtogroup LL_API_CIS +/*! \addtogroup LL_API_ISO * \{ */ +/*************************************************************************************************/ +/*! + * \brief Used by a broadcaster host to command is used to create one or more BISes of a BIG + * in the controller. + * + * \param pCreateBig Create BIG parameters. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlCreateBig(LlCreateBig_t *pCreateBig); + +/*************************************************************************************************/ +/*! + * \brief Used by a broadcaster host to command is used to create one or more BISes of a BIG + * in the ISO test mode. + * + * \param pCreateBigTest Create BIG Test parameters. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlCreateBigTest(LlCreateBigTest_t *pCreateBigTest); + +/*************************************************************************************************/ +/*! + * \brief Used to terminate the transmission of all BISes of a BIG, or to cancel the process + * of creating a BIG using the HCI_LE_Create_BIG command from the Isochronous Broadcaster. + * + * \param bigHandle Used to identify the BIG. + * \param reason Termination reason. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlTerminateBig(uint8_t bigHandle, uint8_t reason); + +/*************************************************************************************************/ +/*! + * \brief Used to synchronize and receive PDUs from one or more BISes within a BIG. + * + * \param pCreateSync BIG Create Sync parameters. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlBigCreateSync(LlBigCreateSync_t *pCreateSync); + +/*************************************************************************************************/ +/*! + * \brief Used to stop synchronization with the BIG or to cancel the process of synchronizing + * to BISes invoked by the HCI_LE_BIG_Create_Sync command + * + * \param bigHandle Used to identify the BIG. + */ +/*************************************************************************************************/ +void LlBigTerminateSync(uint8_t bigHandle); + /*************************************************************************************************/ /*! * \brief Used by a master host to set the parameters of all connected isochronous streams @@ -3951,64 +4078,6 @@ uint8_t LlAcceptCisReq(uint16_t cisHandle); /*************************************************************************************************/ uint8_t LlRejectCisReq(uint16_t cisHandle, uint8_t reason); -/*************************************************************************************************/ -/*! - * \brief Used by a broadcaster host to command is used to create one or more BISes of a BIG - * in the controller. - * - * \param pCreateBig Create BIG parameters. - * - * \return Status error code. - */ -/*************************************************************************************************/ -uint8_t LlCreateBig(LlCreateBig_t *pCreateBig); - -/*************************************************************************************************/ -/*! - * \brief Used by a broadcaster host to command is used to create one or more BISes of a BIG - * in the ISO test mode. - * - * \param pCreateBigTest Create BIG Test parameters. - * - * \return Status error code. - */ -/*************************************************************************************************/ -uint8_t LlCreateBigTest(LlCreateBigTest_t *pCreateBigTest); - -/*************************************************************************************************/ -/*! - * \brief Used to terminate the transmission of all BISes of a BIG, or to cancel the process - * of creating a BIG using the HCI_LE_Create_BIG command from the Isochronous Broadcaster. - * - * \param bigHandle Used to identify the BIG. - * \param reason Termination reason. - * - * \return Status error code. - */ -/*************************************************************************************************/ -uint8_t LlTerminateBig(uint8_t bigHandle, uint8_t reason); - -/*************************************************************************************************/ -/*! - * \brief Used to synchronize and receive PDUs from one or more BISes within a BIG. - * - * \param pCreateSync BIG Create Sync parameters. - * - * \return Status error code. - */ -/*************************************************************************************************/ -uint8_t LlBigCreateSync(LlBigCreateSync_t *pCreateSync); - -/*************************************************************************************************/ -/*! - * \brief Used to stop synchronization with the BIG or to cancel the process of synchronizing - * to BISes invoked by the HCI_LE_BIG_Create_Sync command - * - * \param bigHandle Used to identify the BIG. - */ -/*************************************************************************************************/ -void LlBigTerminateSync(uint8_t bigHandle); - /*************************************************************************************************/ /*! * \brief Read the Time_Stamp and Time_Offset of a transmitted ISO_SDU identified by the @@ -4024,6 +4093,18 @@ void LlBigTerminateSync(uint8_t bigHandle); /*************************************************************************************************/ uint8_t LlReadIsoTxSync(uint16_t handle, uint16_t *pPktSn, uint32_t *pTs, uint32_t *pTimeOffs); +/*************************************************************************************************/ +/*! + * \brief Used to request the Controller to configure the data transport path in a given + * direction between the Controller and the Host. + * + * \param pConfigDataPath Parameters for configure data path. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlConfigureDataPath(LlIsoConfigDataPath_t *pConfigDataPath); + /*************************************************************************************************/ /*! * \brief Used to identify and enable the isochronous data path between the host and the @@ -4182,7 +4263,49 @@ uint8_t *LlRecvIsoData(void); /*************************************************************************************************/ void LlRecvIsoDataComplete(uint8_t numBufs); -/*! \} */ /* LL_API_CIS */ +/*! \} */ /* LL_API_ISO */ + +/*! \addtogroup LL_API_ECU + * \{ */ + +/*************************************************************************************************/ +/*! + * \brief Initialize LL subsystem for enhanced connection update. + * + * This function initializes the LL subsystem for use with enhanced connection updates. + */ +/*************************************************************************************************/ +void LlEnhConnUpdateInit(void); + +/*************************************************************************************************/ +/*! + * \brief Set the initial values for subrating requests. + * + * \param pSubrate Subrate parameter. + * + * \return Status error code. + * + * Set the initial values for the acceptable parameters for subrating requests for all future ACL + * connections where the Controller is the Central. This command does not affect any existing + * connection. + */ +/*************************************************************************************************/ +uint8_t LlSetDefaultSubrate(LlSubrateParam_t *pSubrate); + +/*************************************************************************************************/ +/*! + * \brief Request subrate change. + * + * \param handle Connection handle. + * \param pSubrate Subrate parameter. + * + * Used by a Central or a Peripheral to request a change to the subrating factor and/or other + * parameters applied to an existing connection using the Connection Subrate Update procedure. + */ +/*************************************************************************************************/ +void LlSubrateReq(uint16_t handle, LlSubrateParam_t *pSubrate); + +/*! \} */ /* LL_API_ECU */ #ifdef __cplusplus }; diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/ll_init_api.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/ll_init_api.h index aec6bae717..73eeec1ea8 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/ll_init_api.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/ll_init_api.h @@ -62,7 +62,7 @@ extern "C" { #ifndef BT_VER /*! \brief Initialize default BT version. */ -#define BT_VER LL_VER_BT_CORE_SPEC_5_1 +#define BT_VER LL_VER_BT_CORE_SPEC_5_0 #endif /************************************************************************************************** diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/sch_api_ble.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/sch_api_ble.h index bd8d482a63..869e363cdf 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/sch_api_ble.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/ble/sch_api_ble.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,7 +56,7 @@ extern "C" { enum { SCH_RM_PREF_PERFORMANCE, /*!< Performance is preferred, search from minimum interval. */ - SCH_RM_PREF_CAPACITY /*!< Capacity is preferred, search from maximum interval. */ + SCH_RM_PREF_CAPACITY /*!< Capacity is preferred, search from maximum interval. */ }; /************************************************************************************************** diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/bb_api.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/bb_api.h index 067f7f639e..796eb5aae0 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/bb_api.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/bb_api.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2018 ARM Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -159,6 +159,8 @@ typedef struct BbOpDesc_tag PalBbProt_t protId:8; /*!< Protocol type. */ + bool_t recoverable; /*!< Indicates if the BOD can recover if the dueUsec time is in the past. */ + BbBodCback_t endCback; /*!< End of BOD callback (when BOD ends). */ BbBodCback_t abortCback; /*!< Abort BOD callback (when BOD is removed before beginning). */ @@ -375,7 +377,7 @@ uint32_t BbAdjustTime(uint32_t dueUsec); /*************************************************************************************************/ /*! - * \brief Get Delta between target and reference time. Only valid if target time is in the future. + * \brief Get delta between target and reference time. Only valid if target time is in the future. * * \param targetUsec Target time in microseconds. * \param refUsec Reference time in microseconds. diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/cfg_mac.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/cfg_mac.h index 44b5660f33..15232c93ec 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/cfg_mac.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/cfg_mac.h @@ -39,12 +39,6 @@ extern "C" { #define CHCI_BUF_TAILROOM 4 /*!< Extra byte allocation required for buffer (e.g., for MIC). */ #endif -/*** Scheduler ***/ - -#ifndef SCH_TIMER_REQUIRED -#define SCH_TIMER_REQUIRED TRUE /*!< If hardware timer is required for radio access scheduler.*/ -#endif - #ifdef __cplusplus }; #endif diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/cfg_mac_ble.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/cfg_mac_ble.h index 71c1cdd7c5..f6ddf4324a 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/cfg_mac_ble.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/cfg_mac_ble.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -91,6 +91,18 @@ extern "C" { #define LL_MAX_BN 8 /*!< Absolute maximum number of bursts. */ #endif +#ifndef LL_PC_TBL_POW +#define LL_PC_TBL_POW 2 /*!< Running average power control array sizes, must be a power of 2. */ +#endif + +#ifndef LL_PC_SERVICE_MS +#define LL_PC_SERVICE_MS 1000 /*!< Power control service intervals in milliseconds. */ +#endif + +#ifndef LL_PC_REQ_CHANGE_DBM +#define LL_PC_REQ_CHANGE_DBM 5 /*!< Request of increase/decrease in power value in units of dBm. */ +#endif + #ifndef LHCI_ENABLE_VS #define LHCI_ENABLE_VS 1 /*!< Enable vendor specific command processing. */ #endif @@ -108,7 +120,8 @@ extern "C" { #endif #ifndef BB_ADV_PLD_MAX_LEN -#define BB_ADV_PLD_MAX_LEN 255 /*!< Maximum advertising channel payload length (valid range 95 to 255). */ +#define BB_ADV_PLD_MAX_LEN (BB_DATA_PLD_MAX_LEN + 4) + /*!< Maximum advertising channel payload length (valid range 95 to 255). */ #endif #ifndef BB_FIXED_DATA_PKT_LEN diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/chci_tr.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/chci_tr.h index 591e6452d7..62ba59fea1 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/chci_tr.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/chci_tr.h @@ -68,15 +68,6 @@ void chciTrRecv(uint8_t prot, uint8_t type, uint8_t *pBuf); /*************************************************************************************************/ void chciTrSendComplete(void); -/*************************************************************************************************/ -/*! - * \brief Service the transport device. - * - * \return TRUE if work pending, FALSE if no work is pending. - */ -/*************************************************************************************************/ -bool_t ChciTrService(void); - #ifdef __cplusplus }; #endif diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/sch_api.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/sch_api.h index c1de5179d9..6560ed9c9f 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/sch_api.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/include/common/sch_api.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 ARM Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,19 +49,16 @@ void SchInit(void); void SchHandlerInit(wsfHandlerId_t handlerId); void SchReset(void); uint16_t SchStatsGetHandlerWatermarkUsec(void); -uint16_t SchStatsGetDelayLoadWatermarkCount(void); -uint32_t SchStatsGetDelayLoadTotalCount(void); /* Control */ void SchHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); -void SchLoadHandler(void); /* List maintenance */ void SchInsertNextAvailable(BbOpDesc_t *pBod); bool_t SchInsertAtDueTime(BbOpDesc_t *pBod, BbConflictAct_t conflictCback); bool_t SchInsertEarlyAsPossible(BbOpDesc_t *pBod, uint32_t min, uint32_t max); bool_t SchInsertLateAsPossible(BbOpDesc_t *pBod, uint32_t min, uint32_t max); -bool_t SchRemove(BbOpDesc_t *pBod); +void SchRemove(BbOpDesc_t *pBod); void SchReload(BbOpDesc_t *pBod); bool_t SchIsBodCancellable(BbOpDesc_t *pBod); diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_master.c index 0c584d80e0..95f198b3ee 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_master.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,7 +53,7 @@ extern const BbRtCfg_t *pBbRtCfg; * * \return Scan duration in microseconds. * - * This function is calculates the duration of the scan examining: + * This function calculates the duration of the scan examining: * - total elapsed scan time * - neighboring BOD * - maximum scan period @@ -98,7 +98,6 @@ static uint32_t bbBleCalcScanDurationUsec(BbOpDesc_t *pBod, BbBleMstAdvEvent_t * if (pBod->pNext) { - uint32_t timeToNextOpUsec = BbGetTargetTimeDelta(pBod->pNext->dueUsec, refTime); /* Limit scanning to the edge of neighboring BOD. */ @@ -151,6 +150,13 @@ static bool_t bbContScanOp(BbOpDesc_t *pBod, BbBleMstAdvEvent_t *pScan) return TRUE; } + /* Check if an Aux Scan needs to be started ASAP because of a short auxOffset. */ + if (pScan->auxScanCheckCback && pScan->auxScanCheckCback(pBod, curTime, scanDurUsec)) + { + pBod->prot.pBle->op.mstAdv.auxScanOpRunning = TRUE; + return FALSE; + } + bbBleCb.bbParam.dueUsec = BbAdjustTime(bbBleCb.lastScanStartUsec + BbGetSchSetupDelayUs()); bbBleCb.bbParam.rxTimeoutUsec = scanDurUsec; PalBbBleSetDataParams(&bbBleCb.bbParam); @@ -191,6 +197,18 @@ static void bbMstScanTxCompCback(uint8_t status) bool_t bodComplete = FALSE; bool_t bodCont = FALSE; + if (pScan->auxScanTxCompCback && (pScan->auxScanOpRunning == TRUE)) + { + /* This is a linked operation. Call the Aux Scan callback. */ + if (pScan->auxScanTxCompCback(pScan->auxScanBod, status) == TRUE) + { + /* BOD complete. Clear the linked BOD. */ + pScan->auxScanBod = NULL; + pScan->auxScanOpRunning = FALSE; + } + return; + } + #if (BB_SNIFFER_ENABLED == TRUE) /* Save evtState to be used later in packet forwarding. */ uint8_t evtState = bbBleCb.evtState; @@ -318,6 +336,19 @@ static void bbMstScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint bool_t bodComplete = FALSE; bool_t bodCont = FALSE; + if (pScan->auxScanRxCompCback && pScan->auxScanOpRunning == TRUE) + { + /* This is a linked operation. Call the Aux Scan callback. */ + if (pScan->auxScanRxCompCback(pScan->auxScanBod, status, rssi, crc, timestamp, rxPhyOptions) == TRUE) + { + /* BOD complete. Clear the linked BOD. */ + pScan->auxScanBod = NULL; + pScan->auxScanOpRunning = FALSE; + } + + return; + } + #if (BB_SNIFFER_ENABLED == TRUE) /* Save evtState to be used later in packet forwarding. */ uint8_t evtState = bbBleCb.evtState; @@ -521,6 +552,16 @@ static void bbMstScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint static void bbMstExecuteScanOp(BbOpDesc_t *pBod, BbBleData_t *pBle) { BbBleMstAdvEvent_t * const pScan = &pBod->prot.pBle->op.mstAdv; + uint32_t curTime = PalBbGetCurrentTime(); + + /* Check if dueUsec time is in the past. */ + if (BbGetTargetTimeDelta(pBod->dueUsec, curTime) == 0) + { + /* Update dueUsec time and start Scan for the remaining duration. */ + bbBleCb.lastScanStartUsec = pBod->dueUsec; + pBod->dueUsec = curTime + BbGetSchSetupDelayUs(); + pScan->elapsedUsec = BbGetTargetTimeDelta(curTime, bbBleCb.lastScanStartUsec); + } if (pScan->preExecCback) { diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_master_ae.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_master_ae.c index a87da6c7cc..456c557667 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_master_ae.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_master_ae.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,15 +52,16 @@ static uint8_t bbPerScanBuf[LL_EXT_ADVB_MAX_LEN]; * \brief Tx completion for auxiliary scanning master operation. * * \param status Completion status. + * \param pBod Pointer to the BOD * * Setup for next action in the operation or complete the operation. + * + * \return TRUE if BOD is complete, FALSE otherwise. */ /*************************************************************************************************/ -static void bbMstAuxScanTxCompCback(uint8_t status) +bool_t BbMstAuxScanTxCompHandler(BbOpDesc_t *pBod, uint8_t status) { - BB_ISR_START(); - - WSF_ASSERT(BbGetCurrentBod()); + WSF_ASSERT(pBod); bool_t bodComplete = FALSE; @@ -72,7 +73,6 @@ static void bbMstAuxScanTxCompCback(uint8_t status) { pPkt = bbSnifferCtx.snifferGetPktFn(); } - BbOpDesc_t * const pCur = BbGetCurrentBod(); #endif switch (bbBleCb.evtState++) @@ -128,10 +128,30 @@ static void bbMstAuxScanTxCompCback(uint8_t status) pPkt->pktType.meta.status = status; pPkt->pktType.meta.state = evtState; - bbBleSnifferMstAuxScanPktHandler(pCur, pPkt); + bbBleSnifferMstAuxScanPktHandler(pBod, pPkt); } +#else + (void)pBod; #endif + return bodComplete; +} + +/*************************************************************************************************/ +/*! + * \brief Tx completion for auxiliary scanning master operation. + * + * \param status Completion status. + * + * Setup for next action in the operation or complete the operation. + */ +/*************************************************************************************************/ +static void bbMstAuxScanTxCompCback(uint8_t status) +{ + BB_ISR_START(); + + (void)BbMstAuxScanTxCompHandler(BbGetCurrentBod(), status); + BB_ISR_MARK(bbAuxScanStats.txIsrUsec); } @@ -139,6 +159,7 @@ static void bbMstAuxScanTxCompCback(uint8_t status) /*! * \brief Rx completion for auxiliary scanning master operation. * + * \param pCur Pointer to the BOD * \param status Reception status. * \param rssi RSSI value. * \param crc CRC value. @@ -146,15 +167,14 @@ static void bbMstAuxScanTxCompCback(uint8_t status) * \param rxPhyOptions Rx PHY options. * * Setup for next action in the operation or complete the operation. + * + * \return TRUE if BOD is complete, FALSE otherwise. */ /*************************************************************************************************/ -static void bbMstAuxScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint32_t timestamp, uint8_t rxPhyOptions) +bool_t BbMstAuxScanRxCompHandler(BbOpDesc_t * const pCur, uint8_t status, int8_t rssi, uint32_t crc, uint32_t timestamp, uint8_t rxPhyOptions) { - BB_ISR_START(); + WSF_ASSERT(pCur); - WSF_ASSERT(BbGetCurrentBod()); - - BbOpDesc_t * const pCur = BbGetCurrentBod(); BbBleData_t * const pBle = pCur->prot.pBle; BbBleMstAuxAdvEvent_t * const pAuxScan = &pBle->op.mstAuxAdv; @@ -195,54 +215,65 @@ static void bbMstAuxScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u #endif uint32_t auxOffsetUsec; - if (pAuxScan->rxAuxAdvCback(pCur, bbAuxAdvBuf)) + bool_t txScanReq = pAuxScan->rxAuxAdvCback(pCur, bbAuxAdvBuf); + if ((txScanReq) && (pAuxScan->pTxAuxReqBuf)) { - if (pAuxScan->pTxAuxReqBuf) - { - /* Tx response PDU. */ + /* Tx response PDU. */ - bbBleCb.evtState = BB_EVT_STATE_TX_SCAN_OR_CONN_INIT; + bbBleCb.evtState = BB_EVT_STATE_TX_SCAN_OR_CONN_INIT; - BB_ISR_MARK(bbAuxScanStats.txSetupUsec); + BB_ISR_MARK(bbAuxScanStats.txSetupUsec); - PalBbBleTxBufDesc_t desc = {.pBuf = pAuxScan->pTxAuxReqBuf, .len = pAuxScan->txAuxReqLen}; + PalBbBleTxBufDesc_t desc = {.pBuf = pAuxScan->pTxAuxReqBuf, .len = pAuxScan->txAuxReqLen}; - bbBleSetTifs(); - PalBbBleTxTifsData(&desc, 1); - } - } - else if ((pAuxScan->rxAuxChainCback) && - ((auxOffsetUsec = pAuxScan->rxAuxChainCback(pCur, bbAuxAdvBuf)) > 0)) - { - /* Rx chain indication PDU. */ - - bbBleCb.evtState = BB_EVT_STATE_RX_CHAIN_IND; - - /* Cancel Tifs operation is needed for passive scan and non connectable/scannable adv with chain. */ - PalBbBleCancelTifs(); - - PalBbBleSetChannelParam(&pBle->chan); - bbBleCb.bbParam.dueUsec = BbAdjustTime(timestamp + auxOffsetUsec); - PalBbBleSetDataParams(&bbBleCb.bbParam); - - BB_ISR_MARK(bbAuxScanStats.rxSetupUsec); - - bbBleClrIfs(); /* CHAIN_IND does not use TIFS. */ - PalBbBleRxData(bbAuxAdvBuf, sizeof(bbAuxAdvBuf)); - - WSF_ASSERT(pAuxScan->rxAuxChainPostCback); - if (pAuxScan->rxAuxChainPostCback(pCur, bbAuxAdvBuf) == FALSE) - { - bodCont = TRUE; - } + bbBleSetTifs(); + PalBbBleTxTifsData(&desc, 1); } else { - if (pAuxScan->rxAuxChainPostCback) + PalBbBleCancelTifs(); + } + + if (pAuxScan->rxAuxAdvPostCback) + { + pAuxScan->rxAuxAdvPostCback(pCur, bbAuxAdvBuf); + } + + if (!txScanReq) + { + if ((pAuxScan->rxAuxChainCback) && + ((auxOffsetUsec = pAuxScan->rxAuxChainCback(pCur, bbAuxAdvBuf)) > 0)) { - pAuxScan->rxAuxChainPostCback(pCur, bbAuxAdvBuf); + /* Rx chain indication PDU. */ + + bbBleCb.evtState = BB_EVT_STATE_RX_CHAIN_IND; + + /* Cancel Tifs operation is needed for passive scan and non connectable/scannable adv with chain. */ + PalBbBleCancelTifs(); + + PalBbBleSetChannelParam(&pBle->chan); + bbBleCb.bbParam.dueUsec = BbAdjustTime(timestamp + auxOffsetUsec); + PalBbBleSetDataParams(&bbBleCb.bbParam); + + BB_ISR_MARK(bbAuxScanStats.rxSetupUsec); + + bbBleClrIfs(); /* CHAIN_IND does not use TIFS. */ + PalBbBleRxData(bbAuxAdvBuf, sizeof(bbAuxAdvBuf)); + + WSF_ASSERT(pAuxScan->rxAuxChainPostCback); + if (pAuxScan->rxAuxChainPostCback(pCur, bbAuxAdvBuf) == FALSE) + { + bodCont = TRUE; + } + } + else + { + if (pAuxScan->rxAuxChainPostCback) + { + pAuxScan->rxAuxChainPostCback(pCur, bbAuxAdvBuf); + } + bodCont = TRUE; } - bodCont = TRUE; } break; } @@ -494,8 +525,29 @@ static void bbMstAuxScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u } #endif - BB_ISR_MARK(bbAuxScanStats.rxIsrUsec); + return bodComplete; +} +/*************************************************************************************************/ +/*! + * \brief Rx completion for auxiliary scanning master operation. + * + * \param status Reception status. + * \param rssi RSSI value. + * \param crc CRC value. + * \param timestamp Start of packet timestamp in microseconds. + * \param rxPhyOptions Rx PHY options. + * + * Setup for next action in the operation or complete the operation. + */ +/*************************************************************************************************/ +static void bbMstAuxScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint32_t timestamp, uint8_t rxPhyOptions) +{ + BB_ISR_START(); + + (void)BbMstAuxScanRxCompHandler(BbGetCurrentBod(), status, rssi, crc, timestamp, rxPhyOptions); + + BB_ISR_MARK(bbAuxScanStats.rxIsrUsec); } /*************************************************************************************************/ @@ -856,3 +908,34 @@ void BbBleGetPerScanStats(BbBlePerScanPktStats_t *pStats) *pStats = bbPerScanStats; } +/*************************************************************************************************/ +/*! + * \brief Execute auxiliary scanning master BOD. + * + * \param pBod Pointer to the BOD to execute. + * \param pBle BLE operation parameters. + */ +/*************************************************************************************************/ +void BbMstExecuteLinkedAuxScanOp(BbOpDesc_t *pBod, BbBleData_t *pBle) +{ + BbBleMstAuxAdvEvent_t * const pAuxScan = &pBod->prot.pBle->op.mstAuxAdv; + + PalBbBleSetChannelParam(&pBle->chan); + + bbBleCb.bbParam.rxTimeoutUsec = pAuxScan->rxSyncDelayUsec; + bbBleCb.bbParam.dueUsec = BbAdjustTime(pBod->dueUsec); + pBod->dueUsec = bbBleCb.bbParam.dueUsec; + PalBbBleSetDataParams(&bbBleCb.bbParam); + + bbBleCb.evtState = 0; + + if (pAuxScan->pTxAuxReqBuf) + { + bbBleSetTifs(); /* active scan or initiating */ + } + else + { + bbBleClrIfs(); /* passive scan */ + } + PalBbBleRxData(bbAuxAdvBuf, sizeof(bbAuxAdvBuf)); +} diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_slave.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_slave.c index 32053c4dc0..1a0799cd54 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_slave.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_slave.c @@ -119,7 +119,7 @@ static bool_t bbSetupAdvOp(BbOpDesc_t *pBod, BbBleSlvAdvEvent_t *pAdv, uint8_t s { /* Schedule with absolute frame gap. */ uint32_t advGap = SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, pBle->chan.initTxPhyOptions, pAdv->txAdvLen) + - BbGetSchSetupDelayUs(); + BbGetSchSetupDelayUs(); uint32_t auxOffsUsec = SchBleGetAlignedAuxOffsUsec(advGap); bbBleCb.bbParam.dueUsec = BbAdjustTime(bbBleCb.bbParam.dueUsec + auxOffsUsec); } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_slave_ae.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_slave_ae.c index 0d672ed3fe..59df5bfdd1 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_slave_ae.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_slave_ae.c @@ -193,7 +193,6 @@ Cleanup: BbTerminateBod(); } - #if (BB_SNIFFER_ENABLED == TRUE) if (pPkt) { diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_bis_slave.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_bis_slave.c index d232cf6e3c..13d63c6ad9 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_bis_slave.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_bis_slave.c @@ -137,7 +137,14 @@ void BbBleBisSlaveInit(void) /*************************************************************************************************/ void BbBleBisTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt, uint32_t nextPduTime, PalBbBleChan_t *pNextChan) { - bbBleSetAbsIfs(nextPduTime, pNextChan); + if (pNextChan) + { + bbBleSetAbsIfs(nextPduTime, pNextChan); + } + else + { + bbBleClrIfs(); + } if (bbBleCb.evtState == 0) { @@ -149,3 +156,13 @@ void BbBleBisTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt, uint32_t nextPduTi PalBbBleTxTifsData(descs, cnt); } } + +/*************************************************************************************************/ +/*! + * \brief Get BIS packet statistics. + */ +/*************************************************************************************************/ +void BbBleGetBisStats(BbBleDataPktStats_t *pStats) +{ + *pStats = bbBisStats; +} diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis.c index 472dd1b9b1..c557e035d8 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis.c @@ -80,10 +80,10 @@ void BbBleCisTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) /*************************************************************************************************/ void BbBleCisRxData(uint8_t *pBuf, uint16_t len) { - WSF_ASSERT(!bbBleCb.pRxCisDataBuf); + WSF_ASSERT(!bbBleCb.pRxDataBuf); - bbBleCb.pRxCisDataBuf = pBuf; - bbBleCb.rxCisDataLen = len; + bbBleCb.pRxDataBuf = pBuf; + bbBleCb.rxDataLen = len; if ((BbGetCurrentBod()->prot.pBle->chan.opType == BB_BLE_OP_SLV_CIS_EVENT) && (bbBleCb.evtState == 0)) @@ -95,7 +95,7 @@ void BbBleCisRxData(uint8_t *pBuf, uint16_t len) /*************************************************************************************************/ /*! - * \brief Get connection packet statistics. + * \brief Get CIS packet statistics. */ /*************************************************************************************************/ void BbBleGetCisStats(BbBleDataPktStats_t *pStats) diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis_master.c index f259fce35d..d2f75f9aff 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis_master.c @@ -71,6 +71,11 @@ static bool_t bbMstCisCheckContOp(BbOpDesc_t *pCur, BbBleMstCisEvent_t *pCis, bo return TRUE; } + /* Cancel TIFS timer. */ + PalBbBleCancelTifs(); + + (void)pCis->checkContOpPostCback(pCur, pNewCisCtx); + /* Updated channel parameter. */ BbBleData_t *pBle = pCur->prot.pBle; PalBbBleSetChannelParam(&pBle->chan); @@ -121,13 +126,13 @@ static void bbMstCisTxCompCback(uint8_t status) pCis->txDataCback(pCur, status); - if (bbBleCb.pRxCisDataBuf && + if (bbBleCb.pRxDataBuf && (status == BB_STATUS_SUCCESS)) { BB_ISR_MARK(bbCisStats.rxSetupUsec); bbBleSetTifs(); /* TODO set only if Tx may follow in CE */ - PalBbBleRxTifsData(bbBleCb.pRxCisDataBuf, bbBleCb.rxDataLen); + PalBbBleRxTifsData(bbBleCb.pRxDataBuf, bbBleCb.rxDataLen); } else { @@ -140,10 +145,10 @@ static void bbMstCisTxCompCback(uint8_t status) case BB_STATUS_FAILED: default: /* Free Rx data buffer before BOD end. */ - if (bbBleCb.pRxCisDataBuf != NULL) /* buffer should always exist, but still check */ + if (bbBleCb.pRxDataBuf != NULL) /* buffer should always exist, but still check */ { - uint8_t *pBuf = bbBleCb.pRxCisDataBuf; - bbBleCb.pRxCisDataBuf = NULL; + uint8_t *pBuf = bbBleCb.pRxDataBuf; + bbBleCb.pRxDataBuf = NULL; pCis->rxDataCback(pCur, pBuf, BB_STATUS_CANCELED); } break; @@ -199,9 +204,9 @@ static void bbMstCisRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint3 pCis->rssi = rssi; pCis->rxPhyOptions = rxPhyOptions; - WSF_ASSERT(bbBleCb.pRxCisDataBuf); - uint8_t *pBuf = bbBleCb.pRxCisDataBuf; - bbBleCb.pRxCisDataBuf = NULL; + WSF_ASSERT(bbBleCb.pRxDataBuf); + uint8_t *pBuf = bbBleCb.pRxDataBuf; + bbBleCb.pRxDataBuf = NULL; pCis->rxDataCback(pCur, pBuf, status); @@ -210,7 +215,7 @@ static void bbMstCisRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint3 if (BbGetBodTerminateFlag() || bodComplete) { - WSF_ASSERT(!bbBleCb.pRxCisDataBuf); + WSF_ASSERT(!bbBleCb.pRxDataBuf); /* Cancel TIFS timer if active. */ switch (status) @@ -280,6 +285,7 @@ static void bbMstExecuteCisOp(BbOpDesc_t *pBod, BbBleData_t *pBle) WSF_ASSERT(pBle->op.mstCis.rxDataCback); WSF_ASSERT(pBle->op.mstCis.execCback); WSF_ASSERT(pBle->op.mstCis.checkContOpCback); + WSF_ASSERT(pBle->op.mstCis.checkContOpPostCback); #if(LL_ENABLE_TESTER) pBle->chan.txPower += pBle->chan.txPwrOffset; @@ -317,10 +323,10 @@ static void bbMstCancelCisOp(BbOpDesc_t *pBod, BbBleData_t *pBle) PalBbBleCancelData(); - if (bbBleCb.pRxCisDataBuf) + if (bbBleCb.pRxDataBuf) { - uint8_t *pBuf = bbBleCb.pRxCisDataBuf; - bbBleCb.pRxCisDataBuf = NULL; + uint8_t *pBuf = bbBleCb.pRxDataBuf; + bbBleCb.pRxDataBuf = NULL; /* Buffer free expected to be called during this routine. */ pBle->op.mstCis.rxDataCback(pBod, pBuf, BB_STATUS_CANCELED); diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis_slave.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis_slave.c index 5a38d7bfb6..68ef62fc18 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis_slave.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis_slave.c @@ -83,6 +83,11 @@ static bool_t bbSlvCisCheckNextOp(BbOpDesc_t *pCur, BbBleSlvCisEvent_t *pCis, bo return TRUE; } + /* Cancel TIFS timer. */ + PalBbBleCancelTifs(); + + (void)pCis->checkContOpPostCback(pCur, pNewCisCtx); + /* Update channel parameter. */ BbBleData_t *pBle = pCur->prot.pBle; PalBbBleSetChannelParam(&pBle->chan); @@ -148,10 +153,10 @@ static void bbSlvCisTxCompCback(uint8_t status) { if (bodComplete) { - if (bbBleCb.pRxCisDataBuf != NULL) + if (bbBleCb.pRxDataBuf != NULL) { - uint8_t *pBuf = bbBleCb.pRxCisDataBuf; - bbBleCb.pRxCisDataBuf = NULL; + uint8_t *pBuf = bbBleCb.pRxDataBuf; + bbBleCb.pRxDataBuf = NULL; pCis->rxDataCback(pCur, pBuf, BB_STATUS_CANCELED); } @@ -168,10 +173,10 @@ static void bbSlvCisTxCompCback(uint8_t status) } else { - if (bbBleCb.pRxCisDataBuf != NULL) + if (bbBleCb.pRxDataBuf != NULL) { - uint8_t *pBuf = bbBleCb.pRxCisDataBuf; - bbBleCb.pRxCisDataBuf = NULL; + uint8_t *pBuf = bbBleCb.pRxDataBuf; + bbBleCb.pRxDataBuf = NULL; pCis->rxDataCback(pCur, pBuf, BB_STATUS_CANCELED); } @@ -231,7 +236,7 @@ static void bbSlvCisRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint3 if (pCis->isFirstTs == TRUE) { - /* Update startTs for the successful rx, otherwise use the due time. */ + /* Update startTs for the successful Rx, otherwise use the due time. */ if (status == BB_STATUS_SUCCESS) { pCis->startTsUsec = timestamp; @@ -245,30 +250,49 @@ static void bbSlvCisRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint3 } else { - /* Update rxTs for the successful rx, otherwise use the due time. */ + /* Update rxTs for the successful Rx, otherwise use the due time. */ if (status == BB_STATUS_SUCCESS) { pCis->rxTsUsec = timestamp; } } - WSF_ASSERT(bbBleCb.pRxCisDataBuf); + WSF_ASSERT(bbBleCb.pRxDataBuf); - uint8_t *pBuf = bbBleCb.pRxCisDataBuf; - bbBleCb.pRxCisDataBuf = NULL; + uint8_t *pBuf = bbBleCb.pRxDataBuf; + bbBleCb.pRxDataBuf = NULL; /* Set Tx buffer or BOD cancel expected to be called during this routine. */ pCis->rxDataCback(pCur, pBuf, status); - if ((status != BB_STATUS_RX_TIMEOUT) && /* BB_STATUS_RX_TIMEOUT will setup Tx which will be failed and terminate BOD. */ - BbGetBodTerminateFlag()) + bool_t bodComplete = FALSE; + bool_t newCisCtx = FALSE; + + switch (status) { - WSF_ASSERT(!bbBleCb.pRxCisDataBuf); + case BB_STATUS_RX_TIMEOUT: + case BB_STATUS_FAILED: + bodComplete = bbSlvCisCheckNextOp(pCur, pCis, &newCisCtx); + + /* Skip the post subevent callback if switching to the new CIS context. */ + if (newCisCtx == FALSE) + { + bbSlvCisPostSubEvt(pCur, pCis, status); + } + break; + default: + break; + } + + if (BbGetBodTerminateFlag() || bodComplete) + { + WSF_ASSERT(!bbBleCb.pRxDataBuf); /* Cancel TIFS timer if active. */ switch (status) { case BB_STATUS_SUCCESS: + case BB_STATUS_CRC_FAILED: PalBbBleCancelTifs(); break; default: @@ -320,6 +344,7 @@ static void bbSlvExecuteCisOp(BbOpDesc_t *pBod, BbBleData_t *pBle) WSF_ASSERT(pCis->rxDataCback); WSF_ASSERT(pCis->execCback); WSF_ASSERT(pCis->checkContOpCback); + WSF_ASSERT(pCis->checkContOpPostCback); pCis->isFirstTs = TRUE; pCis->rxTsUsec = pBod->dueUsec; @@ -357,10 +382,10 @@ static void bbSlvCancelCisOp(BbOpDesc_t *pBod, BbBleData_t *pBle) PalBbBleCancelData(); - if (bbBleCb.pRxCisDataBuf) + if (bbBleCb.pRxDataBuf) { - uint8_t *pBuf = bbBleCb.pRxCisDataBuf; - bbBleCb.pRxCisDataBuf = NULL; + uint8_t *pBuf = bbBleCb.pRxDataBuf; + bbBleCb.pRxDataBuf = NULL; /* Buffer free expected to be called during this routine. */ pBle->op.slvCis.rxDataCback(pBod, pBuf, BB_STATUS_CANCELED); diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_int.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_int.h index d9ded94f9c..11a845c9bf 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_int.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_int.h @@ -94,10 +94,6 @@ typedef struct uint16_t rxDataLen; /*!< Receive data buffer length. */ uint8_t *pRxDataBuf; /*!< Current Rx data buffer. */ - - /* TODO combine with above? */ - uint16_t rxCisDataLen; /*!< Receive CIS data buffer length. */ - uint8_t *pRxCisDataBuf; /*!< Current Rx CIS data buffer. */ } bbBleCtrlBlk_t; /************************************************************************************************** diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_master_ae.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_master_ae.h index daf7cc85a9..ada9734f7c 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_master_ae.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_master_ae.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -99,6 +99,13 @@ enum LCTR_SCAN_PHY_ALL = 0xFF /*!< All PHY scanners. */ }; +/*! \brief Periodic scan receive enable bits. */ +enum +{ + LCTR_PER_RECV_ENABLE_REPORT_BIT_POS = 0, /*!< Enable periodic scan reports. */ + LCTR_PER_RECV_ENABLE_FILTERING_BIT_POS = 1 /*!< Enable filtering by ADI of periodic advertising trains. */ +}; + /************************************************************************************************** Data Types **************************************************************************************************/ @@ -142,6 +149,7 @@ typedef struct uint64_t advAddr; /*!< Advertiser Address. */ uint16_t skip; /*!< Skip. */ uint16_t syncTimeOut; /*!< Synchronization Timeout. */ + uint8_t dupFilterEnable; /*!< Duplicate filtering enable. */ } lctrPerCreateSyncMsg_t; /*! \brief Periodic transfer sync message. */ @@ -204,7 +212,7 @@ uint64_t LctrGetPerScanChanMap(uint16_t handle); bool_t lctrMstPerIsSyncHandleValid(uint16_t syncHandle); void LctrPastInit(void); uint8_t LctrPeriodicAdvSyncTransfer(uint16_t connHandle, uint16_t serviceData, uint16_t syncHandle); -void LctrMstPerSetRcvEnable(uint16_t syncHandle, bool_t enable); +void LctrMstPerSetRcvEnable(uint16_t syncHandle, uint8_t enable); #ifdef __cplusplus }; diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_slave_ae.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_slave_ae.h index 058335e96b..00091ab18a 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_slave_ae.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_slave_ae.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_conn.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_conn.h index 578e96c126..0bd705466a 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_conn.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_conn.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -88,7 +88,7 @@ enum LCTR_CONN_MSG_API_CIS_REQ_ACCEPT, /*!< Peer CIS request accept API event. */ LCTR_CONN_MSG_API_CIS_REQ_REJECT, /*!< Peer CIS request accept API event. */ LCTR_CONN_MSG_API_PWR_CTRL_REQ, /*!< Peer power control request API event. */ - + LCTR_CONN_MSG_API_SUBRATE_REQ, /*!< Subrate request API event. */ /* Internal events */ _LCTR_CONN_INT_EVENTS = 40, LCTR_CONN_DATA_PENDING, /*!< New data pending. */ @@ -100,9 +100,12 @@ enum LCTR_CONN_LLCP_VERSION_EXCH, /*!< LL initiated remote version exchange. */ LCTR_CONN_LLCP_FEATURE_EXCH, /*!< LL initiated remote feature exchange. */ LCTR_CONN_LLCP_LENGTH_EXCH, /*!< LL initiated data length exchange. */ - LCTR_CONN_LLCP_PWR_CTRL_REQ, /*!< LL initiated power control request. */ + LCTR_CONN_LLCP_PWR_CTRL_SERVICE, /*!< Service power control monitor. */ LCTR_CONN_LLCP_TERM, /*!< LL initiated termination. */ + LCTR_CONN_LLCP_CHANNEL_STATUS, /*!< LL initiated channel status. */ + LCTR_CONN_LLCP_CHANNEL_REPORTING, /*!< LL initiated channel reporting. */ LCTR_CONN_LLCP_PROC_CMPL, /*!< LLCP procedure completed. */ + LCTR_CONN_LLCP_PROC_ABORTED, /*!< LLCP procedure aborted. */ LCTR_CONN_LLCP_START_PENDING, /*!< Start pending LLCP procedure. */ LCTR_CONN_LLCP_SKIP_CONN_PARAM, /*!< Skip connection parameter exchange. */ LCTR_CONN_LLCP_REJECT_CONN_UPD, /*!< Reject a connection update. */ @@ -240,6 +243,34 @@ typedef struct uint8_t phy; /*!< PHY requested. */ } lctrMsgPwrCtrlReq_t; +/*! \brief Internal subrate request message. */ +typedef struct +{ + lctrMsgHdr_t hdr; /*!< Message Header. */ + uint16_t srMin; /*!< Subrate minimum value. */ + uint16_t srMax; /*!< Subrate maximum value. */ + uint16_t maxLatency; /*!< Maximum latency. */ + uint16_t contNum; /*!< Continuation number. */ + uint16_t svt; /*!< Supervision timeout in 10ms units. */ +} lctrMsgSubrateReq_t; + +/*! \brief Channel reporting indication message. */ +typedef struct +{ + lctrMsgHdr_t hdr; /*!< Message Header. */ + uint8_t enable; /*!< Enable. */ + uint8_t minSpacing; /*!< Minimum status report spacing. */ + uint8_t maxDelay; /*!< Maximum status report delay. */ +} lctrMsgChRptInd_t; + +/*! \brief Channel status indication message. */ +typedef struct +{ + lctrMsgHdr_t hdr; /*!< Message Header. */ + uint8_t chanStatus[LL_MAX_NUM_CHAN_DATA]; + /*!< Status of used channels. */ +} lctrMsgChStatusInd_t; + /*! \brief Link layer controller message data. */ typedef union { @@ -258,6 +289,9 @@ typedef union lctrPerAdvSyncTrsf_t perAdvSyncTrsf; /*!< Periodic advertising sync transfer data. */ lctrScaReq_t scaReq; /*!< Sleep clock accuracy request. */ lctrMsgPwrCtrlReq_t pwrCtrlReq; /*!< Power control request. */ + lctrMsgSubrateReq_t subrateReq; /*!< Subrate request. */ + lctrMsgChRptInd_t chanRptInd; /*!< Channel report indication. */ + lctrMsgChStatusInd_t chanStatusInd; /*!< Channel status indication. */ /* CIS */ lctrCreateCis_t createCis; /*!< Create CIS message data. */ @@ -314,6 +348,8 @@ void LctrVsConnInit(const LctrVsHandlers_t *pHdlrs); uint8_t LctrValidateConnSpec(const LlConnSpec_t *pConnSpec); uint8_t LctrValidateModifyScaParam(uint8_t action); bool_t LctrIsProcActPended(uint16_t handle, uint8_t event); +bool_t LctrIsFeatExchHostInit(uint16_t handle); +void LctrSetHostNotifyFeatExch(uint16_t handle); /* Status */ bool_t LctrIsConnHandleEnabled(uint16_t handle); @@ -326,6 +362,7 @@ uint64_t LctrGetChannelMap(uint16_t handle); uint64_t LctrGetUsedFeatures(uint16_t handle); uint8_t LctrGetTxPhy(uint16_t handle); uint8_t LctrGetRxPhy(uint16_t handle); +bool_t LctrCisTerminationInProgress(uint16_t handle); void LctrGetPeerMinUsedChan(uint16_t handle, uint8_t *pPeerMinUsedChan); bool_t LctrIsWaitingForReply(uint16_t handle, uint8_t reply); bool_t LctrIsCisEnabled(uint16_t handle); @@ -341,7 +378,6 @@ bool_t LctrSetEncMode(uint16_t handle, const LlEncMode_t *pMode); void LctrSetConnOpFlags(uint16_t handle, uint32_t flags, bool_t enable); uint8_t lctrSetPowerMonitorEnable(uint16_t handle, bool_t enable); - /* Data path */ void LctrTxAcl(uint8_t *pAclBuf); uint8_t *LctrRxAcl(void); diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_iso.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_iso.h index c7b6904bea..be168ed2b8 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_iso.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_iso.h @@ -45,6 +45,7 @@ void LctrTxIso(uint8_t *pIsoBuf); uint8_t *LctrRxIso(void); void LctrRxIsoComplete(uint8_t numBufs); uint8_t LctrReadIsoTxSync(uint16_t handle, uint16_t *pPktSn, uint32_t *pTs, uint32_t *pTimeOffs); +uint8_t LctrConfigureDataPath(LlIsoConfigDataPath_t *pConfigDataPath); uint8_t LctrSetupIsoDataPath(LlIsoSetupDataPath_t *pSetupDataPath); uint8_t LctrRemoveIsoDataPath(uint16_t handle, uint8_t dpDir); uint8_t LctrIsoTxTest(uint16_t handle, uint8_t pldType); diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_conn.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_conn.h index c600a6982f..cbadfd3880 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_conn.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_conn.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,14 +53,22 @@ typedef struct uint32_t dataPendMsk; /*!< Bitmask of connection handles with new pending data. */ + /* PHY */ uint8_t allPhys; /*!< Default all PHYs. */ uint8_t txPhys; /*!< Default transmitter PHYs. */ uint8_t rxPhys; /*!< Default receiver PHYs. */ + /* PAST */ uint8_t syncMode; /*!< Default sync transfer mode. */ uint16_t syncSkip; /*!< Default sync skip for periodic adv sync transfer. */ uint16_t syncTimeout; /*!< Default sync timeout for periodic adv sync transfer. */ + /* Enhanced Connection Update */ + uint16_t defSrMin; /*!< Default subrate minimum value. */ + uint16_t defSrMax; /*!< Default subrate maximum value. */ + uint16_t defMaxLatency; /*!< Default maximum latency. */ + uint16_t defContNum; /*!< Default continuation number. */ + uint16_t defSvt; /*!< Default supervision timeout. */ } lmgrConnCtrlBlk_t; /************************************************************************************************** diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/init/init.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/init/init.c index abd7457505..0754f85bce 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/init/init.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/init/init.c @@ -154,7 +154,6 @@ void LlInitLlInit(void) #if (BT_VER >= LL_VER_BT_CORE_SPEC_5_2) LlCisMasterInit(); LlBisMasterInit(); - LlPowerControlInit(); #endif #else #ifdef INIT_OBSERVER @@ -171,7 +170,6 @@ void LlInitLlInit(void) #if (BT_VER >= LL_VER_BT_CORE_SPEC_5_2) LlCisSlaveInit(); LlBisSlaveInit(); - LlPowerControlInit(); #endif #else #ifdef INIT_BROADCASTER @@ -187,6 +185,12 @@ void LlInitLlInit(void) #if (BT_VER >= LL_VER_BT_CORE_SPEC_5_1) LlPastInit(); #endif + #if (BT_VER >= LL_VER_BT_CORE_SPEC_5_2) + LlPowerControlInit(); + #endif + #if (BT_VER >= LL_VER_BT_CORE_SPEC_SYDNEY) + LlEnhConnUpdateInit(); + #endif #endif #endif @@ -263,10 +267,13 @@ uint32_t LlInitSetLlRtCfg(const LlRtCfg_t *pLlRtCfg, uint8_t *pFreeMem, uint32_t LlInitRunTimeCfg(pLlRtCfg); #if defined (INIT_PERIPHERAL) || defined (INIT_CENTRAL) - memUsed = LlInitConnMem(pFreeMem, freeMemAvail); - pFreeMem += memUsed; - freeMemAvail -= memUsed; - totalMemUsed += memUsed; + if (pLlRtCfg->maxConn) + { + memUsed = LlInitConnMem(pFreeMem, freeMemAvail); + pFreeMem += memUsed; + freeMemAvail -= memUsed; + totalMemUsed += memUsed; + } #endif #if (BT_VER >= LL_VER_BT_CORE_SPEC_5_0) diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/init/init_ctr.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/init/init_ctr.c index 9bab8d3186..e6d099c42f 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/init/init_ctr.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/init/init_ctr.c @@ -4,7 +4,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -118,6 +118,9 @@ void LlInitLhciInit(void) #if (BT_VER >= LL_VER_BT_CORE_SPEC_5_1) LhciPastInit(); #endif + #if (BT_VER >= LL_VER_BT_CORE_SPEC_SYDNEY) + LhciEnhConnUpdateInit(); + #endif #endif #endif #endif @@ -141,6 +144,7 @@ void LlInitLhciInit(void) #endif LhciIsoInit(); + LhciPowerControlInit(); #endif } @@ -164,5 +168,12 @@ uint32_t LlInitControllerInit(LlInitRtCfg_t *pCfg) LlInitLhciHandler(); LhciInitFinalize(); + #if (CHCI_TR_COMP_ENA) + { + extern void LhciTrEventComplete(void); + LhciRegisterSendTrCompleteHandler(LhciTrEventComplete); + } + #endif + return totalMemUsed; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_master_ae.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_master_ae.c index e9923bc177..03fa7289a4 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_master_ae.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_master_ae.c @@ -64,6 +64,7 @@ static uint8_t lctrPerScanSetup(lctrPerCreateSyncCtrlBlk_t *pPerCreateSync, lctr pPerScanCtx->syncTimeOutMs = LCTR_PER_SYNC_TIMEOUT_TO_MS(pMsg->syncTimeOut); pPerScanCtx->createDispId = createDispId; pPerScanCtx->repDisabled = pMsg->repDisabled; + pPerScanCtx->dupFilterEnable = pMsg->dupFilterEnable; return LL_SUCCESS; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_slave_ae.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_slave_ae.c index d05fe958b1..570348b768 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_slave_ae.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_slave_ae.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -106,7 +106,6 @@ void lctrExtAdvActStart(lctrAdvSet_t *pAdvSet) pAdvSet->pExtAdvAuxPtr = NULL; pAdvSet->connIndRcvd = FALSE; pAdvSet->shutdown = FALSE; - pAdvSet->bodTermCnt = 0; uint8_t status; if ((status = lctrSlvExtAdvBuildOp(pAdvSet, pLctrSlvExtAdvMsg->enable.durMs)) != LL_SUCCESS) @@ -150,7 +149,6 @@ void lctrExtAdvActSelfStart(lctrAdvSet_t *pAdvSet) pAdvSet->pExtAdvAuxPtr = NULL; pAdvSet->connIndRcvd = FALSE; pAdvSet->shutdown = FALSE; - pAdvSet->bodTermCnt = 0; uint8_t status; if ((status = lctrSlvExtAdvBuildOp(pAdvSet, pLctrSlvExtAdvMsg->enable.durMs)) != LL_SUCCESS) @@ -217,9 +215,10 @@ void lctrExtAdvActShutdown(lctrAdvSet_t *pAdvSet) /*************************************************************************************************/ void lctrExtAdvActResetShutdown(lctrAdvSet_t *pAdvSet) { - /* LCTR_MSG_RESET is broadcasted by hciReset and the processing order between ext ADV SM and periodic ADV SM is not guaranteed. */ - /* If ext ADV SM runs first, it will purge all info and periodic ADV SM may not run as intended. */ - /* So, reset cleanup of periodic advertising has to be done from extended ADV SM. */ + /* LCTR_MSG_RESET is broadcasted by hciReset and the processing order between ext ADV SM and + * periodic ADV SM is not guaranteed. If ext ADV SM runs first, it will purge all info and periodic + * ADV SM may not run as intended. So, reset cleanup of periodic advertising has to be done from + * extended ADV SM. */ if (pAdvSet->perParam.perState == LCTR_PER_ADV_STATE_ENABLED) { lctrPeriodicAdvActShutdown(pAdvSet); @@ -424,9 +423,10 @@ void lctrExtAdvActAdvTerm(lctrAdvSet_t *pAdvSet) /*************************************************************************************************/ void lctrExtAdvActReset(lctrAdvSet_t *pAdvSet) { - /* LCTR_MSG_RESET is broadcasted by hciReset and the processing order between ext ADV SM and periodic ADV SM is not guaranteed. */ - /* If ext ADV SM runs first, it will purge all info and periodic ADV SM may not run as intended. */ - /* So, reset cleanup of periodic advertising has to be done from extended ADV SM. */ + /* LCTR_MSG_RESET is broadcasted by hciReset and the processing order between ext ADV SM and + * periodic ADV SM is not guaranteed. If ext ADV SM runs first, it will purge all info and periodic + * ADV SM may not run as intended. So, reset cleanup of periodic advertising has to be done from + * extended ADV SM. */ if (pAdvSet->perParam.perState == LCTR_PER_ADV_STATE_ENABLED) { lctrPeriodicAdvActShutdown(pAdvSet); @@ -468,6 +468,9 @@ void lctrExtAdvActDurationExpired(lctrAdvSet_t *pAdvSet) /* Signal shutdown, event completion occurs in lctrExtAdvActSelfTerm(). */ pAdvSet->shutdown = TRUE; + + SchRemove(&pAdvSet->advBod); + SchRemove(&pAdvSet->auxAdvBod); } /*************************************************************************************************/ @@ -541,6 +544,11 @@ void lctrPeriodicAdvActStart(lctrAdvSet_t *pAdvSet) pAdvSet->didPerUpdate = TRUE; } + if (pAdvSet->perParam.enableAdi) + { + pAdvSet->perParam.advDID = lctrCalcDID(pAdvSet->advData.pBuf, pAdvSet->advData.len); + } + LmgrSendPeriodicAdvEnableCnf(pAdvSet->handle, LL_SUCCESS); LmgrIncResetRefCount(); } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_bis_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_bis_master.c index 301aed27cd..229d11186a 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_bis_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_bis_master.c @@ -51,11 +51,13 @@ static void lctrNotifyHostBigCreateSyncComplete(lctrBigCtx_t *pBigCtx, LlStatus_ evt.irc = pBigCtx->irc; evt.maxPdu = pBigCtx->maxPdu; evt.isoInterval = LL_MATH_DIV_1250(pBigCtx->isoInterUsec); - evt.numBis = pBigCtx->numBis; - for (unsigned int i = 0; i < evt.numBis; i++) + for (unsigned int i = 0; i < LL_MAX_BIS; i++) { - evt.bisHandle[i] = pBigCtx->pBisCtx[i]->handle; + if (pBigCtx->pBisCtx[i]) + { + evt.bisHandle[evt.numBis++] = pBigCtx->pBisCtx[i]->handle; + } } } @@ -152,12 +154,42 @@ void lctrMstBigActBigSync(lctrBigCtx_t *pBigCtx) for (unsigned int i = 0; i < pBigInfo->numBis; i++) { lctrBisCtx_t *pBisCtx; + unsigned int j; - /* Availability is verified on BIG Create Sync command. */ - pBisCtx = lctrAllocBisCtx(pBigCtx); - WSF_ASSERT(pBisCtx); + for (j = 0; j < pBigCtx->roleData.mst.numBisIdx; j++) + { + /* Check host BIS filter. */ + if (pBigCtx->roleData.mst.bisIdx[j] == (i + 1)) + { + /* Availability is verified on BIG Create Sync command. */ + pBisCtx = lctrAllocBisCtx(pBigCtx); + WSF_ASSERT(pBisCtx); - lctrSetupBisContext(pBisCtx, pBigInfo->seedAccAddr, pBigInfo->baseCrcInit, pBigInfo->chanMap, pBigInfo->phy); + lctrSetupBisContext(pBisCtx, pBigInfo->seedAccAddr, pBigInfo->baseCrcInit, pBigInfo->chanMap, pBigInfo->phy); + + if (pBigCtx->roleData.mst.pFirstBisCtx == NULL) + { + /* Optimize ISR by reducing lookup on every event; store first BIS. */ + pBigCtx->roleData.mst.pFirstBisCtx = pBisCtx; + pBigCtx->roleData.mst.firstBisOffsUsec = pBigCtx->bisSpaceUsec * i; + pBigCtx->roleData.mst.firstBisEvtIdx = i; + } + else if (pBigCtx->roleData.mst.pSecondBisCtx == NULL) + { + /* Optimize ISR by reducing lookup on every event; store second BIS; NULL if none. */ + pBigCtx->roleData.mst.pSecondBisCtx = pBisCtx; + } + + break; + } + + } + + if (j == pBigCtx->roleData.mst.numBisIdx) + { + /* Disable BIS subevent. */ + pBigCtx->pBisCtx[pBigCtx->numBis++] = NULL; + } } lctrMstBigBuildOp(pBigCtx, &pLctrMstBigMsg->bigInfo.data); @@ -176,13 +208,9 @@ void lctrMstBigActBigSync(lctrBigCtx_t *pBigCtx) /*************************************************************************************************/ void lctrMstBigActTerm(lctrBigCtx_t *pBigCtx) { - BbStop(BB_PROT_BLE); + /* Shutdown completes with events generated in BOD end callback. */ - lctrFreeBigCtx(pBigCtx); - - LmgrDecResetRefCount(); - - lctrNotifyHostSyncLost(pBigCtx->handle, pBigCtx->bcp.term.reason); + pBigCtx->roleData.mst.syncLostReason = pBigCtx->bcp.term.reason; } /*************************************************************************************************/ @@ -194,12 +222,7 @@ void lctrMstBigActTerm(lctrBigCtx_t *pBigCtx) /*************************************************************************************************/ void lctrMstBigActShutdown(lctrBigCtx_t *pBigCtx) { - /* By removing BOD from scheduler, BOD end callback will be called. */ - /* Shutdown completes with events generated in BOD end callback. */ - if (!SchRemove(&pBigCtx->bod)) - { - lctrMstBigSendMsg(pBigCtx, LCTR_MST_BIG_INT_TERMINATED_SYNC); - } + /* Shutdown completes with events generated in BOD end callback. */ if (pBigCtx->state == LCTR_MST_BIG_STATE_SYNCING) { @@ -216,12 +239,7 @@ void lctrMstBigActShutdown(lctrBigCtx_t *pBigCtx) /*************************************************************************************************/ void lctrMstBigActSyncLost(lctrBigCtx_t *pBigCtx) { - /* By removing BOD from scheduler, BOD end callback will be called. */ - /* Shutdown completes with events generated in BOD end callback. */ - if (!SchRemove(&pBigCtx->bod)) - { - lctrMstBigSendMsg(pBigCtx, LCTR_MST_BIG_INT_TERMINATED_SYNC); - } + /* Shutdown completes with events generated in BOD end callback. */ pBigCtx->roleData.mst.syncLostReason = LL_ERROR_CODE_CONN_TIMEOUT; } @@ -235,12 +253,7 @@ void lctrMstBigActSyncLost(lctrBigCtx_t *pBigCtx) /*************************************************************************************************/ void lctrMstBigActMicFailed(lctrBigCtx_t *pBigCtx) { - /* By removing BOD from scheduler, BOD end callback will be called. */ - /* Shutdown completes with events generated in BOD end callback. */ - if (!SchRemove(&pBigCtx->bod)) - { - lctrMstBigSendMsg(pBigCtx, LCTR_MST_BIG_INT_TERMINATED_SYNC); - } + /* Shutdown completes with events generated in BOD end callback. */ pBigCtx->roleData.mst.syncLostReason = LL_ERROR_CODE_CONN_TERM_MIC_FAILURE; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis.c index b333ca26d2..264950a612 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,46 @@ Local Functions **************************************************************************************************/ +/*************************************************************************************************/ +/*! + * \brief Send next CIS disconnect LLCP to be processed, if needed. + * + * \param ACL Handle that can continue CIS termination procedures. + */ +/*************************************************************************************************/ +static void lctrCheckPendingCisTermination(uint16_t aclHandle) +{ + for (unsigned int i = 0; i < pLctrRtCfg->maxCis; i++) + { + lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i]; + lctrCisDisc_t *pMsg; + + if ((pCisCtx->aclHandle == aclHandle) && + !pCisCtx->isClosing && pCisCtx->termPend) + { + if ((pMsg = (lctrCisDisc_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->hdr.handle = pCisCtx->aclHandle; + pMsg->hdr.dispId = LCTR_DISP_CONN; + pMsg->hdr.event = LCTR_CONN_MSG_API_DISCONNECT; + + pMsg->cisHandle = pCisCtx->cisHandle; + pMsg->reason = pCisCtx->reason; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + + pCisCtx->termPend = FALSE; + } + else + { + LL_TRACE_WARN1("lctrCisActDisc: CIS OOM while terminating handle %d", pCisCtx->cisHandle); + } + + return; + } + } +} + /*************************************************************************************************/ /*! * \brief Send CIS termination indication PDU. @@ -94,16 +134,16 @@ void lctrNotifyHostCisTerm(lctrCisCtx_t *pCisCtx) { LlDisconnectInd_t evt = { - .hdr = - { - .param = pCisCtx->cisHandle, - .event = LL_DISCONNECT_IND, - .status = LL_SUCCESS - }, + .hdr = + { + .param = pCisCtx->cisHandle, + .event = LL_DISCONNECT_IND, + .status = LL_SUCCESS + }, - .status = LL_SUCCESS, - .handle = pCisCtx->cisHandle, - .reason = pCisCtx->reason + .status = LL_SUCCESS, + .handle = pCisCtx->cisHandle, + .reason = pCisCtx->reason }; LL_TRACE_INFO2("### LlEvent ### LL_DISCONNECT_IND, handle=%u, status=LL_SUCCESS, reason=%u", pCisCtx->cisHandle, pCisCtx->reason); @@ -126,9 +166,9 @@ void lctrNotifyHostCisEst(lctrCisCtx_t *pCisCtx, uint8_t status, uint32_t cigSyn { .hdr = { - .param = pCisCtx->cisHandle, - .event = LL_CIS_EST_IND, - .status = status + .param = pCisCtx->cisHandle, + .event = LL_CIS_EST_IND, + .status = status } }; @@ -146,6 +186,9 @@ void lctrNotifyHostCisEst(lctrCisCtx_t *pCisCtx, uint8_t status, uint32_t cigSyn evt.ftMToS = pCisCtx->ftMToS; evt.ftSToM = pCisCtx->ftSToM; evt.isoInterval = pCisCtx->isoInterval; + evt.maxPduMToS = (pCisCtx->role == LL_ROLE_MASTER) ? pCisCtx->localDataPdu.maxTxLen : pCisCtx->localDataPdu.maxRxLen; + evt.maxPduSToM = (pCisCtx->role == LL_ROLE_SLAVE) ? pCisCtx->localDataPdu.maxTxLen : pCisCtx->localDataPdu.maxRxLen; + LL_TRACE_INFO2("### LlEvent ### LL_CIS_EST_IND, cisHandle=%u, status=%u", pCisCtx->cisHandle, status); @@ -311,18 +354,13 @@ void lctrCisActCisEst(lctrCisCtx_t *pCisCtx) BbBleData_t *pBle = &pConnCtx->bleData; pCigCtx->numCisEsted++; - LL_TRACE_INFO1("lctrCisActCisEst, pCigCtx->numCisEsted=%u", pCigCtx->numCisEsted); - /* Initialize txPower. */ uint8_t txPhy = (pCisCtx->role == LL_ROLE_MASTER) ? pCisCtx->phyMToS : pCisCtx->phySToM; uint8_t option = pBle->chan.initTxPhyOptions; int8_t txPwr = LCTR_GET_TXPOWER(pConnCtx, txPhy, option); - LL_TRACE_INFO1("lctrCisActCisEst phy = %d", txPhy); if ((txPwr == LL_PWR_CTRL_TXPOWER_UNMANAGED) && (pConnCtx->peerReqRecvd)) { - LL_TRACE_INFO0(" txPower previously unmanaged. Initalized txPower."); - LCTR_SET_TXPOWER(pConnCtx, txPhy, pLctrRtCfg->defTxPwrLvl); if (txPhy == LL_PHY_LE_CODED) @@ -330,7 +368,7 @@ void lctrCisActCisEst(lctrCisCtx_t *pCisCtx) LCTR_SET_TXPOWER(pConnCtx, LL_PC_PHY_CODED_S2, pLctrRtCfg->defTxPwrLvl); } - /* pCisCtx->bleData.chan.txPower = LCTR_GET_TXPOWER(pConnCtx, txPhy, option); //Handled in the init */ + /* pCisCtx->bleData.chan.txPower = LCTR_GET_TXPOWER(pConnCtx, txPhy, option); */ /* Handled during initialization. */ if (pConnCtx->usedFeatSet & LL_FEAT_POWER_CHANGE_IND) { pCisCtx->powerIndReq = TRUE; @@ -338,10 +376,10 @@ void lctrCisActCisEst(lctrCisCtx_t *pCisCtx) } else { - LL_TRACE_INFO1(" txPower = %d", txPwr); pCisCtx->bleData.chan.txPower = txPwr; } + LL_TRACE_INFO2("lctrCisActCisEst, numCisEsted=%u txPower=%u", pCigCtx->numCisEsted, txPwr); } /*************************************************************************************************/ @@ -378,16 +416,30 @@ void lctrCisActDisc(lctrCisCtx_t *pCisCtx) { lctrCisDisc_t *pMsg; - if ((pMsg = (lctrCisDisc_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + if (!LctrCisTerminationInProgress(pCisCtx->aclHandle)) { - pMsg->hdr.handle = pCisCtx->aclHandle; - pMsg->hdr.dispId = LCTR_DISP_CONN; - pMsg->hdr.event = LCTR_CONN_MSG_API_DISCONNECT; + if ((pMsg = (lctrCisDisc_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->hdr.handle = pCisCtx->aclHandle; + pMsg->hdr.dispId = LCTR_DISP_CONN; + pMsg->hdr.event = LCTR_CONN_MSG_API_DISCONNECT; - pMsg->cisHandle = pCisCtx->cisHandle; - pMsg->reason = pCisCtx->reason; + pMsg->cisHandle = pCisCtx->cisHandle; + pMsg->reason = pCisCtx->reason; - WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + + pCisCtx->termPend = FALSE; + } + else + { + LL_TRACE_WARN1("lctrCisActDisc: CIS OOM while terminating handle %d", pCisCtx->cisHandle); + } + } + else + { + LL_TRACE_INFO1("lctrCisActDisc: CIS Termination pending, CIS Termination queued for handle %d", pCisCtx->cisHandle); + pCisCtx->termPend = TRUE; } } @@ -400,19 +452,11 @@ void lctrCisActDisc(lctrCisCtx_t *pCisCtx) /*************************************************************************************************/ void lctrCisActClosed(lctrCisCtx_t *pCisCtx) { - /* Stop output data path. */ - switch (pCisCtx->dataPathOutCtx.id) - { - case LL_ISO_DATA_PATH_VS: - WSF_ASSERT(lctrCodecHdlr.stop); - lctrCodecHdlr.stop(pCisCtx->cisHandle); - break; - case LL_ISO_DATA_PATH_DISABLED: - case LL_ISO_DATA_PATH_HCI: - default: - /* No action required. */ - break; - } + uint16_t aclHandle = pCisCtx->aclHandle; + + /* Must do one at a time in case one datapath is not used. */ + LctrRemoveIsoDataPath(pCisCtx->cisHandle, LL_ISO_DATA_PATH_INPUT_BIT); + LctrRemoveIsoDataPath(pCisCtx->cisHandle, LL_ISO_DATA_PATH_OUTPUT_BIT); LL_TRACE_INFO1("lctrCisActClosed, pCisCtx->cisHandle=%u", pCisCtx->cisHandle); @@ -433,6 +477,8 @@ void lctrCisActClosed(lctrCisCtx_t *pCisCtx) pCisCtx->isClosing = FALSE; lctrCleanupCtx(pCisCtx); } + + lctrCheckPendingCisTermination(aclHandle); } /*************************************************************************************************/ @@ -449,12 +495,11 @@ void lctrCisActFail(lctrCisCtx_t *pCisCtx) LL_TRACE_INFO2("lctrCisActFail, pCisCtx->cisHandle=%u pCisCtx->state=%u", pCisCtx->cisHandle, pCisCtx->state); - /* Supervision timeout case */ + /* Supervision timeout or MIC timeout case */ if (pCisCtx->state == LCTR_CIS_STATE_EST) { pCisCtx->isClosing = TRUE; /* Close the context in the CIG BOD end callback. */ SchRemove(&pCigCtx->cigBod); - lctrNotifyHostCisTerm(pCisCtx); } } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis_master.c index 71e1e2f327..c908b9fc28 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis_master.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,8 +50,9 @@ static void lctrCalCeRefFirstCis(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) uint32_t refTime; pCisCtx->ceRef = pCtx->eventCounter + - LL_MIN_INSTANT + 1 + /* +1 for next CE */ - pCtx->maxLatency; /* ensure slave will listen to this packet */ + ((LL_MIN_INSTANT + 1 + /* +1 for next CE */ + pCtx->maxLatency) * /* ensure slave will listen to this packet */ + pCtx->ecu.srFactor); /* include subrating factor */ pCisCtx->cisCeRef = 0; refTime = pConnBod->dueUsec + (pCisCtx->ceRef - pCtx->eventCounter) * LCTR_CONN_IND_US(pCtx->connInterval); @@ -94,8 +95,9 @@ static void lctrCalCeRefNotFirstCis(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) uint32_t offsetUsec = 0; pCisCtx->ceRef = pCtx->eventCounter + - LL_MIN_INSTANT + 1 + /* +1 for next CE */ - pCtx->maxLatency; /* ensure slave will listen to this packet */ + ((LL_MIN_INSTANT + 1 + /* +1 for next CE */ + pCtx->maxLatency) * /* ensure slave will listen to this packet */ + pCtx->ecu.srFactor); /* include subrating factor */ aclRefTime = pConnBod->dueUsec + (pCisCtx->ceRef - pCtx->eventCounter) * LCTR_CONN_IND_US(pCtx->connInterval); @@ -301,7 +303,7 @@ void lctrMstCisLlcpActHostCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) /* Check whether the parameter for the BOD is valid or not. */ if (pCigCtx->isValid == FALSE) { - LL_TRACE_WARN0("Fail to create CIS due to invalid parameters"); + LL_TRACE_WARN0("lctrMstCisLlcpActHostCisReq: Fail to create CIS due to invalid parameters"); lctrCisStoreLocalLowResourceTerminateReason(pCisCtx); result = FALSE; } @@ -313,9 +315,11 @@ void lctrMstCisLlcpActHostCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) SCH_RM_PREF_PERFORMANCE, LCTR_ISO_INT_TO_US(pCigCtx->isoInterval), LCTR_ISO_INT_TO_US(pCigCtx->isoInterval), - pCigCtx->cigSyncDelayUsec, NULL, lctrGetCigRefTime)) + pCigCtx->cigSyncDelayUsec, + NULL, + lctrGetCigRefTime)) { - LL_TRACE_WARN0("Fail to create CIS due to scheduling limitation"); + LL_TRACE_WARN0("lctrMstCisLlcpActHostCisReq: Fail to create CIS due to scheduling limitation"); lctrCisStoreLocalLowResourceTerminateReason(pCisCtx); result = FALSE; } @@ -418,7 +422,7 @@ void lctrMstCisLlcpActPeerCisRsp(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) if (pCigCtx->isBodBuilt == FALSE) { - WSF_ASSERT(pCisCtx->cisCeRef == 0) + WSF_ASSERT(pCisCtx->cisCeRef == 0); lctrMstCisBuildCigOp(pCigCtx); } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis_slave.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis_slave.c index 133d1ba1d2..b033f322ae 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis_slave.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis_slave.c @@ -168,12 +168,12 @@ static void lctrNotifyHostCisReq(lctrCisCtx_t *pCisCtx) { LlCisReqInd_t evt = { - .hdr = - { - .param = pCisCtx->cisHandle, - .event = LL_CIS_REQ_IND, - .status = LL_SUCCESS - } + .hdr = + { + .param = pCisCtx->cisHandle, + .event = LL_CIS_REQ_IND, + .status = LL_SUCCESS + } }; evt.aclHandle = pCisCtx->aclHandle; @@ -181,7 +181,7 @@ static void lctrNotifyHostCisReq(lctrCisCtx_t *pCisCtx) evt.cigId = pCisCtx->cigId; evt.cisId = pCisCtx->cisId; - LL_TRACE_INFO1("### LlEvent ### LL_CIS_REQ_IND, cisHandle=%u", pCisCtx->cisHandle); + LL_TRACE_INFO3("### LlEvent ### LL_CIS_REQ_IND, cisHandle=%u cigId=%u cisId=%u", pCisCtx->cisHandle, pCisCtx->cigId, pCisCtx->cisId); bool_t evtSent = LmgrSendEvent((LlEvt_t *)&evt); @@ -363,7 +363,7 @@ void lctrSlvCisLlcpActPeerCisInd(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) { /* If the anchor point of the stream is before end of the first stream, it is interleaved packing scheme. */ if (BbGetTargetTimeDelta(cigRefTime + pHeadCisCtx->subIntervUsec, - pCisCtx->data.slv.anchorOffsetUsec + pCtx->data.slv.anchorPointUsec + LCTR_CONN_IND_US(pCtx->connInterval)) > 0) + pCisCtx->data.slv.anchorOffsetUsec + pCtx->data.slv.anchorPointUsec + LCTR_CONN_IND_US(pCtx->connInterval)) > 0) { pCigCtx->packing = LL_PACKING_INTERLEAVED; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn.c index 8456c14f02..b8b761b270 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,7 +42,7 @@ Macros **************************************************************************************************/ -/*! \brief Valid feature bits applicable between controllers */ +/*! \brief Valid feature bits applicable between controllers. */ #define LCTR_FEAT_PEER_MASK (LL_FEAT_ENCRYPTION | \ LL_FEAT_CONN_PARAM_REQ_PROC | \ LL_FEAT_EXT_REJECT_IND | \ @@ -68,12 +68,15 @@ LL_FEAT_ISO_HOST_SUPPORT | \ LL_FEAT_POWER_CONTROL_REQUEST | \ LL_FEAT_POWER_CHANGE_IND | \ - LL_FEAT_PATH_LOSS_MONITOR) + LL_FEAT_PATH_LOSS_MONITOR | \ + LL_FEAT_CONN_SUBRATE | \ + LL_FEAT_CONN_SUBRATE_HOST_SUPPORT | \ + LL_FEAT_CHANNEL_CLASSIFICATION) /*! \brief Used feature bitmask. */ #define LCTR_USED_FEAT_SET_MASK 0x000000FFFF -/*! \brief Features bits mask over the air */ +/*! \brief Features bits mask over the air. */ #define LCTR_OTA_FEAT_MASK (~LL_FEAT_REMOTE_PUB_KEY_VALIDATION & LCTR_FEAT_PEER_MASK) /*************************************************************************************************/ @@ -99,7 +102,6 @@ static bool_t lctrValidateConnParam(const lctrConnParam_t *pConnParam) return TRUE; } - /*************************************************************************************************/ /*! * \brief Compute the sleep clock accuracy index in connection context. @@ -126,6 +128,39 @@ static uint8_t lctrComputeConnSca(lctrConnCtx_t *pCtx) return (uint8_t) (sca + pCtx->scaMod); } +/*************************************************************************************************/ +/*! + * \brief Queue channel reporting indication to be sent out. + * + * \param pCtx Connection context. + * \param enable Enable/disable. + */ +/*************************************************************************************************/ +static void lctrQueueChannelReportingInd(lctrConnCtx_t *pCtx, bool_t enable) +{ + + lctrMsgChRptInd_t *pMsg; + if ((pMsg = (lctrMsgChRptInd_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->hdr.handle = LCTR_GET_CONN_HANDLE(pCtx); + pMsg->hdr.dispId = LCTR_DISP_CONN; + pMsg->hdr.event = LCTR_CONN_LLCP_CHANNEL_REPORTING; + + /* Use default if the run-time configuration is not within spec range. */ + uint8_t spacing = pLctrRtCfg->chClassIntSpacing; + if ((spacing > LL_CH_RPT_SPACING_MAX) || + (spacing < LL_CH_RPT_SPACING_MIN)) + { + spacing = LL_CH_RPT_SPACING_DEFAULT; + } + pMsg->enable = enable; + pMsg->maxDelay = spacing; + pMsg->minSpacing = spacing; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } +} + /*************************************************************************************************/ /*! * \brief Notify host of connect indication. @@ -306,8 +341,9 @@ void lctrSendChanMapUpdateInd(lctrConnCtx_t *pCtx) #endif { pCtx->chanMapUpd.instant = pCtx->eventCounter + - LL_MIN_INSTANT + 1 + /* +1 for next CE */ - pCtx->maxLatency; /* ensure slave will listen to this packet */ + ((LL_MIN_INSTANT + 1 + /* +1 for next CE */ + pCtx->maxLatency) * /* ensure slave will listen to this packet */ + pCtx->ecu.srFactor); /* include subrating factor */ } /*** Assemble control PDU. ***/ @@ -407,6 +443,9 @@ void lctrSendFeatureRsp(lctrConnCtx_t *pCtx) /*************************************************************************************************/ void lctrStoreUsedFeatures(lctrConnCtx_t *pCtx) { + pCtx->peerFeatures = lctrDataPdu.pld.featReqRsp.featSet & LCTR_FEAT_PEER_MASK; + + /* TODO: make usedFeatSet calculated when needed based on peerFeatures. Use function LctrGetUsedFeatures. */ pCtx->usedFeatSet = lmgrCb.features & lctrDataPdu.pld.featReqRsp.featSet & LCTR_FEAT_PEER_MASK; pCtx->featExchFlag = TRUE; @@ -415,6 +454,27 @@ void lctrStoreUsedFeatures(lctrConnCtx_t *pCtx) (lctrDataPdu.pld.featReqRsp.featSet & LL_FEAT_STABLE_MOD_IDX_TRANSMITTER) ? TRUE : FALSE; pCtx->bleData.chan.peerRxStableModIdx = (lctrDataPdu.pld.featReqRsp.featSet & LL_FEAT_STABLE_MOD_IDX_RECEIVER) ? TRUE : FALSE; + + /* If channel classification is supported and enabled, turn on channel classification. */ + if ((pCtx->role == LL_ROLE_MASTER) && (!pCtx->chanStatRptEnable) && + (pCtx->usedFeatSet & LL_FEAT_CHANNEL_CLASSIFICATION) && + (lctrGetConnOpFlag(pCtx, LL_OP_MODE_FLAG_ENA_CH_RPT_LLCP_AFTER_FEAT))) + { + lctrQueueChannelReportingInd(pCtx, TRUE); + } + + /* Start timer for power monitor if the feature is supported. */ + if ((pCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST) && + (pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) && + (pCtx->powerMonitorScheme == LCTR_PC_MONITOR_AUTO) && + !lmgrGetOpFlag(LL_OP_MODE_FLAG_DIS_POWER_MONITOR)) + { + WsfTimerStartMs(&pCtx->tmrPowerCtrl, LL_PC_SERVICE_MS); + } + else + { + WsfTimerStop(&pCtx->tmrPowerCtrl); + } } /*************************************************************************************************/ @@ -937,7 +997,6 @@ static void lctrSendDataLengthPdu(lctrConnCtx_t *pCtx, uint8_t opcode) { uint8_t *pBuf = pPdu; - /*** Assemble control PDU. ***/ UINT8_TO_BSTREAM (pBuf, opcode); @@ -945,7 +1004,7 @@ static void lctrSendDataLengthPdu(lctrConnCtx_t *pCtx, uint8_t opcode) uint16_t maxRxTime = pCtx->localDataPdu.maxRxTime; uint16_t maxTxTime = pCtx->localDataPdu.maxTxTime; - /* If LL_FEAT_LE_CODED_PHY is not supported, maxRxTime and maxTxTime can not be more than 2128.*/ + /* If LL_FEAT_LE_CODED_PHY is not supported, maxRxTime and maxTxTime can not be more than 2120 (2128 if CTEs are supported).*/ if (!pCtx->featExchFlag || !(pCtx->usedFeatSet & LL_FEAT_LE_CODED_PHY)) { @@ -1023,7 +1082,7 @@ void lctrStoreRemoteDataLength(lctrConnCtx_t *pCtx) uint16_t maxRxTime = pCtx->localDataPdu.maxRxTime; uint16_t maxTxTime = pCtx->localDataPdu.maxTxTime; - /* If LL_FEAT_LE_CODED_PHY is not supported, maxRxTime and maxTxTime can not be more than 2128. */ + /* If LL_FEAT_LE_CODED_PHY is not supported, maxRxTime and maxTxTime can not be more than 2120 (2128 if CTEs are supported). */ if (!pCtx->featExchFlag || !(pCtx->usedFeatSet & LL_FEAT_LE_CODED_PHY)) { @@ -1185,6 +1244,209 @@ static void lctrSendPeerScaReqPdu(lctrConnCtx_t *pCtx, uint8_t opcode) } } +/*************************************************************************************************/ +/*! + * \brief Send channel reporting indication PDU. + * + * \param pCtx Connection context. + * \param opcode PDU opcode. + */ +/*************************************************************************************************/ +static void lctrSendChannelReportingIndPdu(lctrConnCtx_t *pCtx) +{ + uint8_t *pPdu; + + if ((pPdu = lctrTxCtrlPduAlloc(LL_CH_REPORTING_LEN)) != NULL) + { + uint8_t *pBuf = pPdu; + + /*** Assemble control PDU. ***/ + UINT8_TO_BSTREAM (pBuf, LL_PDU_CH_REPORTING_IND); + UINT8_TO_BSTREAM (pBuf, pLctrConnMsg->chanRptInd.enable); + UINT8_TO_BSTREAM (pBuf, pLctrConnMsg->chanRptInd.minSpacing); + UINT8_TO_BSTREAM (pBuf, pLctrConnMsg->chanRptInd.maxDelay); + + /*** Queue for transmit. ***/ + + lctrTxCtrlPduQueue(pCtx, pPdu); + } +} + +/*************************************************************************************************/ +/*! + * \brief Send channel status indication PDU. + * + * \param pCtx Connection context. + * \param opcode PDU opcode. + */ +/*************************************************************************************************/ +static void lctrSendChannelStatusIndPdu(lctrConnCtx_t *pCtx) +{ + static uint8_t CHAN_STATUS_BIT_LENGTH = 2; + uint8_t *pPdu; + + if ((pPdu = lctrTxCtrlPduAlloc(LL_CH_STATUS_LEN)) != NULL) + { + uint8_t *pBuf = pPdu; + uint8_t i, packedChanByte; + uint8_t curCh = 0; + + /*** Assemble control PDU. ***/ + + UINT8_TO_BSTREAM (pBuf, LL_PDU_CH_STATUS_IND); + + /* Pack all but final byte */ + for (i = 0; i < (LL_CH_STATUS_LEN - 2); i++) + { + packedChanByte = + (pLctrConnMsg->chanStatusInd.chanStatus[curCh]) | + (pLctrConnMsg->chanStatusInd.chanStatus[curCh + 1] << (CHAN_STATUS_BIT_LENGTH * 1)) | + (pLctrConnMsg->chanStatusInd.chanStatus[curCh + 2] << (CHAN_STATUS_BIT_LENGTH * 2)) | + (pLctrConnMsg->chanStatusInd.chanStatus[curCh + 3] << (CHAN_STATUS_BIT_LENGTH * 3)); + + UINT8_TO_BSTREAM (pBuf, packedChanByte); + curCh += 4; + } + + /* Pack final byte here (outside loop because it is not fully packed). */ + packedChanByte = pLctrConnMsg->chanStatusInd.chanStatus[curCh]; + UINT8_TO_BSTREAM (pBuf, packedChanByte); + + /*** Queue for transmit. ***/ + + lctrTxCtrlPduQueue(pCtx, pPdu); + } +} + +/*************************************************************************************************/ +/*! + * \brief Send channel status indication. + * + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +void lctrSendChannelStatusInd(lctrConnCtx_t *pCtx) +{ + lctrSendChannelStatusIndPdu(pCtx); + + /* The procedure completes after sending out the indication. */ + pCtx->llcpNotifyMask &= ~(1 << LCTR_PROC_CMN_CH_STATUS_REPORT); + lctrSendConnMsg(pCtx, LCTR_CONN_LLCP_PROC_CMPL); +} + +/*************************************************************************************************/ +/*! + * \brief Store received channel status indication. + * + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +void lctrStoreChannelStatusInd(lctrConnCtx_t *pCtx) +{ + if (pCtx->role != LL_ROLE_MASTER) + { + LL_TRACE_WARN1("Received CHANNEL_STATUS_IND on peripheral connection handle=%u", LCTR_GET_CONN_HANDLE(pCtx)); + + /* The procedure completes after receiving the indication. */ + lctrSendConnMsg(pCtx, LCTR_CONN_LLCP_PROC_CMPL); + return; + } + + uint32_t receivedTime = PalBbGetCurrentTime(); + if (BbGetTargetTimeDelta(receivedTime, pCtx->data.mst.recvdChanStatTs) >= pCtx->data.mst.chanStatMinIntUs) + { + uint8_t i; + for (i = 0; i < LL_CH_STATUS_LEN - 2; i ++) + { + pCtx->data.mst.peerChannelStatus[i * 4] = lctrDataPdu.pld.chanStatusInd.chanStatusMap[i] & (0x03 << 0); + pCtx->data.mst.peerChannelStatus[(i * 4) + 1] = lctrDataPdu.pld.chanStatusInd.chanStatusMap[i] & (0x03 << 2); + pCtx->data.mst.peerChannelStatus[(i * 4) + 2] = lctrDataPdu.pld.chanStatusInd.chanStatusMap[i] & (0x03 << 4); + pCtx->data.mst.peerChannelStatus[(i * 4) + 3] = lctrDataPdu.pld.chanStatusInd.chanStatusMap[i] & (0x03 << 6); + } + + /* Final byte has less than 4 channels. */ + pCtx->data.mst.peerChannelStatus[i * 4] = lctrDataPdu.pld.chanStatusInd.chanStatusMap[i] & (0x03 << 0); + } + else + { + LL_TRACE_WARN1("Received channel status from peripheral too early. Handle=%u", LCTR_GET_CONN_HANDLE(pCtx)); + } + + /* The procedure completes after receiving the indication. */ + lctrSendConnMsg(pCtx, LCTR_CONN_LLCP_PROC_CMPL); +} + +/*************************************************************************************************/ +/*! + * \brief Send channel reporting indication. + * + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +void lctrSendChannelReportingInd(lctrConnCtx_t *pCtx) +{ + if (pCtx->role != LL_ROLE_MASTER) + { + LL_TRACE_WARN0("lctrSendChannelReportingInd: Shall not be called as a peripheral."); + pCtx->llcpNotifyMask &= ~(1 << LCTR_PROC_CMN_CH_CLASS_REPORTING); + lctrSendConnMsg(pCtx, LCTR_CONN_LLCP_PROC_CMPL); + return; + } + + lctrSendChannelReportingIndPdu(pCtx); + pCtx->chanStatRptEnable = pLctrConnMsg->chanRptInd.enable; + pCtx->data.mst.chanStatMinIntUs = LCTR_CH_RPT_IND_US(pLctrConnMsg->chanRptInd.minSpacing); + + /* Minus minimum spacing to allow a controller to send LL_CHANNEL_STATUS_IND right away if desired. */ + pCtx->data.mst.recvdChanStatTs = PalBbGetCurrentTime() - pCtx->data.mst.chanStatMinIntUs; + + /* The procedure completes after sending out the indication. */ + pCtx->llcpNotifyMask &= ~(1 << LCTR_PROC_CMN_CH_CLASS_REPORTING); + lctrSendConnMsg(pCtx, LCTR_CONN_LLCP_PROC_CMPL); +} + +/*************************************************************************************************/ +/*! + * \brief Store received channel reporting indication. + * + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +void lctrStoreChannelReportingInd(lctrConnCtx_t *pCtx) +{ + if (pCtx->role != LL_ROLE_SLAVE) + { + LL_TRACE_WARN1("lctrStoreChannelReportingInd: Received LL_CH_RPT_IND as a central. Handle=%d", LCTR_GET_CONN_HANDLE(pCtx)); + pCtx->llcpNotifyMask &= ~(1 << LCTR_PROC_CMN_CH_CLASS_REPORTING); + lctrSendConnMsg(pCtx, LCTR_CONN_LLCP_PROC_CMPL); + return; + } + + if ((lctrDataPdu.pld.chanRptInd.enable > TRUE) || + (lctrDataPdu.pld.chanRptInd.minSpacing < LL_CH_RPT_SPACING_MIN) || + (lctrDataPdu.pld.chanRptInd.maxDelay < LL_CH_RPT_SPACING_MIN) || + (lctrDataPdu.pld.chanRptInd.minSpacing > LL_CH_RPT_SPACING_MAX) || + (lctrDataPdu.pld.chanRptInd.maxDelay > LL_CH_RPT_SPACING_MAX) || + (lctrDataPdu.pld.chanRptInd.maxDelay < lctrDataPdu.pld.chanRptInd.minSpacing)) + { + lctrSendRejectInd(pCtx, LL_ERROR_CODE_INVALID_LMP_PARAMS, TRUE); + } + else + { + pCtx->chanStatRptEnable = lctrDataPdu.pld.chanRptInd.enable; + pCtx->data.slv.chanStatMinIntUs = LCTR_CH_RPT_IND_US(lctrDataPdu.pld.chanRptInd.minSpacing); + pCtx->data.slv.chanStatMaxDelay = LCTR_CH_RPT_IND_US(lctrDataPdu.pld.chanRptInd.maxDelay); + if (pCtx->chanStatRptEnable) + { + pCtx->data.slv.queuedChanStatusTs = PalBbGetCurrentTime(); + } + pCtx->data.slv.lastStatusSentTs = PalBbGetCurrentTime(); + } + + /* The procedure completes after receiving the indication. */ + lctrSendConnMsg(pCtx, LCTR_CONN_LLCP_PROC_CMPL); +} + /*************************************************************************************************/ /*! * \brief Update action for sca processing. diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn_past.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn_past.c index 4e5965808a..a721c7962a 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn_past.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn_past.c @@ -6,7 +6,7 @@ * * Copyright (c) 2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_enc.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_enc.c index f574180096..578fff5408 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_enc.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_enc.c @@ -179,13 +179,16 @@ void lctrCalcSessionKey(lctrConnCtx_t *pCtx) /* Use AES to transform LTK to session key using session key diversifier as seed. */ PalCryptoAesEcb(pCtx->ltk, pEnc->sk, pCtx->skd); - WSF_ASSERT(lctrInitCipherBlkHdlr); memcpy(pEnc->iv, pCtx->iv, sizeof(pEnc->iv)); pEnc->dir = (pCtx->role == LL_ROLE_MASTER) ? 1 : 0; /* master = 1; slave = 0 */ pEnc->type = PAL_BB_TYPE_ACL; pCtx->txPktCounter = 0; pCtx->rxPktCounter = 0; - lctrInitCipherBlkHdlr(pEnc, LCTR_GET_CONN_HANDLE(pCtx), pEnc->dir); + + if (lctrInitCipherBlkHdlr) + { + lctrInitCipherBlkHdlr(pEnc, LCTR_GET_CONN_HANDLE(pCtx), pEnc->dir); + } } /*************************************************************************************************/ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_pc.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_pc.c index c8854126b2..5cce52d0d7 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_pc.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_pc.c @@ -4,7 +4,7 @@ * * \brief Link layer controller connection power control state machine action routines. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,6 +37,27 @@ #include #include "lctr_int_pc.h" +/************************************************************************************************** + Constants +**************************************************************************************************/ + +#ifndef PC_ENABLE_DEBUG +/*! \brief Enable power control debug statements. */ +#define PC_ENABLE_DEBUG FALSE +#endif + +#if PC_ENABLE_DEBUG +#define LCTR_PC_DBG_TRACE_INFO0(m) LL_TRACE_INFO0(m) +#define LCTR_PC_DBG_TRACE_INFO1(m, v1) LL_TRACE_INFO1(m, v1) +#define LCTR_PC_DBG_TRACE_INFO2(m, v1, v2) LL_TRACE_INFO2(m, v1, v2) +#define LCTR_PC_DBG_TRACE_INFO3(m, v1, v2, v3) LL_TRACE_INFO3(m, v1, v2, v3) +#else +#define LCTR_PC_DBG_TRACE_INFO0(m) +#define LCTR_PC_DBG_TRACE_INFO1(m, v1) +#define LCTR_PC_DBG_TRACE_INFO2(m, v1, v2) +#define LCTR_PC_DBG_TRACE_INFO3(m, v1, v2, v3) +#endif + /*************************************************************************************************/ /*! * \brief Return the power control index of a phy bit. @@ -83,7 +104,7 @@ int8_t lctrAttemptTxPowerChange(lctrConnCtx_t *pCtx, uint8_t phy, int8_t delta) int8_t reqTxPower, curTxPower, newTxPower; if (LCTR_GET_TXPOWER(pCtx, phy, option) == LL_PWR_CTRL_TXPOWER_UNAVAILABLE) { - /* The current controller does not support this phy. */ + /* The current controller does not support this PHY. */ return 0; } else if (LCTR_GET_TXPOWER(pCtx, phy, option) == LL_PWR_CTRL_TXPOWER_UNMANAGED) @@ -107,7 +128,7 @@ int8_t lctrAttemptTxPowerChange(lctrConnCtx_t *pCtx, uint8_t phy, int8_t delta) newTxPower = PalRadioIncreasePower(reqTxPower, delta); /* Update txPower. */ - LL_TRACE_INFO3("lctrAttemptTxPowerChange: Power change -> handle=%d phy=%d txPow=%d", LCTR_GET_CONN_HANDLE(pCtx), phy + (option == BB_PHY_OPTIONS_BLE_S2) ? 1 : 0, newTxPower); + LCTR_PC_DBG_TRACE_INFO3("lctrAttemptTxPowerChange: Power change -> handle=%d phy=%d txPow=%d", LCTR_GET_CONN_HANDLE(pCtx), phy + (option == BB_PHY_OPTIONS_BLE_S2) ? 1 : 0, newTxPower); LCTR_SET_TXPOWER(pCtx, phy + (((phy == LL_PHY_LE_CODED) && (option == BB_PHY_OPTIONS_BLE_S2)) ? 1 : 0), newTxPower); /* Update current txPower if necessary. */ @@ -204,7 +225,7 @@ void lctrStorePowerControlAction(lctrConnCtx_t *pCtx) pCtx->delta = pLctrConnMsg->pwrCtrlReq.delta; pCtx->reqPhy = pLctrConnMsg->pwrCtrlReq.phy; - LL_TRACE_INFO2("lctrStorePowerControlAction, PHY=%u delta=%u", pCtx->reqPhy, pCtx->delta); + LCTR_PC_DBG_TRACE_INFO2("lctrStorePowerControlAction, phy=%u delta=%u", pCtx->reqPhy, pCtx->delta); /* If the power wasn't managed before, start managing it now. */ if (LCTR_GET_TXPOWER(pCtx, pCtx->reqPhy, BB_PHY_OPTIONS_BLE_S2) == LL_PWR_CTRL_TXPOWER_UNMANAGED) @@ -268,7 +289,7 @@ void lctrStorePeerPowerControlReq(lctrConnCtx_t *pCtx) (pCtx->bleData.chan.rxPhy == phyIdx) && (pCtx->peerTxPower != pld.txPower)) { - lctrNotifyPowerReportInd(pCtx, LL_POWER_REPORT_REASON_REMOTE, phyIdx, pld.txPower, + lctrNotifyPowerReportInd(pCtx, LL_SUCCESS, LL_POWER_REPORT_REASON_REMOTE, phyIdx, pld.txPower, lctrGetPowerLimits(pld.txPower), pld.txPower - pCtx->peerTxPower); } @@ -281,11 +302,11 @@ void lctrStorePeerPowerControlReq(lctrConnCtx_t *pCtx) if ((pCtx->peerTxPower == LL_PWR_CTRL_TXPOWER_UNAVAILABLE) || (pCtx->peerTxPower == LL_PWR_CTRL_TXPOWER_UNMANAGED)) { - LL_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower unmanaged or unavailable. Phy=%d", pld.phy); + LCTR_PC_DBG_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower unmanaged or unavailable, phy=%d", pld.phy); } else { - LL_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower=%d", pCtx->peerTxPower); + LCTR_PC_DBG_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower=%d", pCtx->peerTxPower); } } @@ -315,7 +336,7 @@ void lctrStorePeerPowerControlReq(lctrConnCtx_t *pCtx) } int8_t newTxPower = LCTR_GET_TXPOWER(pCtx, phy, option); - lctrNotifyPowerReportInd(pCtx, LL_POWER_REPORT_REASON_LOCAL, phyIdx, newTxPower, + lctrNotifyPowerReportInd(pCtx, LL_SUCCESS, LL_POWER_REPORT_REASON_LOCAL, phyIdx, newTxPower, lctrGetPowerLimits(newTxPower), pCtx->delta); } @@ -338,7 +359,7 @@ void lctrSendPeerPowerControlRsp(lctrConnCtx_t *pCtx) } else { - LL_TRACE_WARN0("lctrSendPeerPowerControlRsp: Peer sent invalid parameters for power control request."); + LL_TRACE_WARN0("lctrSendPeerPowerControlRsp: peer sent invalid parameters for power control request"); lctrSendRejectInd(pCtx, pCtx->reqErrCode, TRUE); pCtx->reqErrCode = LL_SUCCESS; } @@ -359,7 +380,7 @@ void lctrStorePeerPowerControlRsp(lctrConnCtx_t *pCtx) if ((pCtx->powerRptRemote) && (pCtx->peerTxPower != pld.txPower)) { - lctrNotifyPowerReportInd(pCtx, LL_POWER_REPORT_REASON_REMOTE, pCtx->reqPhy, pld.txPower, + lctrNotifyPowerReportInd(pCtx, LL_SUCCESS, LL_POWER_REPORT_REASON_REMOTE, pCtx->reqPhy, pld.txPower, pld.limits, pld.txPower - pCtx->peerTxPower); } @@ -374,18 +395,18 @@ void lctrStorePeerPowerControlRsp(lctrConnCtx_t *pCtx) if ((pCtx->peerTxPower == LL_PWR_CTRL_TXPOWER_UNAVAILABLE) || (pCtx->peerTxPower == LL_PWR_CTRL_TXPOWER_UNMANAGED)) { - LL_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower unmanaged or unavailable. Phy=%d", pCtx->reqPhy); + LCTR_PC_DBG_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower unmanaged or unavailable, phy=%d", pCtx->reqPhy); } else { - LL_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower=%d", pCtx->peerTxPower); + LCTR_PC_DBG_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower=%d", pCtx->peerTxPower); if (pCtx->controllerInitRead) { pCtx->controllerInitRead = FALSE; } - if (pCtx->monitoringState == LCTR_PC_MONITOR_PATH_LOSS) + if (pCtx->powerMonitorScheme == LCTR_PC_MONITOR_PATH_LOSS) { if (pCtx->pclMonitorParam.pathLoss.initialPathLossRead) { @@ -400,7 +421,7 @@ void lctrStorePeerPowerControlRsp(lctrConnCtx_t *pCtx) /* Store delta for reporting. */ pCtx->delta = pld.delta; - LL_TRACE_INFO3("lctrStorePeerPowerControlRsp: peerTxPower=%d, peerPwrLimits=%d, peerApr=%d", pld.txPower, pld.limits, pld.apr); + LCTR_PC_DBG_TRACE_INFO3("lctrStorePeerPowerControlRsp: peerTxPower=%d, peerPwrLimits=%d, peerApr=%d", pld.txPower, pld.limits, pld.apr); } /*************************************************************************************************/ @@ -408,6 +429,7 @@ void lctrStorePeerPowerControlRsp(lctrConnCtx_t *pCtx) * \brief Notify host of power report indication. * * \param pCtx Connection context. + * \param status Status code. * \param reason Reason this indication was sent. * \param phy PHY. * \param txPower Current txPower. @@ -415,7 +437,7 @@ void lctrStorePeerPowerControlRsp(lctrConnCtx_t *pCtx) * \param delta Delta from last txPower. */ /*************************************************************************************************/ -void lctrNotifyPowerReportInd(lctrConnCtx_t *pCtx, uint8_t reason, uint8_t phy, int8_t txPower, uint8_t limits, int8_t delta) +void lctrNotifyPowerReportInd(lctrConnCtx_t *pCtx, uint8_t status, uint8_t reason, uint8_t phy, int8_t txPower, uint8_t limits, int8_t delta) { const uint16_t handle = LCTR_GET_CONN_HANDLE(pCtx); @@ -425,7 +447,7 @@ void lctrNotifyPowerReportInd(lctrConnCtx_t *pCtx, uint8_t reason, uint8_t phy, { .param = handle, .event = LL_TX_POWER_REPORTING_IND, - .status = LL_SUCCESS + .status = status }, .status = LL_SUCCESS, @@ -437,7 +459,15 @@ void lctrNotifyPowerReportInd(lctrConnCtx_t *pCtx, uint8_t reason, uint8_t phy, .delta = delta }; - LL_TRACE_INFO2("### LlEvent ### lctrNotifyPowerReportInd , handle=%u, reason=%d, status=LL_SUCCESS", handle, reason); + if (status == LL_SUCCESS) + { + LL_TRACE_INFO2("### LlEvent ### lctrNotifyPowerReportInd, handle=%u, reason=%d, status=LL_SUCCESS", handle, reason); + } + else + { + LL_TRACE_INFO1("### LlEvent ### lctrNotifyPowerReportInd, Power procedure rejected, status=%d", status); + } + LmgrSendEvent((LlEvt_t *)&evt); } @@ -463,7 +493,7 @@ static void lctrSendPowerChangePdu(lctrConnCtx_t *pCtx, uint8_t opcode, uint8_t uint8_t *pPdu; - if ((pPdu = lctrTxCtrlPduAlloc(LL_PWR_CHNG_IND_LEN)) != NULL) + if ((pPdu = lctrTxCtrlPduAlloc(LL_PWR_CHANGE_IND_LEN)) != NULL) { bool_t seperateIndNeeded = FALSE; uint8_t *pBuf = pPdu; @@ -521,7 +551,7 @@ static void lctrSendPowerChangePdu(lctrConnCtx_t *pCtx, uint8_t opcode, uint8_t /*************************************************************************************************/ void lctrSendPowerChangeInd(lctrConnCtx_t *pCtx, uint8_t phy, int8_t delta, int8_t txPower, bool_t phyChange) { - lctrSendPowerChangePdu(pCtx, LL_PDU_PWR_CHNG_IND, phy, delta, txPower, phyChange); + lctrSendPowerChangePdu(pCtx, LL_PDU_PWR_CHANGE_IND, phy, delta, txPower, phyChange); } /*************************************************************************************************/ @@ -534,16 +564,15 @@ void lctrSendPowerChangeInd(lctrConnCtx_t *pCtx, uint8_t phy, int8_t delta, int8 void lctrStorePeerPowerInd(lctrConnCtx_t *pCtx) { lctrPwrChngInd_t * pPdu = &lctrDataPdu.pld.pwrChngInd; - LL_TRACE_INFO3("lctrStorePeerPowerInd: Phy=%d Delta=%d txPower=%d", pPdu->phy, pPdu->delta, pPdu->txPower); + LCTR_PC_DBG_TRACE_INFO3("lctrStorePeerPowerInd: phy=%d delta=%d txPower=%d", pPdu->phy, pPdu->delta, pPdu->txPower); if (pPdu->phy & (1 << (pCtx->bleData.chan.rxPhy - 1))) { - if ((pCtx->peerTxPower != pPdu->txPower) && - (pCtx->powerRptRemote)) + if (pCtx->powerRptRemote) { - lctrNotifyPowerReportInd(pCtx, LL_POWER_REPORT_REASON_REMOTE, pCtx->bleData.chan.rxPhy, pPdu->txPower, - pPdu->limits, - pPdu->txPower - pCtx->peerTxPower); + lctrNotifyPowerReportInd(pCtx, LL_SUCCESS, LL_POWER_REPORT_REASON_REMOTE, + pCtx->bleData.chan.rxPhy, pPdu->txPower, pPdu->limits, + pPdu->txPower - pCtx->peerTxPower); } if (pPdu->phy == pCtx->bleData.chan.rxPhy) @@ -553,11 +582,11 @@ void lctrStorePeerPowerInd(lctrConnCtx_t *pCtx) if ((pCtx->peerTxPower == LL_PWR_CTRL_TXPOWER_UNAVAILABLE) || (pCtx->peerTxPower == LL_PWR_CTRL_TXPOWER_UNMANAGED)) { - LL_TRACE_INFO1("lctrStorePeerPowerInd: txPower unmanaged or unavailable. Phy=%d", pPdu->phy); + LCTR_PC_DBG_TRACE_INFO1("lctrStorePeerPowerInd: txPower unmanaged or unavailable, phy=%d", pPdu->phy); } else { - LL_TRACE_INFO1("lctrStorePeerPowerInd: txPower=%d", pCtx->peerTxPower); + LCTR_PC_DBG_TRACE_INFO1("lctrStorePeerPowerInd: txPower=%d", pCtx->peerTxPower); } } } @@ -578,62 +607,53 @@ void lctrSendPeerPowerRsp(lctrConnCtx_t *pCtx) /*************************************************************************************************/ /*! - * \brief Power monitoring action function + * \brief Service connection power monitor. * * \param pCtx Connection context. */ /*************************************************************************************************/ -void lctrAutoPowerMonitorAct(lctrConnCtx_t *pCtx) +void lctrConnServicePowerMonitor(lctrConnCtx_t *pCtx) { - if (!(pCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST)) + if (!(pCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST) || + lmgrGetOpFlag(LL_OP_MODE_FLAG_DIS_POWER_MONITOR)) { pCtx->monitoringState = LCTR_PC_MONITOR_DISABLED; return; } - if (lmgrCb.opModeFlags & LL_OP_MODE_DISABLE_POWER_MONITOR) - { - return; - } - int8_t sendReqDelta = 0; - if ((pCtx->rssi < pCtx->pclMonitorParam.autoMonitor.lowThreshold) || - (pCtx->lastRxStatus != BB_STATUS_SUCCESS)) - { - pCtx->pclMonitorParam.autoMonitor.curTimeSpent++; + /* Restore the sign after finding the absolute value average RSSI. */ + lctrRssiAddAveragePoint(&pCtx->pclMonitorParam.autoMonitor.rssiRunAvg, + -((int8_t) (pCtx->pclMonitorParam.autoMonitor.accumulatedRssi / pCtx->pclMonitorParam.autoMonitor.totalAccumulatedRssi))); + pCtx->pclMonitorParam.autoMonitor.accumulatedRssi = 0; + pCtx->pclMonitorParam.autoMonitor.totalAccumulatedRssi = 0; - if (pCtx->pclMonitorParam.autoMonitor.curTimeSpent >= pCtx->pclMonitorParam.autoMonitor.minTimeSpent) - { - if (!(pCtx->peerPwrLimits & LL_PWR_CONTROL_LIMIT_MAX_BIT)) - { - LL_TRACE_INFO1("RSSI too low, requesting increase in power. phy=%u", pCtx->bleData.chan.rxPhy); - sendReqDelta = pCtx->pclMonitorParam.autoMonitor.requestVal; - } - pCtx->pclMonitorParam.autoMonitor.curTimeSpent = 0; - } - } - else if (pCtx->rssi > pCtx->pclMonitorParam.autoMonitor.highThreshold) + if (pCtx->pclMonitorParam.autoMonitor.rssiRunAvg.avgCount >= LL_PC_TBL_LEN) { - pCtx->pclMonitorParam.autoMonitor.curTimeSpent++; + int8_t averageRunning = lctrRssiGetAverage(&pCtx->pclMonitorParam.autoMonitor.rssiRunAvg); - if (pCtx->pclMonitorParam.autoMonitor.curTimeSpent >= pCtx->pclMonitorParam.autoMonitor.minTimeSpent) + if ((averageRunning > pCtx->pclMonitorParam.autoMonitor.highThreshold) && + (!(pCtx->peerPwrLimits & LL_PWR_CONTROL_LIMIT_MIN_BIT))) { - if (!(pCtx->peerPwrLimits & LL_PWR_CONTROL_LIMIT_MIN_BIT)) - { - LL_TRACE_INFO1("RSSI too high, requesting decrease in power. phy=%u", pCtx->bleData.chan.rxPhy); - sendReqDelta = -(pCtx->pclMonitorParam.autoMonitor.requestVal); - } - pCtx->pclMonitorParam.autoMonitor.curTimeSpent = 0; + sendReqDelta = -(pCtx->pclMonitorParam.autoMonitor.requestVal); + } + else if ((averageRunning < pCtx->pclMonitorParam.autoMonitor.lowThreshold) && + !(pCtx->peerPwrLimits & LL_PWR_CONTROL_LIMIT_MAX_BIT)) + { + sendReqDelta = pCtx->pclMonitorParam.autoMonitor.requestVal; } - } - else - { - pCtx->pclMonitorParam.autoMonitor.curTimeSpent = 0; } if (sendReqDelta != 0) { + if ((pCtx->llcpActiveProc == LCTR_PROC_PWR_CTRL) || + (pCtx->llcpPendMask & (1 << LCTR_PROC_PWR_CTRL))) + { + LL_TRACE_WARN0("Power control LLCP already pending -- try increasing service interval"); + return; + } + uint8_t reqPhy = pCtx->bleData.chan.rxPhy + (((pCtx->bleData.chan.rxPhy == BB_PHY_BLE_CODED) && (pCtx->bleData.chan.initTxPhyOptions == BB_PHY_OPTIONS_BLE_S2)) ? 1 : 0); lctrMsgPwrCtrlReq_t *pMsg; @@ -646,5 +666,7 @@ void lctrAutoPowerMonitorAct(lctrConnCtx_t *pCtx) pMsg->phy = reqPhy; WsfMsgSend(lmgrPersistCb.handlerId, pMsg); } + + pCtx->pclMonitorParam.autoMonitor.rssiRunAvg.avgCount = 0; } } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_phy.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_phy.c index 7c5b60deec..1bf60fb665 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_phy.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_phy.c @@ -186,8 +186,9 @@ void lctrSendPhyUpdateIndPdu(lctrConnCtx_t *pCtx, uint8_t txPhys, uint8_t rxPhys else #endif { - ceOffset = LL_MIN_INSTANT + 1 + /* +1 for next CE */ - pCtx->maxLatency; /* ensure slave will listen this packet */ + ceOffset = ((LL_MIN_INSTANT + 1 + /* +1 for next CE */ + pCtx->maxLatency) * /* ensure slave will listen to this packet */ + pCtx->ecu.srFactor); /* include subrating factor */ } if (txPhys || rxPhys) diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int.h index 055322511e..76328777ff 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -117,6 +117,15 @@ extern "C" { /*! \brief Change supervision timeout value to us. */ #define LCTR_SUP_TIMEOUT_VAL_TO_US(x) (x * 10000) +/*! \brief Array size of running average arrays, derived from LL_PC_TBL_LEN. */ +#define LL_PC_TBL_LEN (1 << LL_PC_TBL_POW) + +/*! \brief Calculate microsecond format from channel reporting parameter (200 millisecond ticks). */ +#define LCTR_CH_RPT_IND_US(x) ((((uint64_t) x) * 200) * 1000) + +/*! \brief Calculate microsecond format from channel reporting parameter (200 millisecond ticks). */ +#define LCTR_CH_RPT_IND_US(x) ((((uint64_t) x) * 200) * 1000) + /************************************************************************************************** Data Types **************************************************************************************************/ @@ -136,6 +145,15 @@ typedef void (*LctrRmCback_t)(uint32_t rsvnOffs[], uint32_t refTime); /*! \brief Channel class update handler call signature. */ typedef uint8_t (*lctrChClassHdlr_t)(uint64_t chanMap); +/*! \brief RSSI running average data type. */ +typedef struct +{ + int8_t averageRssi[LL_PC_TBL_LEN]; + /*!< Running average RSSI. */ + uint8_t rssiIdx; /*!< Running average RSSI index. */ + uint8_t avgCount; /*!< Count of average entries since last reset. */ +} lctrRssiRunAvg_t; + /************************************************************************************************** Globals **************************************************************************************************/ @@ -164,6 +182,10 @@ uint16_t lctrCalcTotalAccuracy(uint8_t mstScaIdx); uint32_t lctrComputeCrcInit(void); uint32_t lctrCalcWindowWideningUsec(uint32_t unsyncTimeUsec, uint32_t caPpm); +/* RSSI Averaging. */ +int8_t lctrRssiGetAverage(lctrRssiRunAvg_t *pAvg); +void lctrRssiAddAveragePoint(lctrRssiRunAvg_t *pAvg, int8_t value); + /* Host events */ void lctrNotifyHostHwErrInd(uint8_t code); void lctrNotifyHostConnectInd(uint16_t handle, uint8_t role, lctrConnInd_t *pConnInd, diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_master_ae.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_master_ae.h index a69af4b68b..1d4d877719 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_master_ae.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_master_ae.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -191,6 +191,7 @@ typedef struct BbBleData_t scanBleData; /*!< BLE BB operation data. */ BbOpDesc_t auxScanBod; /*!< Auxiliary scan BOD. */ BbBleData_t auxBleData; /*!< Auxiliary BLE BB operation data. */ + bool_t scheduleAuxAsap; /*!< Signal BB to program Aux Scan. */ } lctrExtScanCtx_t; /*! \brief Extended scanning control block. */ @@ -234,6 +235,7 @@ typedef struct bool_t cancelByHost; /*!< Cancel command was issued from host. */ bool_t firstPerAdvRcv; /*!< True if first periodic advertising packet is received. */ bool_t repDisabled; /*!< Reporting disabled. */ + bool_t dupFilterEnable; /*!< Filtering by ADI field enabled. */ bool_t bodAborted; /*!< Tue if periodic scan BOD was aborted. */ uint8_t createDispId; /*!< Dispatcher id to tell if periodic sync was created or transferred. */ lctrTermHdlr_t termCback; /*!< Termination callback. */ @@ -257,13 +259,14 @@ typedef struct uint32_t lastAnchorPointUsec;/*!< Last anchor point in microseconds. */ uint16_t lastActiveEvent; /*!< Last active event counter. */ uint16_t initEventCounter; /*!< Initial event counter received from sync_info. */ + uint16_t lastDid; /*!< Last ADI received, if applicable. */ /* ACAD */ lctrAcadParam_t acadParams[LCTR_ACAD_NUM_ID]; /*!< ACAD control block array. */ /* Local periodic scanning parameters */ uint16_t skip; /*!< Skip. */ - uint16_t syncTimeOutMs; /*!< Synchronization Timeout in Milliseconds. */ + uint32_t syncTimeOutMs; /*!< Synchronization Timeout in Milliseconds. */ /* Filtering parameters */ bbBlePerPduFiltParams_t filtParam; /*!< Periodic scan filter parameters. */ @@ -356,12 +359,14 @@ void lctrMstPerScanTransferOpCommit(uint16_t connHandle); bool_t lctrMstDiscoverRxExtAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf); void lctrMstDiscoverRxExtAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf); bool_t lctrMstDiscoverRxAuxAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf); +void lctrMstDiscoverRxAuxAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf); bool_t lctrMstDiscoverRxAuxScanRspHandler(BbOpDesc_t *pOp, const uint8_t *pRspBuf); uint32_t lctrMstDiscoverRxAuxChainHandler(BbOpDesc_t *pOp, const uint8_t *pChainBuf); bool_t lctrMstDiscoverRxAuxChainPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pChainBuf); bool_t lctrMstDiscoverRxLegacyAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf); bool_t lctrMstDiscoverTxLegacyScanReqHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf); bool_t lctrMstDiscoverRxLegacyScanRspHandler(BbOpDesc_t *pOp, const uint8_t *pRspBuf); +bool_t lctrMstLinkAuxOffsetScanSetup(BbOpDesc_t *pBod, uint32_t refTime, uint32_t remScanDur); /* ISR: Discovery BOD handlers */ void lctrMstExtDiscoverEndOp(BbOpDesc_t *pOp); void lctrMstExtDiscoverAbortOp(BbOpDesc_t *pOp); diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_slave.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_slave.h index 87cc8c1806..936666fe25 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_slave.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_slave.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2017 ARM Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,7 +50,6 @@ enum }; /*! \brief Common extended advertising PDU types. */ - enum { LCTR_PDU_ADV_EXT_IND, diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_slave_ae.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_slave_ae.h index 1dd7f971b1..afe0e486d2 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_slave_ae.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_slave_ae.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,7 +43,7 @@ extern "C" { **************************************************************************************************/ /*! \brief Maximum value of the AuxPtr offset field. */ -#define LCTR_AUX_PTR_MAX_OFFSET 0x3FFF +#define LCTR_AUX_PTR_MAX_OFFSET 0x1FFF /*! \brief Number of shifted bytes for Used PHY field from the AUX Offset. */ #define LCTR_AUX_OFFS_USED_PHY_SHIFT 13 @@ -138,6 +138,9 @@ typedef struct bool_t shutdown; /*!< Client initiated shutdown flag. */ uint32_t perAdvInterUsec; /*!< Periodic advertising interval in microseconds. */ + bool_t enableAdi; /*!< Enable ADI field in Periodic Advertising. */ + uint16_t advDID; /*!< Advertising Data ID. */ + uint32_t advInterMinUsec; /*!< Periodic Advertising Interval Minimum in microseconds. */ uint32_t advInterMaxUsec; /*!< Periodic Advertising Interval Maximum in BB ticks. */ uint16_t advEventProp; /*!< Periodic Advertising Event Properties. */ @@ -238,7 +241,6 @@ typedef struct /* BB/ISR context */ bool_t shutdown; /*!< Client initiated shutdown flag. */ - uint8_t bodTermCnt; /*!< Number of BOD terminated. */ BbOpDesc_t advBod; /*!< Advertising BOD. */ BbBleData_t bleData; /*!< BLE data. */ BbOpDesc_t auxAdvBod; /*!< Auxiliary advertising BOD. */ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis.h index c2541366d6..0c462bc0c8 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -66,22 +66,23 @@ typedef struct struct { /* Data */ - wsfQueue_t txDataQ; /*!< Transmit ISO queue. */ - uint8_t numTxSduComp; /*!< Number of Tx completed SDUs. */ - lctrIsoalTxCtx_t isoalTxCtx; /*!< ISOAL transmit context. */ - } slv; /*!< BIS slave specific data. */ + wsfQueue_t txDataQ; /*!< Transmit ISO queue. */ + uint8_t numTxSduComp; /*!< Number of Tx completed SDUs. */ + lctrIsoalTxCtx_t isoalTxCtx; /*!< ISOAL transmit context. */ + lctrInDataPathCtx_t dataPathInCtx; /*!< Datapath input context. */ + } slv; /*!< BIS slave specific data. */ struct { /* Data */ - wsfQueue_t rxDataQ; /*!< Receive ISO Data PDU pending queue. */ - wsfQueue_t rxIsoSduQ; /*!< Receive ISO SDU PDU pending queue. */ - lctrIsoalRxCtx_t isoalRxCtx; /*!< ISOAL Receive context. */ + wsfQueue_t rxDataQ; /*!< Receive ISO Data PDU pending queue. */ + lctrIsoalRxCtx_t isoalRxCtx; /*!< ISOAL receive context. */ + lctrOutDataPathCtx_t dataPathOutCtx; /*!< Output data path context. */ /* ISO test */ - LlIsoTestCtrs_t stats; /*!< Rx statistics. */ - } mst; /*!< BIS master specific data. */ - } roleData; /*!< Role specific data. */ + LlIsoTestCtrs_t stats; /*!< Rx statistics. */ + } mst; /*!< BIS master specific data. */ + } roleData; /*!< Role specific data. */ /* ISO test */ struct @@ -93,22 +94,21 @@ typedef struct { struct { - uint32_t payloadCtr; /*!< Payload counter for framed transmissions. */ - } framed; /*!< Framed context. */ + uint32_t payloadCtr; /*!< Payload counter for framed transmissions. */ + } framed; struct { - uint8_t payloadOffset; /*!< Payload offset for unframed transmissions. */ - } unframed; /*!< Unframed context. */ - } util; /*!< Role-based utility variables. */ - LlIsoPldType_t pldType:8; /*!< Test payload type. */ - } test; /*!< ISO Test data. */ + uint8_t burstIdx; /*!< BN Index for unframed transmissions. */ + } unframed; + } util; + LlIsoPldType_t pldType:8; /*!< Test payload type. */ + } test; /* BB */ lmgrChanParam_t chSelInfo; /*!< Channel selection state. */ PalBbBleChan_t chan; /*!< Channelization parameters. */ /* Data */ - LlIsoDataPath_t path:8; /*!< Input audio data path. */ LlIsoLlid_t lastLlid:8; /*!< Last LLID. */ } lctrBisCtx_t; @@ -164,19 +164,26 @@ typedef struct lctrBigCtx_tag uint8_t bisIdx[LL_MAX_BIS]; /*!< List of indices of BISes. */ /* Sync timeout */ - uint32_t bigSyncTimeoutMs; /*!< Synchronization timeout in microseconds. */ wsfTimer_t bigSyncTmr; /*!< Synchronization timeout timer. */ - - /* Event state */ - uint16_t totalAcc; /*!< Total clock accuracy. */ - uint16_t extraWwUsec; /*!< Extra window widening time in microseconds. */ - uint32_t rxSyncTime; /*!< Last received BIG anchor point. */ - uint32_t anchorPoint; /*!< BIG anchor point. */ + uint32_t bigSyncTimeoutMs; /*!< Synchronization timeout in microseconds. */ /* Encryption */ - uint8_t bcstCode[LL_BC_LEN]; /*!< Broadcast Code. */ - } mst; /*!< BIG master specific data. */ - } roleData; /*!< Role-specific data. */ + uint8_t bcstCode[LL_BC_LEN]; /*!< Broadcast Code. Array address should be word-aligned. */ + + /* Event state */ + uint16_t totalAcc; /*!< Total clock accuracy. */ + uint16_t initWwUsec; /*!< Initial synchronization window widening time in microseconds. */ + uint32_t rxSyncTime; /*!< Last received BIG anchor point. */ + uint32_t anchorPoint; /*!< BIG anchor point. */ + lctrBisCtx_t *pFirstBisCtx; /*!< First BIS context (ISR optimization to reduce lookups). */ + lctrBisCtx_t *pSecondBisCtx; /*!< Second BIS context (ISR optimization to reduce lookups). */ + uint32_t firstBisOffsUsec; /*!< First BIS offset from the anchor point in microseconds. */ + uint8_t firstBisEvtIdx; /*!< First BIS index. */ + + /* Reception status. */ + bool_t lastPduMissed; /*!< Rx failure on last PDU. */ + } mst; /*!< BIG master specific data. */ + } roleData; /*!< Role-specific data. */ /* Control */ struct @@ -210,9 +217,6 @@ typedef struct lctrBigCtx_tag bool_t encrypt; /*!< Encryption enable for BIS. */ uint8_t giv[LL_GIV_LEN]; /*!< GIV. */ uint8_t gskd[LL_GSKD_LEN]; /*!< GSKD. */ - - /* Reception status. */ - bool_t lastPduMissed; /*!< Rx failure on last PDU. */ } lctrBigCtx_t; /*! \brief ISR subevent context. */ @@ -245,7 +249,6 @@ bool_t lctrIsBigSynchronizing(void); /* BIS Context */ lctrBisCtx_t *lctrAllocBisCtx(lctrBigCtx_t *pBigCtx); -void lctrCleanupBisCtx(lctrBisCtx_t *pBisCtx); void lctrFreeBisCtx(lctrBisCtx_t *pBisCtx); lctrBisCtx_t *lctrFindBisByHandle(uint16_t bisHandle); uint8_t lctrGetNumAvailBisCtx(void); @@ -266,11 +269,11 @@ void lctrBigTxCtrlQueuePopCleanup(lctrBigCtx_t *pBigCtx); /* BIS Rx Data Path */ uint8_t *lctrBisRxIsoSduDeq(lctrBisCtx_t *pBisCtx); -void lctrBisRxIsoSduEnq(lctrBisCtx_t *pBisCtx, uint8_t *pBuf); uint8_t *lctrBisRxIsoDataPduAlloc(void); void lctrBisRxIsoDataPduFree(uint8_t *pPdu); -void lctrBisEnqueueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t *pRxBuf, uint64_t evtCtr); -uint8_t *lctrBisDequeueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t *pEvtCtrLsb); +void lctrBisEnqueueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t *pRxBuf, uint8_t burstIdx); +uint8_t *lctrBisDequeueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t burstIdx); +uint8_t *lctrBisDequeueRxDataPduTop(lctrBisCtx_t *pBisCtx); /* ISO Test mode */ uint8_t lctrBisTxTest(lctrBisCtx_t *pBisCtx, uint8_t pldType); @@ -281,9 +284,8 @@ uint8_t LctrBisReadTestCounters(lctrBisCtx_t *pBisCtx, LlIsoTestCtrs_t *pStats); void lctrBisDefaults(void); void lctrNotifyIsoTxComplete(lctrBigCtx_t *pBigCtx); void lctrBisCalcGroupSessionKey(const uint8_t *pGSKD, const uint8_t *pBC, uint8_t *pGSK); -uint8_t lctrBisSetDataPath(lctrBisCtx_t *pBisCtx, LlIsoDataPathDir_t dpDir, LlIsoDataPath_t dpId); -bool_t lctrSlvBisCalcNextIdxSequential(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts); -bool_t lctrSlvBisCalcNextIdxInterleaved(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts); +bool_t lctrBisCalcNextIdxSequential(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts); +bool_t lctrBisCalcNextIdxInterleaved(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts); #ifdef __cplusplus }; diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis_master.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis_master.h index 54b72e3adb..4811b2727c 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis_master.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis_master.h @@ -4,7 +4,7 @@ * * \brief Internal link layer controller isochronous master interface file. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -90,6 +90,7 @@ void lctrMstSetupBigChannel(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo); /* ISR: BOD handlers */ void lctrMstBisRxCompletion(BbOpDesc_t *pBod, uint8_t *pBuf, uint8_t status); void lctrMstBigBeginOp(BbOpDesc_t *pOp); +void lctrMstBigAbortOp(BbOpDesc_t *pOp); void lctrMstBigEndOp(BbOpDesc_t *pOp); #ifdef __cplusplus diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis.h index 02d678254f..cf6f6c2ebc 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -160,6 +160,8 @@ typedef struct uint32_t cigSyncDelayUsec; /*!< CIG synchronous delay in microsecond. */ bool_t cisDone; /*!< CIS transfer is done, no more subevent for the CIS. Used for interleaved CIS only. */ bool_t isClosing; /*!< TRUE if the context is closing. */ + bool_t termPend; /*!< The CIS has pended a termination. */ + bool_t hostInitTerm; /*!< The host has initiated the termination. */ uint8_t subEvtCounter; /*!< Sub event counter. */ bool_t isTxDone; /*!< TRUE if all the Tx are done, start sending NULL packet. */ @@ -172,9 +174,10 @@ typedef struct uint64_t rxPktCounter; /*!< Receive packet counter. */ /* Buffers */ - uint8_t dataHdrBuf[LL_DATA_HDR_LEN]; /*!< Data header buffer */ - uint8_t dataBuf[10]; /*!< Data header buffer */ + uint8_t dataHdrBuf[LL_DATA_HDR_LEN]; /*!< Data header buffer. */ + uint8_t dataBuf[10]; /*!< Data header buffer. */ uint16_t dataCounter; /*!< Data counter. */ + uint8_t dataSn; /*!< Data sequence number. */ /* LLCP */ bool_t isCisReqPend; /*!< True if CIS_REQ is sent and response is not received yet. */ @@ -196,6 +199,7 @@ typedef struct uint32_t firstRxStartTsUsec; /*!< Timestamp of the first received frame regardless of CRC error in microseconds. */ uint8_t consCrcFailed; /*!< Number of consecutive CRC failures. */ uint8_t rxStatus; /*!< Rx status. */ + bool_t lastTxNull; /*!< Last packet sent was a null. */ } slv; /*!< Slave connection specific data. */ struct @@ -220,7 +224,6 @@ typedef struct uint8_t numTxComp; /*!< Number of completed Tx buffers. */ uint32_t delayUsec; /*!< Time between the start of subevent to the start of next subevent in microsecond. Same as subEvtInter for sequential scheme, different for interleaved scheme. */ - uint8_t *pRxBuf; /*!< Pointer to the RX buffer later to be cleaned. */ bool_t validRx; /*!< TRUE if the RX buffer is valid and shall be processed. */ bool_t txPduIsAcked; /*!< TRUE if the TX PDU is acked. */ bool_t txBufPendAck; /*!< A transmit buffer is pending acknowledgement. */ @@ -410,6 +413,7 @@ bool_t lctrCisIsListEmpty(lctrCisList_t *pList); uint8_t lctrCisGetListCount(lctrCisList_t *pList); lctrCisCtx_t * lctrCisGetHeadCis(lctrCisList_t *pList); bool_t lctrCisIsHeadCis(lctrCisList_t *pList, lctrCisCtx_t *pCisCtx); +bool_t lctrCisIsTailCis(lctrCisList_t *pList, lctrCisCtx_t *pCisCtx); lctrCisCtx_t * lctrCisGetNextCis(lctrCisList_t *pList, lctrCisCtx_t *pCurCis); lctrCisCtx_t * lctrCisGetPreCis(lctrCisList_t *pList, lctrCisCtx_t *pCurCis); bool_t lctrCisAreCisCtxDone(lctrCisList_t *pList); @@ -466,7 +470,7 @@ void lctrCisTxQueuePopCleanup(lctrCisCtx_t *pCisCtx); uint8_t lctrCisTxQueueClear(lctrCisCtx_t *pCisCtx); /* CIS Rx data path */ -uint8_t *lctrCisRxPduAlloc(uint16_t maxRxLen); +uint8_t *lctrCisRxPduAlloc(); void lctrCisRxPduFree(uint8_t *pBuf); void lctrCisRxEnq(uint8_t *pBuf, uint16_t eventCounter, uint16_t cisHandle); uint8_t *lctrCisRxDeq(uint16_t *pConnHandle); @@ -487,7 +491,8 @@ void lctrCisTxPduAck(lctrCisCtx_t *pCisCtx); void lctrCisProcessTxAckCleanup(lctrCisCtx_t *pCisCtx); void lctrCisRxPostProcessing(lctrCisCtx_t *pCisCtx, uint8_t *pRxBuf); void lctrCisTxTestPayloadHandler(lctrCisCtx_t * pCisCtx); -void lctrCisPowerMonitorCheckRssi(int8_t rssi, uint8_t status, uint8_t phy, lctrConnCtx_t *pConnCtx); +void lctrCisCheckUnframedFlush(lctrCisCtx_t *pCisCtx); +void lctrCisServicePowerMonitor(lctrConnCtx_t *pConnCtx); /* Scheduler */ BbOpDesc_t *lctrCisResolveConflict(BbOpDesc_t *pNewOp, BbOpDesc_t *pExistOp); @@ -506,7 +511,7 @@ static inline void lctrCisIncPacketCounterTx(lctrCisCtx_t *pCisCtx) /* Set the new packet counter for inline encryption. */ if (lctrSetEncryptPktCountHdlr) { - lctrSetEncryptPktCountHdlr(&pCisCtx->bleData.chan.enc, pCisCtx->txPktCounter); + lctrSetEncryptPktCountHdlr(pCisCtx->txPktCounter); } } @@ -520,11 +525,47 @@ static inline void lctrCisIncPacketCounterTx(lctrCisCtx_t *pCisCtx) static inline void lctrCisIncPacketCounterRx(lctrCisCtx_t *pCisCtx) { pCisCtx->rxPktCounter++; +} - /* Set the new packet counter for inline encryption. */ +/*************************************************************************************************/ +/*! + * \brief Set the CIS Tx packet counter value in the BB. + * + * \param pCisCtx Connection context. + */ +/*************************************************************************************************/ +static inline void lctrSetBbCisPacketCounterTx(lctrCisCtx_t *pCisCtx) +{ + if (lctrSetEncryptPktCountHdlr) + { + PalCryptoEnc_t * const pEnc = &pCisCtx->bleData.chan.enc; + + if (!pEnc->enaEncrypt) + { + return; + } + lctrSetEncryptPktCountHdlr(pCisCtx->txPktCounter); + } +} + +/*************************************************************************************************/ +/*! + * \brief Set the CIS Rx packet counter value in the BB. + * + * \param pCisCtx Connection context. + */ +/*************************************************************************************************/ +static inline void lctrSetBbCisPacketCounterRx(lctrCisCtx_t *pCisCtx) +{ if (lctrSetDecryptPktCountHdlr) { - /* lctrSetDecryptPktCountHdlr(&pCisCtx->bleData.chan.enc, pCisCtx->rxPktCounter); */ /* Not necessary. */ + PalCryptoEnc_t * const pEnc = &pCisCtx->bleData.chan.enc; + + if (!pEnc->enaDecrypt) + { + return; + } + lctrSetDecryptPktCountHdlr(pCisCtx->rxPktCounter); } } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis_master.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis_master.h index 92263d06ea..c76c5b003c 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis_master.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis_master.h @@ -88,6 +88,7 @@ void lctrMstCisCigRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status) /* ISR: BOD handlers */ uint32_t lctrMstCisCheckContOp(BbOpDesc_t *pOp, bool_t *pNewCisCtx); +uint32_t lctrMstCisCheckContOpPostCback(BbOpDesc_t *pOp, bool_t *pNewCisCtx); void lctrMstCisCigBeginOp(BbOpDesc_t *pOp); void lctrMstCisCigContOp(BbOpDesc_t *pOp); void lctrMstCisCigPostSubEvt(BbOpDesc_t *pOp, uint8_t status); diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis_slave.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis_slave.h index 344c528ff2..70af15509a 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis_slave.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis_slave.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -83,6 +83,7 @@ void lctrSlvCisCigBeginOp(BbOpDesc_t *pOp); void lctrSlvCisCigContOp(BbOpDesc_t *pOp); void lctrSlvCisCigPostSubEvt(BbOpDesc_t *pOp, uint8_t status); uint32_t lctrSlvCisCheckContOp(BbOpDesc_t *pOp, bool_t *pNewCisCtx); +uint32_t lctrSlvCisCheckContOpPostCback(BbOpDesc_t *pOp, bool_t *pNewCisCtx); void lctrSlvCisCigEndOp(BbOpDesc_t *pOp); void lctrSlvCisCigCleanupOp(BbOpDesc_t *pOp); void lctrSlvCisCigAbortOp(BbOpDesc_t *pOp); diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_conn.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_conn.h index dce8cd882e..6c738f53fd 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_conn.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_conn.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -67,25 +67,13 @@ extern "C" { /*! \brief Resolve connection context from the handle. */ #define LCTR_GET_CONN_CTX(h) &(pLctrConnTbl[h]) -/*! \brief Resolve txPower from phy index. */ +/*! \brief Resolve txPower from PHY index. */ #define LCTR_GET_TXPOWER(pCtx, phy, option) \ (pCtx->phyTxPower[phy - (((phy == LL_PHY_LE_CODED) && (option == BB_PHY_OPTIONS_BLE_S2)) ? 0 : 1)]) /*! \brief Set the txpower of a specified PHY. */ #define LCTR_SET_TXPOWER(pCtx, phy, pow) (pCtx->phyTxPower[phy - 1] = pow) -/*! \brief Low threshold for power monitoring. */ -#define LCTR_RSSI_LOW_THRESHOLD -65 - -/*! \brief High threshold for power monitoring. */ -#define LCTR_RSSI_HIGH_THRESHOLD -30 - -/*! \brief Minimum time spent until request. */ -#define LCTR_PC_MIN_TIME 15 - -/*! \brief Default request of increase/decrease in value. */ -#define LCTR_PC_REQUEST_VAL 5 - /*! \brief Special reset terminate reason. */ #define LCTR_RESET_TERM_REASON 0xFF @@ -147,6 +135,8 @@ enum LCTR_PROC_CMN_SET_MIN_USED_CHAN, /*!< Set minimum number of used channels procedure. */ LCTR_PROC_CMN_PER_ADV_SYNC_TRSF, /*!< Periodic advertising sync transfer procedure. */ LCTR_PROC_CMN_REQ_PEER_SCA, /*!< Request peer SCA procedure. */ + LCTR_PROC_CMN_CH_CLASS_REPORTING, /*!< Channel classification reporting procedure. */ + LCTR_PROC_CMN_CH_STATUS_REPORT, /*!< Channel status reporting procedure. */ LCTR_PROC_CMN_TOTAL, /*!< Total number of common procedures. */ /* Custom SM LLCP procedures. */ @@ -162,6 +152,7 @@ enum LCTR_PROC_CIS_TERM_PEER, /*!< Peer-initiated CIS termination procedure. */ LCTR_PROC_PWR_IND, /*!< Power indication prodecure. */ LCTR_PROC_PWR_CTRL, /*!< Power control procedure. */ + LCTR_PROC_SUBRATE, /*!< Subrate procedure. */ LCTR_PROC_INVALID = 0xFF /*!< Invalid ID. */ @@ -225,11 +216,19 @@ typedef struct bool_t rxFromMaster; /*!< At least one successful packet received from master. */ uint32_t firstRxStartTsUsec; /*!< Timestamp of the first received frame regardless of CRC error in microseconds. */ + uint32_t lastStatusSentTs; /*!< Timestamp of last channel status update. */ + uint32_t chanStatMinIntUs; /*!< Minimum interval in us between channel status updates. */ + uint32_t chanStatMaxDelay; /*!< Max delay before a change of channel status is allowed to be sent. */ + uint32_t queuedChanStatusTs; /*!< Timestamp of last channel status that is queued to be sent out. */ } slv; /*!< Slave connection specific data. */ struct { bool_t sendConnUpdInd; /*!< Send LL_CONNECTION_UPDATE_IND flag. */ + uint8_t peerChannelStatus[LL_MAX_NUM_CHAN_DATA]; + /*!< Current channel status map of peer. */ + uint32_t recvdChanStatTs; /*!< Timestamp of last received channel status from peer. */ + uint32_t chanStatMinIntUs; /*!< Minimum interval in us between channel status updates. */ } mst; /*!< Master connection specific data. */ } data; /*!< Role specific data. */ @@ -264,6 +263,7 @@ typedef struct wsfQueue_t rxDataQ; /*!< Receive data pending queue. */ uint8_t numTxComp; /*!< Number of completed Tx buffers. */ uint8_t numRxPend; /*!< Number of Rx pending buffers. */ + uint8_t numTxPendCtrlPdu; /*!< Number of pending Control PDUs. */ bool_t emptyPduPend; /*!< Empty PDU ACK pending. */ bool_t emptyPduFirstAtt; /*!< Empty PDU first attempt. */ bool_t forceStartPdu; /*!< Next data will be forced to be a start PDU */ @@ -302,6 +302,7 @@ typedef struct bool_t remoteVerValid; /*!< Peer version data valid. */ lctrVerInd_t remoteVer; /*!< Peer version data. */ bool_t featExchFlag; /*!< Flag for completed feature exchange. */ + uint64_t peerFeatures; /*!< Peer reported features. */ uint64_t usedFeatSet; /*!< Used feature set. */ uint8_t peerSca; /*!< Peer SCA. */ @@ -310,6 +311,9 @@ typedef struct uint8_t peerApr[LL_PC_PHY_TOTAL]; /*!< Acceptable reduction of power as calculated by the peer. */ + /* Channel reporting parameters. */ + bool_t chanStatRptEnable; /*!< Enable status of channel status reporting. */ + /* Data length */ lctrDataLen_t localDataPdu; /*!< Local Data PDU parameters. */ lctrDataLen_t effDataPdu; /*!< Effective Data PDU parameters. */ @@ -332,7 +336,7 @@ typedef struct uint16_t perServiceData; /*!< ID for periodic sync indication. */ uint16_t perSyncHandle; /*!< Periodic sync handle. */ - /* PAST(Periodic advertising sync transfer) parameters. */ + /* PAST parameters. */ uint8_t syncMode; /*!< Sync transfer mode. */ uint16_t syncSkip; /*!< Sync skip for periodic adv sync transfer. */ uint16_t syncTimeout; /*!< Sync timeout for periodic adv sync transfer. */ @@ -342,6 +346,7 @@ typedef struct uint8_t encState; /*!< Current encryption state. */ uint8_t pingState; /*!< Current ping state. */ uint8_t connUpdState; /*!< Connection update state. */ + uint8_t ecuState; /*!< Enhanced connection update state. */ uint8_t phyUpdState; /*!< PHY update state. */ uint8_t cmnState; /*!< Common LLCP state. */ bool_t peerReplyWaiting; /*!< Peer waiting for reply. */ @@ -369,6 +374,7 @@ typedef struct uint8_t reqErrCode; /*!< LLCP error code. */ /* Power Control */ + wsfTimer_t tmrPowerCtrl; /*!< Power control monitor timer. */ int8_t delta; /*!< Power control delta storage. */ bool_t peerReqRecvd; /*!< Peer request received. */ uint8_t reqPhy; /*!< PHY of most recent power control request. */ @@ -381,10 +387,11 @@ typedef struct { struct { - int8_t highThreshold; /*!< High extreme RSSI threshold. */ - int8_t lowThreshold; /*!< Low extreme RSSI threshold. */ - uint8_t minTimeSpent; /*!< Minimum time spent in an extreme RSSI zone to trigger a request. */ - uint8_t curTimeSpent; /*!< Current time spent in an extreme RSSI zone. */ + int8_t highThreshold; /*!< High RSSI threshold. */ + int8_t lowThreshold; /*!< Low RSSI threshold. */ + uint8_t totalAccumulatedRssi; /*!< Total accumulated RSSI samples in current sample slot. */ + uint32_t accumulatedRssi; /*!< Absolute value of accumulated RSSI in current RSSI sample slot (RSSI can never be positive). */ + lctrRssiRunAvg_t rssiRunAvg; /*!< RSSI running average. */ uint8_t requestVal; /*!< Value of increase/decrease in power to request. */ } autoMonitor; /*!< Autonomous RSSI monitoring specific data. */ @@ -403,10 +410,43 @@ typedef struct } pclMonitorParam; /*!< Power control monitoring data. */ /* CIS */ - uint16_t llcpCisHandle; /*!< CIS handle for the LLCP procedure. */ - lctrCheckTermFn_t checkCisTerm; /*!< Pointer to the check CIS termination function. */ - lctrCheckCisEstAclFn_t checkCisEstAcl; /*!< Pointer to the check if CIS is established function. */ - uint8_t cisRssiExtremeTimeSpent; /*!< CIS's current time spent in an extreme zone. */ + uint16_t llcpCisHandle; /*!< CIS handle for the LLCP procedure. */ + lctrCheckTermFn_t checkCisTerm; /*!< Pointer to the check CIS termination function. */ + lctrCheckCisEstAclFn_t checkCisEstAcl; /*!< Pointer to the check if CIS is established function. */ + uint8_t cisRssiExtremeTimeSpent; /*!< CIS's current time spent in an extreme zone. */ + uint8_t cisTotalAccumulatedRssi; /*!< Total accumulated RSSI samples in current sample slot. */ + uint32_t cisAccumulatedRssi; /*!< Absolute value of accumulated RSSI in current RSSI sample slot (RSSI can never be positive). */ + lctrRssiRunAvg_t cisRunAvg; /*!< Running average of RSSI for CIS connection for power control. */ + + /* Enhanced Connection Update */ + struct + { + /* Default values. */ + uint16_t defSrMin; /*!< Subrate minimum value. */ + uint16_t defSrMax; /*!< Subrate maximum value. */ + uint16_t defMaxLatency; /*!< Maximum latency. */ + uint16_t defContNum; /*!< Continuation number. */ + uint16_t defSvt; /*!< Supervision timeout. */ + + /* Active values. */ + uint16_t srFactor; /*!< Active subrate factor. */ + uint16_t srBaseEvent; /*!< Subrate base event. */ + uint16_t contNum; /*!< Continuation number. */ + uint16_t svt; /*!< Supervision timeout. */ + uint16_t contNumCtr; /*!< Number of continuation number in subrate events. */ + + struct + { + uint16_t srFactor; /*!< Active subrate factor. */ + uint16_t srBaseEvent; /*!< Subrate base event. */ + uint16_t contNum; /*!< Continuation number. */ + uint16_t contNumCtr; /*!< Number of continuation number in subrate events. */ + uint16_t maxLatency; /*!< Maximum latency. */ + uint16_t svt; /*!< Supervision timeout. */ + } pending; + + bool_t isSubrateTransMode; /*!< True if central in subrate transition mode. */ + } ecu; /*!< Enhanced connection update parameters. */ } lctrConnCtx_t; /*! \brief Call signature of a cipher block handler. */ @@ -419,7 +459,7 @@ typedef bool_t (*lctrPktEncHdlr_t)(PalCryptoEnc_t *pEnc, uint8_t *pHdr, uint8_t typedef bool_t (*lctrPktDecHdlr_t)(PalCryptoEnc_t *pEnc, uint8_t *pBuf); /*! \brief Call signature of a set packet count handler. */ -typedef void (*lctrPktCntHdlr_t)(PalCryptoEnc_t *pEnc, uint64_t pktCnt); +typedef void (*lctrPktCntHdlr_t)(uint64_t pktCnt); /*! \brief Call signature of a LLCP state machine handler. */ typedef bool_t (*LctrLlcpHdlr_t)(lctrConnCtx_t *pCtx, uint8_t event); @@ -440,21 +480,31 @@ typedef void (*lctrPcMonAct_t)(lctrConnCtx_t *pCtx); typedef void (*lctrPcPowInd_t)(lctrConnCtx_t *pCtx, uint8_t phy, int8_t delta, int8_t txPower, bool_t phyChange); /*! \brief Call signature of power report notification handler. */ -typedef void (*lctrPcNotifyPwr_t)(lctrConnCtx_t *pCtx, uint8_t reason, uint8_t phy, int8_t txPower, uint8_t limits, int8_t delta); +typedef void (*lctrPcNotifyPwr_t)(lctrConnCtx_t *pCtx, uint8_t status, uint8_t reason, uint8_t phy, int8_t txPower, uint8_t limits, int8_t delta); /*! \brief Call signature of CIS pend disconnect function. */ typedef bool_t (*lctrPendCisDisc_t)(lctrConnCtx_t *pCtx); +/*! \brief Call signature of CIS power monitoring function. */ +typedef void (*lctrCisServicePowerMonitor_t)(lctrConnCtx_t *pCtx); + +/*! \brief Call signature of calculate number of subrated connection events. */ +typedef uint16_t (*lctrCalcSubrateConnEvents_t)(lctrConnCtx_t *pCtx, uint16_t numDataPdu); + +/*! \brief Call signature of check LLCP override. */ +typedef bool_t (*lctrCheckLlcpOverride_t)(lctrConnCtx_t *pCtx); + /*! \brief LLCP state machine handlers. */ enum { LCTR_LLCP_SM_ENCRYPT, /*!< Encryption LLCP state machine. */ LCTR_LLCP_SM_PING, /*!< Ping state machine. */ + LCTR_LLCP_SM_ENH_CONN_UPD, /*!< Enhanced connection update state machine. */ LCTR_LLCP_SM_CONN_UPD, /*!< Connection update state machine. */ LCTR_LLCP_SM_PHY_UPD, /*!< PHY update state machine. */ LCTR_LLCP_SM_CIS_EST, /*!< CIS establishment state machine. */ LCTR_LLCP_SM_CIS_TERM, /*!< CIS termination state machine. */ - LCTR_LLCP_SM_PC, /*!< Power control state machine. */ + LCTR_LLCP_SM_PC, /*!< Power control state machine. */ LCTR_LLCP_SM_CMN, /*!< Common LLCP state machine. */ LCTR_LLCP_SM_TOTAL /*!< Total number of LLCP state machine. */ }; @@ -480,9 +530,12 @@ extern lctrLlcpEh_t lctrSendPerSyncFromBcstFn; extern lctrLlcpEh_t lctrStorePeriodicSyncTrsfFn; extern lctrLlcpEh_t lctrSendPeriodicSyncIndFn; extern lctrLlcpEh_t lctrReceivePeriodicSyncIndFn; -extern lctrPcMonAct_t lctrPcActTbl[LCTR_PC_MONITOR_SCHEME_TOTAL]; +extern lctrPcMonAct_t lctrPathLossMonitorActFn; extern lctrPcPowInd_t lctrSendPowerChangeIndCback; extern lctrPcNotifyPwr_t lctrNotifyPowerReportIndCback; +extern lctrCisServicePowerMonitor_t lctrCisServicePowerMonitorFn; +extern lctrCalcSubrateConnEvents_t lctrCalcSubrateConnEventsFn; +extern lctrCheckLlcpOverride_t lctrSlvCheckEncOverridePhyUpdateFn; /************************************************************************************************** Function Declarations @@ -573,6 +626,12 @@ void lctrSendPeerScaRsp(lctrConnCtx_t *pCtx); void lctrStorePeerSca(lctrConnCtx_t *pCtx); void lctrNotifyHostPeerScaCnf(lctrConnCtx_t *pCtx); +/* Channel status reporting actions. */ +void lctrSendChannelStatusInd(lctrConnCtx_t *pCtx); +void lctrStoreChannelStatusInd(lctrConnCtx_t *pCtx); +void lctrSendChannelReportingInd(lctrConnCtx_t *pCtx); +void lctrStoreChannelReportingInd(lctrConnCtx_t *pCtx); + /* Unknown/Unsupported */ void lctrSendUnknownRsp(lctrConnCtx_t *pCtx); void lctrSendRejectInd(lctrConnCtx_t *pCtx, uint8_t reason, bool_t forceRejectExtInd); @@ -637,6 +696,9 @@ uint8_t lctrGetPowerLimits(int8_t txPower); /* Reservation */ uint32_t lctrGetConnRefTime(uint8_t connHandle, uint32_t *pDurUsec); +/* Channel map updating. */ +uint8_t lctrConnChClassUpdate(uint64_t chanMap); + /*************************************************************************************************/ /*! * \brief Set flags for link termination. @@ -749,11 +811,11 @@ static inline void lctrIncPacketCounterTx(lctrConnCtx_t *pCtx) /*************************************************************************************************/ static inline void lctrIncPacketCounterRx(lctrConnCtx_t *pCtx) { - if (lctrSetEncryptPktCountHdlr) + if (lctrSetDecryptPktCountHdlr) { PalCryptoEnc_t * const pEnc = &pCtx->bleData.chan.enc; - if ((pEnc->enaEncrypt) && + if ((pEnc->enaDecrypt) && (pEnc->nonceMode == PAL_BB_NONCE_MODE_PKT_CNTR)) { pCtx->rxPktCounter++; @@ -782,10 +844,10 @@ static inline void lctrSetBbPacketCounterTx(lctrConnCtx_t *pCtx) switch (pEnc->nonceMode) { case PAL_BB_NONCE_MODE_PKT_CNTR: - lctrSetEncryptPktCountHdlr(pEnc, pCtx->txPktCounter); + lctrSetEncryptPktCountHdlr(pCtx->txPktCounter); break; case PAL_BB_NONCE_MODE_EXT16_CNTR: - lctrSetEncryptPktCountHdlr(pEnc, pCtx->eventCounter); + lctrSetEncryptPktCountHdlr(pCtx->eventCounter); break; default: break; @@ -814,10 +876,10 @@ static inline void lctrSetBbPacketCounterRx(lctrConnCtx_t *pCtx) switch (pEnc->nonceMode) { case PAL_BB_NONCE_MODE_PKT_CNTR: - lctrSetDecryptPktCountHdlr(pEnc, pCtx->rxPktCounter); + lctrSetDecryptPktCountHdlr(pCtx->rxPktCounter); break; case PAL_BB_NONCE_MODE_EXT16_CNTR: - lctrSetDecryptPktCountHdlr(pEnc, pCtx->eventCounter); + lctrSetDecryptPktCountHdlr(pCtx->eventCounter); break; default: break; @@ -870,11 +932,11 @@ static inline void lctrStoreConnTimeoutTerminateReason(lctrConnCtx_t *pCtx) /*************************************************************************************************/ static inline void lctrDataTxIncAvailBuf(void) { - WSF_CS_INIT(); + WSF_CS_INIT(cs); - WSF_CS_ENTER(); + WSF_CS_ENTER(cs); lmgrConnCb.availTxBuf++; - WSF_CS_EXIT(); + WSF_CS_EXIT(cs); } /*************************************************************************************************/ @@ -884,11 +946,11 @@ static inline void lctrDataTxIncAvailBuf(void) /*************************************************************************************************/ static inline void lctrDataTxDecAvailBuf(void) { - WSF_CS_INIT(); + WSF_CS_INIT(cs); - WSF_CS_ENTER(); + WSF_CS_ENTER(cs); lmgrConnCb.availTxBuf--; - WSF_CS_EXIT(); + WSF_CS_EXIT(cs); } /*************************************************************************************************/ @@ -900,11 +962,11 @@ static inline void lctrDataTxDecAvailBuf(void) /*************************************************************************************************/ static inline void lctrDataRxIncAvailBuf(uint8_t numBufs) { - WSF_CS_INIT(); + WSF_CS_INIT(cs); - WSF_CS_ENTER(); + WSF_CS_ENTER(cs); lmgrConnCb.availRxBuf += numBufs; - WSF_CS_EXIT(); + WSF_CS_EXIT(cs); } /*************************************************************************************************/ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_iso.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_iso.h index 47ff93cb7c..9671b5c9e9 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_iso.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_iso.h @@ -82,23 +82,23 @@ typedef struct } lctrIsoTxBufDesc_t; /*! \brief Start stream call signature. */ -typedef bool_t (*lctrCodecStartStream)(uint16_t id, PalCodecSreamParam_t *pParam); +typedef bool_t (*lctrCodecStartStream)(uint16_t id, PalCodecStreamParam_t *pParam); /*! \brief Stop stream call signature. */ -typedef void (*lctrCodecStopStream)(uint16_t id); +typedef void (*lctrCodecStopStream)(uint16_t id, PalCodecDir_t dir); -/*! \brief Stream in data call signature. */ -typedef uint16_t (*lctrCodecStreamIn)(uint16_t id, uint8_t *pBuf, uint16_t len, uint32_t *pPktCtr); +/*! \brief Stream in data request call signature. */ +typedef void (*lctrCodecStreamInReq)(uint16_t id, uint8_t *pData, uint16_t len); /*! \brief Stream out data call signature. */ -typedef void (*lctrCodecStreamOut)(uint16_t id, const uint8_t *pBuf, uint16_t len, uint32_t pktCtr); +typedef void (*lctrCodecStreamOut)(uint16_t id, const uint8_t *pBuf, uint16_t len, uint32_t sduRef); /*! \brief Codec event handlers. */ typedef struct { lctrCodecStartStream start; /*!< Start stream. */ lctrCodecStopStream stop; /*!< Stop stream. */ - lctrCodecStreamIn in; /*!< Stream data input. */ + lctrCodecStreamInReq inReq; /*!< Stream data input request. */ lctrCodecStreamOut out; /*!< Stream data output. */ } lctrCodecHandlers_t; @@ -134,7 +134,7 @@ typedef struct { wsfQueue_t pendSduQ; /*!< Pending PDU fragments. */ uint16_t curLen; /*!< Current length of SDU being received. */ - uint8_t ps; /*!< Packet status. */ + lctrPktStatus_t ps:8; /*!< Packet status. */ } unframed; /*!< Unframed specific data. */ } data; /*!< Framing-specific data. */ } lctrIsoalRxCtx_t; @@ -142,30 +142,55 @@ typedef struct /*! \brief Input datapath context. */ typedef struct { - LlIsoDataPath_t id; /*!< Input data path ID. */ -} lctrInDataPathCtx_t; /*!< Input datapath configuration. */ + LlIsoDataPath_t id:8; /*!< Input data path ID. */ + + union + { + struct + { + uint16_t streamId; /*!< Stream ID. */ + } codec; /*!< Codec-specific configuration. */ + } cfg; /*!< Data path specific configuration. */ +} lctrInDataPathCtx_t; /*!< Input data path configuration. */ /*! \brief Output datapath context. */ typedef struct { - LlIsoDataPath_t id; /*!< Output data path ID. */ + LlIsoDataPath_t id:8; /*!< Output data path ID. */ union { struct { wsfQueue_t rxDataQ; /*!< Receive data pending queue. */ - uint8_t numRxPend; /*!< Number of messages pending in the RX queue. */ + uint8_t numRxPend; /*!< Number of messages pending in the Rx queue. */ } hci; /*!< HCI data path configuration. */ - } cfg; /*!< Datapath-specific configuration parameters. */ -} lctrOutDataPathCtx_t; /*!< Output datapath configuration. */ -/*! \brief Datapath context. */ + struct + { + wsfQueue_t rxDataQ; /*!< Receive data pending queue. */ + uint8_t numRxPend; /*!< Number of messages pending in the Rx queue. */ + uint16_t streamId; /*!< Stream ID. */ + } codec; /*!< Codec-specific configuration. */ + } cfg; /*!< Data path specific configuration parameters. */ +} lctrOutDataPathCtx_t; /*!< Output data path configuration. */ + +/*! \brief Data path context. */ typedef union { lctrInDataPathCtx_t in; /*!< Input context. */ lctrOutDataPathCtx_t out; /*!< Output context. */ -} lctrDataPathCtx_t; /*!< Datapath context collection. */ +} lctrDataPathCtx_t; /*!< Data path context collection. */ + +/*! \brief Data path setup parameters. */ +typedef struct +{ + uint16_t handle; /*!< ISO Handle. */ + uint32_t isoInt; /*!< ISO interval. */ + uint32_t pktCtr; /*!< Current packet counter. */ + uint8_t dpDir; /*!< Data path direction. */ + lctrDataPathCtx_t *pDataPathCtx; /*!< Data path context. */ +} lctrDpParams_t; /************************************************************************************************** Function Declarations @@ -179,15 +204,17 @@ void lctrNotifyHostIsoEventComplete(uint8_t handle, uint32_t evtCtr); /* ISO data path */ lctrIsoTxBufDesc_t *lctrAllocIsoTxBufDesc(void); void lctrFreeIsoTxBufDesc(lctrIsoTxBufDesc_t *pDesc); -uint8_t lctrSetupIsoDataPath( LlIsoSetupDataPath_t *pSetupDataPath, lctrDataPathCtx_t *pDataPathCtx); -void lctrIsoSendCodecSdu(uint16_t id); -bool_t lctrIsoRxConnEnq(lctrOutDataPathCtx_t *pOutDataPathCtx, uint16_t handle, uint8_t *pBuf); -void lctrIsoOutDataPathClear(lctrOutDataPathCtx_t *pOutCtx); +uint8_t lctrIsoSetupDataPath(lctrDpParams_t *pDpParam, LlIsoSetupDataPath_t *pSetupDataPath); +void lctrIsoSendCodecSdu(uint16_t id, uint32_t pktCtr, uint32_t ts, uint8_t *pData, uint16_t actLen); +bool_t lctrIsoRxConnEnq(lctrOutDataPathCtx_t *pOutDataPathCtx, uint16_t handle, uint32_t pktCtr, uint8_t *pBuf); +void lctrIsoInDataPathClear(lctrDpParams_t *pDpParam); +void lctrIsoOutDataPathClear(lctrDpParams_t *pDpParam); void lctrIsoalRxDataPathClear(lctrIsoalRxCtx_t *pRxCtx, uint8_t framing); -void lctrIsoOutDataPathSetup(lctrOutDataPathCtx_t *pOutCtx); +uint8_t lctrIsoInDataPathSetup(lctrDpParams_t *pDpParam, LlIsoSetupDataPath_t *pSetupDataPath); +uint8_t lctrIsoOutDataPathSetup(lctrDpParams_t *pDpParam, LlIsoSetupDataPath_t *pSetupDataPath); uint8_t *lctrIsoRxConnDeq(lctrOutDataPathCtx_t *pOutCtx); -bool_t lctrIsoUnframedRxSduPendQueue(lctrIsoalRxCtx_t *pRxCtx, uint8_t *pSdu, uint16_t handle, - uint16_t dataLen, uint8_t llid); +uint8_t *lctrRxSduAlloc(void); +bool_t lctrRecombineRxUnframedSdu(lctrIsoalRxCtx_t *pRxCtx, uint8_t *pSduFrag); /* ISO Test mode. */ uint8_t *lctrGenerateIsoTestData(uint16_t handle, LlIsoPldType_t pldType, uint16_t maxSdu, uint32_t pktCtr); @@ -205,11 +232,11 @@ uint8_t *lctrTxIsoDataPduAlloc(void); /*************************************************************************************************/ static inline void lctrIsoSduTxIncAvailBuf(void) { - WSF_CS_INIT(); + WSF_CS_INIT(cs); - WSF_CS_ENTER(); + WSF_CS_ENTER(cs); lmgrIsoCb.availTxBuf++; - WSF_CS_EXIT(); + WSF_CS_EXIT(cs); } /*************************************************************************************************/ @@ -219,11 +246,11 @@ static inline void lctrIsoSduTxIncAvailBuf(void) /*************************************************************************************************/ static inline void lctrIsoSduTxDecAvailBuf(void) { - WSF_CS_INIT(); + WSF_CS_INIT(cs); - WSF_CS_ENTER(); + WSF_CS_ENTER(cs); lmgrIsoCb.availTxBuf--; - WSF_CS_EXIT(); + WSF_CS_EXIT(cs); } /*************************************************************************************************/ @@ -235,11 +262,11 @@ static inline void lctrIsoSduTxDecAvailBuf(void) /*************************************************************************************************/ static inline void lctrIsoDataRxIncAvailBuf(uint8_t numBufs) { - WSF_CS_INIT(); + WSF_CS_INIT(cs); - WSF_CS_ENTER(); + WSF_CS_ENTER(cs); lmgrIsoCb.availRxBuf += numBufs; - WSF_CS_EXIT(); + WSF_CS_EXIT(cs); } /*************************************************************************************************/ @@ -249,11 +276,11 @@ static inline void lctrIsoDataRxIncAvailBuf(uint8_t numBufs) /*************************************************************************************************/ static inline void lctrIsoDataRxDecAvailBuf(void) { - WSF_CS_INIT(); + WSF_CS_INIT(cs); - WSF_CS_ENTER(); + WSF_CS_ENTER(cs); lmgrIsoCb.availRxBuf--; - WSF_CS_EXIT(); + WSF_CS_EXIT(cs); } #ifdef __cplusplus diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_pc.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_pc.h index 8127ddc50b..10c14d2add 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_pc.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_pc.h @@ -4,7 +4,7 @@ * * \brief Internal link layer controller power control interface file. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,25 +24,17 @@ #define LCTR_INT_PC_H #include "lctr_api.h" -#include "lctr_int_conn.h" +#include "lctr_int_conn_slave.h" +#include "lctr_int_conn_master.h" #ifdef __cplusplus extern "C" { #endif -/************************************************************************************************** - External Constants -**************************************************************************************************/ - -/*! \brief Master LLCP state machine table. */ -extern LctrLlcpHdlr_t lctrMstLlcpSmTbl[LCTR_LLCP_SM_TOTAL]; - -/*! \brief Slave LLCP state machine table. */ -extern LctrLlcpHdlr_t lctrSlvLlcpSmTbl[LCTR_LLCP_SM_TOTAL]; - /************************************************************************************************* * Function Declarations *************************************************************************************************/ + uint8_t lctrCalcPathLossZone(lctrConnCtx_t *pCtx); void lctrNotifyHostPathLossRpt(lctrConnCtx_t *pCtx); void lctrPathLossMonitorAct(lctrConnCtx_t *pCtx); @@ -59,10 +51,10 @@ void lctrSendPeerPowerControlRsp(lctrConnCtx_t *pCtx); void lctrStorePeerPowerControlRsp(lctrConnCtx_t *pCtx); /* Power monitoring actions. */ -void lctrAutoPowerMonitorAct(lctrConnCtx_t *pCtx); +void lctrConnServicePowerMonitor(lctrConnCtx_t *pCtx); /* Power reporting actions. */ -void lctrNotifyPowerReportInd(lctrConnCtx_t *pCtx, uint8_t reason, uint8_t phy, int8_t txPower, uint8_t limits, int8_t delta); +void lctrNotifyPowerReportInd(lctrConnCtx_t *pCtx, uint8_t status, uint8_t reason, uint8_t phy, int8_t txPower, uint8_t limits, int8_t delta); int8_t lctrAttemptTxPowerChange(lctrConnCtx_t *pCtx, uint8_t phy, int8_t delta); void lctrSendPowerChangeInd(lctrConnCtx_t *pCtx, uint8_t phy, int8_t delta, int8_t txPower, bool_t phyChange); diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_slave_phy.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_slave_phy.h index 73a86c037c..77fe86ec4e 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_slave_phy.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_slave_phy.h @@ -6,7 +6,7 @@ * * Copyright (c) 2016-2017 ARM Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,6 +50,8 @@ void lctrSendPhyUpdateIndPdu(lctrConnCtx_t *pCtx, uint8_t txPhys, uint8_t rxPhys void lctrNotifyHostPhyUpdateInd(lctrConnCtx_t *pCtx, uint8_t status); +bool_t lctrSlvCheckEncOverridePhyUpdate(lctrConnCtx_t *pCtx); + #ifdef __cplusplus }; #endif diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_master_ae.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_master_ae.c index eae1d815e7..9fada0d100 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_master_ae.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_master_ae.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ #include "lctr_api_bis_master.h" #include "sch_api.h" #include "sch_api_ble.h" +#include "bb_ble_api_op.h" #include "bb_ble_api_reslist.h" #include "bb_ble_api_whitelist.h" #include "bb_ble_api_periodiclist.h" @@ -879,6 +880,40 @@ bool_t lctrMstDiscoverRxExtAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf return txScanReq; } +/*************************************************************************************************/ +/*! + * \brief Check if an Aux Scan should be programmed ASAP because of a too small auxOffset. + * + * \param pBod Originating operation. + * \param refTime Refference time in microseconds + * \param remScanDur Remaining scan duration in microseconds + * + * \return TRUE if Aux Scan was programmed, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lctrMstLinkAuxOffsetScanSetup(BbOpDesc_t *pBod, uint32_t refTime, uint32_t remScanDur) +{ + bool_t result = FALSE; + lctrExtScanCtx_t * const pExtScanCtx = pBod->pCtx; + BbOpDesc_t * const pAuxBod = &pExtScanCtx->auxScanBod; + + if (pExtScanCtx->scheduleAuxAsap == TRUE) + { + pExtScanCtx->scheduleAuxAsap = FALSE; + + /* Check if Aux Scan can be programmed in the remaining Ext Scan duration. */ + if (BbGetTargetTimeDelta(pAuxBod->dueUsec + pAuxBod->minDurUsec, refTime) < remScanDur) + { + /* The Aux Scan will run in the context of the Ext Scan BOD. */ + pBod->prot.pBle->op.mstAdv.auxScanBod = pAuxBod; + BbMstExecuteLinkedAuxScanOp(pAuxBod, &pExtScanCtx->auxBleData); + result = TRUE; + } + } + + return result; +} + /*************************************************************************************************/ /*! * \brief Extended scan discover state advertising packet receive (primary channel) @@ -947,12 +982,6 @@ void lctrMstDiscoverRxExtAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t else { /* Delay Non-connectable and non-scannable with auxiliary packet PDU filtering in the AUX_ADV_IND.*/ - lctrMstExtScanIsr.advAReceived = FALSE; - lctrMstExtScanIsr.tgtAReceived = FALSE; - lctrMstExtScanIsr.advA = 0; - lctrMstExtScanIsr.tgtA = 0; - lctrMstExtScanIsr.advARand = 0; - lctrMstExtScanIsr.tgtARand = 0; /* Retrieve advA and tgtA if present. */ if (extAdvHdrFlags & LL_EXT_HDR_ADV_ADDR_BIT) @@ -961,12 +990,25 @@ void lctrMstDiscoverRxExtAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t lctrMstExtScanIsr.advA = pExtScanCtx->extAdvHdr.advAddr; lctrMstExtScanIsr.advARand = advHdr.txAddrRnd; } + else + { + lctrMstExtScanIsr.advAReceived = FALSE; + lctrMstExtScanIsr.advA = 0; + lctrMstExtScanIsr.advARand = 0; + } + if (extAdvHdrFlags & LL_EXT_HDR_TGT_ADDR_BIT) { lctrMstExtScanIsr.tgtAReceived = TRUE; lctrMstExtScanIsr.tgtA = pExtScanCtx->extAdvHdr.tgtAddr; lctrMstExtScanIsr.tgtARand = advHdr.rxAddrRnd; } + else + { + lctrMstExtScanIsr.tgtAReceived = FALSE; + lctrMstExtScanIsr.tgtA = 0; + lctrMstExtScanIsr.tgtARand = 0; + } } } /* else case, delay connectable and scannable PDU filtering in the AUX_ADV_IND. */ @@ -1201,98 +1243,7 @@ bool_t lctrMstDiscoverRxAuxAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf /* Continue processing for sync establishment filter even when scan filtering failed. */ } - /*** Periodic advertising event filtering. ***/ - bool_t advAMatch = FALSE; - uint64_t peerIdAddr = 0; - uint8_t peerIdAddrType = 0; - - BbBlePduFiltResultsGetPeerIdAddr(&pAuxScan->filtResults, &peerIdAddr, &peerIdAddrType); - - if ((lctrPerCreateSync.state == LCTR_CREATE_SYNC_STATE_DISCOVER) && - (lctrMstPerScanIsr.filtResult == FALSE)) - { - if ((lctrPerCreateSync.filtParam.advSID != pExtScanCtx->extAdvHdr.sid) || - (lctrPerCreateSync.filtParam.advAddrType != (peerIdAddrType & LL_ADDR_RANDOM_BIT)) || - (lctrPerCreateSync.filtParam.advAddr != peerIdAddr)) - { - /* Address type, address or SID does not match. */ - lctrMstPerScanIsr.filtResult = TRUE; - } - } - - if ((lctrPerCreateSync.state == LCTR_CREATE_SYNC_STATE_DISCOVER) && - (lctrMstPerScanIsr.filtResult == TRUE) && - (lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_ADI_BIT) && - ((lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_ADV_ADDR_BIT) || - (lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_SYNC_INFO_BIT))) - { - if (lctrPerCreateSync.filtParam.filterPolicy == LL_PER_SCAN_FILTER_PL_BIT) - { - if ((BbBlePeriodicListCheckAddr((peerIdAddrType & LL_ADDR_RANDOM_BIT), peerIdAddr, - pExtScanCtx->extAdvHdr.sid)) == FALSE) - { - /* Not in the periodic list. */ - break; - } - else - { - lctrMstPerScanIsr.filtResult = FALSE; - advAMatch = TRUE; - } - } - else - { - if ((lctrPerCreateSync.filtParam.advSID != pExtScanCtx->extAdvHdr.sid) || - (lctrPerCreateSync.filtParam.advAddrType != (peerIdAddrType & LL_ADDR_RANDOM_BIT)) || - (lctrPerCreateSync.filtParam.advAddr != peerIdAddr)) - { - /* Address type, address or SID does not match. */ - break; - } - else - { - lctrMstPerScanIsr.filtResult = FALSE; - advAMatch = TRUE; - } - } - } - - if (pExtScanCtx->extAdvHdr.extHdrFlags & LL_EXT_HDR_SYNC_INFO_BIT) - { - lctrUnpackSyncInfo(&pExtScanCtx->secSyncInfo, pExtScanCtx->extAdvHdr.pSyncInfo); - } - - if ((lctrPerCreateSync.state == LCTR_CREATE_SYNC_STATE_DISCOVER) && - (lctrMstPerScanIsr.filtResult == FALSE) && - (pExtScanCtx->extAdvHdr.extHdrFlags & LL_EXT_HDR_SYNC_INFO_BIT) && - lctrPerCreateSync.createSyncPending == FALSE) - { - lctrPerScanCtx_t *pPerScanCtx = lctrPerCreateSync.pPerScanCtx; - /*** Save peer periodic advertising parameters. ***/ - pPerScanCtx->eventCounter = pExtScanCtx->secSyncInfo.eventCounter; - pPerScanCtx->initEventCounter = pExtScanCtx->secSyncInfo.eventCounter; - pPerScanCtx->perInterUsec = LCTR_PER_INTER_TO_US(pExtScanCtx->secSyncInfo.syncInter); - pPerScanCtx->sca = pExtScanCtx->secSyncInfo.sca; - pPerScanCtx->rxPhys = lctrConvertAuxPtrPhyToBbPhy(pExtScanCtx->priChAuxPtr.auxPhy); - pPerScanCtx->skipInterUsec = pPerScanCtx->perInterUsec * pPerScanCtx->skip; - - if (advAMatch == TRUE) - { - /* AdvA is received in the aux_adv_ind and pass the filtering, save info in the context. */ - pPerScanCtx->advAddr = peerIdAddr; - pPerScanCtx->advAddrType = peerIdAddrType; - pPerScanCtx->advSID = pExtScanCtx->extAdvHdr.sid; - - /* Address to be used for sync transfer. */ - pPerScanCtx->trsfAdvAddr = pExtScanCtx->extAdvHdr.advAddr; - pPerScanCtx->trsfAddrType = lctrMstExtScanIsr.advHdr.txAddrRnd; - } - - uint32_t endTs = pAuxScan->auxStartTsUsec + - SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, pAuxScan->auxRxPhyOptions, pAuxScan->txAuxReqLen); - lctrMstPerScanOpCommit(pExtScanCtx, &pExtScanCtx->priChAuxPtr, &pExtScanCtx->secSyncInfo, pAuxScan->auxStartTsUsec, endTs); - lctrMstPerScanIsr.syncWithSlave = FALSE; - } + /*** Periodic advertising event filtering done in post process. ***/ break; } @@ -1398,6 +1349,131 @@ bool_t lctrMstDiscoverRxAuxAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf return txScanReq; } +/*************************************************************************************************/ +/*! + * \brief Auxiliary scan discover state advertising packet receive + * post process handler. + * + * \param pOp Originating operation. + * \param pAdvBuf Received advertising buffer. + * + */ +/*************************************************************************************************/ +void lctrMstDiscoverRxAuxAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf) +{ + WSF_ASSERT(pOp->protId == BB_PROT_BLE); + WSF_ASSERT(pOp->prot.pBle->chan.opType == BB_BLE_OP_MST_AUX_ADV_EVENT); + + BbBleData_t * const pBle = pOp->prot.pBle; + BbBleMstAuxAdvEvent_t * const pAuxScan = &pBle->op.mstAuxAdv; + lctrExtScanCtx_t * pExtScanCtx = pOp->pCtx; + + /*** Periodic advertising event filtering. ***/ + + switch (lctrMstExtScanIsr.advHdr.pduType) + { + case LL_PDU_AUX_ADV_IND: + { + bool_t advAMatch = FALSE; + uint64_t peerIdAddr = 0; + uint8_t peerIdAddrType = 0; + + BbBlePduFiltResultsGetPeerIdAddr(&pAuxScan->filtResults, &peerIdAddr, &peerIdAddrType); + + if ((lctrPerCreateSync.state == LCTR_CREATE_SYNC_STATE_DISCOVER) && + (lctrMstPerScanIsr.filtResult == FALSE)) + { + if ((lctrPerCreateSync.filtParam.advSID != pExtScanCtx->extAdvHdr.sid) || + (lctrPerCreateSync.filtParam.advAddrType != (peerIdAddrType & LL_ADDR_RANDOM_BIT)) || + (lctrPerCreateSync.filtParam.advAddr != peerIdAddr)) + { + /* Address type, address or SID does not match. */ + lctrMstPerScanIsr.filtResult = TRUE; + } + } + + if ((lctrPerCreateSync.state == LCTR_CREATE_SYNC_STATE_DISCOVER) && + (lctrMstPerScanIsr.filtResult == TRUE) && + (lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_ADI_BIT) && + ((lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_ADV_ADDR_BIT) || + (lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_SYNC_INFO_BIT))) + { + if (lctrPerCreateSync.filtParam.filterPolicy == LL_PER_SCAN_FILTER_PL_BIT) + { + if ((BbBlePeriodicListCheckAddr((peerIdAddrType & LL_ADDR_RANDOM_BIT), peerIdAddr, + pExtScanCtx->extAdvHdr.sid)) == FALSE) + { + /* Not in the periodic list. */ + break; + } + else + { + lctrMstPerScanIsr.filtResult = FALSE; + advAMatch = TRUE; + } + } + else + { + if ((lctrPerCreateSync.filtParam.advSID != pExtScanCtx->extAdvHdr.sid) || + (lctrPerCreateSync.filtParam.advAddrType != (peerIdAddrType & LL_ADDR_RANDOM_BIT)) || + (lctrPerCreateSync.filtParam.advAddr != peerIdAddr)) + { + /* Address type, address or SID does not match. */ + break; + } + else + { + lctrMstPerScanIsr.filtResult = FALSE; + advAMatch = TRUE; + } + } + } + + if (pExtScanCtx->extAdvHdr.extHdrFlags & LL_EXT_HDR_SYNC_INFO_BIT) + { + lctrUnpackSyncInfo(&pExtScanCtx->secSyncInfo, pExtScanCtx->extAdvHdr.pSyncInfo); + } + + if ((lctrPerCreateSync.state == LCTR_CREATE_SYNC_STATE_DISCOVER) && + (lctrMstPerScanIsr.filtResult == FALSE) && + (pExtScanCtx->extAdvHdr.extHdrFlags & LL_EXT_HDR_SYNC_INFO_BIT) && + lctrPerCreateSync.createSyncPending == FALSE) + { + lctrPerScanCtx_t *pPerScanCtx = lctrPerCreateSync.pPerScanCtx; + /* Save peer periodic advertising parameters. */ + pPerScanCtx->eventCounter = pExtScanCtx->secSyncInfo.eventCounter; + pPerScanCtx->initEventCounter = pExtScanCtx->secSyncInfo.eventCounter; + pPerScanCtx->perInterUsec = LCTR_PER_INTER_TO_US(pExtScanCtx->secSyncInfo.syncInter); + pPerScanCtx->sca = pExtScanCtx->secSyncInfo.sca; + pPerScanCtx->rxPhys = lctrConvertAuxPtrPhyToBbPhy(pExtScanCtx->priChAuxPtr.auxPhy); + pPerScanCtx->skipInterUsec = pPerScanCtx->perInterUsec * pPerScanCtx->skip; + + if (advAMatch == TRUE) + { + /* AdvA is received in the aux_adv_ind and pass the filtering, save info in the context. */ + pPerScanCtx->advAddr = peerIdAddr; + pPerScanCtx->advAddrType = peerIdAddrType; + pPerScanCtx->advSID = pExtScanCtx->extAdvHdr.sid; + + /* Address to be used for sync transfer. */ + pPerScanCtx->trsfAdvAddr = pExtScanCtx->extAdvHdr.advAddr; + pPerScanCtx->trsfAddrType = lctrMstExtScanIsr.advHdr.txAddrRnd; + } + + uint32_t endTs = pAuxScan->auxStartTsUsec + + SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, pAuxScan->auxRxPhyOptions, pAuxScan->txAuxReqLen); + lctrMstPerScanOpCommit(pExtScanCtx, &pExtScanCtx->priChAuxPtr, &pExtScanCtx->secSyncInfo, pAuxScan->auxStartTsUsec, endTs); + lctrMstPerScanIsr.syncWithSlave = FALSE; + } + break; + } + + default: + LL_TRACE_WARN1("Received advertising PDU with invalid PDU type=%u", lctrMstExtScanIsr.advHdr.pduType); + lctrMstExtScanIsr.filtResult = TRUE; + } +} + /*************************************************************************************************/ /*! * \brief Master auxiliary scan response receive completion handler. @@ -1969,6 +2045,10 @@ void lctrMstExtDiscoverEndOp(BbOpDesc_t *pOp) return; } + /* Clear Aux Scan BOD link. */ + pExtScanCtx->scanBleData.op.mstAdv.auxScanOpRunning = FALSE; + pExtScanCtx->scanBleData.op.mstAdv.auxScanBod = NULL; + WSF_ASSERT(pOp->protId == BB_PROT_BLE); WSF_ASSERT(pOp->prot.pBle->chan.opType == BB_BLE_OP_MST_ADV_EVENT); @@ -2102,7 +2182,7 @@ void lctrMstPerScanEndOp(BbOpDesc_t *pOp) skip = 1; } - uint16_t numUnsyncIntervals = pPerScanCtx->eventCounter - pPerScanCtx->lastActiveEvent; + uint16_t numUnsyncIntervals = pPerScanCtx->eventCounter - pPerScanCtx->lastActiveEvent; while (TRUE) { @@ -2156,6 +2236,8 @@ void lctrMstPerScanAbortOp(BbOpDesc_t *pOp) { lctrPerScanCtx_t * const pPerScanCtx = pOp->pCtx; + LL_TRACE_WARN2("!!! Periodic Scan BOD aborted, syncHandle=%u, eventCounter=%u", LCTR_GET_PER_SCAN_HANDLE(pPerScanCtx), pPerScanCtx->eventCounter); + pPerScanCtx->bodAborted = TRUE; lctrMstPerScanEndOp(pOp); } @@ -2179,6 +2261,23 @@ uint32_t lctrMstPerScanRxPerAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBu BbBleData_t * const pBle = pOp->prot.pBle; lctrPerScanCtx_t * const pPerScanCtx = pOp->pCtx; + switch (status) + { + case BB_STATUS_SUCCESS: + break; + case BB_STATUS_CRC_FAILED: + LL_TRACE_WARN3("lctrMstPerScanRxPerAdvPktHandler: BB failed with status=CRC_FAILED, syncHandle=%u, bleChan=%u, eventCounter=%u", LCTR_GET_PER_SCAN_HANDLE(pPerScanCtx), pBle->chan.chanIdx, pPerScanCtx->eventCounter); + break; + case BB_STATUS_RX_TIMEOUT: + LL_TRACE_WARN3("lctrMstPerScanRxPerAdvPktHandler: BB failed with status=RX_TIMEOUT, syncHandle=%u, bleChan=%u, eventCounter=%u", LCTR_GET_PER_SCAN_HANDLE(pPerScanCtx), pBle->chan.chanIdx, pPerScanCtx->eventCounter); + break; + case BB_STATUS_FAILED: + LL_TRACE_WARN3("lctrMstPerScanRxPerAdvPktHandler: BB failed with status=FAILED, syncHandle=%u, bleChan=%u, eventCounter=%u", LCTR_GET_PER_SCAN_HANDLE(pPerScanCtx), pBle->chan.chanIdx, pPerScanCtx->eventCounter); + break; + default: + break; + } + /* BB_STATUS_RX_TIMEOUT or BB_STATUS_CRC_FAILED with pAdvBuf NULL. */ if (pAdvBuf == NULL) { @@ -2216,7 +2315,7 @@ uint32_t lctrMstPerScanRxPerAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBu lctrMstPerScanIsr.syncWithSlave = TRUE; } - /*** ACAD processing. ***/ + /*** ACAD processing ***/ lctrMstAcadHandler(pPerScanCtx); @@ -2242,7 +2341,20 @@ uint32_t lctrMstPerScanRxPerAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBu } } - /*** Periodic Advertising Data processing. ***/ + /*** ADI Filtering. ***/ + + if (pPerScanCtx->dupFilterEnable && (lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_ADI_BIT)) + { + /* Duplicate data; do not listen further. */ + if (pPerScanCtx->extAdvHdr.did == pPerScanCtx->lastDid) + { + return 0; + } + + /* pPerScanCtx->lastDid = pPerScanCtx->extAdvHdr.did; */ /* Done in lctrMstPerScanRxPerAdvPktPostHandler() */ + } + + /*** Periodic Advertising Data processing ***/ uint32_t auxOffsetUsec = 0; if (lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_AUX_PTR_BIT) @@ -2278,6 +2390,20 @@ bool_t lctrMstPerScanRxPerAdvPktPostHandler(BbOpDesc_t *pOp, const uint8_t *pAdv if (pPerScanCtx->state == LCTR_PER_SCAN_STATE_SYNC_ESTD) { WsfTimerStartMs(&pPerScanCtx->tmrSupTimeout, pPerScanCtx->syncTimeOutMs); + + if (pPerScanCtx->dupFilterEnable) + { + if (lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_ADI_BIT) + { + /* Received this data before, do not listen further. */ + if (pPerScanCtx->extAdvHdr.did == pPerScanCtx->lastDid) + { + return FALSE; + } + + pPerScanCtx->lastDid = pPerScanCtx->extAdvHdr.did; + } + } } /* BB_STATUS_RX_TIMEOUT or BB_STATUS_CRC_FAILED with pAdvBuf NULL. */ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_slave_ae.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_slave_ae.c index 69db9834b3..a41612f961 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_slave_ae.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_slave_ae.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -476,7 +476,6 @@ bool_t lctrSlvRxAuxConnReqHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf) pAdvSet->rspPduHdr.txAddrRnd = (hdr >> LCTR_ADV_HDR_TX_ADD_SHIFT) & 0x0001; pAdvSet->rspPduHdr.rxAddrRnd = (hdr >> LCTR_ADV_HDR_RX_ADD_SHIFT) & 0x0001; - } #endif @@ -696,19 +695,16 @@ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp) /* Disable (do not reschedule) advertising PDU. */ pAdvSet->shutdown = TRUE; - if (pAdvSet->auxBodUsed && - (pAdvSet->bodTermCnt++ == 0)) + if (pAdvSet->auxBodUsed) { + pAdvSet->auxBodUsed = FALSE; /* Ensure all BODs are de-scheduled. */ - bool_t result = SchRemove(&pAdvSet->auxAdvBod); + SchRemove(&pAdvSet->auxAdvBod); + } + + /* Last BOD to terminate; send terminate event. */ + lctrSendAdvSetMsg(pAdvSet, LCTR_EXT_ADV_MSG_TERMINATE); - (void)result; - } - else - { - /* Last BOD to terminate; send terminate event. */ - lctrSendAdvSetMsg(pAdvSet, LCTR_EXT_ADV_MSG_TERMINATE); - } return; } while (FALSE); @@ -728,18 +724,23 @@ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp) if ((pAdvSet->param.advEventProp & LL_ADV_EVT_PROP_LEGACY_ADV_BIT) == 0) { - /* Update superior PDU including AdvA and TgtA. */ - pAdv->txAdvLen = lctrPackAdvExtIndPdu(pAdvSet, pAdvSet->advHdrBuf, FALSE); + bool_t modified = pAdvSet->advData.alt.ext.modified; - if (pAdvSet->advData.alt.ext.modified && - !pAdvSet->auxBodUsed) + /* Update ADV set before building the PDU. */ + if (pAdvSet->advData.alt.ext.modified) { pAdvSet->advData.alt.ext.modified = FALSE; memcpy(pAdvSet->advData.pBuf, pAdvSet->advData.alt.ext.buf, pAdvSet->advData.alt.ext.len); pAdvSet->advData.len = pAdvSet->advData.alt.ext.len; pAdvSet->param.advDID = pAdvSet->advData.alt.ext.did; pAdvSet->advData.fragPref = pAdvSet->advData.alt.ext.fragPref; + } + /* Update superior PDU including AdvA and TgtA. */ + pAdv->txAdvLen = lctrPackAdvExtIndPdu(pAdvSet, pAdvSet->advHdrBuf, FALSE); + + if (modified && !pAdvSet->auxBodUsed) + { /* Advertising offloading to auxiliary channel. */ if (pAdvSet->pExtAdvAuxPtr) { @@ -912,11 +913,6 @@ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp) uint32_t totalDuration = pOp->minDurUsec; uint32_t prefIntervalUsec; - if (lmgrGetOpFlag(LL_OP_MODE_FLAG_ENA_ADV_DLY)) - { - pOp->dueUsec += BB_BLE_TO_US(lctrCalcAdvDelay()); - } - if (pAdvSet->auxBodUsed) { totalDuration += pAdvSet->auxAdvBod.minDurUsec; @@ -928,10 +924,16 @@ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp) if (pAdvSet->advBodAbort) { pAdvSet->advBodAbort = FALSE; - (void)SchInsertEarlyAsPossible(pOp, 0, LCTR_SCH_MAX_SPAN); + SchInsertNextAvailable(pOp); } else { + if (lmgrGetOpFlag(LL_OP_MODE_FLAG_ENA_ADV_DLY)) + { + pOp->dueUsec += BB_BLE_TO_US(lctrCalcAdvDelay()); + } + + /* Scheduling must succeed with LCTR_SCH_MAX_SPAN. */ (void)SchInsertEarlyAsPossible(pOp, prefIntervalUsec, LCTR_SCH_MAX_SPAN); } } @@ -986,18 +988,12 @@ void lctrSlvAuxAdvEndOp(BbOpDesc_t *pOp) pAdvSet->shutdown = TRUE; pAdvSet->auxBodUsed = FALSE; - if (pAdvSet->bodTermCnt++ == 0) - { - /* Ensure all BODs are de-scheduled. */ - bool_t result = SchRemove(&pAdvSet->advBod); + /* Ensure all BODs are de-scheduled. */ + SchRemove(&pAdvSet->advBod); + + /* Last BOD to terminate; send terminate event. */ + lctrSendAdvSetMsg(pAdvSet, LCTR_EXT_ADV_MSG_TERMINATE); - (void)result; /* It is possible to fail to remove BOD when BOD is not in the list(scheduling conflict) or there is not enough time to remove the BOD. */ - } - else - { - /* Last BOD to terminate; send terminate event. */ - lctrSendAdvSetMsg(pAdvSet, LCTR_EXT_ADV_MSG_TERMINATE); - } return; } while (FALSE); @@ -1107,6 +1103,7 @@ void lctrSlvPeriodicAdvEndOp(BbOpDesc_t *pOp) pAdvSet->perAdvData.alt.ext.modified = FALSE; memcpy(pAdvSet->perAdvData.pBuf, pAdvSet->perAdvData.alt.ext.buf, pAdvSet->perAdvData.alt.ext.len); pAdvSet->perAdvData.len = pAdvSet->perAdvData.alt.ext.len; + pAdvSet->perParam.advDID = pAdvSet->perAdvData.alt.ext.did; } /*** Update operation ***/ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_bis_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_bis_master.c index d253b87311..9b3d4d10b1 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_bis_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_bis_master.c @@ -4,7 +4,7 @@ * * \brief Link layer controller master BIG ISR callbacks. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,6 +43,9 @@ static struct uint8_t *pCtrlBuf; /*!< Received BIS Control PDU buffer. */ uint8_t *pDataBuf[LL_MAX_BIS][LL_MAX_BN]; /*!< Received data buffers. */ + uint8_t numRxPdus[LL_MAX_BIS]; + /*!< Number of successfully received packets for each BIS. */ + uint8_t curChanIdx; /*!< Current channel index. */ } lctrMstBisIsr; /************************************************************************************************** @@ -54,42 +57,86 @@ static struct * \brief Update loop counters for sequential packing. * * \param pBigCtx BIG context. + * \param pReAcqTrain Returns TRUE if re-acquisition is required, unchanged otherwise. * * \return TRUE if more Rx pending, FALSE otherwise. */ /*************************************************************************************************/ -static bool_t lctrMstBisLoopCounterSequential(lctrBigCtx_t *pBigCtx) +static bool_t lctrMstBisLoopCounterSequential(lctrBigCtx_t *pBigCtx, bool_t *pReAcqTrain) { - size_t numSePkts = (pBigCtx->bn * pBigCtx->irc) + lctrMstBisIsr.se.ptIdx; + int numSkipSe = -1; + PalBbBleChan_t *pCurChan = NULL; + uint32_t curSeOffs; - /* BIG Event limit (beyond BIS Control SubEvent). */ - - if (lctrMstBisIsr.se.bisEvtIdx >= pBigCtx->numBis) + do { - return FALSE; - } + numSkipSe++; + uint8_t numSeIntervals = 1; - if (!lctrSlvBisCalcNextIdxSequential(pBigCtx, &lctrMstBisIsr.se, numSePkts)) - { - if (!lctrMstBisIsr.cstf) + unsigned int numSePkts = (pBigCtx->bn * pBigCtx->irc) + lctrMstBisIsr.se.ptIdx; + + /* BIG Event limit (beyond BIS Control SubEvent). */ + + if (lctrMstBisIsr.se.bisEvtIdx >= pBigCtx->numBis) { return FALSE; } - } - /* Compute next channel. */ - lctrSeCtx_t nextSe = lctrMstBisIsr.se; - if (lctrSlvBisCalcNextIdxSequential(pBigCtx, &nextSe, numSePkts)) - { - lctrMstBisIsr.pNextChan = &pBigCtx->pBisCtx[nextSe.bisEvtIdx]->chan; - } - else - { - lctrMstBisIsr.pNextChan = &pBigCtx->ctrChan; - } + if (!lctrBisCalcNextIdxSequential(pBigCtx, &lctrMstBisIsr.se, numSePkts)) + { + if (!lctrMstBisIsr.cstf) + { + return FALSE; + } + } - /* Compute next packet time. */ - lctrMstBisIsr.nextSeOffs += pBigCtx->subInterUsec; + if (lctrMstBisIsr.se.bisEvtIdx < pBigCtx->numBis) + { + /* Compute next channel. */ + pCurChan = lctrMstBisIsr.pNextChan; + lctrSeCtx_t nextSe = lctrMstBisIsr.se; + while (TRUE) + { + if (lctrBisCalcNextIdxSequential(pBigCtx, &nextSe, numSePkts)) + { + if (pBigCtx->pBisCtx[nextSe.bisEvtIdx] == NULL) + { + /* Filtered BIS. */ + numSeIntervals++; + continue; + } + + WSF_ASSERT(pBigCtx->pBisCtx[nextSe.bisEvtIdx] != NULL); + lctrMstBisIsr.pNextChan = &pBigCtx->pBisCtx[nextSe.bisEvtIdx]->chan; + } + else + { + lctrMstBisIsr.pNextChan = &pBigCtx->ctrChan; + } + + break; + } + } + + /* Compute next packet time. */ + curSeOffs = lctrMstBisIsr.nextSeOffs; + lctrMstBisIsr.nextSeOffs += pBigCtx->subInterUsec * numSeIntervals; + + if (lmgrGetOpFlag(LL_OP_MODE_FLAG_ENA_BIS_RECV_DUP)) + { + /* Always receive duplicates. */ + break; + } + + /* Skip SE if data already received; do not receive duplicates. */ + } while (lctrMstBisIsr.pDataBuf[lctrMstBisIsr.se.bisEvtIdx][lctrMstBisIsr.se.burstIdx] != NULL); + + if ((numSkipSe > 0) && pCurChan) + { + /* Re-acquire the receive train. */ + BbBleBisRxDataReAcq(pBigCtx->roleData.mst.anchorPoint + pBigCtx->roleData.mst.firstBisOffsUsec + curSeOffs, pCurChan); + *pReAcqTrain = TRUE; + } return TRUE; } @@ -99,42 +146,69 @@ static bool_t lctrMstBisLoopCounterSequential(lctrBigCtx_t *pBigCtx) * \brief Update loop counters for interleaved packing. * * \param pBigCtx BIG context. + * \param pReAcqTrain Returns TRUE if re-acquisition is required, unchanged otherwise. * * \return TRUE if more Rx pending, FALSE otherwise. */ /*************************************************************************************************/ -static bool_t lctrMstBisLoopCounterInterleaved(lctrBigCtx_t *pBigCtx) +static bool_t lctrMstBisLoopCounterInterleaved(lctrBigCtx_t *pBigCtx, bool_t *pReAcqTrain) { - size_t numSePkts = (pBigCtx->bn * pBigCtx->irc) + lctrMstBisIsr.se.ptIdx; + int numSkipSe = -1; + PalBbBleChan_t *pCurChan; + uint32_t curSeOffs; - /* BIG Event limit (beyond BIS Control SubEvent). */ - - if (numSePkts > pBigCtx->nse) + do { - return FALSE; - } + numSkipSe++; - if (!lctrSlvBisCalcNextIdxInterleaved(pBigCtx, &lctrMstBisIsr.se, numSePkts)) - { - if (!lctrMstBisIsr.cstf) + unsigned int numSePkts = (pBigCtx->bn * pBigCtx->irc) + lctrMstBisIsr.se.ptIdx; + + /* BIG Event limit (beyond BIS Control SubEvent). */ + + if (numSePkts > pBigCtx->nse) { return FALSE; } - } - /* Compute next channel. */ - lctrSeCtx_t nextSe = lctrMstBisIsr.se; - if (lctrSlvBisCalcNextIdxInterleaved(pBigCtx, &nextSe, numSePkts)) - { - lctrMstBisIsr.pNextChan = &pBigCtx->pBisCtx[nextSe.bisEvtIdx]->chan; - } - else - { - lctrMstBisIsr.pNextChan = &pBigCtx->ctrChan; - } + if (!lctrBisCalcNextIdxInterleaved(pBigCtx, &lctrMstBisIsr.se, numSePkts)) + { + if (!lctrMstBisIsr.cstf) + { + return FALSE; + } + } - /* Compute next packet time. */ - lctrMstBisIsr.nextSeOffs += pBigCtx->bisSpaceUsec; + /* Compute next channel. */ + pCurChan = lctrMstBisIsr.pNextChan; + curSeOffs = lctrMstBisIsr.nextSeOffs; + lctrSeCtx_t nextSe = lctrMstBisIsr.se; + if (lctrBisCalcNextIdxInterleaved(pBigCtx, &nextSe, numSePkts)) + { + lctrMstBisIsr.pNextChan = &pBigCtx->pBisCtx[nextSe.bisEvtIdx]->chan; + } + else + { + lctrMstBisIsr.pNextChan = &pBigCtx->ctrChan; + } + + /* Compute next packet time. */ + lctrMstBisIsr.nextSeOffs += pBigCtx->bisSpaceUsec; + + if (lmgrGetOpFlag(LL_OP_MODE_FLAG_ENA_BIS_RECV_DUP)) + { + /* Always receive duplicates. */ + break; + } + + /* Skip SE if data already received; do not receive duplicates. */ + } while (lctrMstBisIsr.pDataBuf[lctrMstBisIsr.se.bisEvtIdx][lctrMstBisIsr.se.burstIdx] != NULL); + + if (numSkipSe > 0) + { + /* Re-acquire the receive train. */ + BbBleBisRxDataReAcq(pBigCtx->roleData.mst.anchorPoint + pBigCtx->roleData.mst.firstBisOffsUsec + curSeOffs, pCurChan); + *pReAcqTrain = TRUE; + } return TRUE; } @@ -161,18 +235,47 @@ static bool_t lctrMstBisRxData(lctrBigCtx_t *pBigCtx, bool_t reAcqSync, uint8_t return FALSE; } - /*** Commit transmission ***/ + /*** Commit reception ***/ - lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[lctrMstBisIsr.se.bisEvtIdx]; - BbBleBisRxData(pBuf, LL_ISO_DATA_HDR_LEN + BB_DATA_PLD_MAX_LEN, - pBigCtx->roleData.mst.anchorPoint + lctrMstBisIsr.nextSeOffs, + /* Set the inline decryption packet counter. */ + if (pBigCtx->encrypt && lctrSetDecryptPktCountHdlr) + { + uint64_t pktCtr; + + /* Check if this is the control subevent. */ + if (lctrMstBisIsr.pNextChan == &pBigCtx->ctrChan) + { + /* Set packet counter to the bisPayloadCounter of the first subevent. */ + pktCtr = pBigCtx->eventCounter * pBigCtx->bn; + lctrSetDecryptPktCountHdlr(pktCtr); + } + else + { + /* Set packet counter to the current bisPayloadCounter. */ + pktCtr = (pBigCtx->eventCounter * pBigCtx->bn) + lctrMstBisIsr.se.burstIdx; + lctrSetDecryptPktCountHdlr(pktCtr); + } + } + + BbBleBisRxData(pBuf, LL_ISO_DATA_HDR_LEN + pBigCtx->maxPdu + (pBigCtx->encrypt ? LL_DATA_MIC_LEN : 0), + pBigCtx->roleData.mst.anchorPoint + pBigCtx->roleData.mst.firstBisOffsUsec + lctrMstBisIsr.nextSeOffs, lctrMstBisIsr.pNextChan, reAcqSync); /*** Post-commit calculation ***/ - /* Now that channel data is set in BB, compute next channel information. */ - pBisCtx->chan.chanIdx = LmgrSelectNextSubEvtChannel(&pBisCtx->chSelInfo); + if (lctrMstBisIsr.se.bisEvtIdx < pBigCtx->numBis) + { + lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[lctrMstBisIsr.se.bisEvtIdx]; + + if (pBisCtx && pBisCtx->enabled) + { + lctrMstBisIsr.curChanIdx = pBisCtx->chan.chanIdx; + + /* Now that channel data is set in BB, compute next channel information. */ + pBisCtx->chan.chanIdx = LmgrSelectNextSubEvtChannel(&pBisCtx->chSelInfo); + } + } return TRUE; } @@ -272,6 +375,7 @@ static void lctrMstBigControlPostProcess(lctrBigCtx_t *pBigCtx) } lctrBisRxIsoDataPduFree(lctrMstBisIsr.pCtrlBuf); + lctrMstBisIsr.pCtrlBuf = NULL; } /*************************************************************************************************/ @@ -314,7 +418,7 @@ static void lctrMstBigControlProcedureHandler(lctrBigCtx_t *pBigCtx) * \param rxEvtCtr Received event counter. */ /*************************************************************************************************/ -static void lctrMstBisRxDataPduHandler(lctrBigCtx_t *pBigCtx, uint32_t rxEvtCtr) +static void lctrMstBisRxDataPduHandler(lctrBigCtx_t *pBigCtx, uint32_t rxEvtCtr, uint32_t sduRef) { uint8_t numHandles = 0; uint16_t handles[LL_MAX_BIS] = { 0 }; @@ -322,20 +426,26 @@ static void lctrMstBisRxDataPduHandler(lctrBigCtx_t *pBigCtx, uint32_t rxEvtCtr) uint64_t pktCtrBase = rxEvtCtr * pBigCtx->bn; lctrIsoalRxCtx_t *pRxCtx; - for (unsigned int i = 0; i < pBigCtx->numBis; i++) + for (unsigned int bisIdx = 0; bisIdx < pBigCtx->numBis; bisIdx++) { - lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[i]; + lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[bisIdx]; + + if (pBisCtx == NULL) + { + /* Filtered BIS. */ + continue; + } + pRxCtx = &pBisCtx->roleData.mst.isoalRxCtx; - uint8_t *pDataPdu; - uint8_t pldCtrOffs; - - while ((pDataPdu = lctrBisDequeueRxDataPdu(pBisCtx, &pldCtrOffs)) != NULL) + for (uint8_t burstIdx = 0; burstIdx < pBigCtx->bn; burstIdx++) { - uint64_t pktCtr = pktCtrBase + pldCtrOffs; + uint8_t *pDataPdu = lctrBisDequeueRxDataPdu(pBisCtx, burstIdx); + + uint64_t pktCtr = pktCtrBase + burstIdx; pBisCtx->chan.enc.pRxPktCounter = &pktCtr; - if (lctrPktDecryptHdlr) + if (pDataPdu && lctrPktDecryptHdlr) { if (!lctrPktDecryptHdlr(&pBisCtx->chan.enc, pDataPdu)) { @@ -348,160 +458,268 @@ static void lctrMstBisRxDataPduHandler(lctrBigCtx_t *pBigCtx, uint32_t rxEvtCtr) if (pBisCtx->pBigCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED) { - /* Store payload offset for test transit. */ - pBisCtx->test.util.unframed.payloadOffset = pldCtrOffs; - - lctrBisDataPduHdr_t pduHdr; - lctrBisUnpackDataPduHdr(&pduHdr, pDataPdu); - - /*** Assemble ISO SDU ***/ - - uint8_t * const pIsoSdu = pDataPdu - LCTR_ISO_SDU_START_OFFSET; - - switch (pBisCtx->path) + if (pDataPdu) { - case LL_ISO_DATA_PATH_HCI: + /* Store payload offset for test transit. */ + pBisCtx->test.util.unframed.burstIdx = burstIdx; + + lctrBisDataPduHdr_t pduHdr; + lctrBisUnpackDataPduHdr(&pduHdr, pDataPdu); + + /*** Assemble ISO SDU ***/ + + uint8_t * const pIsoSdu = pDataPdu - LCTR_ISO_SDU_START_OFFSET; + + lctrIsoHdr_t isoHdr = { - lctrIsoHdr_t isoHdr = - { - /* ISO header */ - .handle = pBisCtx->handle, - .len = pduHdr.len, - /* .pb = 0, */ /* assigned below */ - .tsFlag = FALSE, + /* ISO header */ + .handle = pBisCtx->handle, + .len = pduHdr.len, + /* .pb = 0, */ /* assigned below */ + .tsFlag = FALSE, - /* Data load */ - .ts = 0, - .pktSn = pktCtr, - .sduLen = pduHdr.len, - .ps = LCTR_PS_VALID - }; + /* Data load */ + .ts = sduRef, + .pktSn = pktCtr, + .sduLen = pduHdr.len, + .ps = LCTR_PS_VALID + }; - if (pBigCtx->lastPduMissed) - { - pRxCtx->data.unframed.ps = LCTR_PS_INVALID; - } - - switch (pBisCtx->lastLlid) + switch (pBisCtx->lastLlid) + { + case LL_LLID_ISO_UNF_END_PDU: { + switch (pduHdr.llid) + { case LL_LLID_ISO_UNF_END_PDU: - { - switch (pduHdr.llid) - { - case LL_LLID_ISO_UNF_END_PDU: - default: - isoHdr.pb = LCTR_PB_COMP; - isoHdr.tsFlag = TRUE; - break; - case LL_LLID_ISO_UNF_CONT_PDU: - isoHdr.pb = LCTR_PB_FIRST; - isoHdr.tsFlag = TRUE; - break; - } - break; - } - case LL_LLID_ISO_UNF_CONT_PDU: - { - switch (pduHdr.llid) - { - case LL_LLID_ISO_UNF_END_PDU: - default: - isoHdr.pb = LCTR_PB_LAST; - break; - case LL_LLID_ISO_UNF_CONT_PDU: - isoHdr.pb = LCTR_PB_CONT; - break; - } - break; - } default: - LL_TRACE_WARN2("Unexpected LLID recieved; dropping Rx ISO PDU, bigHandle=%u, pktCtr[15:0]=%u", pBigCtx->handle, pktCtr); - WsfMsgFree(pIsoSdu); - continue; - } - - pBisCtx->lastLlid = pduHdr.llid; - - uint8_t hdrLen; - hdrLen = lctrIsoPackHdr(pIsoSdu, &isoHdr); - /* Adjust SDU payload to start immediately after the header. */ - memmove(pIsoSdu + hdrLen, pDataPdu + LL_ISO_DATA_HDR_LEN, isoHdr.sduLen); - - /* Move to temporary queue to collect SDU fragments until complete. */ - if (!lctrIsoUnframedRxSduPendQueue(pRxCtx, pIsoSdu, pBisCtx->handle, isoHdr.sduLen, pduHdr.llid)) - { + isoHdr.pb = LCTR_PB_COMP; + isoHdr.tsFlag = TRUE; + isoHdr.ts = PalBbGetCurrentTime(); + break; + case LL_LLID_ISO_UNF_CONT_PDU: + isoHdr.pb = LCTR_PB_FIRST; + isoHdr.tsFlag = TRUE; + isoHdr.ts = PalBbGetCurrentTime(); + break; + } break; } - - /* Complete SDU ready to go out. Empty the temp queue and send it out. */ - uint8_t handlerId; - uint8_t *pSduFrag; - while ((pSduFrag = WsfMsgDeq(&pRxCtx->data.unframed.pendSduQ, &handlerId)) != NULL) + case LL_LLID_ISO_UNF_CONT_PDU: { - lctrBisRxIsoSduEnq(pBisCtx, pSduFrag); + switch (pduHdr.llid) + { + case LL_LLID_ISO_UNF_END_PDU: + default: + isoHdr.pb = LCTR_PB_LAST; + break; + case LL_LLID_ISO_UNF_CONT_PDU: + isoHdr.pb = LCTR_PB_CONT; + break; + } + break; + } + default: + LL_TRACE_WARN2("Unexpected LLID received; dropping Rx ISO PDU, bigHandle=%u, pktCtr[15:0]=%u", pBigCtx->handle, pktCtr); + WsfMsgFree(pIsoSdu); + continue; + } + + pBisCtx->lastLlid = pduHdr.llid; + + uint8_t hdrLen; + hdrLen = lctrIsoPackHdr(pIsoSdu, &isoHdr); + /* Adjust SDU payload to start immediately after the header. */ + /* TODO optimize memory layout, cf. lctrRecombineRxUnframedSdu(). */ + memmove(pIsoSdu + hdrLen, pDataPdu + LL_ISO_DATA_HDR_LEN, isoHdr.sduLen); + + /* Store fragment until complete fragment received. */ + if (!lctrRecombineRxUnframedSdu(pRxCtx, pIsoSdu)) + { + break; + } + + /* Deliver the SDU fragments. */ + uint8_t handlerId; + uint8_t *pSdu; + while ((pSdu = WsfMsgDeq(&pRxCtx->data.unframed.pendSduQ, &handlerId)) != NULL) + { + if (pBisCtx->test.enabled) /* In cases of test mode, queue it here. */ + { + lctrOutDataPathCtx_t *pOutDataPathCtx = &pBisCtx->roleData.mst.dataPathOutCtx; + WSF_ASSERT(pOutDataPathCtx->id != LL_ISO_DATA_PATH_VS); + + WsfMsgEnq(&pOutDataPathCtx->cfg.hci.rxDataQ, pBisCtx->handle, pSdu); + pOutDataPathCtx->cfg.hci.numRxPend++; + /* TODO optimize counter, accounting upon allocation. */ + lctrIsoDataRxDecAvailBuf(); + } + else if (lctrIsoRxConnEnq(&pBisCtx->roleData.mst.dataPathOutCtx, + pBisCtx->handle, pktCtr, pSdu)) + { + /* Implies HCI data path. */ numSdu[numHandles]++; } - break; + else + { + WsfMsgFree(pSdu); + } } + } + else /* (pDataPdu == NULL) */ + { + /* Indicate SDU has missing data. */ + pRxCtx->data.unframed.ps = LCTR_PS_INVALID; - case LL_ISO_DATA_PATH_VS: + /* End fragment lost. */ + if ((burstIdx + 1) == pBigCtx->bn) { - WSF_ASSERT(lctrCodecHdlr.out); - lctrCodecHdlr.out(pBisCtx->handle, pDataPdu + LL_ISO_DATA_HDR_LEN, pDataPdu[LCTR_ISO_DATA_PDU_LEN_OFFSET], pktCtr); - WsfMsgFree(pIsoSdu); /* TODO Resolve PDU free in Audio layer */ - break; - } + /* NULL signals lost PDU; release previously stored fragments. */ + if (lctrRecombineRxUnframedSdu(pRxCtx, NULL)) + { + /* Deliver the SDU fragments. */ + uint8_t handlerId; + uint8_t *pSdu; + while ((pSdu = WsfMsgDeq(&pRxCtx->data.unframed.pendSduQ, &handlerId)) != NULL) + { + if (pBisCtx->test.enabled) /* In cases of test mode, queue it here. */ + { + lctrOutDataPathCtx_t *pOutDataPathCtx = &pBisCtx->roleData.mst.dataPathOutCtx; + WSF_ASSERT(pOutDataPathCtx->id != LL_ISO_DATA_PATH_VS); - default: - { - LL_TRACE_WARN2("Data path disabled; dropping Rx ISO PDU, bigHandle=%u, pktCtr[15:0]=%u", pBigCtx->handle, pktCtr); - WsfMsgFree(pIsoSdu); - break; + WsfMsgEnq(&pOutDataPathCtx->cfg.hci.rxDataQ, pBisCtx->handle, pSdu); + pOutDataPathCtx->cfg.hci.numRxPend++; + /* TODO optimize counter, accounting upon allocation. */ + lctrIsoDataRxDecAvailBuf(); + } + else if (lctrIsoRxConnEnq(&pBisCtx->roleData.mst.dataPathOutCtx, + pBisCtx->handle, pktCtr, pSdu)) + { + /* Implies HCI data path. */ + numSdu[numHandles]++; + } + else + { + WsfMsgFree(pSdu); + } + } + } + else + { + if (lmgrGetOpFlag(LL_OP_MODE_FLAG_ENA_ISO_LOST_NOTIFY) && + (lctrMstBisIsr.numRxPdus[bisIdx] == 0)) + { + /* No prior fragments; send lost SDU. */ + uint8_t *pSdu = lctrBisRxIsoDataPduAlloc(); + + if (pSdu) + { + uint8_t *pIsoSdu = pSdu - LCTR_ISO_SDU_START_OFFSET; + lctrIsoHdr_t isoHdr = + { + /* ISO header */ + .handle = pBisCtx->handle, + .pb = LCTR_PB_COMP, + .tsFlag = FALSE, + .len = 0, + + /* Data load */ + .ts = sduRef, + .pktSn = pktCtr, + .sduLen = 0, + .ps = LCTR_PS_LOST + }; + + lctrIsoPackHdr(pIsoSdu, &isoHdr); + + if (pBisCtx->test.enabled) /* In cases of test mode, queue it here. */ + { + lctrOutDataPathCtx_t *pOutDataPathCtx = &pBisCtx->roleData.mst.dataPathOutCtx; + WSF_ASSERT(pOutDataPathCtx->id != LL_ISO_DATA_PATH_VS); + + WsfMsgEnq(&pOutDataPathCtx->cfg.hci.rxDataQ, pBisCtx->handle, pSdu); + pOutDataPathCtx->cfg.hci.numRxPend++; + /* TODO optimize counter, accounting upon allocation. */ + lctrIsoDataRxDecAvailBuf(); + } + else if (lctrIsoRxConnEnq(&pBisCtx->roleData.mst.dataPathOutCtx, + pBisCtx->handle, pktCtr, pIsoSdu)) + { + /* Implies HCI data path. */ + numSdu[numHandles]++; + } + else + { + WsfMsgFree(pIsoSdu); + } + } + else + { + LL_TRACE_WARN2("ISO SDU data flow controlled, lost SDU sync packet delivery failed, bigHandle=%u, pktCtr[15:0]=%u", pBigCtx->handle, pktCtr); + } + } + } } } } else /* LL_ISO_PDU_TYPE_FRAMED */ { - switch (pBisCtx->path) + if (pDataPdu) { - case LL_ISO_DATA_PATH_HCI: + switch (pBisCtx->roleData.mst.dataPathOutCtx.id) { - numSdu[numHandles] += lctrAssembleRxFramedSdu(&pBisCtx->roleData.mst.isoalRxCtx, &pBisCtx->roleData.mst.rxIsoSduQ, - pBisCtx->handle, pDataPdu, pDataPdu[LCTR_ISO_DATA_PDU_LEN_OFFSET]); - - break; - } - case LL_ISO_DATA_PATH_VS: - { - WSF_ASSERT(lctrCodecHdlr.out); - - lctrAssembleRxFramedSdu(&pBisCtx->roleData.mst.isoalRxCtx, &pBisCtx->roleData.mst.rxIsoSduQ, - pBisCtx->handle, pDataPdu, pDataPdu[LCTR_ISO_DATA_PDU_LEN_OFFSET]); - - uint8_t *pIsoBuf; - while ((pIsoBuf = lctrBisRxIsoSduDeq(pBisCtx)) != NULL) + case LL_ISO_DATA_PATH_HCI: { - lctrIsoHdr_t isoHdr; - lctrIsoUnpackHdr(&isoHdr, pIsoBuf); + numSdu[numHandles] += lctrAssembleRxFramedSdu(&pBisCtx->roleData.mst.isoalRxCtx, &pBisCtx->roleData.mst.dataPathOutCtx.cfg.hci.rxDataQ, + pBisCtx->handle, pDataPdu, pDataPdu[LCTR_ISO_DATA_PDU_LEN_OFFSET]); - lctrCodecHdlr.out(pBisCtx->handle, isoHdr.pSdu, isoHdr.sduLen, pktCtr); - WsfMsgFree(pIsoBuf); /* TODO Resolve PDU free in Audio layer */ + break; + } + case LL_ISO_DATA_PATH_VS: + { + WSF_ASSERT(lctrCodecHdlr.out); + + lctrAssembleRxFramedSdu(&pBisCtx->roleData.mst.isoalRxCtx, &pBisCtx->roleData.mst.dataPathOutCtx.cfg.codec.rxDataQ, + pBisCtx->handle, pDataPdu, pDataPdu[LCTR_ISO_DATA_PDU_LEN_OFFSET]); + + uint8_t *pIsoBuf; + while ((pIsoBuf = lctrBisRxIsoSduDeq(pBisCtx)) != NULL) + { + lctrIsoHdr_t isoHdr; + lctrIsoUnpackHdr(&isoHdr, pIsoBuf); + + lctrCodecHdlr.out(pBisCtx->handle, isoHdr.pSdu, isoHdr.sduLen, isoHdr.ts); + WsfMsgFree(pIsoBuf); + lctrIsoDataRxIncAvailBuf(1); + } + break; + } + default: + { + if (pBisCtx->test.enabled) + { + numSdu[numHandles] += lctrAssembleRxFramedSdu(&pBisCtx->roleData.mst.isoalRxCtx, &pBisCtx->roleData.mst.dataPathOutCtx.cfg.hci.rxDataQ, + pBisCtx->handle, pDataPdu, pDataPdu[LCTR_ISO_DATA_PDU_LEN_OFFSET]); + + break; + } + + LL_TRACE_WARN2("Data path disabled; dropping Rx ISO PDU, bigHandle=%u, pktCtr[15:0]=%u", pBigCtx->handle, pktCtr); + break; } - break; - } - default: - { - LL_TRACE_WARN2("Data path disabled; dropping Rx ISO PDU, bigHandle=%u, pktCtr[15:0]=%u", pBigCtx->handle, pktCtr); - break; } + lctrBisRxIsoDataPduFree(pDataPdu); + } + else /* (pDataPdu == NULL) */ + { + /* TODO Send NULL audio sync to ISOAL assembler */ } - lctrBisRxIsoDataPduFree(pDataPdu); } } if (numSdu[numHandles]) { - if (!pBisCtx->test.enabled) + if (!pBisCtx->test.enabled && (pBisCtx->roleData.mst.dataPathOutCtx.id != LL_ISO_DATA_PATH_VS)) { handles[numHandles] = pBisCtx->handle; numHandles++; @@ -513,7 +731,7 @@ static void lctrMstBisRxDataPduHandler(lctrBigCtx_t *pBigCtx, uint32_t rxEvtCtr) } } - if (numHandles) + if (lmgrPersistCb.recvIsoPendCback && numHandles) { /* Notify host received SDUs. */ lmgrPersistCb.recvIsoPendCback(numHandles, handles, numSdu); @@ -534,7 +752,13 @@ static void lctrMstBisRxTestPduHandler(lctrBigCtx_t *pBigCtx, uint32_t rxEvtCtr) { lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[i]; - /* Consume data for RX test. */ + if (pBisCtx == NULL) + { + /* Filtered BIS. */ + continue; + } + + /* Consume data for Rx test. */ if (pBisCtx->test.enabled) { if (!pBisCtx->test.term) @@ -557,13 +781,11 @@ static void lctrMstBisRxTestPduHandler(lctrBigCtx_t *pBigCtx, uint32_t rxEvtCtr) pBisCtx->test.pendInit = FALSE; } - LL_TRACE_INFO1("COUNTER = %d", pBisCtx->test.util.framed.payloadCtr); expPayloadCtr = pBisCtx->test.util.framed.payloadCtr++; } else /* LL_ISO_PDU_TYPE_UNFRAMED */ { - expPayloadCtr = (rxEvtCtr * pBigCtx->bn) + - pBisCtx->test.util.unframed.payloadOffset; + expPayloadCtr = (rxEvtCtr * pBigCtx->bn) + pBisCtx->test.util.unframed.burstIdx; } lctrValidateIsoTestData((uint8_t *)isoHdr.pSdu, isoHdr.sduLen, &pBisCtx->roleData.mst.stats, @@ -609,6 +831,10 @@ void lctrMstBisRxCompletion(BbOpDesc_t *pOp, uint8_t *pBuf, uint8_t status) if (status == BB_STATUS_SUCCESS) { lctrMstBisIsr.numRcvdPkt++; + lctrMstBisIsr.numRxPdus[lctrMstBisIsr.se.bisEvtIdx]++; + + /* Extra WW only needed for initial received packet. */ + pBigCtx->roleData.mst.initWwUsec = 0; } if (pBigCtx->state != LCTR_MST_BIG_STATE_SYNCED) @@ -619,11 +845,32 @@ void lctrMstBisRxCompletion(BbOpDesc_t *pOp, uint8_t *pBuf, uint8_t status) switch (status) { + case BB_STATUS_CRC_FAILED: + LL_TRACE_WARN3("BB failed with status=CRC_FAILED, bigHandle=%u, bleChan=%u, eventCounter=%u", pBigCtx->handle, lctrMstBisIsr.curChanIdx, pBigCtx->eventCounter); + LL_TRACE_WARN3(" bisEvtIdx=%u, burstIdx=%u, repIdx=%u", lctrMstBisIsr.se.bisEvtIdx, lctrMstBisIsr.se.burstIdx, lctrMstBisIsr.se.repIdx); + break; + + case BB_STATUS_RX_TIMEOUT: + LL_TRACE_WARN3("BB failed with status=RX_TIMEOUT, bigHandle=%u, bleChan=%u, eventCounter=%u", pBigCtx->handle, lctrMstBisIsr.curChanIdx, pBigCtx->eventCounter); + LL_TRACE_WARN3(" bisEvtIdx=%u, burstIdx=%u, repIdx=%u", lctrMstBisIsr.se.bisEvtIdx, lctrMstBisIsr.se.burstIdx, lctrMstBisIsr.se.repIdx); + break; + + case BB_STATUS_MIC_FAILED: + LL_TRACE_WARN2("lctrMstBisRxCompletion: BB failed with status MIC_FAILED Data/Control PDU received, bigHandle=%u", pBigCtx->handle, pBigCtx->eventCounter); + lctrMstBigSendMsg(pBigCtx, LCTR_MST_BIG_INT_MIC_FAILED); + BbSetBodTerminateFlag(); + goto RxPostProcess; + break; + case BB_STATUS_FAILED: + LL_TRACE_ERR3("BB failed with status=FAILED, bigHandle=%u, bleChan=%u, eventCounter=%u", pBigCtx->handle, lctrMstBisIsr.curChanIdx, pBigCtx->eventCounter); + LL_TRACE_ERR3(" bisEvtIdx=%u, burstIdx=%u, repIdx=%u", lctrMstBisIsr.se.bisEvtIdx, lctrMstBisIsr.se.burstIdx, lctrMstBisIsr.se.repIdx); + /* Fallthrough */ case BB_STATUS_CANCELED: /* Continue to next BIG Event. */ BbSetBodTerminateFlag(); goto RxPostProcess; + break; default: break; @@ -640,7 +887,7 @@ void lctrMstBisRxCompletion(BbOpDesc_t *pOp, uint8_t *pBuf, uint8_t status) case BB_STATUS_SUCCESS: case BB_STATUS_CRC_FAILED: /* Store peer's timing info for synchronizing next BIS Events and ISO Events. */ - pBigCtx->roleData.mst.anchorPoint = pBigCtx->roleData.mst.rxSyncTime = pBis->startTsUsec; + pBigCtx->roleData.mst.anchorPoint = pBigCtx->roleData.mst.rxSyncTime = pBis->startTsUsec - pBigCtx->roleData.mst.firstBisOffsUsec; break; default: @@ -682,10 +929,9 @@ void lctrMstBisRxCompletion(BbOpDesc_t *pOp, uint8_t *pBuf, uint8_t status) { case BB_STATUS_RX_TIMEOUT: /* Re-acquire the receive train. */ - BbBleBisRxDataReAcq(pBigCtx->roleData.mst.anchorPoint + lctrMstBisIsr.nextSeOffs, + BbBleBisRxDataReAcq(pBigCtx->roleData.mst.anchorPoint + pBigCtx->roleData.mst.firstBisOffsUsec + lctrMstBisIsr.nextSeOffs, lctrMstBisIsr.pNextChan); reAcqTrain = TRUE; - pBigCtx->lastPduMissed = TRUE; break; default: @@ -697,7 +943,7 @@ void lctrMstBisRxCompletion(BbOpDesc_t *pOp, uint8_t *pBuf, uint8_t status) switch (pBigCtx->packing) { case LL_PACKING_INTERLEAVED: - if (!lctrMstBisLoopCounterInterleaved(pBigCtx)) + if (!lctrMstBisLoopCounterInterleaved(pBigCtx, &reAcqTrain)) { /* Continue to next BIG Event. */ BbSetBodTerminateFlag(); @@ -707,7 +953,7 @@ void lctrMstBisRxCompletion(BbOpDesc_t *pOp, uint8_t *pBuf, uint8_t status) case LL_PACKING_SEQUENTIAL: default: - if (!lctrMstBisLoopCounterSequential(pBigCtx)) + if (!lctrMstBisLoopCounterSequential(pBigCtx, &reAcqTrain)) { /* Continue to next BIG Event. */ BbSetBodTerminateFlag(); @@ -742,7 +988,7 @@ RxPostProcess: } else if (hdr.cssn == pBigCtx->bcp.cssn) { - LL_TRACE_WARN1("Unexpected duplicate BIS Control PDU recieved, bigHandle=%u", pBigCtx->handle); + LL_TRACE_WARN1("Unexpected duplicate BIS Control PDU received, bigHandle=%u", pBigCtx->handle); } else { @@ -788,22 +1034,23 @@ void lctrMstBigBeginOp(BbOpDesc_t *pOp) } memset(&lctrMstBisIsr, 0, sizeof(lctrMstBisIsr)); + lctrMstBisIsr.se.bisEvtIdx = pBigCtx->roleData.mst.firstBisEvtIdx; /* Compute next packet time. */ + lctrMstBisIsr.pNextChan = NULL; switch (pBigCtx->packing) { case LL_PACKING_INTERLEAVED: if (pBigCtx->numBis > 1) { - lctrMstBisIsr.pNextChan = &pBigCtx->pBisCtx[1]->chan; + if (pBigCtx->roleData.mst.pSecondBisCtx) + { + lctrMstBisIsr.pNextChan = &pBigCtx->roleData.mst.pSecondBisCtx->chan; + } } else if (pBigCtx->nse > 1) { - lctrMstBisIsr.pNextChan = &pBigCtx->pBisCtx[0]->chan; - } - else - { - lctrMstBisIsr.pNextChan = &pBigCtx->ctrChan; + lctrMstBisIsr.pNextChan = &pBigCtx->roleData.mst.pFirstBisCtx->chan; } lctrMstBisIsr.nextSeOffs = pBigCtx->bisSpaceUsec; @@ -813,21 +1060,25 @@ void lctrMstBigBeginOp(BbOpDesc_t *pOp) default: if (pBigCtx->nse > 1) { - lctrMstBisIsr.pNextChan = &pBigCtx->pBisCtx[0]->chan; + lctrMstBisIsr.pNextChan = &pBigCtx->roleData.mst.pFirstBisCtx->chan; } else if (pBigCtx->numBis > 1) { - lctrMstBisIsr.pNextChan = &pBigCtx->pBisCtx[1]->chan; - } - else - { - lctrMstBisIsr.pNextChan = &pBigCtx->ctrChan; + if (pBigCtx->roleData.mst.pSecondBisCtx) + { + lctrMstBisIsr.pNextChan = &pBigCtx->roleData.mst.pSecondBisCtx->chan; + } } lctrMstBisIsr.nextSeOffs = pBigCtx->subInterUsec; break; } + if (lctrMstBisIsr.pNextChan == NULL) + { + lctrMstBisIsr.pNextChan = &pBigCtx->ctrChan; + } + lctrMstBisIsr.cstf = TRUE; /* receive Control PDU by default */ lctrMstBisIsr.cssn = 0xFF; @@ -838,6 +1089,26 @@ void lctrMstBigBeginOp(BbOpDesc_t *pOp) } } +/*************************************************************************************************/ +/*! + * \brief Abort a BIS operation. + * + * \param pOp Aborted operation. + */ +/*************************************************************************************************/ +void lctrMstBigAbortOp(BbOpDesc_t *pOp) +{ + WSF_ASSERT(pOp->protId == BB_PROT_BLE); + WSF_ASSERT(pOp->prot.pBle->chan.opType == BB_BLE_OP_MST_BIS_EVENT); + + LL_TRACE_WARN1("!!! BIG Synchronizer BOD aborted, eventCounter=%u", ((lctrBigCtx_t *)pOp->pCtx)->eventCounter); + + /* Clear state since abort is called without lctrMstBigBeginOp() initializing state. */ + memset(&lctrMstBisIsr, 0, sizeof(lctrMstBisIsr)); + + lctrMstBigEndOp(pOp); +} + /*************************************************************************************************/ /*! * \brief End a BIS operation. @@ -850,12 +1121,7 @@ void lctrMstBigEndOp(BbOpDesc_t *pOp) lctrBigCtx_t * const pBigCtx = pOp->pCtx; BbBleData_t * const pBle = &pBigCtx->bleData; BbBleMstBisEvent_t * const pBis = &pBle->op.mstBis; - if (pBigCtx->state != LCTR_MST_BIG_STATE_SYNCED) - { - lctrMstBigSendMsg(pBigCtx, LCTR_MST_BIG_INT_TERMINATED_SYNC); - WsfTimerStop(&pBigCtx->roleData.mst.bigSyncTmr); - return; - } + uint32_t sduRef = pBigCtx->roleData.mst.anchorPoint; /* Enqueue BIS Data PDUs. */ @@ -863,17 +1129,39 @@ void lctrMstBigEndOp(BbOpDesc_t *pOp) for (unsigned int bisIdx = 0; bisIdx < pBigCtx->numBis; bisIdx++) { - for (unsigned int bnIdx = 0; bnIdx < pBigCtx->bn; bnIdx++) + for (unsigned int burstIdx = 0; burstIdx < pBigCtx->bn; burstIdx++) { - if (lctrMstBisIsr.pDataBuf[bisIdx][bnIdx]) + if (lctrMstBisIsr.pDataBuf[bisIdx][burstIdx]) { - lctrBisEnqueueRxDataPdu(pBigCtx->pBisCtx[bisIdx], - lctrMstBisIsr.pDataBuf[bisIdx][bnIdx], - bnIdx); /* payload counter offset from rxEventCounter */ + if (pBigCtx->pBisCtx[bisIdx]) + { + lctrBisEnqueueRxDataPdu(pBigCtx->pBisCtx[bisIdx], + lctrMstBisIsr.pDataBuf[bisIdx][burstIdx], + burstIdx); + } + else + { + lctrBisRxIsoDataPduFree(lctrMstBisIsr.pDataBuf[bisIdx][burstIdx]); + } } } } + if (pBigCtx->state != LCTR_MST_BIG_STATE_SYNCED) + { + /* Terminate after PDUs are queued by lctrBisEnqueueRxDataPdu(). */ + lctrMstBigSendMsg(pBigCtx, LCTR_MST_BIG_INT_TERMINATED_SYNC); + WsfTimerStop(&pBigCtx->roleData.mst.bigSyncTmr); + + if (lctrMstBisIsr.pCtrlBuf) + { + lctrBisRxIsoDataPduFree(lctrMstBisIsr.pCtrlBuf); + lctrMstBisIsr.pCtrlBuf = NULL; + } + + return; + } + /* BIG Control procedure. */ if (lctrMstBisIsr.pCtrlBuf) @@ -884,6 +1172,7 @@ void lctrMstBigEndOp(BbOpDesc_t *pOp) } else { + /* No need to continue Rx process on MIC errors. */ goto RxPostProcess; } } @@ -907,10 +1196,10 @@ void lctrMstBigEndOp(BbOpDesc_t *pOp) unsyncTimeUsec += pBigCtx->isoInterUsec; uint32_t wwTotalUsec = lctrCalcWindowWideningUsec(unsyncTimeUsec, pBigCtx->roleData.mst.totalAcc) - + pBigCtx->roleData.mst.extraWwUsec; + + pBigCtx->roleData.mst.initWwUsec; /* TODO Limit to half the ISO Interval size */ - pOp->dueUsec = pBigCtx->roleData.mst.anchorPoint - wwTotalUsec; + pOp->dueUsec = pBigCtx->roleData.mst.anchorPoint + pBigCtx->roleData.mst.firstBisOffsUsec - wwTotalUsec; pBis->rxSyncDelayUsec = wwTotalUsec << 1; /* multiply 2 for before and after BIG Anchor Point */ lctrSelectBigChannels(pBigCtx); @@ -927,7 +1216,7 @@ void lctrMstBigEndOp(BbOpDesc_t *pOp) RxPostProcess: /* Consume ISO Data PDU. */ - lctrMstBisRxDataPduHandler(pBigCtx, rxEventCounter); + lctrMstBisRxDataPduHandler(pBigCtx, rxEventCounter, sduRef); lctrMstBisRxTestPduHandler(pBigCtx, rxEventCounter); if (lmgrCb.sendIsoCmplEvt) diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_bis_slave.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_bis_slave.c index fc86e93ebc..31ad09ac25 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_bis_slave.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_bis_slave.c @@ -120,12 +120,6 @@ static void lctrMstBigControlEncrypt(lctrBigCtx_t *pBigCtx) uint64_t pktCtr = pBigCtx->eventCounter * pBigCtx->bn; pBigCtx->ctrChan.enc.pTxPktCounter = &pktCtr; - /* Set the new packet counter for inline encryption. */ - if (lctrSetEncryptPktCountHdlr) - { - lctrSetEncryptPktCountHdlr(&pBigCtx->ctrChan.enc, pktCtr); - } - if (pBigCtx->encrypt && lctrPktEncryptHdlr) { uint16_t len = lctrSlvBisIsr.pCtrlBuf[LCTR_ISO_DATA_PDU_LEN_OFFSET]; @@ -174,6 +168,13 @@ static void lctrSlvBisTxControl(lctrBigCtx_t *pBigCtx) LCTR_BIS_WR_CSSN(desc.pBuf[LCTR_ISO_DATA_PDU_FC_OFFSET], pBigCtx->bcp.cssn); LCTR_BIS_CLR_CSTF(desc.pBuf[LCTR_ISO_DATA_PDU_FC_OFFSET]); + /* Set the control packet counter for inline encryption. */ + if (pBigCtx->encrypt && lctrSetEncryptPktCountHdlr) + { + uint64_t pktCtr = pBigCtx->eventCounter * pBigCtx->bn; + lctrSetEncryptPktCountHdlr(pktCtr); + } + BbBleBisTxData(&desc, 1, 0, NULL); } @@ -242,6 +243,13 @@ static void lctrSlvBisTxData(lctrBigCtx_t *pBigCtx) } #endif + /* set the inline encryption packet counter to the current bisPayloadCounter */ + if (pBigCtx->encrypt && lctrSetEncryptPktCountHdlr) + { + uint64_t pktCtr = (pBigCtx->eventCounter * pBigCtx->bn) + lctrSlvBisIsr.se.burstIdx; + lctrSetEncryptPktCountHdlr(pktCtr); + } + BbBleBisTxData(pTxDesc, descCnt, pBigCtx->bod.dueUsec + lctrSlvBisIsr.nextSeOffs, lctrSlvBisIsr.pNextChan); @@ -480,7 +488,7 @@ void lctrSlvBisTxCompletionSequential(BbOpDesc_t *pOp, uint8_t status) size_t numSePkts = (pBigCtx->bn * pBigCtx->irc) + lctrSlvBisIsr.se.ptIdx; - if (!lctrSlvBisCalcNextIdxSequential(pBigCtx, &lctrSlvBisIsr.se, numSePkts)) + if (!lctrBisCalcNextIdxSequential(pBigCtx, &lctrSlvBisIsr.se, numSePkts)) { if (lctrSlvBisIsr.pCtrlBuf) { @@ -495,13 +503,20 @@ void lctrSlvBisTxCompletionSequential(BbOpDesc_t *pOp, uint8_t status) /* Compute next channel. */ lctrSeCtx_t nextSe = lctrSlvBisIsr.se; - if (lctrSlvBisCalcNextIdxSequential(pBigCtx, &nextSe, numSePkts)) + if (lctrBisCalcNextIdxSequential(pBigCtx, &nextSe, numSePkts)) { lctrSlvBisIsr.pNextChan = &pBigCtx->pBisCtx[nextSe.bisEvtIdx]->chan; } else { - lctrSlvBisIsr.pNextChan = &pBigCtx->ctrChan; + if (lctrSlvBisIsr.pCtrlBuf == NULL) + { + lctrSlvBisIsr.pNextChan = NULL; + } + else + { + lctrSlvBisIsr.pNextChan = &pBigCtx->ctrChan; + } } /* Compute next packet time. */ @@ -542,7 +557,7 @@ void lctrSlvBisTxCompletionInterleaved(BbOpDesc_t *pOp, uint8_t status) /* BIS loop. */ - if (!lctrSlvBisCalcNextIdxInterleaved(pBigCtx, &lctrSlvBisIsr.se, numSePkts)) + if (!lctrBisCalcNextIdxInterleaved(pBigCtx, &lctrSlvBisIsr.se, numSePkts)) { if (lctrSlvBisIsr.pCtrlBuf) { @@ -558,13 +573,20 @@ void lctrSlvBisTxCompletionInterleaved(BbOpDesc_t *pOp, uint8_t status) /* Compute next channel. */ lctrSeCtx_t nextSe = lctrSlvBisIsr.se; - if (lctrSlvBisCalcNextIdxInterleaved(pBigCtx, &nextSe, numSePkts)) + if (lctrBisCalcNextIdxInterleaved(pBigCtx, &nextSe, numSePkts)) { lctrSlvBisIsr.pNextChan = &pBigCtx->pBisCtx[nextSe.bisEvtIdx]->chan; } else { - lctrSlvBisIsr.pNextChan = &pBigCtx->ctrChan; + if (lctrSlvBisIsr.pCtrlBuf == NULL) + { + lctrSlvBisIsr.pNextChan = NULL; + } + else + { + lctrSlvBisIsr.pNextChan = &pBigCtx->ctrChan; + } } /* Compute next packet time. */ @@ -724,10 +746,29 @@ void lctrSlvBigEndOp(BbOpDesc_t *pOp) LL_TRACE_WARN2("!!! BIG schedule conflict handle=%u, ec[15:0]=%u", pBigCtx->handle, pBigCtx->eventCounter); } - /* SDU generator. */ + /* SDU input. */ lctrSlvBisTxTestPayloadHandler(pBigCtx); + for (unsigned int i = 0; i < pBigCtx->numBis; i++) + { + lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[i]; + + if (pBisCtx->roleData.slv.dataPathInCtx.id == LL_ISO_DATA_PATH_VS) + { + uint8_t *pSduBuf; + if ((pSduBuf = WsfMsgAlloc(pLctrRtCfg->maxIsoSduLen + HCI_ISO_DL_MAX_LEN)) != NULL) + { + WSF_ASSERT(lctrCodecHdlr.inReq); + lctrCodecHdlr.inReq(pBisCtx->handle, pSduBuf + HCI_ISO_HDR_LEN + HCI_ISO_DL_MAX_LEN, pBigCtx->maxSdu); + } + else + { + LL_TRACE_WARN1("!!! Out of memory; dropping input SDU, handle=%u", pBisCtx->handle); + } + } + } + /* Update BIG Info. */ lctrAdvSet_t * const pAdvSet = pBigCtx->roleData.slv.pAdvSet; @@ -740,9 +781,13 @@ void lctrSlvBigEndOp(BbOpDesc_t *pOp) /* SDU queue maintenance. */ - if (pBigCtx->framing == LL_ISO_PDU_TYPE_FRAMED) + switch (pBigCtx->framing) { - lctrSlvCheckPendingSdu(pBigCtx); + case LL_ISO_PDU_TYPE_FRAMED: + lctrSlvCheckPendingSdu(pBigCtx); + break; + default: + break; } /* Notifications. */ @@ -765,7 +810,10 @@ void lctrSlvBigAbortOp(BbOpDesc_t *pOp) WSF_ASSERT(pOp->protId == BB_PROT_BLE); WSF_ASSERT(pOp->prot.pBle->chan.opType == BB_BLE_OP_SLV_BIS_EVENT); - LL_TRACE_WARN1("BIG BOD aborted, eventCounter=%u", ((lctrBigCtx_t *)pOp->pCtx)->eventCounter); + LL_TRACE_WARN1("!!! BIG Broadcaster BOD aborted, eventCounter=%u", ((lctrBigCtx_t *)pOp->pCtx)->eventCounter); + + /* Clear state since abort is called without lctrMstBigBeginOp() initializing state. */ + memset(&lctrSlvBisIsr, 0, sizeof(lctrSlvBisIsr)); lctrSlvBigEndOp(pOp); } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis.c index 4cec77a5df..11bb0ae1fb 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 ARM Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -120,9 +120,9 @@ bool_t lctrCisProcessRxAck(lctrCisCtx_t *pCisCtx) { bool_t result = FALSE; + /* Nulls must not be ACKed. */ if (pCisCtx->rxHdr.np == 1) { - /* NULL PDU doesn't need to be acked or processed.*/ return result; } @@ -141,7 +141,10 @@ bool_t lctrCisProcessRxAck(lctrCisCtx_t *pCisCtx) if ((pCisCtx->rxHdr.len) || ((pCisCtx->rxHdr.len == 0) && (pCisCtx->rxHdr.llid == LL_LLID_ISO_UNF_END_PDU))) { - /* lctrCisIncPacketCounterRx(pCisCtx) */ /* done after decryption in lctrCisRxPendingHandler */ + if (lctrSetDecryptPktCountHdlr) + { + lctrCisIncPacketCounterRx(pCisCtx); + } result = TRUE; } else /* Empty PDU. */ @@ -152,7 +155,10 @@ bool_t lctrCisProcessRxAck(lctrCisCtx_t *pCisCtx) /* length of 0 and LLID of LL_LLID_EMPTY_PDU implies padding/empty PDU. */ pCisCtx->txHdr.nesn++; - pCisCtx->rxFtParamList.pHead->ftParam.pduRcved = TRUE; + if (pCisCtx->rxFtParamList.pHead != NULL) + { + pCisCtx->rxFtParamList.pHead->ftParam.pduRcved = TRUE; + } return result; } @@ -191,10 +197,9 @@ void lctrCisTxPduAck(lctrCisCtx_t *pCisCtx) /*************************************************************************************************/ bool_t lctrCisProcessTxAck(lctrCisCtx_t *pCisCtx) { - if (((pCisCtx->rxHdr.nesn ^ pCisCtx->txHdr.sn) & 1) == 1) /* bits are different */ + if (((pCisCtx->rxHdr.nesn ^ pCisCtx->dataSn) & 1) == 1) /* bits are different */ { - pCisCtx->txHdr.sn++; - + pCisCtx->dataSn++; if (pCisCtx->txBufPendAck) { @@ -205,11 +210,13 @@ bool_t lctrCisProcessTxAck(lctrCisCtx_t *pCisCtx) else { /*** Peer ACK'ed an Empty PDU ***/ - pCisCtx->txDataCounter++; } - pCisCtx->txFtParamList.pHead->ftParam.pduAcked = TRUE; + if (pCisCtx->txFtParamList.pHead != NULL) + { + pCisCtx->txFtParamList.pHead->ftParam.pduAcked = TRUE; + } return TRUE; } @@ -276,6 +283,7 @@ uint16_t lctrCisSetupForTx(lctrCigCtx_t *pCigCtx, uint8_t rxStatus, bool_t reqTx pCisCtx->txHdr.np = 0; pCisCtx->txHdr.len = 0; pCisCtx->txHdr.llid = LL_LLID_ISO_UNF_END_PDU; + pCisCtx->txHdr.sn = pCisCtx->dataSn; if ((rxStatus != BB_STATUS_SUCCESS) || reqTx) @@ -312,6 +320,7 @@ uint16_t lctrCisSetupForTx(lctrCigCtx_t *pCigCtx, uint8_t rxStatus, bool_t reqTx bbDesc[0].pBuf[0] ^= llTesterCb.pktLlId & 0x03; #endif + lctrSetBbCisPacketCounterTx(pCisCtx); BbBleCisTxData(&bbDesc[0], bbDescCnt); numTxBytes = LL_DATA_HDR_LEN + bbDesc[0].pBuf[LCTR_ISO_DATA_PDU_LEN_OFFSET]; @@ -325,7 +334,10 @@ uint16_t lctrCisSetupForTx(lctrCigCtx_t *pCigCtx, uint8_t rxStatus, bool_t reqTx /*** Send Empty PDU ***/ lctrCisBuildEmptyPdu(pCisCtx); - pFtParam->pduType[pFtParam->pduCounter] = LCTR_CIS_PDU_EMPTY; + if (pFtParam != NULL) + { + pFtParam->pduType[pFtParam->pduCounter] = LCTR_CIS_PDU_EMPTY; + } PalBbBleTxBufDesc_t desc = {.pBuf = lctrCisIsr.emptyPdu, .len = sizeof(lctrCisIsr.emptyPdu)}; BbBleCisTxData(&desc, 1); @@ -347,12 +359,12 @@ uint16_t lctrCisSetupForTx(lctrCigCtx_t *pCigCtx, uint8_t rxStatus, bool_t reqTx /*************************************************************************************************/ void lctrCisRxPostProcessing(lctrCisCtx_t *pCisCtx, uint8_t *pRxBuf) { - if (pCisCtx->validRx) /* Another buffer ready to replace the received one. */ - { - lctrCisRxEnq(pRxBuf, pCisCtx->cisEvtCounter, pCisCtx->cisHandle); - } - else + if (!pCisCtx->validRx && (pRxBuf != NULL)) /* Another buffer ready to replace the received one. */ { lctrCisRxPduFree(pRxBuf); + pRxBuf = NULL; } + + /* Notify the task */ + lctrCisRxEnq(pRxBuf, pCisCtx->cisEvtCounter, pCisCtx->cisHandle); } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis_master.c index d970825935..8941d45a9d 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis_master.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -70,16 +70,28 @@ static void lctrMstCisInitIsr(lctrCisCtx_t *pCisCtx) pCisCtx->txDataCounter = 0; pCisCtx->rxDataCounter = 0; - pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter = 0; - pCisCtx->rxFtParamList.pHead->ftParam.subEvtCounter = 0; - - if (pCisCtx->txFtParamList.pHead->ftParam.bn == 0) + /* List may be empty if BN_S_To_M is 0 */ + if (pCisCtx->rxFtParamList.pHead != NULL) { - pCisCtx->isTxDone = TRUE; + pCisCtx->rxFtParamList.pHead->ftParam.subEvtCounter = 0; + } + + /* List may be empty if BN_M_To_S is 0 */ + if (pCisCtx->txFtParamList.pHead != NULL) + { + pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter = 0; + if (pCisCtx->txFtParamList.pHead->ftParam.bn == 0) + { + pCisCtx->isTxDone = TRUE; + } + else + { + pCisCtx->isTxDone = FALSE; + } } else { - pCisCtx->isTxDone = FALSE; + pCisCtx->isTxDone = TRUE; } /*** Setup for transmit ***/ @@ -115,7 +127,7 @@ static void lctrMstCisSetupRx(lctrCigCtx_t *pCigCtx, lctrCisCtx_t *pCisCtx) /*** Setup for receive ***/ - if ((pBuf = lctrCisRxPduAlloc(pCisCtx->localDataPdu.maxRxLen)) != NULL) + if ((pBuf = lctrCisRxPduAlloc()) != NULL) { #if (LL_ENABLE_TESTER) /* Invalidate access address if trigger is set. */ @@ -136,12 +148,13 @@ static void lctrMstCisSetupRx(lctrCigCtx_t *pCigCtx, lctrCisCtx_t *pCisCtx) } #endif + lctrSetBbCisPacketCounterRx(pCisCtx); BbBleCisRxData(pBuf, LCTR_CIS_DATA_PDU_LEN(pCisCtx->localDataPdu.maxRxLen)); /* Rx may fail; no more important statements in this code path */ } else { - LL_TRACE_ERR1("!!! OOM while initializing receive buffer at start of CE, cisHandle=%u", pCisCtx->cisHandle); + LL_TRACE_ERR2("!!! OOM while initializing receive buffer at start of CE, cisHandle=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->cisEvtCounter); BbSetBodTerminateFlag(); } } @@ -196,7 +209,7 @@ static void lctrCisCheckTxFtAfterRx(lctrCisCtx_t *pCisCtx) if (pFtParam->subEvtCounter == pFtParam->lastSubEvtFt[pFtParam->pduCounter]) { /* PDU needs to be flushed. */ - pCisCtx->txHdr.sn++; + pCisCtx->dataSn++; pFtParam->isPduDone[pFtParam->pduCounter] = TRUE; /* The PDU is done. */ if (pFtParam->pduType[pFtParam->pduCounter] == LCTR_CIS_PDU_NON_EMPTY) @@ -205,12 +218,17 @@ static void lctrCisCheckTxFtAfterRx(lctrCisCtx_t *pCisCtx) lctrCisTxPduAck(pCisCtx); pCisCtx->pduFlushed = TRUE; /* Set the flag, lctrCisProcessTxAckCleanup will be called to do the cleanup later in the lctrMstCisCigPostSubEvt. */ } - pFtParam->pduCounter++; + lctrCisIncPacketCounterTx(pCisCtx); pCisCtx->isoLinkQualStats.txUnAckPkt++; + pFtParam->pduCounter++; + } + else /* Implies that a retransmit will happen. */ + { + pCisCtx->isoLinkQualStats.retransmitPkt++; } } - else /* Implies that a retransmit will happen. */ + else { pCisCtx->isoLinkQualStats.retransmitPkt++; } @@ -253,12 +271,6 @@ static void lctrCisCheckRxFtAfterRx(lctrCisCtx_t *pCisCtx) return; } - if (pCisCtx->rxHdr.np) - { - /* NULL PDU doesn't need to be acked or flushed. */ - return; - } - lctrFtParam_t *pFtParam = &pCisCtx->rxFtParamList.pHead->ftParam; if (pFtParam->pduRcved) @@ -282,6 +294,11 @@ static void lctrCisCheckRxFtAfterRx(lctrCisCtx_t *pCisCtx) pCisCtx->isoalRxCtx.pduFlushed = TRUE; pCisCtx->isoalRxCtx.packetSequence++; pCisCtx->numRxMissed++; + if (pCisCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED) + { + /* Indicate SDU has missing data. */ + pCisCtx->isoalRxCtx.data.unframed.ps = LCTR_PS_INVALID; + } } } } @@ -317,12 +334,6 @@ static void lctrCisCheckTxFtAfterBod(lctrCisCtx_t *pCisCtx) return; } - if (pCisCtx->txHdr.np) - { - /* NULL PDU doesn't need to be acked or flushed. */ - return; - } - lctrFtParamNode_t *pNode = pCisCtx->txFtParamList.pHead; /* Increment interval counter for all the node in the list. */ @@ -340,7 +351,7 @@ static void lctrCisCheckTxFtAfterBod(lctrCisCtx_t *pCisCtx) pFtParam->intervalCounter == pFtParam->intervalTotal) /* Check if the PDU needs to be flush in this interval. */ { pFtParam->isPduDone[i] = TRUE; - pCisCtx->txHdr.sn++; + pCisCtx->dataSn++; if (pFtParam->pduType[i] == LCTR_CIS_PDU_NON_EMPTY) { @@ -349,6 +360,8 @@ static void lctrCisCheckTxFtAfterBod(lctrCisCtx_t *pCisCtx) lctrCisTxQueuePopCleanup(pCisCtx); } pFtParam->pduCounter++; + + lctrCisIncPacketCounterTx(pCisCtx); } } @@ -403,7 +416,9 @@ static void lctrCisCheckRxFtAfterBod(lctrCisCtx_t *pCisCtx) { pFtParam->isPduDone[i] = TRUE; pCisCtx->txHdr.nesn++; + lctrCisIncPacketCounterRx(pCisCtx); pFtParam->pduCounter++; + pCisCtx->isoalRxCtx.pduFlushed = TRUE; } } @@ -453,6 +468,98 @@ static void lctrCisCheckFtAfterBod(lctrCisCtx_t *pCisCtx) External Functions **************************************************************************************************/ +/*************************************************************************************************/ +/*! + * \brief Check whether continue the current operation. + * + * \param pOp Operation. + * \param pNewCisCtx A new CIS operation. + * + * \return zero + */ +/*************************************************************************************************/ +uint32_t lctrMstCisCheckContOpPostCback(BbOpDesc_t *pOp, bool_t *pNewCisCtx) +{ + lctrCigCtx_t * const pCigCtx = pOp->pCtx; + lctrCisCtx_t *pCisCtx = pCigCtx->pCisCtx; + BbBleData_t *pBle = &pCisCtx->bleData; + + if (*pNewCisCtx == FALSE) + { + return 0; + } + + if (pCigCtx->packing == LL_PACKING_INTERLEAVED) + { + if ((pCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCisCtx)) == NULL) + { + /* End of the list, loop back to the head of the CIS. */ + pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + pCigCtx->isLoopBack = TRUE; + + pBle = &pCisCtx->bleData; + + /* Point to the next CIS. */ + pOp->prot.pBle = pBle; + pCigCtx->pCisCtx = pCisCtx; + memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan)); + pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */ + + /* For interleaved CIS there is always a switch to a new CisCtx, so nextSubEvtChanIdx is not updated in bbMstCisRxCompCback()*/ + if (pCisCtx->subEvtCounter <= pCisCtx->nse) + { + lctrMstCisCigPostSubEvt(pOp, BB_STATUS_SUCCESS); + } + } + else + { + /* TODO need to check whether this pCisCtx->rxHdr.cie || pCisCtx->txHdr.cie and no sending more PDU for this CIS. */ + + /* Get the next CIS in the list. */ + if (pCigCtx->isLoopBack == FALSE) + { + lctrFtParam_t txFtParam, rxFtParam; + + if (pCisCtx->bnMToS) + { + lctrCisInitFtParam(&txFtParam, pCisCtx->bnMToS, pCisCtx->ftMToS, pCisCtx->nse); + (void)lctrCisFtInsertTail(&pCisCtx->txFtParamList, &txFtParam); /* Assume there is memory. */ + } + + if (pCisCtx->bnSToM) + { + lctrCisInitFtParam(&rxFtParam, pCisCtx->bnSToM, pCisCtx->ftSToM, pCisCtx->nse); + (void)lctrCisFtInsertTail(&pCisCtx->rxFtParamList, &rxFtParam); /* Assume there is memory. */ + } + + lctrMstCisInitIsr(pCisCtx); + } + + pBle = &pCisCtx->bleData; + + /* Point to the next CIS. */ + pOp->prot.pBle = pBle; + pCigCtx->pCisCtx = pCisCtx; + memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan)); + if (pCigCtx->isLoopBack == FALSE) + { + pBle->chan.chanIdx = pCigCtx->pCisCtx->chIdx; /* Set the next channel to the first channel in the next CIS. */ + } + else + { + pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */ + + /* For interleaved CIS there is always a switch to a new CisCtx, so nextSubEvtChanIdx is not updated in bbMstCisRxCompCback()*/ + if (pCisCtx->subEvtCounter <= pCisCtx->nse) + { + lctrMstCisCigPostSubEvt(pOp, BB_STATUS_SUCCESS); + } + } + } + } + return 0; +} + /*************************************************************************************************/ /*! * \brief Check whether continue the current operation. @@ -622,18 +729,8 @@ SwitchInt: goto Done; } - /* End of the list, loop back to the head of the CIS. */ - pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); - pCigCtx->isLoopBack = TRUE; - - pBle = &pCisCtx->bleData; *pNewCisCtx = TRUE; - - /* Point to the next CIS. */ - pOp->prot.pBle = pBle; - pCigCtx->pCisCtx = pCisCtx; - memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan)); - pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */ + /* Processing will continue in the lctrMstCisCheckContOpPostCback() */ return delayUsec; /* Return the offset from the old CIS */ } @@ -684,43 +781,8 @@ SwitchInt: return (subIntervUsec - addDelayUsec); } - /* TODO need to check whether this pCisCtx->rxHdr.cie || pCisCtx->txHdr.cie and no sending more PDU for this CIS. */ - - /* Get the next CIS in the list. */ - if (pCigCtx->isLoopBack == FALSE) - { - lctrFtParam_t txFtParam, rxFtParam; - - if (pCisCtx->bnMToS) - { - lctrCisInitFtParam(&txFtParam, pCisCtx->bnMToS, pCisCtx->ftMToS, pCisCtx->nse); - (void)lctrCisFtInsertTail(&pCisCtx->txFtParamList, &txFtParam); /* Assume there is memory. */ - } - - if (pCisCtx->bnSToM) - { - lctrCisInitFtParam(&rxFtParam, pCisCtx->bnSToM, pCisCtx->ftSToM, pCisCtx->nse); - (void)lctrCisFtInsertTail(&pCisCtx->rxFtParamList, &rxFtParam); /* Assume there is memory. */ - } - - lctrMstCisInitIsr(pCisCtx); - } - - pBle = &pCisCtx->bleData; *pNewCisCtx = TRUE; - - /* Point to the next CIS. */ - pOp->prot.pBle = pBle; - pCigCtx->pCisCtx = pCisCtx; - memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan)); - if (pCigCtx->isLoopBack == FALSE) - { - pBle->chan.chanIdx = pCigCtx->pCisCtx->chIdx; /* Set the next channel to the first channel in the next CIS. */ - } - else - { - pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */ - } + /* Processing will continue in the lctrMstCisCheckContOpPostCback() */ return delayUsec; /* Return the offset from the old CIS */ } @@ -850,6 +912,14 @@ void lctrMstCisCigEndOp(BbOpDesc_t *pOp) while (pCisCtx) { + /* Check for unframed flushed PDUs. */ + if ((pCisCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED) && + (pCisCtx->isoalRxCtx.pduFlushed == TRUE)) + { + pCisCtx->isoalRxCtx.pduFlushed = FALSE; + lctrCisCheckUnframedFlush(pCisCtx); + } + pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); /* LL_CIS_TERMINATION case */ @@ -857,10 +927,20 @@ void lctrMstCisCigEndOp(BbOpDesc_t *pOp) (pConnCtx->enabled == FALSE) || (lctrResetEnabled == TRUE)) { - /* This variable set to TRUE means it is a CIS disconnect that requires an event generation. */ - if (pCisCtx->isClosing == TRUE) + /* Notify host when terminate happens unless reseted. */ + if (lctrResetEnabled == FALSE) { - /* This was a host-initiated termination of the CIS. */ + if (pConnCtx->enabled == FALSE) + { + pCisCtx->reason = HCI_ERR_REMOTE_TERMINATED; + } + /* If host initiates the termination, the reason code shall be HCI_ERR_LOCAL_TERMINATED in the disconnect complete event. */ + else if (pCisCtx->hostInitTerm) + { + pCisCtx->reason = HCI_ERR_LOCAL_TERMINATED; + pCisCtx->hostInitTerm = FALSE; + } + lctrNotifyHostCisTerm(pCisCtx); } @@ -993,6 +1073,21 @@ void lctrMstCisCigEndOp(BbOpDesc_t *pOp) } } + if (pCisCtx->sduSizeMToS && + (pCisCtx->dataPathInCtx.id == LL_ISO_DATA_PATH_VS)) + { + uint8_t *pSduBuf; + if ((pSduBuf = lctrTxIsoDataPduAlloc()) != NULL) + { + WSF_ASSERT(lctrCodecHdlr.inReq); + lctrCodecHdlr.inReq(pCisCtx->cisHandle, pSduBuf + HCI_ISO_HDR_LEN + HCI_ISO_DL_MAX_LEN, pCisCtx->sduSizeMToS); + } + else + { + LL_TRACE_WARN1("!!! Out of memory; dropping input SDU, handle=%u", pCisCtx->cisHandle); + } + } + /* Assemble framed data. */ if ((pCisCtx->framing == LL_ISO_PDU_TYPE_FRAMED) && pCisCtx->isoalTxCtx.pendQueueSize) @@ -1028,7 +1123,7 @@ void lctrMstCisCigEndOp(BbOpDesc_t *pOp) } pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); - LL_TRACE_WARN1("!!! CIS master schedule conflict eventCounter=%u", pCisCtx->cisEvtCounter); + LL_TRACE_WARN2("!!! CIS master schedule conflict handle=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->cisEvtCounter); } if (lmgrCb.sendIsoCmplEvt) @@ -1048,6 +1143,8 @@ void lctrMstCisCigAbortOp(BbOpDesc_t *pOp) { lctrCigCtx_t * const pCigCtx = pOp->pCtx; + LL_TRACE_WARN1("!!! CIG Master BOD aborted, cigHandle=%u", pCigCtx->cigHandle); + /* Need to setup Tx/Rx flush timeout parameter first since some field will be used in the lctrSlvCisInitIsr. */ if (pCigCtx->numCisEsted > 0) @@ -1093,7 +1190,10 @@ void lctrMstCisCigTxCompletion(BbOpDesc_t *pOp, uint8_t status) lctrCigCtx_t * const pCigCtx = pOp->pCtx; lctrCisCtx_t *pCisCtx = pCigCtx->pCisCtx; - pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter++; + if (pCisCtx->txFtParamList.pHead != NULL) + { + pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter++; + } } /*************************************************************************************************/ @@ -1110,21 +1210,29 @@ void lctrMstCisCigRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status) lctrCigCtx_t * const pCigCtx = pOp->pCtx; lctrCisCtx_t *pCisCtx = pCigCtx->pCisCtx; lctrConnCtx_t *pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); - BbBleData_t * const pBle = &pCisCtx->bleData; - pCisCtx->txFtParamList.pHead->ftParam.pduAcked = FALSE; - pCisCtx->rxFtParamList.pHead->ftParam.subEvtCounter++; - pCisCtx->rxFtParamList.pHead->ftParam.pduRcved = FALSE; + if (pCisCtx->txFtParamList.pHead != NULL) + { + pCisCtx->txFtParamList.pHead->ftParam.pduAcked = FALSE; + } + + if (pCisCtx->rxFtParamList.pHead != NULL) + { + pCisCtx->rxFtParamList.pHead->ftParam.subEvtCounter++; + pCisCtx->rxFtParamList.pHead->ftParam.pduRcved = FALSE; + } + pCisCtx->validRx = FALSE; pCisCtx->txPduIsAcked = FALSE; pCisCtx->pduFlushed = FALSE; + pCisCtx->isoalRxCtx.pduFlushed = FALSE; if (status == BB_STATUS_CRC_FAILED) { pCisCtx->isoLinkQualStats.crcErrPkt++; } - /*** Cancellation processing ***/ + /*** Cancelled processing ***/ if (status == BB_STATUS_CANCELED) { @@ -1134,22 +1242,58 @@ void lctrMstCisCigRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status) /*** Receive packet pre-processing ***/ - if (status == BB_STATUS_SUCCESS) + /* Add RSSI to average if monitoring power. */ + if ((pConnCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) && + (pConnCtx->powerMonitorScheme == LCTR_PC_MONITOR_AUTO)) { + int8_t rssi = (status == LL_SUCCESS) ? pOp->prot.pBle->op.mstCis.rssi : 0x80; + + /* Calculations handled on timer expiration for tmrPowerCtrl. */ + /* Use a positive value to hold accumulated RSSI, as RSSI will never be positive. */ + pConnCtx->cisAccumulatedRssi += (uint32_t) -rssi; + pConnCtx->cisTotalAccumulatedRssi++; + } + + switch (status) + { + case BB_STATUS_SUCCESS: pCisCtx->firstFromPeer = TRUE; pCisCtx->data.mst.rxFromSlave = TRUE; - } - else if (status == BB_STATUS_CRC_FAILED || - status == BB_STATUS_RX_TIMEOUT || - status == BB_STATUS_FAILED) - { - LL_TRACE_WARN2("lctrMstCisCigRxCompletion: BB failed with status=%u, handle=%u", status, pCisCtx->cisHandle); - LL_TRACE_WARN2("lctrMstCisCigRxCompletion: BB failed with cisEvtCounter=%d, bleChan=%u", pCisCtx->cisEvtCounter, pCisCtx->bleData.chan.chanIdx); + break; + + case BB_STATUS_CRC_FAILED: + LL_TRACE_WARN3("lctrMstCisCigRxCompletion: BB failed with status=CRC_FAILED, handle=%u, bleChan=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->bleData.chan.chanIdx, pCisCtx->cisEvtCounter); goto PostProcessing; + + case BB_STATUS_RX_TIMEOUT: + LL_TRACE_WARN3("lctrMstCisCigRxCompletion: BB failed with status=RX_TIMEOUT, handle=%u, bleChan=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->bleData.chan.chanIdx, pCisCtx->cisEvtCounter); + pCisCtx->validRx = FALSE; + pCisCtx->txPduIsAcked = FALSE; + goto PostProcessing; + + case BB_STATUS_FAILED: + LL_TRACE_WARN3("lctrMstCisCigRxCompletion: BB failed with status=FAILED, handle=%u, bleChan=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->bleData.chan.chanIdx, pCisCtx->cisEvtCounter); + pCisCtx->validRx = FALSE; + pCisCtx->txPduIsAcked = FALSE; + goto PostProcessing; + + default: + break; } lctrCisUnpackDataPduHdr(&pCisCtx->rxHdr, pRxBuf); + /* Check for MIC failure and if this is not a re-transmission */ + if ((status == BB_STATUS_MIC_FAILED) && + ((pCisCtx->rxHdr.sn ^ pCisCtx->txHdr.nesn) & 1) == 0) + { + LL_TRACE_WARN3("lctrMstCisCigRxCompletion: BB failed with MIC_FAILED, handle=%u, rxPacketNum=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->rxPktCounter, pCisCtx->cisEvtCounter); + lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_TERM_MIC_FAILED); + lctrCisRxPduFree(pRxBuf); + BbSetBodTerminateFlag(); + goto Done; + } + #if (LL_ENABLE_TESTER) if ((llTesterCb.cisAckMode != LL_TESTER_ACK_MODE_NORMAL) || (llTesterCb.cisFwdPkt == TRUE)) @@ -1172,34 +1316,22 @@ void lctrMstCisCigRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status) /*** Packet post-processing ***/ PostProcessing: - /* Save the Rx buffer and process in the lctrMstCisCigPostSubEvt. */ - pCisCtx->pRxBuf = pRxBuf; - /* Check rssi value if power monitoring. */ - if (pConnCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) - { - lctrCisPowerMonitorCheckRssi(pOp->prot.pBle->op.mstCis.rssi, - status, - pCisCtx->phySToM + - (((pCisCtx->phySToM == LL_PHY_LE_CODED) && - (pBle->chan.initTxPhyOptions == LL_PHY_OPTIONS_S2_PREFERRED)) ? 1 : 0), - pConnCtx); - } + lctrCisCheckFtAfterRx(pCisCtx); + + /* Tx post-processing. */ + lctrCisProcessTxAckCleanup(pCisCtx); + + /* Rx post-processing. */ + lctrCisRxPostProcessing(pCisCtx, pRxBuf); + + return; /*** ISR complete ***/ Done: + lctrCisCheckFtAfterRx(pCisCtx); - if (status == BB_STATUS_SUCCESS || - status == BB_STATUS_RX_TIMEOUT || - status == BB_STATUS_CRC_FAILED || - status == BB_STATUS_FAILED) - { - - lctrCisProcessTxAckCleanup(pCisCtx); - lctrCisRxPostProcessing(pCisCtx, pCisCtx->pRxBuf); - } - - return; + lctrCisProcessTxAckCleanup(pCisCtx); } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis_slave.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis_slave.c index 269c90468b..3148fb6477 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis_slave.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis_slave.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -72,16 +72,29 @@ static void lctrSlvCisInitIsr(lctrCisCtx_t *pCisCtx) pCisCtx->txDataCounter = 0; pCisCtx->rxDataCounter = 0; - pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter = 0; - pCisCtx->rxFtParamList.pHead->ftParam.subEvtCounter = 0; - - if (pCisCtx->txFtParamList.pHead->ftParam.bn == 0) + /* List may be empty if BN M_S is 0 */ + if (pCisCtx->rxFtParamList.pHead != NULL) { - pCisCtx->isTxDone = TRUE; + pCisCtx->rxFtParamList.pHead->ftParam.subEvtCounter = 0; + } + + /* List may be empty if BN S_M is 0 */ + if (pCisCtx->txFtParamList.pHead != NULL) + { + pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter = 0; + + if (pCisCtx->txFtParamList.pHead->ftParam.bn == 0) + { + pCisCtx->isTxDone = TRUE; + } + else + { + pCisCtx->isTxDone = FALSE; + } } else { - pCisCtx->isTxDone = FALSE; + pCisCtx->isTxDone = TRUE; } /*** Setup for transmit ***/ @@ -116,7 +129,7 @@ static void lctrSlvCisCigExecOp(lctrCisCtx_t *pCisCtx) /*** Setup receiver ***/ - if ((pBuf = lctrCisRxPduAlloc(pCisCtx->localDataPdu.maxRxLen)) != NULL) + if ((pBuf = lctrCisRxPduAlloc()) != NULL) { #if (LL_ENABLE_TESTER) if (llTesterCb.isoAccAddrSeTrigMask && @@ -136,6 +149,7 @@ static void lctrSlvCisCigExecOp(lctrCisCtx_t *pCisCtx) } #endif + lctrSetBbCisPacketCounterRx(pCisCtx); BbBleCisRxData(pBuf, LCTR_CIS_DATA_PDU_LEN(pCisCtx->localDataPdu.maxRxLen)); /* Rx may fail; no more important statements in this code path */ } @@ -161,7 +175,7 @@ static void lctrCisCheckTxFtAfterRx(lctrCisCtx_t *pCisCtx) return; } - if (pCisCtx->txHdr.np) + if (pCisCtx->data.slv.lastTxNull) { /* NULL PDU doesn't need to be acked or flushed. */ return; @@ -183,19 +197,23 @@ static void lctrCisCheckTxFtAfterRx(lctrCisCtx_t *pCisCtx) if (pFtParam->subEvtCounter == pFtParam->lastSubEvtFt[pFtParam->pduCounter]) { /* PDU needs to be flushed. */ - pCisCtx->txHdr.sn++; + pCisCtx->dataSn++; lctrCisIncPacketCounterTx(pCisCtx); pFtParam->isPduDone[pFtParam->pduCounter] = TRUE; /* The PDU is done. */ + pFtParam->pduCounter++; + pCisCtx->isoLinkQualStats.txUnAckPkt++; if (pFtParam->pduType[pFtParam->pduCounter] == LCTR_CIS_PDU_NON_EMPTY) { /* Need to remove from ack queue if non-empty PDU. */ lctrCisTxPduAck(pCisCtx); - pCisCtx->pduFlushed = TRUE; /* Set the flag, lctrCisProcessTxAckCleanup will be called to do the cleanup later in the lctrMstCisCigPostSubEvt. */ + pCisCtx->pduFlushed = TRUE; /* Set the flag, lctrCisProcessTxAckCleanup will be called to do the cleanup later in the lctrSlvCisCigPostSubEvt. */ } - pFtParam->pduCounter++; - pCisCtx->isoLinkQualStats.txUnAckPkt++; + } + else /* Implies that a retransmit will happen. */ + { + pCisCtx->isoLinkQualStats.retransmitPkt++; } } else /* Implies that a retransmit will happen. */ @@ -241,12 +259,6 @@ static void lctrCisCheckRxFtAfterRx(lctrCisCtx_t *pCisCtx) return; } - if (pCisCtx->rxHdr.np) - { - /* NULL PDU doesn't need to be acked or flushed. */ - return; - } - lctrFtParam_t *pFtParam = &pCisCtx->rxFtParamList.pHead->ftParam; if (pFtParam->pduRcved) @@ -270,6 +282,11 @@ static void lctrCisCheckRxFtAfterRx(lctrCisCtx_t *pCisCtx) pCisCtx->isoalRxCtx.pduFlushed = TRUE; pCisCtx->isoalRxCtx.packetSequence++; pCisCtx->numRxMissed++; + if (pCisCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED) + { + /* Indicate SDU has missing data. */ + pCisCtx->isoalRxCtx.data.unframed.ps = LCTR_PS_INVALID; + } } } } @@ -305,12 +322,6 @@ static void lctrCisCheckTxFtAfterBod(lctrCisCtx_t *pCisCtx) return; } - if (pCisCtx->txHdr.np) - { - /* NULL PDU doesn't need to be acked or flushed. */ - return; - } - lctrFtParamNode_t *pNode = pCisCtx->txFtParamList.pHead; /* Increment interval counter for all the node in the list. */ @@ -328,16 +339,17 @@ static void lctrCisCheckTxFtAfterBod(lctrCisCtx_t *pCisCtx) pFtParam->intervalCounter == pFtParam->intervalTotal) /* Check if the PDU needs to be flush in this interval. */ { pFtParam->isPduDone[i] = TRUE; - pCisCtx->txHdr.sn++; + pCisCtx->dataSn++; - PalBbBleTxBufDesc_t bbDesc[3]; - if (lctrCisTxQueuePeek(pCisCtx, &bbDesc[0])) + if (pFtParam->pduType[i] == LCTR_CIS_PDU_NON_EMPTY) { /* Need to remove from ack queue if non-empty PDU. */ lctrCisTxPduAck(pCisCtx); lctrCisTxQueuePopCleanup(pCisCtx); } pFtParam->pduCounter++; + + lctrCisIncPacketCounterTx(pCisCtx); } } @@ -393,6 +405,7 @@ static void lctrCisCheckRxFtAfterBod(lctrCisCtx_t *pCisCtx) pCisCtx->txHdr.nesn++; lctrCisIncPacketCounterRx(pCisCtx); pFtParam->pduCounter++; + pCisCtx->isoalRxCtx.pduFlushed = TRUE; } } @@ -441,6 +454,95 @@ static void lctrCisCheckFtAfterBod(lctrCisCtx_t *pCisCtx) /************************************************************************************************** External Functions **************************************************************************************************/ +/*************************************************************************************************/ +/*! + * \brief Setup for the next current operation. + * + * \param pOp Begin operation. + * \param pNewCisCtx New CIS context to begin. + * + * \return zero. + */ +/*************************************************************************************************/ +uint32_t lctrSlvCisCheckContOpPostCback(BbOpDesc_t *pOp, bool_t *pNewCisCtx) +{ + lctrCigCtx_t * const pCigCtx = pOp->pCtx; + lctrCisCtx_t *pCisCtx = pCigCtx->pCisCtx; + BbBleData_t *pBle = &pCisCtx->bleData; + + if (*pNewCisCtx == FALSE) + { + return 0; + } + + if (pCigCtx->packing == LL_PACKING_INTERLEAVED) + { + if ((pCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCisCtx)) == NULL) + { + /* End of the list, loop back to the head of the CIS. */ + pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + pCigCtx->isLoopBack = TRUE; + + pBle = &pCisCtx->bleData; + + /* Point to the next CIS. */ + pOp->prot.pBle = pBle; + pCigCtx->pCisCtx = pCisCtx; + memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan)); + pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */ + + /* For interleaved CIS there is always a switch to a new CisCtx, so nextSubEvtChanIdx is not updated in bbMstCisRxCompCback()*/ + if (pCisCtx->subEvtCounter <= pCisCtx->nse) + { + lctrSlvCisCigPostSubEvt(pOp, BB_STATUS_SUCCESS); + } + } + else + { + if (pCigCtx->isLoopBack == FALSE) + { + lctrFtParam_t txFtParam, rxFtParam; + + if (pCisCtx->bnSToM) + { + lctrCisInitFtParam(&txFtParam, pCisCtx->bnSToM, pCisCtx->ftSToM, pCisCtx->nse); + (void)lctrCisFtInsertTail(&pCisCtx->txFtParamList, &txFtParam); /* Assume there is memory. */ + } + + if (pCisCtx->bnMToS) + { + lctrCisInitFtParam(&rxFtParam, pCisCtx->bnMToS, pCisCtx->ftMToS, pCisCtx->nse); + (void)lctrCisFtInsertTail(&pCisCtx->rxFtParamList, &rxFtParam); /* Assume there is memory. */ + } + + lctrSlvCisInitIsr(pCisCtx); + } + + pBle = &pCisCtx->bleData; + + /* Point to the next CIS. */ + pOp->prot.pBle = pBle; + pCigCtx->pCisCtx = pCisCtx; + memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan)); + if (pCigCtx->isLoopBack == FALSE) + { + pBle->chan.chanIdx = pCigCtx->pCisCtx->chIdx; /* Set the next channel to the first channel in the next CIS. */ + } + else + { + pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */ + + /* For interleaved CIS there is always a switch to a new CisCtx, so nextSubEvtChanIdx is not updated in bbMstCisRxCompCback()*/ + if (pCisCtx->subEvtCounter <= pCisCtx->nse) + { + lctrSlvCisCigPostSubEvt(pOp, BB_STATUS_SUCCESS); + } + } + } + } + + return 0; +} /*************************************************************************************************/ /*! @@ -629,18 +731,8 @@ SwitchInt: goto Done; } - /* End of the list, loop back to the head of the CIS. */ - pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); - pCigCtx->isLoopBack = TRUE; - - pBle = &pCisCtx->bleData; *pNewCisCtx = TRUE; - - /* Point to the next CIS. */ - pOp->prot.pBle = pBle; - pCigCtx->pCisCtx = pCisCtx; - memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan)); - pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */ + /* Processing will continue in the lctrSlvCisCheckContOpPostCback() */ /* Only apply WW when rx success. */ if (isSuccess) @@ -715,40 +807,8 @@ SwitchInt: return (offsetUsec - addDelayUsec); } - if (pCigCtx->isLoopBack == FALSE) - { - lctrFtParam_t txFtParam, rxFtParam; - - if (pCisCtx->bnSToM) - { - lctrCisInitFtParam(&txFtParam, pCisCtx->bnSToM, pCisCtx->ftSToM, pCisCtx->nse); - (void)lctrCisFtInsertTail(&pCisCtx->txFtParamList, &txFtParam); /* Assume there is memory. */ - } - - if (pCisCtx->bnMToS) - { - lctrCisInitFtParam(&rxFtParam, pCisCtx->bnMToS, pCisCtx->ftMToS, pCisCtx->nse); - (void)lctrCisFtInsertTail(&pCisCtx->rxFtParamList, &rxFtParam); /* Assume there is memory. */ - } - - lctrSlvCisInitIsr(pCisCtx); - } - - pBle = &pCisCtx->bleData; *pNewCisCtx = TRUE; - - /* Point to the next CIS. */ - pOp->prot.pBle = pBle; - pCigCtx->pCisCtx = pCisCtx; - memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan)); - if (pCigCtx->isLoopBack == FALSE) - { - pBle->chan.chanIdx = pCigCtx->pCisCtx->chIdx; /* Set the next channel to the first channel in the next CIS. */ - } - else - { - pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */ - } + /* Processing will continue in the lctrSlvCisCheckContOpPostCback() */ /* Only apply WW when rx success. */ if (isSuccess) @@ -770,6 +830,7 @@ Done: pCigCtx->pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); pOp->prot.pBle = &pCigCtx->pCisCtx->bleData; *pNewCisCtx = TRUE; + lctrCisClearCisDone(&pCigCtx->list); return 0; } @@ -805,19 +866,40 @@ void lctrSlvCisCigEndOp(BbOpDesc_t *pOp) /* Re-sync to master's clock. */ pCigCtx->roleData.slv.anchorPointUsec = pCisCtx->data.slv.firstRxStartTsUsec; pCigCtx->roleData.slv.lastActiveEvent = pCigCtx->roleData.slv.cigEvtCounter; + + /* Reset ISR variables. */ + pCisCtx->data.slv.syncWithMaster = FALSE; } while (pCisCtx) { + /* Check for unframed flushed PDUs. */ + if ((pCisCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED) && + (pCisCtx->isoalRxCtx.pduFlushed == TRUE)) + { + pCisCtx->isoalRxCtx.pduFlushed = FALSE; + lctrCisCheckUnframedFlush(pCisCtx); + } + /* LL_CIS_TERMINATION case */ if ((pCisCtx->isClosing == TRUE) || (pConnCtx->enabled == FALSE) || (lctrResetEnabled == TRUE)) { - /* This variable set to TRUE means it is a CIS disconnect that requires an event generation. */ - if (pCisCtx->isClosing == TRUE) + /* Notify host when terminate happens unless reset occurred. */ + if (lctrResetEnabled == FALSE) { - /* This was a host-initiated termination of the CIS. */ + if (pConnCtx->enabled == FALSE) + { + pCisCtx->reason = pConnCtx->termReason; + } + /* If host initiates the termination, the reason code shall be HCI_ERR_LOCAL_TERMINATED in the disconnect complete event. */ + else if (pCisCtx->hostInitTerm) + { + pCisCtx->reason = HCI_ERR_LOCAL_TERMINATED; + pCisCtx->hostInitTerm = FALSE; + } + lctrNotifyHostCisTerm(pCisCtx); } @@ -934,6 +1016,21 @@ void lctrSlvCisCigEndOp(BbOpDesc_t *pOp) } } + if (pCisCtx->sduSizeSToM && + (pCisCtx->dataPathInCtx.id == LL_ISO_DATA_PATH_VS)) + { + uint8_t *pSduBuf; + if ((pSduBuf = WsfMsgAlloc(pLctrRtCfg->maxIsoSduLen + HCI_ISO_DL_MAX_LEN)) != NULL) + { + WSF_ASSERT(lctrCodecHdlr.inReq); + lctrCodecHdlr.inReq(pCisCtx->cisHandle, pSduBuf + HCI_ISO_HDR_LEN + HCI_ISO_DL_MAX_LEN, pCisCtx->sduSizeSToM); + } + else + { + LL_TRACE_WARN1("!!! Out of memory; dropping input SDU, handle=%u", pCisCtx->cisHandle); + } + } + /* Assemble framed data. */ if ((pCisCtx->framing == LL_ISO_PDU_TYPE_FRAMED) && pCisCtx->isoalTxCtx.pendQueueSize) @@ -997,8 +1094,11 @@ void lctrSlvCisCigEndOp(BbOpDesc_t *pOp) /* Advance to next interval. */ pOp->dueUsec = pCigCtx->roleData.slv.anchorPointUsec + unsyncTimeUsec - wwTotalUsec; - pOp->minDurUsec = pCigCtx->cigSyncDelayUsec + wwTotalUsec; - pCigCtx->pCisCtx->bleData.op.slvCis.rxSyncDelayUsec = (wwTotalUsec << 1); + /* Use small minDurUsec to improve scheduling. */ + pOp->minDurUsec = pCigCtx->list.pHead->pCisCtx->subIntervUsec + wwTotalUsec; + + /* TODO: confirm extra rxTimeout time allocation. */ + pCigCtx->pCisCtx->bleData.op.slvCis.rxSyncDelayUsec = (wwTotalUsec << 1) + 10; if (pCigCtx->headCisRmved == TRUE) { @@ -1016,7 +1116,6 @@ void lctrSlvCisCigEndOp(BbOpDesc_t *pOp) LL_TRACE_WARN1("!!! CIG slave schedule conflict eventCounter=%u", pCisCtx->cisEvtCounter); } - if (lmgrCb.sendIsoCmplEvt) { lctrNotifyHostIsoEventComplete(pCigCtx->cigHandle, (uint32_t) pCisCtx->cisEvtCounter); @@ -1034,9 +1133,11 @@ void lctrSlvCisCigAbortOp(BbOpDesc_t *pOp) { lctrCigCtx_t * const pCigCtx = pOp->pCtx; + LL_TRACE_WARN1("!!! CIG Slave BOD aborted, cigHandle=%u", pCigCtx->cigHandle); + if (pCigCtx->numCisEsted > 0) { - lctrCisCtx_t *pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + lctrCisCtx_t *pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); /* It is possible there is no CIS since it is aborting. */ while (pCisCtx) @@ -1078,7 +1179,10 @@ void lctrSlvCisCigTxCompletion(BbOpDesc_t *pOp, uint8_t status) lctrCigCtx_t * const pCigCtx = pOp->pCtx; lctrCisCtx_t *pCisCtx = pCigCtx->pCisCtx; - pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter++; + if (pCisCtx->txFtParamList.pHead != NULL) + { + pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter++; + } } /*************************************************************************************************/ @@ -1100,24 +1204,44 @@ void lctrSlvCisCigRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status) pCisCtx->data.slv.rxStatus = status; - pCisCtx->rxFtParamList.pHead->ftParam.subEvtCounter++; - pCisCtx->txFtParamList.pHead->ftParam.pduAcked = FALSE; - pCisCtx->rxFtParamList.pHead->ftParam.pduRcved = FALSE; + if (pCisCtx->rxFtParamList.pHead != NULL) + { + pCisCtx->rxFtParamList.pHead->ftParam.subEvtCounter++; + pCisCtx->rxFtParamList.pHead->ftParam.pduRcved = FALSE; + } + + if (pCisCtx->txFtParamList.pHead != NULL) + { + pCisCtx->txFtParamList.pHead->ftParam.pduAcked = FALSE; + } + pCisCtx->validRx = FALSE; pCisCtx->txPduIsAcked = FALSE; pCisCtx->pduFlushed = FALSE; + pCisCtx->isoalRxCtx.pduFlushed = FALSE; - /*** Cancellation processing ***/ + /*** Cancelled processing ***/ if (status == BB_STATUS_CANCELED) { lctrCisRxPduFree(pRxBuf); - goto Done; } /*** CIS event pre-processing ***/ + /* Add RSSI to average if monitoring power. */ + if ((pConnCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) && + (pConnCtx->powerMonitorScheme == LCTR_PC_MONITOR_AUTO)) + { + int8_t rssi = (status == LL_SUCCESS) ? pOp->prot.pBle->op.slvCis.rssi : 0x80; + + /* Calculations handled on timer expiration for tmrPowerCtrl. */ + /* Use a positive value to hold accumulated RSSI, as RSSI will never be positive. */ + pConnCtx->cisAccumulatedRssi += (uint32_t) (-(rssi)); + pConnCtx->cisTotalAccumulatedRssi++; + } + /* Save time stamp for the first Rx. */ if (pCisCtx->data.slv.firstRxFromMaster == TRUE) { @@ -1141,25 +1265,45 @@ void lctrSlvCisCigRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status) pCisCtx->data.slv.rxFromMaster = TRUE; pCisCtx->data.slv.consCrcFailed = 0; break; - case BB_STATUS_CRC_FAILED: - pCisCtx->isoLinkQualStats.crcErrPkt++; - /* Fallthrough */ - case BB_STATUS_FAILED: - case BB_STATUS_RX_TIMEOUT: - LL_TRACE_WARN2("lctrSlvCisCigRxCompletion: BB failed with status=%u, handle=%u", status, pCisCtx->cisHandle); - LL_TRACE_WARN2("lctrSlvCisCigRxCompletion: BB failed with cisEvtCounter=%d, bleChan=%u", pCisCtx->cisEvtCounter, pCisCtx->bleData.chan.chanIdx); + case BB_STATUS_CRC_FAILED: + LL_TRACE_WARN3("lctrSlvCisCigRxCompletion: BB failed with status=CRC_FAILED, handle=%u, bleChan=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->bleData.chan.chanIdx, pCisCtx->cisEvtCounter); + pCisCtx->isoLinkQualStats.crcErrPkt++; pCisCtx->validRx = FALSE; pCisCtx->txPduIsAcked = FALSE; - goto SetupTx; + case BB_STATUS_RX_TIMEOUT: + LL_TRACE_WARN3("lctrSlvCisCigRxCompletion: BB failed with status=RX_TIMEOUT, handle=%u, bleChan=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->bleData.chan.chanIdx, pCisCtx->cisEvtCounter); + pCisCtx->validRx = FALSE; + pCisCtx->txPduIsAcked = FALSE; + lctrCisRxPduFree(pRxBuf); + goto Done; + + case BB_STATUS_FAILED: + LL_TRACE_WARN3("lctrSlvCisCigRxCompletion: BB failed with status=FAILED, handle=%u, bleChan=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->bleData.chan.chanIdx, pCisCtx->cisEvtCounter); + pCisCtx->validRx = FALSE; + pCisCtx->txPduIsAcked = FALSE; + lctrCisRxPduFree(pRxBuf); + goto Done; + default: break; } lctrCisUnpackDataPduHdr(&pCisCtx->rxHdr, pRxBuf); + /* Check for MIC failure and if this is not a re-transmission */ + if ((status == BB_STATUS_MIC_FAILED) && + ((pCisCtx->rxHdr.sn ^ pCisCtx->txHdr.nesn) & 1) == 0) + { + LL_TRACE_WARN3("lctrSlvCisCigRxCompletion: BB failed with MIC_FAILED, handle=%u, rxPacketNum=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->rxPktCounter, pCisCtx->cisEvtCounter); + lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_TERM_MIC_FAILED); + lctrCisRxPduFree(pRxBuf); + BbSetBodTerminateFlag(); + goto Done; + } + #if (LL_ENABLE_TESTER) if ((llTesterCb.cisAckMode != LL_TESTER_ACK_MODE_NORMAL) || (llTesterCb.cisFwdPkt == TRUE)) @@ -1187,6 +1331,7 @@ SetupTx: /* Slave always transmits after receiving. */ lctrCisSetupForTx(pCigCtx, status, TRUE); + pCisCtx->data.slv.lastTxNull = pCisCtx->txHdr.np; /* Tx post-processing. */ lctrCisProcessTxAckCleanup(pCisCtx); @@ -1194,28 +1339,17 @@ SetupTx: /* Rx post-processing. */ lctrCisRxPostProcessing(pCisCtx, pRxBuf); - /* Check rssi value if power monitoring. */ - if (pConnCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) - { - lctrCisPowerMonitorCheckRssi(pOp->prot.pBle->op.slvCis.rssi, - status, - pCisCtx->phySToM + - (((pCisCtx->phySToM == LL_PHY_LE_CODED) && - (pBle->chan.initTxPhyOptions == LL_PHY_OPTIONS_S2_PREFERRED)) ? 1 : 0), - pConnCtx); - } - return; /*** ISR complete ***/ Done: + lctrCisCheckFtAfterRx(pCisCtx); - /* Tx post-processing. */ - lctrCisProcessTxAckCleanup(pCisCtx); + pCisCtx->data.slv.lastTxNull = pCisCtx->isTxDone; - return; + lctrCisProcessTxAckCleanup(pCisCtx); } /*************************************************************************************************/ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn.c index 9493c0d377..d101b17853 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn.c @@ -164,10 +164,11 @@ uint8_t *lctrProcessRxAck(lctrConnCtx_t *pCtx) pCtx->txHdr.nesn++; return NULL; } + + lctrIncPacketCounterRx(pCtx); } pCtx->txHdr.nesn++; - lctrIncPacketCounterRx(pCtx); return pNextRxBuf; } @@ -211,6 +212,12 @@ bool_t lctrProcessTxAck(lctrConnCtx_t *pCtx) if (pCtx->txHdr.len) /* last packet from ARQ queue; zero length implies empty PDU */ { + if ((pCtx->txHdr.llid == LL_LLID_CTRL_PDU) && + (pCtx->numTxPendCtrlPdu > 0)) + { + pCtx->numTxPendCtrlPdu--; + } + /*** Peer ACK'ed a Data PDU ***/ lctrTxPduAck(pCtx); diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn_master.c index d6ef7af539..666c7f738a 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn_master.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,6 +47,8 @@ static struct { uint8_t consCrcFailed; /*!< Number of consecutive CRC failures. Used only by active operation. */ bool_t rxFromSlave; /*!< At least one packet received from slave. */ + uint16_t numTxData; /*!< Number of Tx data PDU in a single CE. */ + uint16_t numRxData; /*!< Number of Rx data PDU in a single CE. */ } lctrMstConnIsr; /*! \brief Check BB meets data PDU requirements. */ @@ -216,10 +218,12 @@ void lctrMstConnBeginOp(BbOpDesc_t *pOp) pLctrVsHdlrs->ceSetup(LCTR_GET_CONN_HANDLE(pCtx)); } - /*** Initialize connection event resources. ***/ + /*** Initialize connection event resources ***/ lctrMstConnIsr.consCrcFailed = 0; lctrMstConnIsr.rxFromSlave = FALSE; + lctrMstConnIsr.numTxData = 0; + lctrMstConnIsr.numRxData = 0; /*** Setup for transmit ***/ @@ -295,6 +299,14 @@ void lctrMstConnEndOp(BbOpDesc_t *pOp) lctrStoreConnTimeoutTerminateReason(pCtx); WsfTimerStartMs(&pCtx->tmrSupTimeout, pCtx->supTimeoutMs); + if (!lmgrGetOpFlag(LL_OP_MODE_FLAG_ENA_FEAT_LLCP_STARTUP) && + (pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) && + (pCtx->powerMonitorScheme == LCTR_PC_MONITOR_AUTO) && + !lmgrGetOpFlag(LL_OP_MODE_FLAG_DIS_POWER_MONITOR)) + { + WsfTimerStartMs(&pCtx->tmrPowerCtrl, LL_PC_SERVICE_MS); + } + pCtx->connEst = TRUE; } else if (lctrMstConnIsr.rxFromSlave) @@ -304,13 +316,34 @@ void lctrMstConnEndOp(BbOpDesc_t *pOp) } pCtx->rssi = pConn->rssi; - - if ((pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) && - (pCtx->lastRxStatus == BB_STATUS_SUCCESS)) + if ((pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED)) { - if (lctrPcActTbl[pCtx->powerMonitorScheme]) + /* If a packet did not receive for whatever reason, add a datapoint with the lowest RSSI. */ + if (pCtx->lastRxStatus != BB_STATUS_SUCCESS) { - lctrPcActTbl[pCtx->powerMonitorScheme](pCtx); + pCtx->rssi = 0x80; /* Most negative 8 bit number. */ + } + + switch (pCtx->powerMonitorScheme) + { + case LCTR_PC_MONITOR_AUTO: + { + /* Calculations handled on timer expiration for tmrPowerCtrl. */ + /* Use a positive value to hold accumulated RSSI, as RSSI will never be positive. */ + pCtx->pclMonitorParam.autoMonitor.accumulatedRssi += (uint32_t) (-(pCtx->rssi)); + pCtx->pclMonitorParam.autoMonitor.totalAccumulatedRssi++; + break; + } + case LCTR_PC_MONITOR_PATH_LOSS: + { + /* Power control monitoring being enabled implies that this function exists. */ + lctrPathLossMonitorActFn(pCtx); + break; + } + default: + /* Should not happen. */ + WSF_ASSERT(FALSE); + break; } } @@ -327,6 +360,17 @@ void lctrMstConnEndOp(BbOpDesc_t *pOp) return; } + /* Enhanced Connection Update. */ + uint16_t numIntervals = 0; + if (lctrCalcSubrateConnEventsFn) + { + if ((numIntervals = lctrCalcSubrateConnEventsFn(pCtx, lctrMstConnIsr.numTxData + lctrMstConnIsr.numRxData)) > 0) + { + pCtx->eventCounter += numIntervals; + lctrChSelHdlr[pCtx->usedChSel](pCtx, numIntervals - 1); + } + } + if (pCtx->data.mst.sendConnUpdInd) { uint8_t *pPdu; @@ -344,8 +388,9 @@ void lctrMstConnEndOp(BbOpDesc_t *pOp) else #endif { - ceOffset = LL_MIN_INSTANT + 1 + /* +1 for next CE */ - pCtx->maxLatency; /* ensure slave will listen this packet */ + ceOffset = ((LL_MIN_INSTANT + 1 + /* +1 for next CE */ + pCtx->maxLatency) * /* ensure slave will listen to this packet */ + pCtx->ecu.srFactor); /* include subrating factor */ /* TODO: accommodate pCtx->connParam.offset[]. */ } @@ -382,8 +427,7 @@ void lctrMstConnEndOp(BbOpDesc_t *pOp) /*** Update for next operation ***/ - uint32_t anchorPointUsec = pOp->dueUsec; - uint16_t numIntervals = 0; + uint32_t anchorPointUsec = pOp->dueUsec; if (pBle->chan.tifsTxPhyOptions != BB_PHY_OPTIONS_DEFAULT) { @@ -455,7 +499,7 @@ void lctrMstConnAbortOp(BbOpDesc_t *pOp) { lctrConnCtx_t * const pCtx = pOp->pCtx; - LL_TRACE_INFO2("!!! Connection Master BOD aborted, handle=%u, eventCounter=%u", LCTR_GET_CONN_HANDLE(pCtx), pCtx->eventCounter); + LL_TRACE_WARN2("!!! Connection Master BOD aborted, handle=%u, eventCounter=%u", LCTR_GET_CONN_HANDLE(pCtx), pCtx->eventCounter); /* Reset operation to state before BOD began */ if (pCtx->emptyPduPend && @@ -470,6 +514,9 @@ void lctrMstConnAbortOp(BbOpDesc_t *pOp) return; } + lctrMstConnIsr.consCrcFailed = 0; + lctrMstConnIsr.rxFromSlave = FALSE; + lctrMstConnEndOp(pOp); } @@ -488,6 +535,11 @@ void lctrMstConnTxCompletion(BbOpDesc_t *pOp, uint8_t status) lctrConnCtx_t * const pCtx = pOp->pCtx; lctrSetControlPduAck(pCtx); + + if (pCtx->txHdr.len) + { + lctrMstConnIsr.numTxData++; + } } } @@ -571,6 +623,23 @@ void lctrMstConnRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status) lctrUnpackDataPduHdr(&pCtx->rxHdr, pRxBuf); + /* Check for MIC failure and if this is not a re-transmission */ + if ((status == BB_STATUS_MIC_FAILED) && + ((pCtx->rxHdr.sn ^ pCtx->txHdr.nesn) & 1) == 0) + { + LL_TRACE_WARN3("lctrMstConnRxCompletion: BB failed with status=MIC_FAILED, eventCounter=%u, bleChan=%u, handle=%u", pCtx->eventCounter, pCtx->bleData.chan.chanIdx, LCTR_GET_CONN_HANDLE(pCtx)); + lctrSendConnMsg(pCtx, LCTR_CONN_TERM_MIC_FAILED); + /* Close connection event. */ + BbSetBodTerminateFlag(); + lctrRxPduFree(pRxBuf); + goto Done; + } + + if (pCtx->rxHdr.len) + { + lctrMstConnIsr.numRxData++; + } + #if (LL_ENABLE_TESTER) if (llTesterCb.ackMode != LL_TESTER_ACK_MODE_NORMAL) { diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn_slave.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn_slave.c index 7358c1f79f..016e0f6ba3 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn_slave.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn_slave.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,6 +46,13 @@ WSF_CT_ASSERT((BB_FIXED_DATA_PKT_LEN == 0) || (BB_FIXED_DATA_PKT_LEN >= LCTR_DATA_PDU_MAX_LEN)); +/*! \brief Slave connection ISR control block. */ +static struct +{ + uint16_t numTxData; /*!< Number of Tx data PDU in a single CE. */ + uint16_t numRxData; /*!< Number of Rx data PDU in a single CE. */ +} lctrSlvConnIsr; + /************************************************************************************************** Function Declarations **************************************************************************************************/ @@ -160,7 +167,7 @@ static void lctrSlvConnUpdateOp(lctrConnCtx_t *pCtx, bool_t ignoreOffset) pCtx->data.slv.txWinSizeUsec = txWinSizeUsec; /* Add additional time due to Tx window size and WW due to Tx window offset. */ - pOp->minDurUsec += txWinSizeUsec + wwTxWinOffsetUsec; + pOp->minDurUsec += wwTxWinOffsetUsec; /*** BLE general setup ***/ @@ -280,6 +287,25 @@ static void lctrSlvInitConnIsr(lctrConnCtx_t *pCtx) pCtx->data.slv.syncWithMaster = FALSE; pCtx->data.slv.rxFromMaster = FALSE; pCtx->data.slv.firstRxStartTsUsec = 0; + + lctrSlvConnIsr.numTxData = 0; + lctrSlvConnIsr.numRxData = 0; +} + +/*************************************************************************************************/ +/*! + * \brief Pack a channel status message. + * + * \param pBuf Packed buffer. + */ +/*************************************************************************************************/ +static void lctrPackChannelStatusMsg(uint8_t *pBuf) +{ + unsigned int i; + for (i = 0; i < LL_MAX_NUM_CHAN_DATA; i++) + { + UINT8_TO_BSTREAM(pBuf, (((UINT64_C(1) << i) & lmgrCb.chanClass) ? LL_CH_CLASS_UNKNOWN : LL_CH_CLASS_BAD)); + } } /*************************************************************************************************/ @@ -308,7 +334,8 @@ void lctrSlvConnBeginOp(BbOpDesc_t *pOp) pLctrVsHdlrs->ceSetup(LCTR_GET_CONN_HANDLE(pCtx)); } - /*** Initialize connection event resources. ***/ + /*** Initialize connection event resources ***/ + lctrSlvInitConnIsr(pCtx); /*** Setup receiver ***/ @@ -364,13 +391,35 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp) } pCtx->rssi = pConn->rssi; - - if ((pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) && - (pCtx->lastRxStatus == BB_STATUS_SUCCESS)) + if (pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) { - if (lctrPcActTbl[pCtx->powerMonitorScheme]) + + /* If a packet did not receive for whatever reason, add a datapoint with the lowest RSSI. */ + if (pCtx->lastRxStatus != BB_STATUS_SUCCESS) { - lctrPcActTbl[pCtx->powerMonitorScheme](pCtx); + pCtx->rssi = 0x80; /* Most negative 8 bit number. */ + } + + switch (pCtx->powerMonitorScheme) + { + case LCTR_PC_MONITOR_AUTO: + { + /* Calculations handled on timer expiration for tmrPowerCtrl. */ + /* Use a positive value to hold accumulated RSSI, as RSSI will never be positive. */ + pCtx->pclMonitorParam.autoMonitor.accumulatedRssi += (uint32_t) (-(pCtx->rssi)); + pCtx->pclMonitorParam.autoMonitor.totalAccumulatedRssi++; + break; + } + case LCTR_PC_MONITOR_PATH_LOSS: + { + /* Power control monitoring being enabled implies that this function exists. */ + lctrPathLossMonitorActFn(pCtx); + break; + } + default: + /* Should not happen. */ + WSF_ASSERT(FALSE); + break; } } @@ -393,6 +442,14 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp) lctrStoreConnTimeoutTerminateReason(pCtx); WsfTimerStartMs(&pCtx->tmrSupTimeout, pCtx->supTimeoutMs); + if (!lmgrGetOpFlag(LL_OP_MODE_FLAG_ENA_FEAT_LLCP_STARTUP) && + (pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) && + (pCtx->powerMonitorScheme == LCTR_PC_MONITOR_AUTO) && + !lmgrGetOpFlag(LL_OP_MODE_FLAG_DIS_POWER_MONITOR)) + { + WsfTimerStartMs(&pCtx->tmrPowerCtrl, LL_PC_SERVICE_MS); + } + pCtx->connEst = TRUE; } else if (pCtx->data.slv.rxFromMaster) @@ -447,8 +504,7 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp) } } - /* Slave received connection update on the instant. */ - /* Immediately use that packet as the new anchor point and do not apply txWinOffset and txWinSize. */ + /* Check if channel status update is required. */ if ((pCtx->llcpActiveProc == LCTR_PROC_CONN_UPD) && lctrSlvCheckConnUpdInstant(pCtx) && (pCtx->eventCounter == pCtx->connUpd.instant)) { @@ -456,32 +512,68 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp) LL_TRACE_WARN1("Received connection update at instant, applying immediately at CE=%d", pCtx->eventCounter); } + /* If the channel map has changed since the last time, */ + /* Send master the status indication. */ + if (pCtx->chanStatRptEnable && pCtx->data.slv.queuedChanStatusTs && + (BbGetTargetTimeDelta(pOp->dueUsec, pCtx->data.slv.lastStatusSentTs) > pCtx->data.slv.chanStatMinIntUs)) + { + /* Make sure that the report has not passed the max delay parameter. */ + if (BbGetTargetTimeDelta(pOp->dueUsec, pCtx->data.slv.queuedChanStatusTs) < pCtx->data.slv.chanStatMaxDelay) + { + pCtx->data.slv.lastStatusSentTs = pOp->dueUsec; + + lctrMsgChStatusInd_t *pMsg; + if ((pMsg = (lctrMsgChStatusInd_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->hdr.handle = LCTR_GET_CONN_HANDLE(pCtx); + pMsg->hdr.dispId = LCTR_DISP_CONN; + pMsg->hdr.event = LCTR_CONN_LLCP_CHANNEL_STATUS; + + lctrPackChannelStatusMsg(pMsg->chanStatus); + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } + } + + /* Reset the timestamp to signal that there is no pending status report. */ + pCtx->data.slv.queuedChanStatusTs = 0; + } + /*** Update for next operation ***/ uint16_t numUnsyncIntervals = pCtx->eventCounter - pCtx->data.slv.lastActiveEvent + 1; uint16_t numSkipCe = 0; + uint16_t numSkipSr = 0; + uint16_t srLatency = pCtx->maxLatency; + + /* Enhanced Connection Update. */ + if (lctrCalcSubrateConnEventsFn) + { + numSkipSr = lctrCalcSubrateConnEventsFn(pCtx, lctrSlvConnIsr.numTxData + lctrSlvConnIsr.numRxData); + srLatency = (pCtx->maxLatency * pCtx->ecu.srFactor) + numSkipSr; + } if ((pCtx->data.slv.abortSlvLatency == FALSE) && lctrGetConnOpFlag(pCtx, LL_OP_MODE_FLAG_ENA_SLV_LATENCY) && - (pCtx->maxLatency && - pCtx->data.slv.initAckRcvd && - pCtx->data.slv.rxFromMaster && - (WsfQueueEmpty(&pCtx->txArqQ)) && - (pCtx->state != LCTR_CONN_STATE_TERMINATING))) + pCtx->maxLatency && + pCtx->data.slv.initAckRcvd && + pCtx->data.slv.rxFromMaster && + WsfQueueEmpty(&pCtx->txArqQ) && + (pCtx->state != LCTR_CONN_STATE_TERMINATING)) { if (pCtx->llcpActiveProc == LCTR_PROC_INVALID) { - numSkipCe = pCtx->maxLatency; + numSkipCe = srLatency; } else { /* Still apply the slave latency if the instant is not reached for the following LLCPs. */ if ((pCtx->llcpActiveProc == LCTR_PROC_CONN_UPD) && lctrSlvCheckConnUpdInstant(pCtx)) { - if ((uint16_t)(pCtx->connUpd.instant - pCtx->eventCounter) > (pCtx->maxLatency + 1)) + if ((uint16_t)(pCtx->connUpd.instant - pCtx->eventCounter) > (srLatency + 1)) { - numSkipCe = pCtx->maxLatency; + numSkipCe = srLatency; } else if ((pCtx->connUpd.instant - pCtx->eventCounter) > 1) { @@ -492,9 +584,9 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp) else if ((pCtx->llcpActiveProc == LCTR_PROC_CMN_CH_MAP_UPD) && (pCtx->cmnState == LCTR_CMN_STATE_BUSY)) { - if ((uint16_t)(pCtx->chanMapUpd.instant - pCtx->eventCounter) > (pCtx->maxLatency + 1)) + if ((uint16_t)(pCtx->chanMapUpd.instant - pCtx->eventCounter) > (srLatency + 1)) { - numSkipCe = pCtx->maxLatency; + numSkipCe = srLatency; } else if ((pCtx->chanMapUpd.instant - pCtx->eventCounter) > 1) { @@ -504,9 +596,9 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp) } else if ((pCtx->llcpActiveProc == LCTR_PROC_PHY_UPD) && (pCtx->isSlvPhyUpdInstant == TRUE)) { - if ((uint16_t)(pCtx->phyUpd.instant - pCtx->eventCounter) > (pCtx->maxLatency + 1)) + if ((uint16_t)(pCtx->phyUpd.instant - pCtx->eventCounter) > (srLatency + 1)) { - numSkipCe = pCtx->maxLatency; + numSkipCe = srLatency; } else if ((pCtx->phyUpd.instant - pCtx->eventCounter) > 1) { @@ -516,15 +608,23 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp) } } } + else + { + /* No slave latency; listen at the next subrated connection events. */ + numSkipCe = numSkipSr; + } if (numSkipCe > 0) { + if (numSkipCe > numSkipSr) + { + LL_TRACE_INFO2("Applying slave latency, last attended eventCounter=%u, wake up at eventCounter=%u", pCtx->eventCounter, pCtx->eventCounter + numSkipCe + 1); + } + pCtx->eventCounter += numSkipCe; numUnsyncIntervals += numSkipCe; lctrChSelHdlr[pCtx->usedChSel](pCtx, numSkipCe - 1); - - LL_TRACE_INFO2("Applying slave latency, waking up at eventCounter=%u, numSkipCE=%u", pCtx->eventCounter + 1, numSkipCe); } while (TRUE) @@ -551,7 +651,9 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp) /* Advance to next interval. */ pOp->dueUsec = pCtx->data.slv.anchorPointUsec + connInterUsec - wwTotalUsec; - pOp->minDurUsec = pCtx->data.slv.txWinSizeUsec + pCtx->effConnDurUsec + wwTotalUsec; + /* Use small minDurUsec to improve scheduling. */ + pOp->minDurUsec = pCtx->data.slv.txWinSizeUsec + (2 * LL_MAX_DATA_TIME_MIN) + LL_BLE_TIFS_US + wwTotalUsec; + pConn->rxSyncDelayUsec = pCtx->data.slv.txWinSizeUsec + (wwTotalUsec << 1); if ((pCtx->llcpActiveProc == LCTR_PROC_CONN_UPD) && @@ -568,12 +670,12 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp) lctrSlvConnUpdateOp(pCtx, FALSE); } else if ((pCtx->llcpActiveProc == LCTR_PROC_CMN_CH_MAP_UPD) && - (pCtx->eventCounter == pCtx->chanMapUpd.instant)) + (pCtx->eventCounter == pCtx->chanMapUpd.instant)) { lctrSlvChanMapUpdateOp(pCtx); } else if ((pCtx->llcpActiveProc == LCTR_PROC_PHY_UPD) && - (pCtx->eventCounter == pCtx->phyUpd.instant)) + (pCtx->eventCounter == pCtx->phyUpd.instant)) { lctrSlvPhyUpdateOp(pCtx); } @@ -620,6 +722,8 @@ void lctrSlvConnAbortOp(BbOpDesc_t *pOp) { lctrConnCtx_t * const pCtx = pOp->pCtx; + LL_TRACE_WARN2("!!! Connection Slave BOD aborted, handle=%u, eventCounter=%u", LCTR_GET_CONN_HANDLE(pCtx), pCtx->eventCounter); + lctrSlvInitConnIsr(pCtx); lctrSlvConnEndOp(pOp); } @@ -639,6 +743,11 @@ void lctrSlvConnTxCompletion(BbOpDesc_t *pOp, uint8_t status) lctrConnCtx_t * const pCtx = pOp->pCtx; lctrSetControlPduAck(pCtx); + + if (pCtx->txHdr.len) + { + lctrSlvConnIsr.numTxData++; + } } } @@ -693,12 +802,12 @@ void lctrSlvConnRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status) { if (status == BB_STATUS_RX_TIMEOUT) { - LL_TRACE_WARN3("lctrSlvConnRxCompletion: BB failed with status=RX_TIMEOUT, handle=%u, bleChan=%u, eventCounter=%u", LCTR_GET_CONN_HANDLE(pCtx), pBle->chan.chanIdx, pCtx->eventCounter); + LL_TRACE_WARN3("lctrSlvConnRxCompletion: BB failed with status=RX_TIMEOUT, eventCounter=%u, bleChan=%u, handle=%u", pCtx->eventCounter, pCtx->bleData.chan.chanIdx, LCTR_GET_CONN_HANDLE(pCtx)); } if (status == BB_STATUS_FAILED) { - LL_TRACE_ERR3("lctrSlvConnRxCompletion: BB failed with status=FAILED, handle=%u, bleChan=%u, eventCounter=%u", LCTR_GET_CONN_HANDLE(pCtx), pBle->chan.chanIdx, pCtx->eventCounter); + LL_TRACE_ERR3("lctrSlvConnRxCompletion: BB failed with status=FAILED, eventCounter=%u, bleChan=%u, handle=%u", pCtx->eventCounter, pCtx->bleData.chan.chanIdx, LCTR_GET_CONN_HANDLE(pCtx)); } BbSetBodTerminateFlag(); @@ -741,6 +850,23 @@ void lctrSlvConnRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status) lctrUnpackDataPduHdr(&pCtx->rxHdr, pRxBuf); + /* Check for MIC failure and if this is not a re-transmission */ + if ((status == BB_STATUS_MIC_FAILED) && + ((pCtx->rxHdr.sn ^ pCtx->txHdr.nesn) & 1) == 0) + { + LL_TRACE_WARN3("lctrSlvConnRxCompletion: BB failed with status=MIC_FAILED, eventCounter=%u, bleChan=%u, handle=%u", pCtx->eventCounter, pCtx->bleData.chan.chanIdx, LCTR_GET_CONN_HANDLE(pCtx)); + lctrSendConnMsg(pCtx, LCTR_CONN_TERM_MIC_FAILED); + /* Close connection event. */ + BbSetBodTerminateFlag(); + lctrRxPduFree(pRxBuf); + goto Done; + } + + if (pCtx->rxHdr.len) + { + lctrSlvConnIsr.numRxData++; + } + /* Check LLID from master. */ if ((pCtx->isSlvReadySent == FALSE) && (pCtx->rxHdr.llid != LL_LLID_CTRL_PDU) && diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main.c index 563a2bc9bf..5c6f05b6af 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main.c @@ -414,6 +414,16 @@ void lctrRegisterChClassHandler(lctrChClassHdlr_t cback) { /* Ensure registration does not exceed limits. */ WSF_ASSERT(lctrChClassHandlerCnt < LCTR_NUM_CH_CLASS_HANDLERS); + + /* If callback is already registered, do nothing. */ + for (unsigned int i = 0; i < lctrChClassHandlerCnt; i++) + { + if (lctrChClassHandlerTbl[0] == cback) + { + return; + } + } + lctrChClassHandlerTbl[lctrChClassHandlerCnt++] = cback; } @@ -451,3 +461,42 @@ uint8_t LctrSetChannelClass(uint64_t chanMap) return result; } + +/*************************************************************************************************/ +/*! + * \brief Get average RSSI of an averaging unit. + * + * \param pAvg Average block + * + * \return Average block average. + */ +/*************************************************************************************************/ +int8_t lctrRssiGetAverage(lctrRssiRunAvg_t *pAvg) +{ + WSF_ASSERT(pAvg->avgCount >= LL_PC_TBL_LEN); + + int32_t total = 0; + for (int i = 0; i < LL_PC_TBL_LEN; i++) + { + total += (int32_t) pAvg->averageRssi[i]; + } + + return (int8_t) (total >> LL_PC_TBL_POW); +} + +/*************************************************************************************************/ +/*! + * \brief Add a value to the average block. + * + * \param pAvg Average block + * \param value Value to add + * + * \note oldest value will be overwritten. + */ +/*************************************************************************************************/ +void lctrRssiAddAveragePoint(lctrRssiRunAvg_t *pAvg, int8_t value) +{ + pAvg->averageRssi[pAvg->rssiIdx] = value; + pAvg->rssiIdx = ((pAvg->rssiIdx + 1) == LL_PC_TBL_LEN) ? 0 : (pAvg->rssiIdx + 1); + pAvg->avgCount++; +} diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_master.c index 8cd90fe3ce..51ab76dc65 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_master.c @@ -275,6 +275,7 @@ void lctrMstDiscoverBuildOp(void) pOp->pCtx = &lctrMstScan; pOp->endCback = lctrMstDiscoverEndOp; pOp->abortCback = lctrMstDiscoverEndOp; + pOp->recoverable = TRUE; /*** BLE General Setup ***/ @@ -415,6 +416,9 @@ void lctrMstDiscoverBuildOp(void) SchInsertNextAvailable(pOp); lctrMstScan.scanWinStartUsec = pOp->dueUsec; + + LL_TRACE_INFO1(" >>> Discover started, dueUsec=%u <<<", pOp->dueUsec); + LL_TRACE_INFO1(" pBod=0x%08x", pOp); } @@ -740,13 +744,13 @@ void LctrMstScanDefaults(void) /*************************************************************************************************/ void lctrAdvReportsInc(void) { - WSF_CS_INIT(); + WSF_CS_INIT(cs); WSF_ASSERT(lmgrMstScanCb.numAdvReport < pLctrRtCfg->maxAdvReports); - WSF_CS_ENTER(); + WSF_CS_ENTER(cs); lmgrMstScanCb.numAdvReport++; - WSF_CS_EXIT(); + WSF_CS_EXIT(cs); } /*************************************************************************************************/ @@ -756,13 +760,13 @@ void lctrAdvReportsInc(void) /*************************************************************************************************/ void lctrAdvReportsDec(void) { - WSF_CS_INIT(); + WSF_CS_INIT(cs); WSF_ASSERT(lmgrMstScanCb.numAdvReport > 0); - WSF_CS_ENTER(); + WSF_CS_ENTER(cs); lmgrMstScanCb.numAdvReport--; - WSF_CS_EXIT(); + WSF_CS_EXIT(cs); } /*************************************************************************************************/ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_master_ae.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_master_ae.c index 40f45ba3bb..36ddbc4df6 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_master_ae.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_master_ae.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -437,6 +437,7 @@ uint8_t lctrMstExtDiscoverBuildOp(lctrExtScanCtx_t *pExtScanCtx) pOp->endCback = lctrMstExtDiscoverEndOp; pOp->abortCback = lctrMstExtDiscoverAbortOp; pOp->pCtx = pExtScanCtx; + pOp->recoverable = TRUE; /*** BLE General Setup ***/ @@ -486,6 +487,9 @@ uint8_t lctrMstExtDiscoverBuildOp(lctrExtScanCtx_t *pExtScanCtx) pScan->rxAdvCback = lctrMstDiscoverRxExtAdvPktHandler; pScan->rxAdvPostCback = lctrMstDiscoverRxExtAdvPktPostProcessHandler; + pScan->auxScanCheckCback = lctrMstLinkAuxOffsetScanSetup; + pScan->auxScanTxCompCback = BbMstAuxScanTxCompHandler; + pScan->auxScanRxCompCback = BbMstAuxScanRxCompHandler; if ((pScan->pRxAdvBuf = WsfMsgAlloc(LL_ADV_HDR_LEN + LL_EXT_ADV_HDR_MAX_LEN)) == NULL) { @@ -607,6 +611,10 @@ uint8_t lctrMstExtDiscoverBuildOp(lctrExtScanCtx_t *pExtScanCtx) lctrActiveExtScan.scanMask |= (1 << scanPhyIndex); + LL_TRACE_INFO1(" >>> ExtDiscover started, handle=%u <<<", LCTR_GET_EXT_SCAN_HANDLE(pExtScanCtx)); + LL_TRACE_INFO1(" dueUsec=%u, 0=deferred", pOp->dueUsec); + LL_TRACE_INFO1(" pBod=0x%08x", pOp); + return LL_SUCCESS; } @@ -673,6 +681,7 @@ uint8_t lctrMstAuxDiscoverBuildOp(lctrExtScanCtx_t *pExtScanCtx) pAuxScan->isInit = FALSE; pAuxScan->rxAuxAdvCback = lctrMstDiscoverRxAuxAdvPktHandler; + pAuxScan->rxAuxAdvPostCback = lctrMstDiscoverRxAuxAdvPktPostProcessHandler; /*** BLE Scan Setup: Tx scan request packet ***/ @@ -731,7 +740,7 @@ uint8_t lctrMstAuxDiscoverBuildOp(lctrExtScanCtx_t *pExtScanCtx) /*** Commit operation ***/ - /* pOp->minDurUsec = 0; */ /* Defer assignment until AuxPtr is received. */ + /* pOp->minDurUsec = 0; */ /* Defer assignment until AuxPtr is received, lctrMstAuxDiscoverOpCommit(). */ /* pOp->maxDurUsec = 0; */ /* Not used for aux scan. */ pExtScanCtx->selfTerm = FALSE; @@ -740,6 +749,8 @@ uint8_t lctrMstAuxDiscoverBuildOp(lctrExtScanCtx_t *pExtScanCtx) /* Defer scheduling until AuxPtr is received. */ + LL_TRACE_INFO1(" >>> AuxDiscover ready, pBod=0x%08x <<<", pOp); + return LL_SUCCESS; } @@ -783,7 +794,12 @@ void lctrMstAuxDiscoverOpCommit(lctrExtScanCtx_t *pExtScanCtx, lctrAuxPtr_t *pAu pOp->dueUsec = startTs + auxOffsetUsec; SchBleCalcAdvOpDuration(pOp, 0); - if (SchInsertAtDueTime(pOp, NULL)) + if (auxOffsetUsec < BbGetSchSetupDelayUs()) + { + /* Signal the lower layer to start Aux Scan ASAP, since the auxOffset is too small to run the scheduler. */ + pExtScanCtx->scheduleAuxAsap = TRUE; + } + else if (SchInsertAtDueTime(pOp, NULL)) { pExtScanCtx->auxOpPending = TRUE; } @@ -879,7 +895,7 @@ void LctrMstExtScanDefaults(void) uint16_t LctrInitExtScanMem(uint8_t *pFreeMem, uint32_t freeMemSize) { /* Extended Scanning requires receiving at least 251 bytes. */ - WSF_ASSERT(pLctrRtCfg->maxExtScanDataLen >= LL_EXT_ADVBU_MAX_LEN); + WSF_ASSERT(pLctrRtCfg->maxExtScanDataLen >= WSF_MIN(LL_EXT_ADVBU_MAX_LEN, BB_ADV_PLD_MAX_LEN)); uint8_t *pAvailMem = pFreeMem; @@ -1307,7 +1323,7 @@ void lctrMstPerScanOpCommit(lctrExtScanCtx_t *pExtScanCtx, lctrAuxPtr_t *pAuxPtr pOp->dueUsec = startTs + syncOffsetUsec; /* Ensure minimum packet is scheduled; allow PerAdv to schedule tight operations. */ - pPerScanCtx->minDurUsec = pOp->minDurUsec = SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, BB_PHY_OPTIONS_DEFAULT, LL_ADVB_MIN_LEN); + pPerScanCtx->minDurUsec = pOp->minDurUsec = SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, BB_PHY_OPTIONS_DEFAULT, LL_EXT_ADV_HDR_MIN_LEN); uint16_t numUnsyncIntervals = 0; while (TRUE) @@ -1315,7 +1331,6 @@ void lctrMstPerScanOpCommit(lctrExtScanCtx_t *pExtScanCtx, lctrAuxPtr_t *pAuxPtr if (SchInsertAtDueTime(pOp, lctrPerScanResolveConflict)) { LL_TRACE_INFO1(" >>> Periodic scan started, handle=%u <<<", LCTR_GET_PER_SCAN_HANDLE(pPerScanCtx)); - LL_TRACE_INFO1(" pOp=%08x", pOp); LL_TRACE_INFO1(" dueUsec=%u", pOp->dueUsec); LL_TRACE_INFO1(" eventCounter=%u", pPerScanCtx->eventCounter); LL_TRACE_INFO1(" chanIdx=%u", pBle->chan.chanIdx); @@ -1360,7 +1375,7 @@ void lctrMstPerScanTransferOpCommit(uint16_t connHandle) uint32_t refTime; uint16_t peC; /* paEventCounter for the AUX_SYNC_IND PDU that we are attempting to receive. */ uint32_t startTs; /* Anchor point of the connection event. */ - uint16_t numInterval; + uint32_t numInterval; /* Pre-resolve common structures for efficient access. */ lctrPerScanCtx_t *pPerScanCtx = lctrPerTransferSync.pPerScanCtx; @@ -1373,6 +1388,12 @@ void lctrMstPerScanTransferOpCommit(uint16_t connHandle) pPerScanCtx->repDisabled = TRUE; } + if (pConnCtx->syncMode == LL_SYNC_TRSF_MODE_DUP_FILTERED) + { + pPerScanCtx->dupFilterEnable = TRUE; + pPerScanCtx->lastDid = LL_DID_NOT_PRESENT; + } + pPerScanCtx->syncTimeOutMs = LCTR_PER_SYNC_TIMEOUT_TO_MS(pConnCtx->syncTimeout); pPerScanCtx->skip = pConnCtx->syncSkip; pPerScanCtx->sca = trsfSyncInfo.sca; @@ -1409,16 +1430,16 @@ void lctrMstPerScanTransferOpCommit(uint16_t connHandle) startTs = lctrConnGetAnchorPoint(pConnCtx, pConnCtx->eventCounter); peC = trsfSyncInfo.eventCounter; - if (BbGetTargetTimeDelta(refTime, startTs + pConnOp->minDurUsec) > 0) + if ((uint16_t)(lctrPerTransferSync.ceRef - pConnCtx->eventCounter) < (uint16_t)LCTR_MAX_INSTANT) /* ceCounter is in the future. */ { - numInterval = BbGetTargetTimeDelta(refTime, startTs + pConnOp->minDurUsec) / pPerScanCtx->perInterUsec; + numInterval = ((uint16_t)(lctrPerTransferSync.ceRef - pConnCtx->eventCounter) * LCTR_CONN_IND_US(pConnCtx->connInterval) + pConnOp->minDurUsec) / pPerScanCtx->perInterUsec; refTime -= numInterval * pPerScanCtx->perInterUsec; peC -= numInterval; offsetUsec = BbGetTargetTimeDelta(refTime , startTs); } else /* refTime is in the past. */ { - numInterval = 1 + BbGetTargetTimeDelta(startTs + pConnOp->minDurUsec, refTime)/ pPerScanCtx->perInterUsec; + numInterval = 1 + ((uint16_t)(pConnCtx->eventCounter - lctrPerTransferSync.ceRef) * LCTR_CONN_IND_US(pConnCtx->connInterval) + pConnOp->minDurUsec) / pPerScanCtx->perInterUsec; refTime += numInterval * pPerScanCtx->perInterUsec; peC += numInterval; offsetUsec = BbGetTargetTimeDelta(refTime , startTs); @@ -1463,7 +1484,6 @@ void lctrMstPerScanTransferOpCommit(uint16_t connHandle) if (SchInsertAtDueTime(pOp, lctrPerScanResolveConflict)) { LL_TRACE_INFO1(" >>> Periodic scan from transfer started, handle=%u <<<", LCTR_GET_PER_SCAN_HANDLE(pPerScanCtx)); - LL_TRACE_INFO1(" pOp=%08x", pOp); LL_TRACE_INFO1(" dueUsec=%u", pOp->dueUsec); LL_TRACE_INFO1(" eventCounter=%u", pPerScanCtx->eventCounter); LL_TRACE_INFO1(" pBle->chan.chanIdx=%u", pBle->chan.chanIdx); @@ -1568,6 +1588,9 @@ lctrPerScanCtx_t *lctrAllocPerScanCtx(void) /* Default PHY. */ pCtx->rxPhys = lmgrConnCb.rxPhys; + /* ADI filtering. */ + pCtx->lastDid = LL_DID_NOT_PRESENT; + return pCtx; } } @@ -1602,8 +1625,6 @@ BbOpDesc_t *lctrPerScanResolveConflict(BbOpDesc_t *pNewOp, BbOpDesc_t *pExistOp) } /* Supervision timeout is imminent (2 PI). */ - LL_TRACE_WARN2("Exit timeout=%u, interval=%u", pExistCtx->tmrSupTimeout.ticks * WSF_MS_PER_TICK * 1000, (uint32_t)(pExistCtx->perInterUsec << 1)); - LL_TRACE_WARN2("New timeout=%u, interval=%u", pNewCtx->tmrSupTimeout.ticks * WSF_MS_PER_TICK * 1000, (uint32_t)(pExistCtx->perInterUsec << 1)); if ((pExistCtx->tmrSupTimeout.ticks * WSF_MS_PER_TICK * 1000) < (uint32_t)(pExistCtx->perInterUsec << 1)) { LL_TRACE_WARN2("!!! Scheduling conflict, imminent SVT: existing handle=%u prioritized over incoming handle=%u", LCTR_GET_PER_SCAN_HANDLE(pExistCtx), LCTR_GET_PER_SCAN_HANDLE(pNewCtx)); @@ -1617,7 +1638,6 @@ BbOpDesc_t *lctrPerScanResolveConflict(BbOpDesc_t *pNewOp, BbOpDesc_t *pExistOp) } /* Less frequent perInterval (4x). */ - if ((LCTR_PER_INTER_TO_MS(pExistCtx->perInterUsec) >> 2) > LCTR_PER_INTER_TO_MS(pNewCtx->perInterUsec)) { LL_TRACE_WARN2("!!! Scheduling conflict, PI frequency: existing handle=%u prioritized over incoming handle=%u", LCTR_GET_PER_SCAN_HANDLE(pExistCtx), LCTR_GET_PER_SCAN_HANDLE(pNewCtx)); @@ -1698,13 +1718,17 @@ void LctrSendPerSyncTrsfRcvdEvt(uint8_t status, lctrPerScanCtx_t *pPerScanCtx) * \brief Enable or disable reports for the periodic advertising sync. * * \param syncHandle Periodic sync handle. - * \param enable Enable or disable reporting. + * \param enable Enable options. */ /*************************************************************************************************/ -void LctrMstPerSetRcvEnable(uint16_t syncHandle, bool_t enable) +void LctrMstPerSetRcvEnable(uint16_t syncHandle, uint8_t enable) { WSF_ASSERT(syncHandle < LL_MAX_PER_SCAN); lctrPerScanCtx_t *pPerScanCtx = LCTR_GET_PER_SCAN_CTX(syncHandle); - pPerScanCtx->repDisabled = !enable; + pPerScanCtx->repDisabled = !((bool_t) ((enable >> LCTR_PER_RECV_ENABLE_REPORT_BIT_POS) & 1)); + if (!pPerScanCtx->repDisabled) + { + pPerScanCtx->dupFilterEnable = (bool_t) ((enable >> LCTR_PER_RECV_ENABLE_FILTERING_BIT_POS) & 1); + } } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_slave.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_slave.c index 4d3779c30c..f4287ce4f8 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_slave.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_slave.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -190,16 +190,18 @@ void lctrChooseAdvA(BbBleData_t * const pBle, lctrAdvbPduHdr_t *pPduHdr, void lctrChoosePeerAddr(BbBleData_t * const pBle, uint8_t ownAddrType, uint8_t peerAddrType, uint64_t peerAddr, uint64_t *pPeerRpa) { + /* Attempt to generate RPA for peer. */ + BbBleResListGeneratePeer(peerAddrType, peerAddr, pPeerRpa); + + /* Resolve peer RPAs whether or not a RPA was generated for peer, unless address resolution is disabled. */ if (lmgrCb.addrResEna) { - /* Attempt to generate RPA for peer. */ - if (ownAddrType & LL_ADDR_IDENTITY_BIT) - { - BbBleResListGeneratePeer(peerAddrType, peerAddr, pPeerRpa); - } - /* Resolve peer RPAs whether or not a RPA was generated for peer. */ BB_BLE_PDU_FILT_SET_FLAG(&pBle->pduFilt, PEER_ADDR_RES_ENA); } + else + { + BB_BLE_PDU_FILT_CLR_FLAG(&pBle->pduFilt, PEER_ADDR_RES_ENA); + } } /*************************************************************************************************/ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_slave_ae.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_slave_ae.c index d8dc6b8e3f..b7f1f4f931 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_slave_ae.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_slave_ae.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -451,57 +451,23 @@ static uint8_t lctrSetExtAdvDataSm(lctrAdvSet_t *pAdvSet, lctrAdvDataBuf_t *pDat /*** Complete single fragment buffer (no reassembly required) while advertising is enabled. ***/ if (pAdvSet->state == LCTR_EXT_ADV_STATE_ENABLED) { - bool_t isCancelled = FALSE; + /* BOD's are already running. Data will be updated in the end callback of the BOD's. */ + pDataBuf->alt.ext.len = fragLen; + memcpy(pDataBuf->alt.ext.buf, pFragBuf, fragLen); + pDataBuf->alt.ext.did = lctrCalcDID(pFragBuf, fragLen); + pDataBuf->alt.ext.fragPref = fragPref; + pDataBuf->alt.ext.modified = TRUE; - WSF_CS_ENTER(); /* Renew BOD's to make the data updated immediately if possible. */ if (SchIsBodCancellable(&pAdvSet->advBod) && ((pAdvSet->auxBodUsed == FALSE) || SchIsBodCancellable(&pAdvSet->auxAdvBod))) { - /* Temporarily disable abort callbacks. */ - pAdvSet->advBod.abortCback = NULL; - pAdvSet->auxAdvBod.abortCback = NULL; - - /* Remove BOD's */ - SchRemove(&pAdvSet->advBod); + /* Remove BOD's; remove completes in abortCback(). */ if (pAdvSet->auxBodUsed) { SchRemove(&pAdvSet->auxAdvBod); } - - isCancelled = TRUE; - } - WSF_CS_EXIT(); - - if (isCancelled) - { - pAdvSet->advData.len = fragLen; - memcpy(pAdvSet->advData.pBuf, pFragBuf, fragLen); - pAdvSet->param.advDID = lctrCalcDID(pFragBuf, fragLen); - pAdvSet->advData.fragPref = fragPref; - - /* Update superior PDU. */ - BbBleSlvAdvEvent_t * const pAdv = &pAdvSet->bleData.op.slvAdv; - pAdv->txAdvLen = lctrPackAdvExtIndPdu(pAdvSet, pAdvSet->advHdrBuf, FALSE); - - /* Re-insert BOD's */ - pAdvSet->advBod.abortCback = lctrSlvExtAdvAbortOp; - (void)SchInsertAtDueTime(&pAdvSet->advBod, NULL); - - if (pAdvSet->auxBodUsed) - { - pAdvSet->auxAdvBod.abortCback = lctrSlvAuxAdvEndOp; - (void)SchInsertAtDueTime(&pAdvSet->auxAdvBod, NULL); - } - } - else - { - /* BOD's are already running. Data will be updated in the end callback of the BOD's. */ - pDataBuf->alt.ext.len = fragLen; - memcpy(pDataBuf->alt.ext.buf, pFragBuf, fragLen); - pDataBuf->alt.ext.did = lctrCalcDID(pFragBuf, fragLen); - pDataBuf->alt.ext.fragPref = fragPref; - pDataBuf->alt.ext.modified = TRUE; + SchRemove(&pAdvSet->advBod); } return LL_SUCCESS; @@ -629,6 +595,7 @@ static uint8_t lctrSetPerAdvDataSm(lctrAdvSet_t *pAdvSet, lctrAdvDataBuf_t *pDat { pDataBuf->alt.ext.len = fragLen; memcpy(pDataBuf->alt.ext.buf, pFragBuf, fragLen); + pDataBuf->alt.ext.did = lctrCalcDID(pFragBuf, fragLen); pDataBuf->alt.ext.modified = TRUE; return LL_SUCCESS; @@ -676,16 +643,19 @@ static uint8_t lctrSetPerAdvDataSm(lctrAdvSet_t *pAdvSet, lctrAdvDataBuf_t *pDat /* Append buffer. */ memcpy(pDataBuf->pBuf + pDataBuf->len, pFragBuf, fragLen); pDataBuf->len += fragLen; + pAdvSet->perParam.advDID = lctrCalcDID(pFragBuf, fragLen); pDataBuf->ready = TRUE; break; case LL_ADV_DATA_OP_COMP: /* New buffer (discard old buffer). */ memcpy(pDataBuf->pBuf, pFragBuf, fragLen); pDataBuf->len = fragLen; + pAdvSet->perParam.advDID = lctrCalcDID(pFragBuf, fragLen); pDataBuf->ready = TRUE; break; case LL_ADV_DATA_OP_UNCHANGED: /* Same buffer. */ + pAdvSet->perParam.advDID = lctrCalcDID(pFragBuf, fragLen); pDataBuf->ready = TRUE; break; default: @@ -931,8 +901,6 @@ uint8_t lctrSlvExtAdvBuildOp(lctrAdvSet_t *pAdvSet, uint32_t maxStartMs) SchInsertNextAvailable(pOp); } - LL_TRACE_INFO1("### ExtAdvEvent ### Advertising enabled, dueUsec=%u", pOp->dueUsec); - /* Advertising offloading to auxiliary channel. */ if (pAdvSet->pExtAdvAuxPtr) { @@ -971,6 +939,13 @@ uint8_t lctrSlvExtAdvBuildOp(lctrAdvSet_t *pAdvSet, uint32_t maxStartMs) lctrSlvTxSetupExtAdvHandler(pOp, pOp->dueUsec); } + LL_TRACE_INFO1(" >>> ExtAdv started, handle=%u <<<", pAdvSet->handle); + LL_TRACE_INFO1(" priAdvInterMinUsec=%u", pAdvSet->param.priAdvInterMinUsec); + LL_TRACE_INFO1(" priAdvInterMaxUsec=%u", pAdvSet->param.priAdvInterMaxUsec); + LL_TRACE_INFO1(" dueUsec=%u", pOp->dueUsec); + LL_TRACE_INFO1(" pAdvBod=0x%08x", pOp); + LL_TRACE_INFO1(" pAuxAdvBod=0x%08x", &pAdvSet->auxAdvBod); + return LL_SUCCESS; } @@ -985,8 +960,8 @@ uint8_t lctrSlvExtAdvBuildOp(lctrAdvSet_t *pAdvSet, uint32_t maxStartMs) void lctrSlvAuxRescheduleOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pOp) { uint32_t auxOffsUsec = pAdvSet->advBod.minDurUsec + - WSF_MAX(BbGetSchSetupDelayUs(), LL_BLE_MAFS_US) + - WSF_MAX(pAdvSet->auxDelayUsec, pLctrRtCfg->auxDelayUsec); + WSF_MAX(BbGetSchSetupDelayUs(), LL_BLE_MAFS_US) + + WSF_MAX(pAdvSet->auxDelayUsec, pLctrRtCfg->auxDelayUsec); auxOffsUsec = WSF_MIN(auxOffsUsec, LL_AUX_PTR_MAX_USEC); @@ -996,14 +971,14 @@ void lctrSlvAuxRescheduleOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pOp) /* Update BOD duration because extended header length might have been updated. */ SchBleCalcAdvOpDuration(pOp, (pAdvSet->advData.fragPref == LL_ADV_DATA_FRAG_ALLOW) ? pAdvSet->advDataFragLen : 0); - pOp->dueUsec = pAdvSet->advBod.dueUsec + auxOffsUsec + pLctrRtCfg->auxPtrOffsetUsec; - if (pAdvSet->auxSkipInterUsec == 0) { + pOp->dueUsec = pAdvSet->advBod.dueUsec; + do { /* No delay after primary channel operation. */ - if (SchInsertAtDueTime(pOp, NULL)) + if (SchInsertEarlyAsPossible(pOp, auxOffsUsec + pLctrRtCfg->auxPtrOffsetUsec, pAdvSet->param.priAdvInterMaxUsec)) { break; } @@ -1017,10 +992,13 @@ void lctrSlvAuxRescheduleOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pOp) } else { + /* Using EXT_ADV_IND due time as a reference ensures AuxOffset value does not overflow. */ + pOp->dueUsec = pAdvSet->advBod.dueUsec; + do { /* Link multiple primary channel operations. */ - if (SchInsertLateAsPossible(pOp, 0, pAdvSet->auxSkipInterUsec)) + if (SchInsertLateAsPossible(pOp, auxOffsUsec + pLctrRtCfg->auxPtrOffsetUsec, pAdvSet->auxSkipInterUsec)) { break; } @@ -1054,13 +1032,13 @@ static void lctrSlvAuxCommitOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pOp) uint32_t advEvtDurUsec = pAdvSet->advBod.minDurUsec; uint32_t skipTimeUsec = pAdvSet->param.secAdvMaxSkip * /* number of skip events */ - (pAdvSet->param.priAdvInterMinUsec + /* minimum interval */ + (pAdvSet->param.priAdvInterMinUsec + /* minimum interval */ ((LL_MAX_ADV_DLY_MS >> 1) * 1000)) + /* average advDelay */ (LL_MAX_ADV_DLY_MS * 1000); /* ensure no overlap due to advDelay */ - skipTimeUsec = WSF_MIN(skipTimeUsec, - LCTR_AUX_PTR_MAX_OFFSET * 300); /* limit maximum */ + skipTimeUsec = WSF_MIN(skipTimeUsec, (LCTR_AUX_PTR_MAX_OFFSET * 300)); /* limit maximum */ + + pAdvSet->auxSkipInterUsec = WSF_MAX(skipTimeUsec, advEvtDurUsec); /* ensure minimum */ - pAdvSet->auxSkipInterUsec = WSF_MAX(skipTimeUsec, advEvtDurUsec); /* ensure minimum */ } lctrSlvAuxRescheduleOp(pAdvSet, pOp); @@ -2156,13 +2134,23 @@ uint8_t LctrSetPeriodicAdvData(uint8_t handle, uint8_t op, uint8_t len, const ui return LL_ERROR_CODE_UNKNOWN_ADV_ID; } - if ((pAdvSet->perParam.advParamReady == FALSE) || /* Adv set is not configured for periodic adv. */ - (pAdvSet->perParam.perAdvEnabled == TRUE && op != LL_ADV_DATA_OP_COMP) || /* When periodic adv is enabled, complete data shall be provided. Never gonna happen. */ - (len == 0 && op != LL_ADV_DATA_OP_COMP)) /* Existing data shall be deleted and no new data provided. */ + if (pAdvSet->perParam.advParamReady == FALSE) /* AdvSet is not configured for Periodic Advertising. */ { return LL_ERROR_CODE_CMD_DISALLOWED; } + if ((op != LL_ADV_DATA_OP_COMP) && (op != LL_ADV_DATA_OP_UNCHANGED)) + { + if (len == 0) + { + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + + if (pAdvSet->perParam.perAdvEnabled) + { + return LL_ERROR_CODE_CMD_DISALLOWED; + } + } uint32_t worstCaseUsec; uint16_t mafOffset = WSF_MAX(pAdvSet->auxDelayUsec, pLctrRtCfg->auxDelayUsec); @@ -2213,6 +2201,15 @@ uint8_t LctrSetPeriodicAdvData(uint8_t handle, uint8_t op, uint8_t len, const ui void LctrSetPeriodicAdvEnable(uint8_t handle, bool_t enable) { lctrAdvSet_t *pAdvSet; + bool_t enableAdv = enable & LL_PER_ADV_ENABLE_ADV_ENABLE_BIT; + bool_t enableAdi = (enable & LL_PER_ADV_ENABLE_ADI_ENABLE_BIT) >> 1; + + if ((enableAdv == TRUE) && (enableAdi == TRUE) && + !(lmgrCb.features & LL_FEAT_PER_ADV_ADI_SUP)) + { + LmgrSendPeriodicAdvEnableCnf(handle, LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE); + return; + } if ((pAdvSet = lctrFindAdvSet(handle)) == NULL) { @@ -2221,7 +2218,7 @@ void LctrSetPeriodicAdvEnable(uint8_t handle, bool_t enable) } if ((pAdvSet->perParam.advParamReady == FALSE) || /* Periodic advertising parameters shall be set. */ - ((enable == TRUE) && (pAdvSet->perAdvData.ready == FALSE)) || /* Periodic advertising data shall be complete. */ + ((enableAdv == TRUE) && (pAdvSet->perAdvData.ready == FALSE)) || /* Periodic advertising data shall be complete. */ (pAdvSet->param.advEventProp & (LL_ADV_EVT_PROP_CONN_ADV_BIT | LL_ADV_EVT_PROP_SCAN_ADV_BIT | /* Only non-connectable and non-scannable is allowed. */ LL_ADV_EVT_PROP_HIGH_DUTY_ADV_BIT | LL_ADV_EVT_PROP_OMIT_AA_BIT)))/* No high duty cycle, No anonymous advertising. */ { @@ -2229,13 +2226,15 @@ void LctrSetPeriodicAdvEnable(uint8_t handle, bool_t enable) return; } + pAdvSet->perParam.enableAdi = enableAdi; + LctrPerAdvEnableMsg_t *pMsg; if ((pMsg = WsfMsgAlloc(sizeof(*pMsg))) != NULL) { pMsg->hdr.handle = handle; pMsg->hdr.dispId = LCTR_DISP_PER_ADV; - pMsg->hdr.event = enable ? LCTR_PER_ADV_MSG_START : LCTR_PER_ADV_MSG_STOP; + pMsg->hdr.event = enableAdv ? LCTR_PER_ADV_MSG_START : LCTR_PER_ADV_MSG_STOP; WsfMsgSend(lmgrPersistCb.handlerId, pMsg); } @@ -2596,6 +2595,11 @@ void LctrSlvPeriodicAdvInit(void) { lmgrPersistCb.featuresDefault |= LL_FEAT_LE_PER_ADV; } + + if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_SYDNEY) + { + lmgrPersistCb.featuresDefault |= LL_FEAT_PER_ADV_ADI_SUP; + } } /*************************************************************************************************/ @@ -2635,8 +2639,6 @@ static void lctrSlvPeriodicCommitOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pO /* Advance to next interval. */ pOp->dueUsec = anchorPointUsec + perInterUsec; } - - LL_TRACE_INFO1("### ExtAdvEvent ### Periodic advertising enabled, dueUsec=%u", pOp->dueUsec); } /*************************************************************************************************/ @@ -2753,6 +2755,11 @@ uint8_t lctrSlvPeriodicAdvBuildOp(lctrAdvSet_t *pAdvSet) pAdvSet->perParam.perAdvInterUsec = perInterUsec; lctrSlvPeriodicCommitOp(pAdvSet, pOp); + LL_TRACE_INFO2(" >>> PerAdv started, AdvSet.handle=%u perChHopInc=%u <<<", pAdvSet->handle, pAdvSet->perParam.perChHopInc); + LL_TRACE_INFO1(" perInterUsec=%u", perInterUsec); + LL_TRACE_INFO1(" perAccessAddr=0x%08x", pAdvSet->perParam.perAccessAddr); + LL_TRACE_INFO1(" pPerAdvBod=0x%08x", pOp); + return LL_SUCCESS; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis.c index 86a91a7acc..f2eef9e3ce 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -133,12 +133,6 @@ static void lctrBisFragmentIsoSdu(lctrBisCtx_t *pBisCtx, lctrIsoHdr_t *pIsoHdr, uint64_t pktCtr = (pBisCtx->pBigCtx->eventCounter * pBisCtx->pBigCtx->bn) + pDesc->fragCnt; pBisCtx->chan.enc.pTxPktCounter = &pktCtr; - /* Set the new packet counter for inline encryption. */ - if (lctrSetEncryptPktCountHdlr) - { - lctrSetEncryptPktCountHdlr(&pBisCtx->chan.enc, pktCtr); - } - if (lctrPktEncryptHdlr && lctrPktEncryptHdlr(&pBisCtx->chan.enc, pDesc->frag[pDesc->fragCnt].hdr, @@ -221,14 +215,19 @@ void lctrFreeBigCtx(lctrBigCtx_t *pBigCtx) { lctrBisCtx_t *pBisCtx = pBigCtx->pBisCtx[i]; + if (pBisCtx == NULL) + { + /* Filtered BIS. */ + continue; + } + switch (pBigCtx->role) { case LL_ROLE_SLAVE: - lctrBisSetDataPath(pBisCtx, LL_ISO_DATA_DIR_INPUT, LL_ISO_DATA_PATH_DISABLED); - lctrNotifyIsoTxComplete(pBigCtx); + LctrRemoveIsoDataPath(pBisCtx->handle, LL_ISO_DATA_PATH_INPUT_BIT); break; case LL_ROLE_MASTER: - lctrBisSetDataPath(pBisCtx, LL_ISO_DATA_DIR_OUTPUT, LL_ISO_DATA_PATH_DISABLED); + LctrRemoveIsoDataPath(pBisCtx->handle, LL_ISO_DATA_PATH_OUTPUT_BIT); break; default: break; @@ -269,7 +268,8 @@ uint8_t lctrBigIsPerAdvUsed(uint8_t advHandle) if ((pBigCtx->enabled) && (pBigCtx->role == LL_ROLE_SLAVE) && - (pBigCtx->roleData.slv.pAdvSet)) + (pBigCtx->roleData.slv.pAdvSet) && + (pBigCtx->roleData.slv.pAdvSet->handle == advHandle)) { return TRUE; } @@ -372,7 +372,14 @@ lctrBisCtx_t *lctrAllocBisCtx(lctrBigCtx_t *pBigCtx) pBisCtx->pBigCtx = pBigCtx; pBisCtx->bisNum = pBigCtx->numBis + 1; - pBisCtx->path = LL_ISO_DATA_PATH_DISABLED; + if (pBigCtx->role == LL_ROLE_MASTER) + { + pBisCtx->roleData.mst.dataPathOutCtx.id = LL_ISO_DATA_PATH_DISABLED; + } + else + { + pBisCtx->roleData.slv.dataPathInCtx.id = LL_ISO_DATA_PATH_DISABLED; + } /* Parent context. */ pBigCtx->pBisCtx[pBigCtx->numBis++] = pBisCtx; @@ -384,17 +391,6 @@ lctrBisCtx_t *lctrAllocBisCtx(lctrBigCtx_t *pBigCtx) return NULL; } -/*************************************************************************************************/ -/*! - * \brief Cleanup BIS context, clean BIG context if necessary for slave. - * - * \param pBisCtx BIS context to free. - */ -/*************************************************************************************************/ -void lctrCleanupBisCtx(lctrBisCtx_t *pBisCtx) -{ -} - /*************************************************************************************************/ /*! * \brief Free a BIS context. @@ -413,11 +409,18 @@ void lctrFreeBisCtx(lctrBisCtx_t *pBisCtx) switch (pBisCtx->pBigCtx->role) { case LL_ROLE_MASTER: - while ((pPdu = lctrBisDequeueRxDataPdu(pBisCtx, NULL)) != NULL) + while ((pPdu = lctrBisDequeueRxDataPduTop(pBisCtx)) != NULL) { lctrBisRxIsoDataPduFree(pPdu); } + uint8_t *pIsoSdu; + while ((pIsoSdu = lctrBisRxIsoSduDeq(pBisCtx)) != NULL) + { + WsfMsgFree(pIsoSdu); + lctrIsoDataRxIncAvailBuf(1); + } + lctrIsoalRxDataPathClear(&pBisCtx->roleData.mst.isoalRxCtx, pBisCtx->pBigCtx->framing); break; case LL_ROLE_SLAVE: @@ -585,7 +588,10 @@ void lctrSetupBisContext(lctrBisCtx_t *pBisCtx, uint32_t seedAccAddr, uint16_t b pBisCtx->chan.enc.dir = 1; pBisCtx->chan.enc.type = PAL_BB_TYPE_BIS; - lctrInitCipherBlkHdlr(&pBisCtx->chan.enc, pBisCtx->handle, 1); + if (lctrInitCipherBlkHdlr) + { + lctrInitCipherBlkHdlr(&pBisCtx->chan.enc, pBisCtx->handle, 1); + } } } @@ -602,15 +608,25 @@ void lctrSelectBigChannels(lctrBigCtx_t *pBigCtx) for (unsigned int i = 0; i < pBigCtx->numBis; i++) { lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[i]; - pBisCtx->chan.chanIdx = LmgrSelectNextChannel(&pBisCtx->chSelInfo, pBigCtx->eventCounter, 0, TRUE); + + if (pBisCtx) + { + pBisCtx->chan.chanIdx = LmgrSelectNextChannel(&pBisCtx->chSelInfo, pBigCtx->eventCounter, 0, TRUE); + } } /* Select BIG Control channel. */ pBigCtx->ctrChan.chanIdx = LmgrSelectNextChannel(&pBigCtx->ctrChSelInfo, pBigCtx->eventCounter, 0, TRUE); /* Setup BOD for next BIG Event. */ - pBigCtx->bleData.chan.chanIdx = pBigCtx->pBisCtx[0]->chan.chanIdx; - + if (pBigCtx->role == LL_ROLE_SLAVE) + { + pBigCtx->bleData.chan.chanIdx = pBigCtx->pBisCtx[0]->chan.chanIdx; + } + else /* LL_ROLE_MASTER */ + { + pBigCtx->bleData.chan.chanIdx = pBigCtx->roleData.mst.pFirstBisCtx->chan.chanIdx; + } } /*************************************************************************************************/ @@ -627,8 +643,12 @@ void lctrRemapBigChannels(lctrBigCtx_t *pBigCtx, uint64_t chanMap) for (unsigned int i = 0; i < pBigCtx->numBis; i++) { lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[i]; - pBisCtx->chSelInfo.chanMask = chanMap; - LmgrBuildRemapTable(&pBisCtx->chSelInfo); + + if (pBisCtx) + { + pBisCtx->chSelInfo.chanMask = chanMap; + LmgrBuildRemapTable(&pBisCtx->chSelInfo); + } } /* Select BIG Control channel. */ @@ -653,7 +673,8 @@ void lctrBisTxIsoPduQueue(lctrBisCtx_t *pBisCtx, lctrIsoHdr_t *pIsoHdr, uint8_t { LL_TRACE_ERR1("Failed to allocate transmit buffer descriptor: bisHandle=%u", pIsoHdr->handle); WsfMsgFree(pIsoSdu); - if (!pBisCtx->test.enabled) + if (lmgrPersistCb.sendIsoCompCback && + !pBisCtx->test.enabled) { uint16_t handle = pIsoHdr->handle; uint16_t numSdu = 1; @@ -773,7 +794,7 @@ void lctrBisTxQueuePopCleanup(lctrBisCtx_t *pBisCtx, uint8_t numFrag) lctrFreeIsoTxBufDesc(pDesc); lctrIsoSduTxIncAvailBuf(); - if (pBisCtx->path == LL_ISO_DATA_PATH_HCI) + if (pBisCtx->roleData.slv.dataPathInCtx.id == LL_ISO_DATA_PATH_HCI) { /* ISO Test does not send Tx Complete notifications. */ if (!pBisCtx->test.enabled) @@ -931,8 +952,8 @@ uint8_t *lctrBisRxIsoDataPduAlloc(void) /* Return start of ISO Data PDU. */ pPdu += LCTR_ISO_SDU_START_OFFSET; - /* Do not claim buffer until committed. */ - /* lctrIsoDataRxDecAvailBuf(); */ + /* Do not claim buffer until SDU is committed. */ + /* lctrIsoDataRxDecAvailBuf(); */ /* SDU committed in lctrBisRxIsoSduEnq(). */ } return pPdu; @@ -952,25 +973,29 @@ uint8_t *lctrBisRxIsoDataPduAlloc(void) uint8_t *lctrBisRxIsoSduDeq(lctrBisCtx_t *pBisCtx) { wsfHandlerId_t bisHandle; + uint8_t *pSdu = NULL; - uint8_t *pSdu = WsfMsgDeq(&pBisCtx->roleData.mst.rxIsoSduQ, &bisHandle); + if (pBisCtx->test.enabled) + { + pSdu = WsfMsgDeq(&pBisCtx->roleData.mst.dataPathOutCtx.cfg.hci.rxDataQ, &bisHandle); + return pSdu; + } + + switch (pBisCtx->roleData.mst.dataPathOutCtx.id) + { + case LL_ISO_DATA_PATH_HCI: + pSdu = WsfMsgDeq(&pBisCtx->roleData.mst.dataPathOutCtx.cfg.hci.rxDataQ, &bisHandle); + break; + case LL_ISO_DATA_PATH_VS: + pSdu = WsfMsgDeq(&pBisCtx->roleData.mst.dataPathOutCtx.cfg.codec.rxDataQ, &bisHandle); + break; + default: + break; + } return pSdu; } -/*************************************************************************************************/ -/*! - * \brief Enqueue a received ISO SDU buffer. - * - * \param pBisCtx BIS context. - * \param pSdu BIS Data SDU buffer. - */ -/*************************************************************************************************/ -void lctrBisRxIsoSduEnq(lctrBisCtx_t *pBisCtx, uint8_t *pSdu) -{ - WsfMsgEnq(&pBisCtx->roleData.mst.rxIsoSduQ, pBisCtx->handle, pSdu); - lctrIsoDataRxDecAvailBuf(); -} /*************************************************************************************************/ /*! @@ -991,12 +1016,43 @@ void lctrBisRxIsoDataPduFree(uint8_t *pPdu) * * \param pBisCtx BIS context. * \param pRxBuf Received PDU data buffer to queue. - * \param evtCtr Event counter when packet was received. + * \param burstIdx Burst index. */ /*************************************************************************************************/ -void lctrBisEnqueueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t *pRxBuf, uint64_t evtCtr) +void lctrBisEnqueueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t *pRxBuf, uint8_t burstIdx) { - WsfMsgEnq(&pBisCtx->roleData.mst.rxDataQ, (uint8_t)evtCtr, pRxBuf - LCTR_ISO_SDU_START_OFFSET); + WsfMsgEnq(&pBisCtx->roleData.mst.rxDataQ, burstIdx, pRxBuf - LCTR_ISO_SDU_START_OFFSET); +} + +/*************************************************************************************************/ +/*! + * \brief Pop top element from Tx queue if it matches given \a bnIdx. + * + * \param pBisCtx BIS context. + * \param bnIdx Burst Number index. + * + * \return Pointer to ISO Data PDU. + */ +/*************************************************************************************************/ +uint8_t *lctrBisDequeueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t burstIdx) +{ + uint8_t *pBuf; + + uint8_t actBurstIdx; + + if (WsfMsgPeek(&pBisCtx->roleData.mst.rxDataQ, &actBurstIdx) == NULL) + { + return NULL; + } + + if (actBurstIdx != burstIdx) + { + return NULL; + } + + pBuf = WsfMsgDeq(&pBisCtx->roleData.mst.rxDataQ, &actBurstIdx); + + return pBuf + LCTR_ISO_SDU_START_OFFSET; } /*************************************************************************************************/ @@ -1004,22 +1060,16 @@ void lctrBisEnqueueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t *pRxBuf, uint64_t ev * \brief Pop top element from Tx queue. * * \param pBisCtx BIS context. - * \param pEvtCtrLsb Least significant byte of the event counter. * * \return Pointer to ISO Data PDU. */ /*************************************************************************************************/ -uint8_t *lctrBisDequeueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t *pEvtCtrLsb) +uint8_t *lctrBisDequeueRxDataPduTop(lctrBisCtx_t *pBisCtx) { uint8_t *pBuf; uint8_t temp8; - if (pEvtCtrLsb == NULL) - { - pEvtCtrLsb = &temp8; - } - - if ((pBuf = WsfMsgDeq(&pBisCtx->roleData.mst.rxDataQ, pEvtCtrLsb)) == NULL) + if ((pBuf = WsfMsgDeq(&pBisCtx->roleData.mst.rxDataQ, &temp8)) == NULL) { return NULL; } @@ -1074,6 +1124,7 @@ uint8_t lctrBisTxTest(lctrBisCtx_t *pBisCtx, uint8_t pldType) * \param pldType Payload length type. * * \return Status error code. + * */ /*************************************************************************************************/ uint8_t lctrBisRxTest(lctrBisCtx_t *pBisCtx, uint8_t pldType) @@ -1189,7 +1240,8 @@ void lctrNotifyIsoTxComplete(lctrBigCtx_t *pBigCtx) { lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[i]; - if (pBisCtx->path == LL_ISO_DATA_PATH_HCI) + if (pBisCtx && + (pBisCtx->roleData.slv.dataPathInCtx.id == LL_ISO_DATA_PATH_HCI)) { if (pBisCtx->roleData.slv.numTxSduComp) { @@ -1201,7 +1253,7 @@ void lctrNotifyIsoTxComplete(lctrBigCtx_t *pBigCtx) } } - if (numHandles) + if (lmgrPersistCb.sendIsoCompCback && numHandles) { /* Notify host completed SDUs. */ lmgrPersistCb.sendIsoCompCback(numHandles, handle, numSdu); @@ -1237,86 +1289,6 @@ void lctrBisCalcGroupSessionKey(const uint8_t *pGSKD, const uint8_t *pBC, uint8_ PalCryptoAesCmac(ik, pGSK, big3, 4); } -/*************************************************************************************************/ -/*! - * \brief Set the BIS data path. - * - * \param pBisCtx BIS context. - * \param dpDir Data path direction. - * \param dpId Data path ID. - * - * \return Status error code. - */ -/*************************************************************************************************/ -uint8_t lctrBisSetDataPath(lctrBisCtx_t *pBisCtx, LlIsoDataPathDir_t dpDir, LlIsoDataPath_t dpId) -{ - if (pBisCtx->path == dpId) - { - /* No change. */ - return LL_SUCCESS; - } - - /*** Stop current data path. ***/ - - switch (pBisCtx->path) - { - case LL_ISO_DATA_PATH_VS: - if (!lctrCodecHdlr.stop) - { - return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; - } - lctrCodecHdlr.stop(pBisCtx->handle); - break; - case LL_ISO_DATA_PATH_DISABLED: - case LL_ISO_DATA_PATH_HCI: - default: - /* No action required. */ - break; - } - - /*** Start new data path. ***/ - - pBisCtx->path = dpId; - - switch (dpId) - { - case LL_ISO_DATA_PATH_VS: - if (lctrCodecHdlr.start) - { - PalCodecSreamParam_t param = - { - .dir = (dpDir == LL_ISO_DATA_DIR_INPUT) ? PAL_CODEC_DIR_INPUT : PAL_CODEC_DIR_OUTPUT, - .chMask = PAL_CODEC_CH_LEFT_BIT | PAL_CODEC_CH_RIGHT_BIT, - .intervalUsec = pBisCtx->pBigCtx->isoInterUsec, - .pktCtr = (pBisCtx->pBigCtx->eventCounter + 1) * pBisCtx->pBigCtx->bn, - .rdyCback = lctrIsoSendCodecSdu - }; - - if (!lctrCodecHdlr.start(pBisCtx->handle, ¶m)) - { - LL_TRACE_WARN1("Failed to start the codec, dpId=%u", dpId); - pBisCtx->path = LL_ISO_DATA_PATH_DISABLED; - return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES; - } - } - else - { - LL_TRACE_WARN1("Codec not found, dpId=%u", dpId); - return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; - } - break; - case LL_ISO_DATA_PATH_DISABLED: - case LL_ISO_DATA_PATH_HCI: - /* No action required. */ - break; - default: - LL_TRACE_WARN1("Unknown Data Path, dpId=%u", dpId); - return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; - } - - return LL_SUCCESS; -} - /*************************************************************************************************/ /*! * \brief Calculate next subevent index values, using sequential packing. @@ -1328,7 +1300,7 @@ uint8_t lctrBisSetDataPath(lctrBisCtx_t *pBisCtx, LlIsoDataPathDir_t dpDir, LlIs * \return TRUE if more subevents pending, FALSE otherwise. */ /*************************************************************************************************/ -bool_t lctrSlvBisCalcNextIdxSequential(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts) +bool_t lctrBisCalcNextIdxSequential(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts) { /* Burst loop. */ @@ -1382,7 +1354,7 @@ bool_t lctrSlvBisCalcNextIdxSequential(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCt * \return TRUE if more subevents pending, FALSE otherwise. */ /*************************************************************************************************/ -bool_t lctrSlvBisCalcNextIdxInterleaved(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts) +bool_t lctrBisCalcNextIdxInterleaved(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts) { /* BIS loop. */ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis_master.c index 3b93cd3896..ae109f1757 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis_master.c @@ -6,7 +6,7 @@ * * Copyright (c) 2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -122,7 +122,7 @@ void LctrMstBisInit(void) /* Set supported features. */ if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_5_1) { - lmgrPersistCb.featuresDefault |= LL_FEAT_ISO_BROADCASTER; + lmgrPersistCb.featuresDefault |= LL_FEAT_ISO_SYNC; } } @@ -150,7 +150,7 @@ uint8_t LctrMstBigCreateSync(LlBigCreateSync_t *pParam) if (lctrFindBigByHandle(pParam->bigHandle) != NULL) { LL_TRACE_WARN1("LctrMstBigCreateSync: bigHandle=%u already in use", pParam->bigHandle); - return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; + return LL_ERROR_CODE_CMD_DISALLOWED; } pPerScanCtx = LCTR_GET_PER_SCAN_CTX(pParam->syncHandle); @@ -175,6 +175,17 @@ uint8_t LctrMstBigCreateSync(LlBigCreateSync_t *pParam) } pBigInfo = &pPerScanCtx->acadParams[LCTR_ACAD_ID_BIG_INFO].bigInfo; + if (pParam->numBis > pBigInfo->numBis) + { + LL_TRACE_WARN2("LctrMstBigCreateSync: invalid value for numBis=%u for this sync handle, validRange=1..%u", pParam->numBis, pBigInfo->numBis); + return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; + } + + if (pParam->numBis > LL_MAX_BIS) + { + LL_TRACE_WARN2("LctrMstBigCreateSync: invalid value for numBis=%u, validRange=1..%u", pParam->numBis, LL_MAX_BIS); + return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES; + } if (pParam->numBis > lctrGetNumAvailBisCtx()) { @@ -182,12 +193,6 @@ uint8_t LctrMstBigCreateSync(LlBigCreateSync_t *pParam) return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES; } - if (pParam->numBis > WSF_MIN(pBigInfo->numBis, LL_MAX_BIS)) - { - LL_TRACE_WARN2("LctrMstBigCreateSync: invalid value for numBis=%u, validRange=1..%u", pParam->numBis, WSF_MIN(pBigInfo->numBis, LL_MAX_BIS)); - return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; - } - for (unsigned int i = 0; i < pParam->numBis; i++) { if ((pParam->bis[i] < LL_MIN_BIS) || @@ -286,7 +291,7 @@ void LctrMstBigTerminateSync(uint8_t bigHandle) /*************************************************************************************************/ void lctrMstBigBuildOp(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo) { - lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[0]; + lctrBisCtx_t * const pBisCtx = pBigCtx->roleData.mst.pFirstBisCtx; BbOpDesc_t * const pOp = &pBigCtx->bod; BbBleData_t * const pBle = &pBigCtx->bleData; @@ -302,7 +307,7 @@ void lctrMstBigBuildOp(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo) pOp->protId = BB_PROT_BLE; pOp->prot.pBle = pBle; pOp->endCback = lctrMstBigEndOp; - pOp->abortCback = lctrMstBigEndOp; + pOp->abortCback = lctrMstBigAbortOp; pOp->pCtx = pBigCtx; /*** BLE General Setup ***/ @@ -337,17 +342,18 @@ void lctrMstBigBuildOp(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo) pBigCtx->roleData.mst.anchorPoint = pBigInfo->bigAnchorPoint; pBigCtx->roleData.mst.rxSyncTime = pBigCtx->roleData.mst.anchorPoint - pBigCtx->isoInterUsec; /* Expand receive window for initial synchronization due to resolution uncertainty. */ - pBigCtx->roleData.mst.extraWwUsec = (pBigInfo->bigOffsUnits == 0) ? 30 : 300; + pBigCtx->roleData.mst.initWwUsec = (pBigInfo->bigOffsUnits == 0) ? 30 : 300; uint32_t unsyncTimeUsec = 0; while (TRUE) { - uint32_t wwTotalUsec = lctrCalcWindowWideningUsec(unsyncTimeUsec, pBigCtx->roleData.mst.totalAcc); + uint32_t wwTotalUsec = lctrCalcWindowWideningUsec(unsyncTimeUsec, pBigCtx->roleData.mst.totalAcc) + + pBigCtx->roleData.mst.initWwUsec; /* TODO Limit to half the ISO Interval size */ - pOp->dueUsec = pBigCtx->roleData.mst.anchorPoint - wwTotalUsec; + pOp->dueUsec = pBigCtx->roleData.mst.anchorPoint + pBigCtx->roleData.mst.firstBisOffsUsec - wwTotalUsec; /* Multiply 2 for before and after BIG Anchor Point. */ - pBis->rxSyncDelayUsec = (wwTotalUsec << 1) + pBigCtx->roleData.mst.extraWwUsec; + pBis->rxSyncDelayUsec = (wwTotalUsec << 1); lctrSelectBigChannels(pBigCtx); @@ -356,7 +362,7 @@ void lctrMstBigBuildOp(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo) break; } - LL_TRACE_WARN1("!!! BIG schedule conflict handle=%u", pBigCtx->handle); + LL_TRACE_WARN2("!!! BIG schedule conflict handle=%u, ec[15:0]=%u", pBigCtx->handle, pBigCtx->eventCounter); /* Advance to next interval. */ pBigCtx->eventCounter += 1; @@ -443,14 +449,15 @@ void lctrMstSetupBigContext(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo) /*************************************************************************************************/ void lctrMstSetupBigChannel(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo) { - pBigCtx->ctrChSelInfo.chanMask = pBigInfo->chanMap; - pBigCtx->ctrChSelInfo.usedChSel = LL_CH_SEL_2; - pBigCtx->ctrChSelInfo.chIdentifier = (uint16_t)(LL_BIG_CONTROL_ACCESS_ADDR >> 16) ^ - (uint16_t)(LL_BIG_CONTROL_ACCESS_ADDR >> 0); - LmgrBuildRemapTable(&pBigCtx->ctrChSelInfo); - pBigCtx->ctrChan.opType = BB_BLE_OP_MST_BIS_EVENT; pBigCtx->ctrChan.accAddr = lctrComputeBisAccessAddr(pBigInfo->seedAccAddr, 0); + + pBigCtx->ctrChSelInfo.chanMask = pBigInfo->chanMap; + pBigCtx->ctrChSelInfo.usedChSel = LL_CH_SEL_2; + pBigCtx->ctrChSelInfo.chIdentifier = (uint16_t)(pBigCtx->ctrChan.accAddr >> 16) ^ + (uint16_t)(pBigCtx->ctrChan.accAddr >> 0); + LmgrBuildRemapTable(&pBigCtx->ctrChSelInfo); + pBigCtx->ctrChan.crcInit = (pBigCtx->baseCrcInit << 8) | 0; pBigCtx->ctrChan.rxPhy = pBigCtx->phy; @@ -468,10 +475,10 @@ void lctrMstSetupBigChannel(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo) pBigCtx->ctrChan.enc.nonceMode = PAL_BB_NONCE_MODE_EXT64_CNTR; memcpy(pBigCtx->ctrChan.enc.iv, pBigCtx->giv, LL_IV_LEN); - pBigCtx->ctrChan.enc.iv[0] ^= LL_BIG_CONTROL_ACCESS_ADDR >> 0; - pBigCtx->ctrChan.enc.iv[1] ^= LL_BIG_CONTROL_ACCESS_ADDR >> 8; - pBigCtx->ctrChan.enc.iv[2] ^= LL_BIG_CONTROL_ACCESS_ADDR >> 16; - pBigCtx->ctrChan.enc.iv[3] ^= LL_BIG_CONTROL_ACCESS_ADDR >> 24; + pBigCtx->ctrChan.enc.iv[0] ^= pBigCtx->ctrChan.accAddr >> 0; + pBigCtx->ctrChan.enc.iv[1] ^= pBigCtx->ctrChan.accAddr >> 8; + pBigCtx->ctrChan.enc.iv[2] ^= pBigCtx->ctrChan.accAddr >> 16; + pBigCtx->ctrChan.enc.iv[3] ^= pBigCtx->ctrChan.accAddr >> 24; memcpy(pBigCtx->ctrChan.enc.sk, pBigCtx->bleData.chan.enc.sk, PAL_CRYPTO_LL_KEY_LEN); @@ -479,7 +486,10 @@ void lctrMstSetupBigChannel(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo) pBigCtx->ctrChan.enc.dir = 1; pBigCtx->ctrChan.enc.type = PAL_BB_TYPE_BIS; - lctrInitCipherBlkHdlr(&pBigCtx->ctrChan.enc, LCTR_BIG_CTRL_ENC_ID(pBigCtx), 1); + if (lctrInitCipherBlkHdlr) + { + lctrInitCipherBlkHdlr(&pBigCtx->ctrChan.enc, LCTR_BIG_CTRL_ENC_ID(pBigCtx), 1); + } } } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis_slave.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis_slave.c index 1928a6384b..ce50e076e8 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis_slave.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis_slave.c @@ -6,7 +6,7 @@ * * Copyright (c) 2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -124,8 +124,8 @@ static void lctrSlvSetupBigContext(lctrBigCtx_t *pBigCtx, LlCreateBig_t *pCreate case LL_PACKING_INTERLEAVED: { pBigCtx->bisSpaceUsec = lctrBisCalcMaxPduTimeUsec(pBigCtx->phy, pBigCtx->maxPdu, pCreateBig->encrypt); - pBigCtx->subInterUsec = pBigCtx->bisSpaceUsec * pBigCtx->nse; - pBigCtx->syncDelayUsec = pCreateBig->numBis * pBigCtx->subInterUsec; + pBigCtx->subInterUsec = pBigCtx->bisSpaceUsec * pCreateBig->numBis; + pBigCtx->syncDelayUsec = (pCreateBig->numBis * pBigCtx->subInterUsec) - LL_BLE_TMSS_US; break; } @@ -134,7 +134,7 @@ static void lctrSlvSetupBigContext(lctrBigCtx_t *pBigCtx, LlCreateBig_t *pCreate { pBigCtx->subInterUsec = lctrBisCalcMaxPduTimeUsec(pBigCtx->phy, pBigCtx->maxPdu, pCreateBig->encrypt); pBigCtx->bisSpaceUsec = pBigCtx->subInterUsec * pBigCtx->nse; - pBigCtx->syncDelayUsec = pCreateBig->numBis * pBigCtx->bisSpaceUsec; + pBigCtx->syncDelayUsec = (pCreateBig->numBis * pBigCtx->bisSpaceUsec) - LL_BLE_TMSS_US; break; } } @@ -142,9 +142,18 @@ static void lctrSlvSetupBigContext(lctrBigCtx_t *pBigCtx, LlCreateBig_t *pCreate /* Ensure successful divide. */ if (pBigCtx->bn || pBigCtx->sduInterUsec) { - pBigCtx->transLatUsec = pBigCtx->syncDelayUsec + - pBigCtx->pto * (pBigCtx->nse / pBigCtx->bn - pBigCtx->irc) * pBigCtx->isoInterUsec + - ((pBigCtx->isoInterUsec / pBigCtx->sduInterUsec) - 1) * pBigCtx->sduInterUsec; + if (pBigCtx->framing == LL_ISO_PDU_TYPE_FRAMED) + { + pBigCtx->transLatUsec = pBigCtx->syncDelayUsec + + pBigCtx->pto * (pBigCtx->nse / pBigCtx->bn - pBigCtx->irc) * pBigCtx->isoInterUsec + + pBigCtx->isoInterUsec + pBigCtx->sduInterUsec; + } + else + { + pBigCtx->transLatUsec = pBigCtx->syncDelayUsec + + pBigCtx->pto * (pBigCtx->nse / pBigCtx->bn - pBigCtx->irc) * pBigCtx->isoInterUsec + + ((pBigCtx->isoInterUsec / pBigCtx->sduInterUsec) - 1) * pBigCtx->sduInterUsec; + } } else { @@ -188,15 +197,15 @@ static void lctrSlvSetupBigTestContext(lctrBigCtx_t *pBigCtx, LlCreateBigTest_t pBigCtx->bn = pCreateBigTest->bn; pBigCtx->irc = pCreateBigTest->irc; pBigCtx->pto = pCreateBigTest->pto; - pBigCtx->nse = (pBigCtx->bn + pBigCtx->pto) * pBigCtx->irc; + pBigCtx->nse = pCreateBigTest->nse; switch (pBigCtx->packing) { case LL_PACKING_INTERLEAVED: { pBigCtx->bisSpaceUsec = lctrBisCalcMaxPduTimeUsec(pBigCtx->phy, pBigCtx->maxPdu, pCreateBigTest->encrypt); - pBigCtx->subInterUsec = pBigCtx->bisSpaceUsec * pBigCtx->nse; - pBigCtx->syncDelayUsec = pCreateBigTest->numBis * pBigCtx->subInterUsec; + pBigCtx->subInterUsec = pBigCtx->bisSpaceUsec * pCreateBigTest->numBis; + pBigCtx->syncDelayUsec = (pCreateBigTest->numBis * pBigCtx->subInterUsec) - LL_BLE_TMSS_US; break; } @@ -205,7 +214,7 @@ static void lctrSlvSetupBigTestContext(lctrBigCtx_t *pBigCtx, LlCreateBigTest_t { pBigCtx->subInterUsec = lctrBisCalcMaxPduTimeUsec(pBigCtx->phy, pBigCtx->maxPdu, pCreateBigTest->encrypt); pBigCtx->bisSpaceUsec = pBigCtx->subInterUsec * pBigCtx->nse; - pBigCtx->syncDelayUsec = pCreateBigTest->numBis * pBigCtx->bisSpaceUsec; + pBigCtx->syncDelayUsec = (pCreateBigTest->numBis * pBigCtx->bisSpaceUsec) - LL_BLE_TMSS_US; break; } } @@ -213,9 +222,18 @@ static void lctrSlvSetupBigTestContext(lctrBigCtx_t *pBigCtx, LlCreateBigTest_t /* Ensure successful divide. */ if (pBigCtx->bn || pBigCtx->sduInterUsec) { - pBigCtx->transLatUsec = pBigCtx->syncDelayUsec + - pBigCtx->pto * (pBigCtx->nse / pBigCtx->bn - pBigCtx->irc) * pBigCtx->isoInterUsec + - ((pBigCtx->isoInterUsec / pBigCtx->sduInterUsec) - 1) * pBigCtx->sduInterUsec; + if (pBigCtx->framing == LL_ISO_PDU_TYPE_FRAMED) + { + pBigCtx->transLatUsec = pBigCtx->syncDelayUsec + + pBigCtx->pto * (pBigCtx->nse / pBigCtx->bn - pBigCtx->irc) * pBigCtx->isoInterUsec + + pBigCtx->isoInterUsec + pBigCtx->sduInterUsec; + } + else + { + pBigCtx->transLatUsec = pBigCtx->syncDelayUsec + + pBigCtx->pto * (pBigCtx->nse / pBigCtx->bn - pBigCtx->irc) * pBigCtx->isoInterUsec + + ((pBigCtx->isoInterUsec / pBigCtx->sduInterUsec) - 1) * pBigCtx->sduInterUsec; + } } else { @@ -236,15 +254,15 @@ static void lctrSlvSetupBigChannel(lctrBigCtx_t *pBigCtx) pBigCtx->seedAccAddr = lctrComputeSeedAccessAddr(); pBigCtx->baseCrcInit = lctrComputeCrcInit() >> 8; - pBigCtx->ctrChSelInfo.chanMask = lmgrCb.chanClass; - pBigCtx->ctrChSelInfo.usedChSel = LL_CH_SEL_2; - pBigCtx->ctrChSelInfo.chIdentifier = (uint16_t)(LL_BIG_CONTROL_ACCESS_ADDR >> 16) ^ - (uint16_t)(LL_BIG_CONTROL_ACCESS_ADDR >> 0); - LmgrBuildRemapTable(&pBigCtx->ctrChSelInfo); - pBigCtx->ctrChan.opType = BB_BLE_OP_SLV_BIS_EVENT; pBigCtx->ctrChan.accAddr = lctrComputeBisAccessAddr(pBigCtx->seedAccAddr, 0); + pBigCtx->ctrChSelInfo.chanMask = lmgrCb.chanClass; + pBigCtx->ctrChSelInfo.usedChSel = LL_CH_SEL_2; + pBigCtx->ctrChSelInfo.chIdentifier = (uint16_t)(pBigCtx->ctrChan.accAddr >> 16) ^ + (uint16_t)(pBigCtx->ctrChan.accAddr >> 0); + LmgrBuildRemapTable(&pBigCtx->ctrChSelInfo); + pBigCtx->ctrChan.crcInit = (pBigCtx->baseCrcInit << 8) | 0; pBigCtx->ctrChan.txPower = lmgrCb.advTxPwr; pBigCtx->ctrChan.txPhy = pBigCtx->phy; @@ -266,10 +284,10 @@ static void lctrSlvSetupBigChannel(lctrBigCtx_t *pBigCtx) pBigCtx->ctrChan.enc.nonceMode = PAL_BB_NONCE_MODE_EXT64_CNTR; memcpy(pBigCtx->ctrChan.enc.iv, pBigCtx->giv, LL_IV_LEN); - pBigCtx->ctrChan.enc.iv[0] ^= LL_BIG_CONTROL_ACCESS_ADDR >> 0; - pBigCtx->ctrChan.enc.iv[1] ^= LL_BIG_CONTROL_ACCESS_ADDR >> 8; - pBigCtx->ctrChan.enc.iv[2] ^= LL_BIG_CONTROL_ACCESS_ADDR >> 16; - pBigCtx->ctrChan.enc.iv[3] ^= LL_BIG_CONTROL_ACCESS_ADDR >> 24; + pBigCtx->ctrChan.enc.iv[0] ^= pBigCtx->ctrChan.accAddr >> 0; + pBigCtx->ctrChan.enc.iv[1] ^= pBigCtx->ctrChan.accAddr >> 8; + pBigCtx->ctrChan.enc.iv[2] ^= pBigCtx->ctrChan.accAddr >> 16; + pBigCtx->ctrChan.enc.iv[3] ^= pBigCtx->ctrChan.accAddr >> 24; memcpy(pBigCtx->ctrChan.enc.sk, pBigCtx->bleData.chan.enc.sk, PAL_CRYPTO_LL_KEY_LEN); @@ -277,7 +295,10 @@ static void lctrSlvSetupBigChannel(lctrBigCtx_t *pBigCtx) pBigCtx->ctrChan.enc.dir = 1; pBigCtx->ctrChan.enc.type = PAL_BB_TYPE_BIS; - lctrInitCipherBlkHdlr(&pBigCtx->ctrChan.enc, LCTR_BIG_CTRL_ENC_ID(pBigCtx), 1); + if (lctrInitCipherBlkHdlr) + { + lctrInitCipherBlkHdlr(&pBigCtx->ctrChan.enc, LCTR_BIG_CTRL_ENC_ID(pBigCtx), 1); + } } } @@ -508,7 +529,7 @@ void LctrSlvBisInit(void) /* Set supported features. */ if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_5_1) { - lmgrPersistCb.featuresDefault |= LL_FEAT_ISO_BROADCASTER; + lmgrPersistCb.featuresDefault |= LL_FEAT_ISO_SYNC; } } @@ -574,7 +595,8 @@ uint8_t LctrSlvBisCreateBig(LlCreateBig_t *pCreateBig) if (pBisCtx) { - lctrSetupBisContext(pBisCtx, pBigCtx->seedAccAddr, pBigCtx->baseCrcInit, lmgrCb.chanClass, pBigCtx->phy); + lctrSetupBisContext(pBisCtx, pBigCtx->seedAccAddr, pBigCtx->baseCrcInit, lmgrCb.chanClass, + (LlPhy_t)pBigCtx->phy); } else { @@ -663,7 +685,8 @@ uint8_t LctrSlvBisCreateBigTest(LlCreateBigTest_t *pCreateBigTest) if (pBisCtx) { - lctrSetupBisContext(pBisCtx, pBigCtx->seedAccAddr, pBigCtx->baseCrcInit, lmgrCb.chanClass, pBigCtx->phy); + lctrSetupBisContext(pBisCtx, pBigCtx->seedAccAddr, pBigCtx->baseCrcInit, lmgrCb.chanClass, + (LlPhy_t)pBigCtx->phy); } else { @@ -932,10 +955,10 @@ uint8_t lctrSlvBigBuildOp(lctrBigCtx_t *pBigCtx) return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES; } - const uint32_t curTime = PalBbGetCurrentTime(); - uint32_t offsetUsec = SchRmGetOffsetUsec(pOp->minDurUsec, - LCTR_BIG_TO_RM_HANDLE(pBigCtx), curTime); - pOp->dueUsec = curTime + offsetUsec; + const uint32_t refTime = pBigCtx->roleData.slv.pAdvSet->advBod.dueUsec; + uint32_t offsetUsec = SchRmGetOffsetUsec(pBigCtx->isoInterUsec, + LCTR_BIG_TO_RM_HANDLE(pBigCtx), refTime); + pOp->dueUsec = refTime + offsetUsec; while (TRUE) { diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis.c index 7bba985c83..efbac7ad72 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -143,6 +143,38 @@ void lctrCleanupCtx(lctrCisCtx_t *pCisCtx) lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); WSF_ASSERT(pCigCtx); + uint8_t *pBuf; + uint8_t numTxBufs; + wsfHandlerId_t handlerId; + + pCisCtx->cisEvtCounter = 0; + pCisCtx->firstFromPeer = FALSE; + pCisCtx->connEst = FALSE; + + /* Must do one at a time in case one datapath is not used. */ + LctrRemoveIsoDataPath(pCisCtx->cisHandle, LL_ISO_DATA_PATH_INPUT_BIT); + LctrRemoveIsoDataPath(pCisCtx->cisHandle, LL_ISO_DATA_PATH_OUTPUT_BIT); + + /* Flush remaining transmit packets. */ + numTxBufs = lctrCisTxQueueClear(pCisCtx); + + /* Flush remaining transmit packets. */ + while ((pBuf = WsfMsgDeq(&pCisCtx->txIsoQ, &handlerId)) != NULL) + { + lctrDataTxIncAvailBuf(); + numTxBufs++; + + WsfMsgFree(pBuf); + } + + /* Flush remaining Tx/Rx flush timeout list. */ + lctrCisFtListClear(&pCisCtx->txFtParamList); + lctrCisFtListClear(&pCisCtx->rxFtParamList); + + /* Cleanup timers. */ + WsfTimerStop(&pCisCtx->tmrSupTimeout); + WsfTimerStop(&pCisCtx->tmrProcRsp); + if (lctrCisIsHeadCis(&pCigCtx->list, pCisCtx) == TRUE) { pCigCtx->headCisRmved = TRUE; @@ -177,6 +209,11 @@ void lctrCleanupCtx(lctrCisCtx_t *pCisCtx) if (lctrCisIsListEmpty(&pCigCtx->list)) { + /* Refresh CIG context to get ready for re-starting CIS. */ + pCigCtx->headCisRmved = FALSE; + pCigCtx->isBodBuilt = FALSE; + pCigCtx->isBodStarted = FALSE; + if (pCigCtx->isRmAdded == TRUE) { SchRmRemove(LCTR_GET_CIG_RM_HANDLE(pCigCtx)); @@ -204,7 +241,6 @@ void lctrCleanupCtx(lctrCisCtx_t *pCisCtx) } void *pIsoBuf; - uint8_t handlerId; while ((pIsoBuf = WsfMsgDeq(&pCisCtx->isoalTxCtx.pendingSduQ, &handlerId)) != NULL) { WsfMsgFree(pIsoBuf); @@ -222,36 +258,8 @@ void lctrCleanupCtx(lctrCisCtx_t *pCisCtx) /*************************************************************************************************/ void lctrFreeCisCtx(lctrCisCtx_t *pCisCtx) { - uint8_t *pBuf; - uint8_t numTxBufs; - wsfHandlerId_t handlerId; - WSF_ASSERT(pCisCtx->enabled); pCisCtx->enabled = FALSE; - - /* Clean up receive context. */ - lctrIsoOutDataPathClear(&pCisCtx->dataPathOutCtx); - - /* Flush remaining transmit packets. */ - numTxBufs = lctrCisTxQueueClear(pCisCtx); - - /* Flush remaining transmit packets. */ - while ((pBuf = WsfMsgDeq(&pCisCtx->txIsoQ, &handlerId)) != NULL) - { - lctrDataTxIncAvailBuf(); - numTxBufs++; - - WsfMsgFree(pBuf); - } - - /* Flush remaining Tx/Rx flush timeout list. */ - lctrCisFtListClear(&pCisCtx->txFtParamList); - lctrCisFtListClear(&pCisCtx->rxFtParamList); - - /* Cleanup timers. */ - WsfTimerStop(&pCisCtx->tmrSupTimeout); - WsfTimerStop(&pCisCtx->tmrProcRsp); - } /*************************************************************************************************/ @@ -444,7 +452,6 @@ uint16_t LctrInitCisMem(uint8_t *pFreeMem, uint32_t freeMemSize) pLctrCisTbl = (lctrCisCtx_t *)pAvailMem; pAvailMem += sizeof(lctrCisCtx_t) * pLctrRtCfg->maxCis; - if (((uint32_t)pAvailMem) & 3) { /* Align to next word. */ @@ -493,7 +500,7 @@ void lctrCisInitFtParam(lctrFtParam_t *pFtParam, uint8_t bn, uint8_t ft, uint8_t if (bn == 1) { /* BN = 1, numSubEvtFt[0] = BN * NSE */ - pFtParam->lastSubEvtFt[0] = bn * nse; + pFtParam->lastSubEvtFt[0] = nse; pFtParam->isPduDone[0] = FALSE; pFtParam->pduType[0] = LCTR_CIS_PDU_DEFAULT; } @@ -784,7 +791,6 @@ void lctrCisSetupEncrypt(lctrCisCtx_t *pCisCtx) PalCryptoAesEcb(pCtx->ltk, pEnc->sk, pCtx->skd); - WSF_ASSERT(lctrInitCipherBlkHdlr); memcpy(pEnc->iv, pCtx->iv, sizeof(pEnc->iv)); uint8_t *pTemp, accAddr[4]; pTemp = accAddr; @@ -796,7 +802,10 @@ void lctrCisSetupEncrypt(lctrCisCtx_t *pCisCtx) pEnc->dir = (pCisCtx->role == LL_ROLE_MASTER) ? 1 : 0; /* master = 1; slave = 0 */ pEnc->type = PAL_BB_TYPE_CIS; - lctrInitCipherBlkHdlr(pEnc, pCisCtx->cisHandle, pEnc->dir); + if (lctrInitCipherBlkHdlr) + { + lctrInitCipherBlkHdlr(pEnc, pCisCtx->cisHandle, pEnc->dir); + } pEnc->enaEncrypt = pCtx->bleData.chan.enc.enaEncrypt; pEnc->enaDecrypt = pCtx->bleData.chan.enc.enaDecrypt; @@ -1638,7 +1647,14 @@ uint32_t lctrCisCalcSubEvtDurationUsecSeq(uint8_t phyMToS, uint8_t phySToM, uint duration += LL_DATA_LEN_TO_TIME_2M(plMToS, TRUE); break; case BB_PHY_BLE_CODED: - duration += LL_DATA_LEN_TO_TIME_CODED_S8(plMToS, TRUE); + if (lmgrGetOpFlag(LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2)) + { + duration += LL_DATA_LEN_TO_TIME_CODED_S2(plMToS, TRUE); + } + else + { + duration += LL_DATA_LEN_TO_TIME_CODED_S8(plMToS, TRUE); + } break; } @@ -1655,7 +1671,14 @@ uint32_t lctrCisCalcSubEvtDurationUsecSeq(uint8_t phyMToS, uint8_t phySToM, uint duration += LL_DATA_LEN_TO_TIME_2M(plSToM, TRUE); break; case BB_PHY_BLE_CODED: - duration += LL_DATA_LEN_TO_TIME_CODED_S8(plSToM, TRUE); + if (lmgrGetOpFlag(LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2)) + { + duration += LL_DATA_LEN_TO_TIME_CODED_S2(plSToM, TRUE); + } + else + { + duration += LL_DATA_LEN_TO_TIME_CODED_S8(plSToM, TRUE); + } break; } @@ -1745,65 +1768,168 @@ void lctrCisTxTestPayloadHandler(lctrCisCtx_t * pCisCtx) /*************************************************************************************************/ /*! - * \brief Action function for cis power monitoring. + * \brief Generate a lost/invalid SDU in case of flushed SDU. * - * \param rssi CIS RX RSSI. - * \param status rx status. - * \param phy phy. - * \param pConnCtx Connection context. -*************************************************************************************************/ -void lctrCisPowerMonitorCheckRssi(int8_t rssi, uint8_t status, uint8_t phy, lctrConnCtx_t *pConnCtx) + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisCheckUnframedFlush(lctrCisCtx_t *pCisCtx) { - if (!(pConnCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST)) + /*** Send up error SDU ***/ + uint8_t handlerId; + uint8_t *pSdu; + uint8_t numHandles = 0; + uint16_t handles[1] = { pCisCtx->cisHandle }; + uint16_t numSdu[1] = { 0 }; + + /* NULL signals lost PDU; release previously stored fragments. */ + if (lctrRecombineRxUnframedSdu(&pCisCtx->isoalRxCtx, NULL)) + { + while ((pSdu = WsfMsgDeq(&pCisCtx->isoalRxCtx.data.unframed.pendSduQ, &handlerId)) != NULL) + { + /* Enqueue SDU for processing. */ + if (!lctrIsoRxConnEnq(&pCisCtx->dataPathOutCtx, pCisCtx->cisHandle, + pCisCtx->rxPktCounter, pSdu)) + { + /* The buffer was not freed, so free it now. */ + WsfMsgFree(pSdu); + } + + numHandles = 1; + numSdu[0]++; + } + } + else + { + if (lmgrGetOpFlag(LL_OP_MODE_FLAG_ENA_ISO_LOST_NOTIFY) && + (((pCisCtx->role == LL_ROLE_SLAVE) && (pCisCtx->data.slv.rxFromMaster == FALSE)) || + ((pCisCtx->role == LL_ROLE_MASTER) && (pCisCtx->data.mst.rxFromSlave == FALSE)))) + { + /* No prior fragments; send lost SDU. */ + if ((pSdu = lctrRxSduAlloc()) != NULL) + { + /* TODO: This code path increases this twice: once in lctrRxSduAlloc and lctrIsoRxConnEnq. + * Change to only increase once. + */ + lctrIsoDataRxIncAvailBuf(1); + + lctrIsoHdr_t isoHdr = + { + /* ISO header */ + .handle = pCisCtx->cisHandle, + .pb = LCTR_PB_COMP, + .tsFlag = FALSE, + .len = 0, + + /* Data load */ + .ts = 0, + .pktSn = pCisCtx->rxPktCounter, + .sduLen = 0, + .ps = LCTR_PS_LOST + }; + + lctrIsoPackHdr(pSdu, &isoHdr); + + /* Enqueue SDU for processing. */ + if (!lctrIsoRxConnEnq(&pCisCtx->dataPathOutCtx, pCisCtx->cisHandle, + pCisCtx->rxPktCounter, pSdu)) + { + /* The buffer was not freed, so free it now. */ + WsfMsgFree(pSdu); + } + numHandles = 1; + numSdu[0]++; + } + else + { + LL_TRACE_WARN0("SDU Could not be allocated."); + } + } + } + + if (lmgrPersistCb.recvIsoPendCback && numHandles) + { + /* Notify host received SDUs. */ + lmgrPersistCb.recvIsoPendCback(numHandles, handles, numSdu); + } +} + +/*************************************************************************************************/ +/*! + * \brief Service function for CIS power control. + * + * \param pConnCtx Connection context. + * +*************************************************************************************************/ +void lctrCisServicePowerMonitor(lctrConnCtx_t *pConnCtx) +{ + if (!(pConnCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST) || + lmgrGetOpFlag(LL_OP_MODE_FLAG_DIS_POWER_MONITOR)) { pConnCtx->monitoringState = LCTR_PC_MONITOR_DISABLED; return; } - if (lmgrCb.opModeFlags & LL_OP_MODE_DISABLE_POWER_MONITOR) - { - return; - } - int8_t sendReqDelta = 0; + lctrCisCtx_t *pCisCtx = NULL; - if ((rssi < pConnCtx->pclMonitorParam.autoMonitor.lowThreshold) || - (status != BB_STATUS_SUCCESS)) + for (unsigned int i = 0; i < pLctrRtCfg->maxCis; i++) { - pConnCtx->cisRssiExtremeTimeSpent++; + pCisCtx = &pLctrCisTbl[i]; - if (pConnCtx->cisRssiExtremeTimeSpent >= pConnCtx->pclMonitorParam.autoMonitor.minTimeSpent) + if ((pCisCtx->aclHandle == LCTR_GET_CONN_HANDLE(pConnCtx)) && + (pCisCtx->enabled) && (pCisCtx->connEst)) { - if (!(pConnCtx->peerPwrLimits & LL_PWR_CONTROL_LIMIT_MAX_BIT)) + if (((pCisCtx->role == LL_ROLE_SLAVE) && (pCisCtx->phyMToS == pConnCtx->bleData.chan.rxPhy)) || + ((pCisCtx->role == LL_ROLE_MASTER) && (pCisCtx->phySToM == pConnCtx->bleData.chan.rxPhy))) { - LL_TRACE_INFO1("RSSI too low, requesting increase in power. phy=%u", phy); - sendReqDelta = pConnCtx->pclMonitorParam.autoMonitor.requestVal; + /* This power is already managed by ACL, so no need to run management on CIS. */ + return; } - pConnCtx->cisRssiExtremeTimeSpent = 0; + + goto CisManageRssiPower; } } - else if (rssi > pConnCtx->pclMonitorParam.autoMonitor.highThreshold) - { - pConnCtx->cisRssiExtremeTimeSpent++; + return; - if (pConnCtx->cisRssiExtremeTimeSpent >= pConnCtx->pclMonitorParam.autoMonitor.minTimeSpent) - { - if (!(pConnCtx->peerPwrLimits & LL_PWR_CONTROL_LIMIT_MIN_BIT)) - { - LL_TRACE_INFO1("RSSI too high, requesting decrease in power. phy=%u", phy); - sendReqDelta = -(pConnCtx->pclMonitorParam.autoMonitor.requestVal); - } - pConnCtx->cisRssiExtremeTimeSpent = 0; - } - } - else +CisManageRssiPower: + + lctrRssiAddAveragePoint(&pConnCtx->cisRunAvg, -((int8_t) (pConnCtx->cisAccumulatedRssi / pConnCtx->cisTotalAccumulatedRssi))); + pConnCtx->cisAccumulatedRssi = 0; + pConnCtx->cisTotalAccumulatedRssi = 0; + + if (pConnCtx->cisRunAvg.avgCount >= LL_PC_TBL_LEN) { - pConnCtx->cisRssiExtremeTimeSpent = 0; + int8_t averageRunning = lctrRssiGetAverage(&pConnCtx->cisRunAvg); + + if ((averageRunning > pConnCtx->pclMonitorParam.autoMonitor.highThreshold) && + !(pConnCtx->peerPwrLimits & LL_PWR_CONTROL_LIMIT_MIN_BIT)) + { + sendReqDelta = -(pConnCtx->pclMonitorParam.autoMonitor.requestVal); + } + else if ((averageRunning < pConnCtx->pclMonitorParam.autoMonitor.lowThreshold) && + !(pConnCtx->peerPwrLimits & LL_PWR_CONTROL_LIMIT_MAX_BIT)) + { + sendReqDelta = pConnCtx->pclMonitorParam.autoMonitor.requestVal; + } } if (sendReqDelta != 0) { + if ((pConnCtx->llcpActiveProc == LCTR_PROC_PWR_CTRL) || + (pConnCtx->llcpPendMask & (1 << LCTR_PROC_PWR_CTRL))) + { + LL_TRACE_WARN0("Power control LLCP already ongoing or pended upon attempt to start new power control process."); + return; + } + lctrMsgPwrCtrlReq_t *pMsg; + uint8_t phy = ((pCisCtx->role == LL_ROLE_MASTER) ? pCisCtx->phySToM : pCisCtx->phyMToS); + + /* Decide to request S8 or S2 PHY. */ + phy += (((phy == LL_PHY_LE_CODED) && + (pCisCtx->bleData.chan.initTxPhyOptions == LL_PHY_OPTIONS_S2_PREFERRED)) ? 1 : 0); + if ((pMsg = (lctrMsgPwrCtrlReq_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) { pMsg->hdr.handle = LCTR_GET_CONN_HANDLE(pConnCtx); @@ -1814,6 +1940,8 @@ void lctrCisPowerMonitorCheckRssi(int8_t rssi, uint8_t status, uint8_t phy, lctr WsfMsgSend(lmgrPersistCb.handlerId, pMsg); } + + pConnCtx->cisRunAvg.avgCount = 0; } } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis_master.c index da28cbc1c4..517c24495d 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis_master.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -207,7 +207,11 @@ static void lctrSetCis(lctrCisCtx_t *pCisCtx, LlCisCigParams_t *pSetCigParam, Ll pCisCtx->ftMToS = LlMathDivideUint32(pSetCigParam->transLatMToS * 1000, LCTR_ISO_INT_TO_US(pCisCtx->isoInterval)); pCisCtx->ftSToM = LlMathDivideUint32(pSetCigParam->transLatSToM * 1000, LCTR_ISO_INT_TO_US(pCisCtx->isoInterval)); - if (pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen * pCisCtx->localDataPdu.maxTxLen < pCisCtx->sduSizeMToS) + if (pCisCtx->localDataPdu.maxTxLen == 0) + { + pCisCtx->bnMToS = 0; + } + else if (pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen * pCisCtx->localDataPdu.maxTxLen < pCisCtx->sduSizeMToS) { pCisCtx->bnMToS = pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen + 1; } @@ -216,7 +220,11 @@ static void lctrSetCis(lctrCisCtx_t *pCisCtx, LlCisCigParams_t *pSetCigParam, Ll pCisCtx->bnMToS = pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen; } - if (pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen * pCisCtx->localDataPdu.maxRxLen < pCisCtx->sduSizeSToM) + if (pCisCtx->localDataPdu.maxRxLen == 0) + { + pCisCtx->bnSToM = 0; + } + else if (pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen * pCisCtx->localDataPdu.maxRxLen < pCisCtx->sduSizeSToM) { pCisCtx->bnSToM = pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen + 1; } @@ -255,7 +263,11 @@ static void lctrSetCis(lctrCisCtx_t *pCisCtx, LlCisCigParams_t *pSetCigParam, Ll pCisCtx->ftMToS = LlMathDivideUint32(pSetCigParam->transLatMToS * 1000, LCTR_ISO_INT_TO_US(pCisCtx->isoInterval)); pCisCtx->ftSToM = LlMathDivideUint32(pSetCigParam->transLatSToM * 1000, LCTR_ISO_INT_TO_US(pCisCtx->isoInterval)); - if (pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen * pCisCtx->localDataPdu.maxTxLen < pCisCtx->sduSizeMToS) + if (pCisCtx->localDataPdu.maxTxLen == 0) + { + pCisCtx->bnMToS = 0; + } + else if (pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen * pCisCtx->localDataPdu.maxTxLen < pCisCtx->sduSizeMToS) { pCisCtx->bnMToS = pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen + 1; } @@ -264,7 +276,11 @@ static void lctrSetCis(lctrCisCtx_t *pCisCtx, LlCisCigParams_t *pSetCigParam, Ll pCisCtx->bnMToS = pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen; } - if (pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen * pCisCtx->localDataPdu.maxRxLen < pCisCtx->sduSizeSToM) + if (pCisCtx->localDataPdu.maxRxLen == 0) + { + pCisCtx->bnSToM = 0; + } + else if (pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen * pCisCtx->localDataPdu.maxRxLen < pCisCtx->sduSizeSToM) { pCisCtx->bnSToM = pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen + 1; } @@ -359,6 +375,7 @@ static void lctrSetCig(lctrCigCtx_t *pCigCtx, LlCisCigParams_t *pSetCigParam) pCisCtx = lctrFindCisById(pSetCigParam->cigId, pSetCigParam->pCisParam[i].cisId); WSF_ASSERT(pCisCtx); + pCisCtx->cisSyncDelayUsec = 0; for (unsigned int j = i; j < pSetCigParam->numCis; j++) { @@ -569,6 +586,40 @@ uint8_t LctrSetCigParam(LlCisCigParams_t *pSetCigParam, uint16_t *pCisHandles) pCisHandles[i] = pCisCtx->cisHandle; } lctrSetCig(pCigCtx, pSetCigParam); + + /* Invalid CIG parameters. Attempt adjusting of CIG parameters. */ + bool_t paramsChanged = TRUE; + if (pCigCtx->isValid == FALSE) + { + LL_TRACE_WARN1("LctrSetCigParam, invalid parameters in cigID=%u; adjust parameters", pSetCigParam->cigId); + } + while ((pCigCtx->isValid == FALSE) && (paramsChanged == TRUE)) + { + paramsChanged = FALSE; + for (unsigned int i = 0; i < pSetCigParam->numCis; i++) + { + /* Try to adjust CIS RTE to lower than host-reccomended value. */ + pCisCtx = lctrFindCisByHandle(pCisHandles[i]); + if (pSetCigParam->pCisParam[i].rteMToS > 0) + { + pSetCigParam->pCisParam[i].rteMToS--; + paramsChanged = TRUE; + } + if (pSetCigParam->pCisParam[i].rteSToM > 0) + { + pSetCigParam->pCisParam[i].rteSToM--; + paramsChanged = TRUE; + } + + /* Re-apply parameters. */ + lctrSetCis(pCisCtx, pSetCigParam, &pSetCigParam->pCisParam[i]); + lctrSetCig(pCigCtx, pSetCigParam); + if (pCigCtx->isValid) + { + break; + } + } + } } } else @@ -597,6 +648,40 @@ uint8_t LctrSetCigParam(LlCisCigParams_t *pSetCigParam, uint16_t *pCisHandles) } lctrSetCig(pCigCtx, pSetCigParam); } + + /* Invalid CIG parameters. Attempt adjusting of CIG parameters. */ + bool_t paramsChanged = TRUE; + if (pCigCtx->isValid == FALSE) + { + LL_TRACE_WARN1("LctrSetCigParam: invalid parameters in cigID=%u; adjust parameters", pSetCigParam->cigId); + } + while ((pCigCtx->isValid == FALSE) && (paramsChanged == TRUE)) + { + paramsChanged = FALSE; + for (unsigned int i = 0; i < pSetCigParam->numCis; i++) + { + /* Try to adjust CIS RTE to lower than host-reccomended value. */ + pCisCtx = lctrFindCisByHandle(pCisHandles[i]); + if (pSetCigParam->pCisParam[i].rteMToS > 0) + { + pSetCigParam->pCisParam[i].rteMToS--; + paramsChanged = TRUE; + } + if (pSetCigParam->pCisParam[i].rteSToM > 0) + { + pSetCigParam->pCisParam[i].rteSToM--; + paramsChanged = TRUE; + } + + /* Re-apply parameters. */ + lctrSetCis(pCisCtx, pSetCigParam, &pSetCigParam->pCisParam[i]); + lctrSetCig(pCigCtx, pSetCigParam); + if (pCigCtx->isValid) + { + break; + } + } + } } pCigCtx->roleData.mst.numCis = pSetCigParam->numCis; @@ -772,6 +857,7 @@ void LctrMstCisInit(void) /* Add CIS function pointers */ LctrUpdateCisChanMapFn = LctrCisUpdateChanMap; lctrRegisterChClassHandler(lctrMstCisChClassUpdate); + lctrCisServicePowerMonitorFn = lctrCisServicePowerMonitor; /* Add CIS event handlers. */ lctrEventHdlrTbl[LCTR_EVENT_CIS_TX_PENDING] = lctrIsoTxPendingHandler; @@ -826,6 +912,8 @@ uint8_t LctrCreateCis(uint8_t numCis, LlCisCreateCisParams_t *pCreateCisParam) LL_TRACE_WARN0("LctrCreateCis, CIS is already established"); return LL_ERROR_CODE_ACL_CONN_ALREADY_EXISTS; } + + pCisCtx->isClosing = FALSE; } lmgrCisMstCb.createCisPend = TRUE; @@ -873,6 +961,7 @@ void lctrMstCisBuildCigOp(lctrCigCtx_t *pCigCtx) BbBleData_t * const pBle = &pCisCtx->bleData; BbBleMstCisEvent_t * const pCis = &pBle->op.mstCis; + lctrConnCtx_t * pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); memset(pOp, 0, sizeof(BbOpDesc_t)); memset(pBle, 0, sizeof(BbBleData_t)); @@ -897,8 +986,18 @@ void lctrMstCisBuildCigOp(lctrCigCtx_t *pCigCtx) pBle->chan.peerTxStableModIdx = TRUE; pBle->chan.peerRxStableModIdx = TRUE; - /* Set PHY options to mirror acl connection option. */ - pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S8; + if (lmgrGetOpFlag(LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2)) + { + /* Force Coded PHY option to S2. */ + pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S2; + pBle->chan.tifsTxPhyOptions = BB_PHY_OPTIONS_BLE_S2; + } + else + { + /* Set PHY options to mirror ACL connection option. */ + pBle->chan.initTxPhyOptions = pConnCtx->bleData.chan.initTxPhyOptions; + pBle->chan.tifsTxPhyOptions = pConnCtx->bleData.chan.tifsTxPhyOptions; + } #if (LL_ENABLE_TESTER) pBle->chan.accAddrRx = pCisCtx->accessAddr ^ llTesterCb.cisAccessAddrRx; @@ -916,8 +1015,7 @@ void lctrMstCisBuildCigOp(lctrCigCtx_t *pCigCtx) /*** General setup ***/ - /* pOp->minDurUsec = pFirstCisCtx->subIntervUsec * WSF_MAX(pFirstCisCtx->bnMToS, pFirstCisCtx->bnSToM); */ /* Guarantee at least Max BN */ - pOp->minDurUsec = pCigCtx->cigSyncDelayUsec; + pOp->minDurUsec = pCisCtx->subIntervUsec * WSF_MAX(pCisCtx->bnMToS, pCisCtx->bnSToM); /* Guarantee at least Max BN */ pOp->maxDurUsec = pCigCtx->cigSyncDelayUsec; /* pOp->due = 0 */ /* set in lctrMstCisCigOpCommit() */ @@ -931,6 +1029,7 @@ void lctrMstCisBuildCigOp(lctrCigCtx_t *pCigCtx) /*** BLE stream setup ***/ pCis->checkContOpCback = lctrMstCisCheckContOp; + pCis->checkContOpPostCback = lctrMstCisCheckContOpPostCback; pCis->execCback = lctrMstCisCigBeginOp; pCis->contExecCback = lctrMstCisCigContOp; pCis->postSubEvtCback = lctrMstCisCigPostSubEvt; @@ -979,15 +1078,17 @@ void lctrMstCisBuildCisData(lctrCisCtx_t *pCisCtx) pBle->chan.peerTxStableModIdx = TRUE; pBle->chan.peerRxStableModIdx = TRUE; - /* Set PHY options to mirror acl connection option. */ - if (pConnCtx->bleData.chan.tifsTxPhyOptions != BB_PHY_OPTIONS_DEFAULT) + if (lmgrGetOpFlag(LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2)) { - /* Set PHY options to host defined behavior. */ - pBle->chan.initTxPhyOptions = pConnCtx->bleData.chan.tifsTxPhyOptions; + /* Force Coded PHY option to S2. */ + pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S2; + pBle->chan.tifsTxPhyOptions = BB_PHY_OPTIONS_BLE_S2; } else { - pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S8; + /* Set PHY options to mirror ACL connection option. */ + pBle->chan.initTxPhyOptions = pConnCtx->bleData.chan.initTxPhyOptions; + pBle->chan.tifsTxPhyOptions = pConnCtx->bleData.chan.tifsTxPhyOptions; } #if (LL_ENABLE_TESTER) @@ -1007,6 +1108,7 @@ void lctrMstCisBuildCisData(lctrCisCtx_t *pCisCtx) /*** BLE stream setup ***/ pCis->checkContOpCback = lctrMstCisCheckContOp; + pCis->checkContOpPostCback = lctrMstCisCheckContOpPostCback; pCis->execCback = lctrMstCisCigBeginOp; pCis->contExecCback = lctrMstCisCigContOp; pCis->postSubEvtCback = lctrMstCisCigPostSubEvt; @@ -1034,8 +1136,9 @@ void lctrMstCisCigOpCommit(lctrCigCtx_t *pCigCtx, lctrConnCtx_t *pCtx, lctrCisCt { /* Recalculate the CE ref if it is already past. */ pCisCtx->ceRef = pCtx->eventCounter + - LL_MIN_INSTANT + 1 + /* +1 for next CE */ - pCtx->maxLatency; /* ensure slave will listen to this packet */ + ((LL_MIN_INSTANT + 1 + /* +1 for next CE */ + pCtx->maxLatency) * /* ensure slave will listen to this packet */ + pCtx->ecu.srFactor); /* include subrating factor */ refTime = pConnBod->dueUsec + (pCisCtx->ceRef - pCtx->eventCounter) * LCTR_CONN_IND_US(pCtx->connInterval); diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis_slave.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis_slave.c index 34baaddec4..4413887054 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis_slave.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis_slave.c @@ -71,12 +71,11 @@ void LctrCisSlvInit(void) lctrResetHdlrTbl[LCTR_DISP_CIS] = lctrSlvCisResetHandler; /* Add connection message dispatcher. */ - if (lctrMsgDispTbl[LCTR_DISP_CIS] != NULL) - { - lctrMsgDispTbl[LCTR_DISP_CIS] = (LctrMsgDisp_t)lctrCisDisp; - } + lctrMsgDispTbl[LCTR_DISP_CIS] = (LctrMsgDisp_t)lctrCisDisp; - lctrCisDefaults(); + /* Add CIS function pointers */ + LctrUpdateCisChanMapFn = LctrCisUpdateChanMap; + lctrCisServicePowerMonitorFn = lctrCisServicePowerMonitor; /* Add connection event handlers. */ lctrEventHdlrTbl[LCTR_EVENT_CIS_RX_PENDING] = lctrCisRxPendingHandler; @@ -86,6 +85,8 @@ void LctrCisSlvInit(void) lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_EST] = lctrSlvLlcpExecuteCisEstSm; lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM] = lctrLlcpExecuteCisTermSm; + lctrCisDefaults(); + /* Set supported features. */ if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_5_1) { @@ -207,6 +208,7 @@ void lctrSlvCisBuildCigOp(lctrCigCtx_t *pCigCtx) BbBleData_t * const pBle = &pCisCtx->bleData; BbBleSlvCisEvent_t * const pCis = &pBle->op.slvCis; + lctrConnCtx_t * const pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); memset(pOp, 0, sizeof(BbOpDesc_t)); memset(pBle, 0, sizeof(BbBleData_t)); @@ -235,8 +237,18 @@ void lctrSlvCisBuildCigOp(lctrCigCtx_t *pCigCtx) pBle->chan.peerTxStableModIdx = TRUE; pBle->chan.peerRxStableModIdx = TRUE; - /* Set PHY options to mirror acl connection option. */ - pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S8; + if (lmgrGetOpFlag(LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2)) + { + /* Force Coded PHY option to S2. */ + pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S2; + pBle->chan.tifsTxPhyOptions = BB_PHY_OPTIONS_BLE_S2; + } + else + { + /* Set PHY options to mirror ACL connection option. */ + pBle->chan.initTxPhyOptions = pConnCtx->bleData.chan.initTxPhyOptions; + pBle->chan.tifsTxPhyOptions = pConnCtx->bleData.chan.tifsTxPhyOptions; + } #if (LL_ENABLE_TESTER) pBle->chan.accAddrRx = pCisCtx->accessAddr ^ llTesterCb.cisAccessAddrRx; @@ -254,7 +266,8 @@ void lctrSlvCisBuildCigOp(lctrCigCtx_t *pCigCtx) /*** General setup ***/ - pOp->minDurUsec = pCisCtx->subIntervUsec * WSF_MAX(pCisCtx->bnMToS, pCisCtx->bnSToM); /* Guarantee at least Max BN */ + /* Use small minDurUsec to improve scheduling. */ + pOp->minDurUsec = pCisCtx->subIntervUsec; pOp->maxDurUsec = pCigCtx->cigSyncDelayUsec; /* pOp->due = 0 */ /* set in lctrCisMstCigOpCommit() */ @@ -268,6 +281,7 @@ void lctrSlvCisBuildCigOp(lctrCigCtx_t *pCigCtx) /*** BLE stream setup ***/ pCis->checkContOpCback = lctrSlvCisCheckContOp; + pCis->checkContOpPostCback = lctrSlvCisCheckContOpPostCback; pCis->execCback = lctrSlvCisCigBeginOp; pCis->contExecCback = lctrSlvCisCigContOp; pCis->postSubEvtCback = lctrSlvCisCigPostSubEvt; @@ -292,7 +306,7 @@ void lctrSlvCisBuildCisData(lctrCisCtx_t *pCisCtx) { BbBleData_t * const pBle = &pCisCtx->bleData; BbBleSlvCisEvent_t * const pCis = &pBle->op.slvCis; - lctrConnCtx_t * pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); + lctrConnCtx_t * const pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); memset(pBle, 0, sizeof(BbBleData_t)); memset(pCis, 0, sizeof(BbBleMstCisEvent_t)); @@ -316,15 +330,17 @@ void lctrSlvCisBuildCisData(lctrCisCtx_t *pCisCtx) pBle->chan.peerTxStableModIdx = TRUE; pBle->chan.peerRxStableModIdx = TRUE; - /* Set PHY options to mirror acl connection option. */ - if (pConnCtx->bleData.chan.tifsTxPhyOptions != BB_PHY_OPTIONS_DEFAULT) + if (lmgrGetOpFlag(LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2)) { - /* Set PHY options to host defined behavior. */ - pBle->chan.initTxPhyOptions = pConnCtx->bleData.chan.tifsTxPhyOptions; + /* Force Coded PHY option to S2. */ + pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S2; + pBle->chan.tifsTxPhyOptions = BB_PHY_OPTIONS_BLE_S2; } else { - pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S8; + /* Set PHY options to mirror ACL connection option. */ + pBle->chan.initTxPhyOptions = pConnCtx->bleData.chan.initTxPhyOptions; + pBle->chan.tifsTxPhyOptions = pConnCtx->bleData.chan.tifsTxPhyOptions; } #if (LL_ENABLE_TESTER) @@ -344,6 +360,7 @@ void lctrSlvCisBuildCisData(lctrCisCtx_t *pCisCtx) /*** BLE stream setup ***/ pCis->checkContOpCback = lctrSlvCisCheckContOp; + pCis->checkContOpPostCback = lctrSlvCisCheckContOpPostCback; pCis->execCback = lctrSlvCisCigBeginOp; pCis->contExecCback = lctrSlvCisCigContOp; pCis->postSubEvtCback = lctrSlvCisCigPostSubEvt; diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn.c index 766c5170ec..dcb5962eb7 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -91,8 +91,8 @@ lctrLlcpEh_t lctrStorePeriodicSyncTrsfFn = NULL; /*! \brief Pointer to lctrReceivePeriodicSyncInd function. */ lctrLlcpEh_t lctrReceivePeriodicSyncIndFn = NULL; -/*! \brief Power monitoring scheme action table. */ -lctrPcMonAct_t lctrPcActTbl[LCTR_PC_MONITOR_SCHEME_TOTAL]; +/*! \brief Pointer to path lctrPathLossMonitorAct function. */ +lctrPcMonAct_t lctrPathLossMonitorActFn = NULL; /*! \brief Pointer to lctrSendPowerChangeInd function. */ lctrPcPowInd_t lctrSendPowerChangeIndCback = NULL; @@ -100,6 +100,18 @@ lctrPcPowInd_t lctrSendPowerChangeIndCback = NULL; /*! \brief Pointer to lctrNotifyPowerReportInd function. */ lctrPcNotifyPwr_t lctrNotifyPowerReportIndCback = NULL; +/*! \brief Pointer to lctrCisServicePowerMonitor Function. */ +lctrCisServicePowerMonitor_t lctrCisServicePowerMonitorFn = NULL; + +/*! \brief Last channel class map since host update (Used for slave channel status indications). */ +static uint64_t lastChanClassMap = LL_CHAN_DATA_ALL; + +/*! \brief Calculate number of subrated connection events. */ +lctrCalcSubrateConnEvents_t lctrCalcSubrateConnEventsFn = NULL; + +/*! \brief Calculate number of subrated connection events. */ +lctrCheckLlcpOverride_t lctrSlvCheckEncOverridePhyUpdateFn = NULL; + /*************************************************************************************************/ /*! * \brief Return PHYs supported by LL. @@ -287,6 +299,44 @@ bool_t LctrIsProcActPended(uint16_t handle, uint8_t event) return FALSE; } +/*************************************************************************************************/ +/*! + * \brief Check whether a feature exchange procedure was host-initiated, or initiated as a result of connection startup. + * + * \param handle Connection handle. + * + * \return TRUE if the procedure was host-initiated. FALSE if not. + */ +/*************************************************************************************************/ +bool_t LctrIsFeatExchHostInit(uint16_t handle) +{ + lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(handle); + + if (!pCtx->enabled) + { + /* Should not happen. */ + return FALSE; + } + + return (pCtx->llcpNotifyMask & (1 << LCTR_PROC_CMN_FEAT_EXCH)) ? TRUE : FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Set controller to notify host when feature exchange completes. + * + * \param handle Connection handle. + * + */ +/*************************************************************************************************/ +void LctrSetHostNotifyFeatExch(uint16_t handle) +{ + + lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(handle); + + pCtx->llcpNotifyMask |= (1 << LCTR_PROC_CMN_FEAT_EXCH); +} + /*************************************************************************************************/ /*! * \brief Get encryption mode used in a connection. @@ -415,6 +465,13 @@ lctrConnCtx_t *lctrAllocConnCtx(void) pMsg->dispId = LCTR_DISP_CONN; pMsg->event = LCTR_CONN_TMR_AUTH_PAYLOAD_EXP; + /* Setup power control timer. */ + pCtx->tmrPowerCtrl.handlerId = lmgrPersistCb.handlerId; + pMsg = (lctrMsgHdr_t *)&pCtx->tmrPowerCtrl.msg; + pMsg->handle = connIdx; + pMsg->dispId = LCTR_DISP_CONN; + pMsg->event = LCTR_CONN_LLCP_PWR_CTRL_SERVICE; + /* Default packet lengths. */ pCtx->localDataPdu.maxTxLen = lmgrConnCb.maxTxLen; pCtx->localDataPdu.maxRxLen = WSF_MIN(LCTR_MAX_DATA_LEN_MAX, pLctrRtCfg->maxAclLen); @@ -457,17 +514,33 @@ lctrConnCtx_t *lctrAllocConnCtx(void) } /* Power control initialization. */ - if (pCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST) + if ((pCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST) && + !lmgrGetOpFlag(LL_OP_MODE_FLAG_DIS_POWER_MONITOR)) { pCtx->powerMonitorScheme = LCTR_PC_MONITOR_AUTO; pCtx->monitoringState = LCTR_PC_MONITOR_ENABLED; - pCtx->pclMonitorParam.autoMonitor.highThreshold = LCTR_RSSI_HIGH_THRESHOLD; - pCtx->pclMonitorParam.autoMonitor.lowThreshold = LCTR_RSSI_LOW_THRESHOLD; - pCtx->pclMonitorParam.autoMonitor.minTimeSpent = LCTR_PC_MIN_TIME; - pCtx->pclMonitorParam.autoMonitor.requestVal = LCTR_PC_REQUEST_VAL; - pCtx->pclMonitorParam.autoMonitor.curTimeSpent = 0; + pCtx->pclMonitorParam.autoMonitor.highThreshold = pLctrRtCfg->pcHighThreshold; + pCtx->pclMonitorParam.autoMonitor.lowThreshold = pLctrRtCfg->pcLowThreshold; + pCtx->pclMonitorParam.autoMonitor.requestVal = LL_PC_REQ_CHANGE_DBM; + + /* Reset average counters. */ + pCtx->pclMonitorParam.autoMonitor.accumulatedRssi = 0; + pCtx->pclMonitorParam.autoMonitor.totalAccumulatedRssi = 0; + pCtx->pclMonitorParam.autoMonitor.rssiRunAvg.avgCount = 0; + pCtx->cisAccumulatedRssi = 0; + pCtx->cisTotalAccumulatedRssi = 0; + pCtx->cisRunAvg.avgCount = 0; } + /* Default Enhanced Connection Update. */ + pCtx->ecu.srFactor = 1; + /* pCtx->ecu.contNum = 0; */ + pCtx->ecu.defSrMin = lmgrConnCb.defSrMin; + pCtx->ecu.defSrMax = lmgrConnCb.defSrMax; + pCtx->ecu.defMaxLatency = lmgrConnCb.defMaxLatency; + pCtx->ecu.defContNum = lmgrConnCb.defContNum; + pCtx->ecu.defSvt = lmgrConnCb.defSvt; + LmgrIncResetRefCount(); lmgrCb.numConnEnabled++; @@ -519,6 +592,7 @@ void lctrFreeConnCtx(lctrConnCtx_t *pCtx) WsfTimerStop(&pCtx->tmrProcRsp); WsfTimerStop(&pCtx->tmrPingTimeout); WsfTimerStop(&pCtx->tmrAuthTimeout); + WsfTimerStop(&pCtx->tmrPowerCtrl); uint16_t handle = LCTR_GET_CONN_HANDLE(pCtx); @@ -695,18 +769,10 @@ void lctrConnRxPendingHandler(void) lctrUnpackDataPduHdr(&rxHdr, pRxBuf); /* Decrypt PDU. */ - if (lctrPktDecryptHdlr) + if (pCtx->bleData.chan.enc.enaDecrypt) { - if (lctrPktDecryptHdlr(&pCtx->bleData.chan.enc, pRxBuf)) - { - if (pCtx->bleData.chan.enc.enaDecrypt) - { - /* Restart authentication timers. */ - WsfTimerStartMs(&pCtx->tmrAuthTimeout, pCtx->authTimeoutMs); - WsfTimerStartMs(&pCtx->tmrPingTimeout, pCtx->pingPeriodMs); - } - } - else + if (lctrPktDecryptHdlr && + (!lctrPktDecryptHdlr(&pCtx->bleData.chan.enc, pRxBuf))) { LL_TRACE_ERR1("!!! MIC verification failed on connHandle=%u", connHandle); lctrRxPduFree(pRxBuf); @@ -714,6 +780,10 @@ void lctrConnRxPendingHandler(void) lctrSendConnMsg(pCtx, LCTR_CONN_TERM_MIC_FAILED); continue; } + + /* Restart authentication timers. */ + WsfTimerStartMs(&pCtx->tmrAuthTimeout, pCtx->authTimeoutMs); + WsfTimerStartMs(&pCtx->tmrPingTimeout, pCtx->pingPeriodMs); } /* Demux PDU. */ @@ -1076,7 +1146,7 @@ void LctrSetTxPowerLevel(uint16_t handle, int8_t level) { if (lctrNotifyPowerReportIndCback) { - lctrNotifyPowerReportIndCback(pCtx, LL_POWER_REPORT_REASON_LOCAL, phy, adjustedLevel, + lctrNotifyPowerReportIndCback(pCtx, LL_SUCCESS, LL_POWER_REPORT_REASON_LOCAL, phy, adjustedLevel, lctrGetPowerLimits(adjustedLevel), adjustedLevel - txPwrOld[phy]); } @@ -1144,7 +1214,7 @@ void LctrSetPhyTxPowerLevel(uint16_t handle, int8_t level, uint8_t phy) { if (lctrNotifyPowerReportIndCback) { - lctrNotifyPowerReportIndCback(pCtx, LL_POWER_REPORT_REASON_LOCAL, pBle->chan.txPhy, adjustedLevel, + lctrNotifyPowerReportIndCback(pCtx, LL_SUCCESS, LL_POWER_REPORT_REASON_LOCAL, pBle->chan.txPhy, adjustedLevel, lctrGetPowerLimits(pBle->chan.txPower), delta); } @@ -1211,6 +1281,30 @@ uint8_t LctrGetRxPhy(uint16_t handle) return pLctrConnTbl[handle].bleData.chan.rxPhy; } +/*************************************************************************************************/ +/*! + * \brief Get status of CIS termination procedure. + * + * \param handle Connection handle. + * + * \return TRUE if termination is currently pending, FALSE if not. + */ +/*************************************************************************************************/ +bool_t LctrCisTerminationInProgress(uint16_t handle) +{ + WSF_ASSERT(handle < pLctrRtCfg->maxConn); + + lctrConnCtx_t *pCtx = &pLctrConnTbl[handle]; + + if ((pCtx->llcpActiveProc == LCTR_PROC_CIS_TERM) || + (pCtx->llcpPendMask & (1 << LCTR_PROC_CIS_TERM))) + { + return TRUE; + } + + return FALSE; +} + /*************************************************************************************************/ /*! * \brief Get peer minimum number of used channels. @@ -1327,7 +1421,7 @@ BbOpDesc_t *lctrConnResolveConflict(BbOpDesc_t *pNewOp, BbOpDesc_t *pExistOp) !((pExistOp->prot.pBle->chan.opType == BB_BLE_OP_SLV_CONN_EVENT) || (pExistOp->prot.pBle->chan.opType == BB_BLE_OP_MST_CONN_EVENT))) { - LL_TRACE_WARN1("!!! Scheduling conflict, BLE connections: incoming handle=%u prioritized over non-BLE operation", LCTR_GET_CONN_HANDLE(pNewCtx)); + LL_TRACE_WARN1("!!! Scheduling conflict, BLE connections: incoming handle=%u prioritized over non-connection operation", LCTR_GET_CONN_HANDLE(pNewCtx)); return pNewOp; } @@ -1603,11 +1697,17 @@ uint8_t lctrSetPowerMonitorEnable(uint16_t handle, bool_t enable) pCtx->powerMonitorScheme = LCTR_PC_MONITOR_AUTO; pCtx->monitoringState = enable; - pCtx->pclMonitorParam.autoMonitor.highThreshold = LCTR_RSSI_HIGH_THRESHOLD; - pCtx->pclMonitorParam.autoMonitor.lowThreshold = LCTR_RSSI_LOW_THRESHOLD; - pCtx->pclMonitorParam.autoMonitor.minTimeSpent = LCTR_PC_MIN_TIME; - pCtx->pclMonitorParam.autoMonitor.requestVal = LCTR_PC_REQUEST_VAL; - pCtx->pclMonitorParam.autoMonitor.curTimeSpent = 0; + pCtx->pclMonitorParam.autoMonitor.highThreshold = pLctrRtCfg->pcHighThreshold; + pCtx->pclMonitorParam.autoMonitor.lowThreshold = pLctrRtCfg->pcLowThreshold; + pCtx->pclMonitorParam.autoMonitor.requestVal = LL_PC_REQ_CHANGE_DBM; + + /* Initialize average function. */ + pCtx->pclMonitorParam.autoMonitor.accumulatedRssi = 0; + pCtx->pclMonitorParam.autoMonitor.totalAccumulatedRssi = 0; + pCtx->pclMonitorParam.autoMonitor.rssiRunAvg.avgCount = 0; + pCtx->cisAccumulatedRssi = 0; + pCtx->cisTotalAccumulatedRssi = 0; + pCtx->cisRunAvg.avgCount = 0; return LL_SUCCESS; } @@ -1648,3 +1748,75 @@ uint8_t lctrGetPowerLimits(int8_t txPower) return 0; } } + +/*************************************************************************************************/ +/*! + * \brief Host channel class update handler for connections. + * + * \param chanMap Updated channel map. + * + * \return Status code. + */ +/*************************************************************************************************/ +uint8_t lctrConnChClassUpdate(uint64_t chanMap) +{ + lctrChanMapUpdate_t *pMsg; + lctrConnCtx_t *pCtx; + uint16_t handle; + uint8_t status = LL_SUCCESS; + + /* Update for connections */ + for (handle = 0; handle < pLctrRtCfg->maxConn; handle++) + { + if (LctrIsConnHandleEnabled(handle)) + { + if (LctrGetRole(handle) == LL_ROLE_MASTER) + { + /* Update the channel map for CIS master as well. */ + if (LctrUpdateCisChanMapFn) + { + LctrUpdateCisChanMapFn(handle); + } + + if (LctrIsProcActPended(handle, LCTR_CONN_MSG_API_CHAN_MAP_UPDATE) == TRUE) + { + status = LL_ERROR_CODE_CMD_DISALLOWED; + } + + if ((pMsg = (lctrChanMapUpdate_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->hdr.handle = handle; + pMsg->hdr.dispId = LCTR_DISP_CONN; + pMsg->hdr.event = LCTR_CONN_MSG_API_CHAN_MAP_UPDATE; + + pMsg->chanMap = chanMap; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } + else + { + LL_TRACE_ERR0("lctrConnChClassUpdate: out of message buffers"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + } + else /* LL_ROLE_SLAVE */ + { + if (lastChanClassMap != chanMap) + { + pCtx = LCTR_GET_CONN_CTX(handle); + + if ((pCtx->usedFeatSet & LL_FEAT_CHANNEL_CLASSIFICATION) && + pCtx->chanStatRptEnable) + { + pCtx->data.slv.queuedChanStatusTs = PalBbGetCurrentTime(); + /* Update is sent to host in lctrSlvConnEndOp(). */ + } + + lastChanClassMap = chanMap; + } + } + } + } + + return status; +} diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_data.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_data.c index 47d2ae670a..5ee778461c 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_data.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_data.c @@ -606,6 +606,8 @@ void lctrTxDataPduQueue(lctrConnCtx_t *pCtx, uint16_t fragLen, lctrAclHdr_t *pAc /*************************************************************************************************/ void lctrTxCtrlPduQueue(lctrConnCtx_t *pCtx, uint8_t *pBuf) { + pCtx->numTxPendCtrlPdu++; + #if (LL_ENABLE_TESTER) uint16_t connHandle = LCTR_GET_CONN_HANDLE(pCtx); #endif diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_master.c index b099194ac0..a44285da2e 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_master.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -192,59 +192,6 @@ static void lctrMstConnDisp(lctrConnMsg_t *pMsg) } } -/*************************************************************************************************/ -/*! - * \brief Host channel class update handler for connections. - * - * \param chanMap Updated channel map. - * - * \return Status code. - */ -/*************************************************************************************************/ -static uint8_t lctrConnChClassUpdate(uint64_t chanMap) -{ - lctrChanMapUpdate_t *pMsg; - uint16_t handle; - uint8_t status = LL_SUCCESS; - - /* Update for connections */ - for (handle = 0; handle < pLctrRtCfg->maxConn; handle++) - { - if ((LctrIsConnHandleEnabled(handle)) && - (LctrGetRole(handle) == LL_ROLE_MASTER)) - { - /* Update the channel map for CIS master as well. */ - if (LctrUpdateCisChanMapFn) - { - LctrUpdateCisChanMapFn(handle); - } - - if (LctrIsProcActPended(handle, LCTR_CONN_MSG_API_CHAN_MAP_UPDATE) == TRUE) - { - status = LL_ERROR_CODE_CMD_DISALLOWED; - } - - if ((pMsg = (lctrChanMapUpdate_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) - { - pMsg->hdr.handle = handle; - pMsg->hdr.dispId = LCTR_DISP_CONN; - pMsg->hdr.event = LCTR_CONN_MSG_API_CHAN_MAP_UPDATE; - - pMsg->chanMap = chanMap; - - WsfMsgSend(lmgrPersistCb.handlerId, pMsg); - } - else - { - LL_TRACE_ERR0("lctrConnChClassUpdate: out of message buffers"); - return LL_ERROR_CODE_CMD_DISALLOWED; - } - } - } - - return status; -} - /*************************************************************************************************/ /*! * \brief Build a connection operation. @@ -357,8 +304,10 @@ void lctrMstSetEstablishConn(lctrConnCtx_t *pCtx) const uint16_t txWinOffsetCnt = pConnInd->txWinOffset + LCTR_DATA_CHAN_DLY; /* Initially use fast termination. */ + /* The first CE starts after transmitWindowDelay + transmitWindowOffset + transmitWindowSize. + Then an additional 5 CI are required + the duration of the last connection event. */ uint32_t fastTermCnt = txWinOffsetCnt + pConnInd->txWinSize + - (LCTR_FAST_TERM_CNT * pConnInd->interval); + ((LCTR_FAST_TERM_CNT - 1) * pConnInd->interval) + (pConnInd->interval >> 1); WsfTimerStartMs(&pCtx->tmrSupTimeout, LCTR_CONN_IND_MS(fastTermCnt)); /* Set initial channel. */ @@ -371,6 +320,7 @@ void lctrMstSetEstablishConn(lctrConnCtx_t *pCtx) LL_TRACE_INFO1(" >>> Connection established, handle=%u <<<", LCTR_GET_CONN_HANDLE(pCtx)); LL_TRACE_INFO1(" connIntervalUsec=%u", LCTR_CONN_IND_US(pCtx->connInterval)); LL_TRACE_INFO1(" dueUsec=%u", pCtx->connBod.dueUsec); + LL_TRACE_INFO1(" pBod=0x%08x", &pCtx->connBod); } /*************************************************************************************************/ @@ -401,6 +351,7 @@ void LctrMstConnInit(void) /* Add channel selection handler. */ lctrChSelHdlr[LL_CH_SEL_1] = lctrSelectNextDataChannel; + /* Register channel class update handler. */ lctrRegisterChClassHandler(lctrConnChClassUpdate); lctrConnDefaults(); @@ -426,7 +377,13 @@ void LctrMstConnInit(void) if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_5_1) { lmgrPersistCb.featuresDefault |= - (LL_FEAT_PAST_SENDER | LL_FEAT_SCA_UPDATE); + LL_FEAT_PAST_SENDER | + LL_FEAT_SCA_UPDATE; + } + if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_SYDNEY) + { + lmgrPersistCb.featuresDefault |= + LL_FEAT_CHANNEL_CLASSIFICATION; } } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_slave.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_slave.c index 79830502ee..5411382cdf 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_slave.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_slave.c @@ -375,6 +375,7 @@ void lctrSlvConnBuildOp(lctrConnCtx_t *pCtx) LL_TRACE_INFO1(" connIntervalUsec=%u", LCTR_CONN_IND_US(pCtx->connInterval)); LL_TRACE_INFO1(" dueUsec=%u", pOp->dueUsec); LL_TRACE_INFO1(" minDurUsec=%u", pOp->minDurUsec); + LL_TRACE_INFO1(" pBod=0x%08x", pOp); break; } @@ -432,6 +433,9 @@ void LctrSlvConnInit(void) /* Add channel selection handler. */ lctrChSelHdlr[LL_CH_SEL_1] = lctrSelectNextDataChannel; + /* Register channel class update handler. */ + lctrRegisterChClassHandler(lctrConnChClassUpdate); + lctrConnDefaults(); /* Set supported features. */ @@ -455,7 +459,13 @@ void LctrSlvConnInit(void) if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_5_1) { lmgrPersistCb.featuresDefault |= - (LL_FEAT_PAST_SENDER | LL_FEAT_SCA_UPDATE); + LL_FEAT_PAST_SENDER | + LL_FEAT_SCA_UPDATE; + } + if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_SYDNEY) + { + lmgrPersistCb.featuresDefault |= + LL_FEAT_CHANNEL_CLASSIFICATION; } } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_enc_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_enc_master.c index db7d60f372..54b3f5381a 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_enc_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_enc_master.c @@ -105,16 +105,18 @@ void LctrMstConnEncInit(void) lctrCtrlPduHdlr = lctrMstEncProcessDataPdu; /* Add packet encryption handlers. */ +#if (!(BB_ENABLE_INLINE_ENC_TX && BB_ENABLE_INLINE_DEC_RX)) lctrInitCipherBlkHdlr = PalCryptoAesEnable; +#endif #if (!BB_ENABLE_INLINE_ENC_TX) lctrPktEncryptHdlr = PalCryptoAesCcmEncrypt; #else - lctrSetEncryptPktCountHdlr = PalCryptoSetEncryptPacketCount; + lctrSetEncryptPktCountHdlr = PalBbBleSetInlineEncryptPacketCount; #endif #if (!BB_ENABLE_INLINE_DEC_RX) lctrPktDecryptHdlr = PalCryptoAesCcmDecrypt; #else - lctrSetDecryptPktCountHdlr = PalCryptoSetDecryptPacketCount; + lctrSetDecryptPktCountHdlr = PalBbBleSetInlineDecryptPacketCount; #endif /* Set supported features. */ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_enc_slave.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_enc_slave.c index 1a506a943c..18c603951f 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_enc_slave.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_enc_slave.c @@ -84,16 +84,18 @@ void LctrSlvConnEncInit(void) } /* Add packet encryption handlers. */ +#if (!(BB_ENABLE_INLINE_ENC_TX && BB_ENABLE_INLINE_DEC_RX)) lctrInitCipherBlkHdlr = PalCryptoAesEnable; +#endif #if (!BB_ENABLE_INLINE_ENC_TX) lctrPktEncryptHdlr = PalCryptoAesCcmEncrypt; #else - lctrSetEncryptPktCountHdlr = PalCryptoSetEncryptPacketCount; + lctrSetEncryptPktCountHdlr = PalBbBleSetInlineEncryptPacketCount; #endif #if (!BB_ENABLE_INLINE_DEC_RX) lctrPktDecryptHdlr = PalCryptoAesCcmDecrypt; #else - lctrSetDecryptPktCountHdlr = PalCryptoSetDecryptPacketCount; + lctrSetDecryptPktCountHdlr = PalBbBleSetInlineDecryptPacketCount; #endif /* Set supported features. */ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_init_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_init_master.c index a03d60bec0..4e801476e3 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_init_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_init_master.c @@ -242,6 +242,9 @@ void lctrMstInitiateOpCommit(void) SchInsertNextAvailable(pOp); lctrMstInit.scanWinStartUsec = pOp->dueUsec; + + LL_TRACE_INFO1(" >>> Initiate started, dueUsec=%u <<<", pOp->dueUsec); + LL_TRACE_INFO1(" pBod=0x%08x", pOp); } /*************************************************************************************************/ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_init_master_ae.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_init_master_ae.c index 6921013794..febc880370 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_init_master_ae.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_init_master_ae.c @@ -398,6 +398,9 @@ void lctrMstExtInitiateOpCommit(lctrExtScanCtx_t *pExtInitCtx) SchInsertNextAvailable(pOp); pExtInitCtx->data.init.scanWinStartUsec = pOp->dueUsec; + + LL_TRACE_INFO1(" >>> ExtInitiate started, dueUsec=%u <<<", pOp->dueUsec); + LL_TRACE_INFO1(" pBod=0x%08x", pOp); } /*************************************************************************************************/ @@ -460,6 +463,7 @@ uint8_t lctrMstAuxInitiateBuildOp(lctrExtScanCtx_t *pExtInitCtx, LlConnSpec_t *p /*** BLE Scan Setup: Rx packets ***/ pAuxScan->isInit = TRUE; pAuxScan->rxAuxAdvCback = lctrMstInitiateRxAuxAdvPktHandler; + pAuxScan->rxAuxAdvPostCback = NULL; /*** BLE Scan Setup: Tx connect request packet ***/ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_iso.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_iso.c index 369609871c..928d647074 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_iso.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_iso.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -58,7 +58,7 @@ static void lctrIsoProcessRxTestData(lctrCisCtx_t *pCisCtx, uint8_t *pDataBuf, u uint16_t pldType = 0; uint64_t plTestCounter = pCisCtx->rxPktCounter; - if (pCisCtx->rxPendInit) + if (pCisCtx->rxPendInit && (dataLen >= LL_ISO_TEST_VAR_MIN_LEN)) { memcpy(&pCisCtx->expectedPkt, pDataBuf, 4); pCisCtx->rxPendInit = FALSE; @@ -94,12 +94,15 @@ static void lctrIsoProcessRxTestData(lctrCisCtx_t *pCisCtx, uint8_t *pDataBuf, u if ((dataLen == pldType) && (pktNum == pCisCtx->expectedPkt)) { + pCisCtx->expectedPkt++; pCisCtx->numRxSuccess++; + } else { pCisCtx->expectedPkt = pktNum + 1; pCisCtx->numRxFailed++; + } break; @@ -107,7 +110,8 @@ static void lctrIsoProcessRxTestData(lctrCisCtx_t *pCisCtx, uint8_t *pDataBuf, u if ((dataLen >= LL_ISO_TEST_VAR_MIN_LEN) && (pktNum == pCisCtx->expectedPkt)) { - pCisCtx->numRxSuccess++; + pCisCtx->numRxSuccess++; + pCisCtx->expectedPkt++; } else { @@ -224,7 +228,7 @@ void LctrInitCodec(void) /* Add codec. */ lctrCodecHdlr.start = PalCodecDataStartStream; lctrCodecHdlr.stop = PalCodecDataStopStream; - lctrCodecHdlr.in = PalCodecDataStreamIn; + lctrCodecHdlr.inReq = PalCodecDataStreamIn; lctrCodecHdlr.out = PalCodecDataStreamOut; } @@ -269,9 +273,8 @@ void lctrIsoTxCompletedHandler(void) WSF_CS_EXIT(cs); - if (numHandles) + if (lmgrPersistCb.sendIsoCompCback && numHandles) { - /* Notify host. */ lmgrPersistCb.sendIsoCompCback(numHandles, handle, numSdu); } } @@ -285,14 +288,14 @@ void lctrCisRxPendingHandler(void) { uint16_t cisHandle = 0; uint8_t *pRxBuf; + lctrCisCtx_t *pCisCtx; /* Route and demux received Data PDUs. */ - while ((pRxBuf = lctrCisRxDeq(&cisHandle)) != NULL) { WSF_ASSERT(pRxBuf); - lctrCisCtx_t *pCisCtx = lctrFindCisByHandle(cisHandle); + pCisCtx = lctrFindCisByHandle(cisHandle); lctrIsoalRxCtx_t *pRxCtx = &pCisCtx->isoalRxCtx; if (!pCisCtx->enabled) @@ -317,18 +320,31 @@ void lctrCisRxPendingHandler(void) lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_TERM_MIC_FAILED); continue; } + /* Increase packet counter after decryption. */ + lctrCisIncPacketCounterRx(pCisCtx); } - /* Increase packet counter after decryption. */ - lctrCisIncPacketCounterRx(pCisCtx); - lctrCisDataPduHdr_t cisDataHdr; lctrCisUnpackDataPduHdr(&cisDataHdr, pRxBuf); /* Demux PDU. */ if (pCisCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED) { - lctrIsoHdr_t isoHdr = { 0 }; + lctrIsoHdr_t isoHdr = + { + /* ISO header */ + .handle = cisHandle, + .len = pRxBuf[LCTR_ISO_DATA_PDU_LEN_OFFSET], + /* .pb = 0, */ /* assigned below */ + .tsFlag = FALSE, + + /* Data load */ + .ts = 0, + /* .pktSn = 0, */ /* assigned below */ + .sduLen = pRxBuf[LCTR_ISO_DATA_PDU_LEN_OFFSET], + .ps = LCTR_PS_VALID + }; + switch (rxHdr.llid) { /* Received a end/complete PDU. */ @@ -346,6 +362,7 @@ void lctrCisRxPendingHandler(void) lctrCisRxPduFree(pRxBuf); LL_TRACE_ERR2("!!! Invalid rxState; dropping Rx data PDU, connHandle=%u, rxState=%u", cisHandle, pRxCtx->rxState); pRxCtx->rxState = LL_ISO_SDU_STATE_NEW; + continue; } break; @@ -359,24 +376,7 @@ void lctrCisRxPendingHandler(void) default: lctrCisRxPduFree(pRxBuf); LL_TRACE_ERR2("!!! Invalid LLID; dropping Rx data PDU, connHandle=%u llid=%u", cisHandle, rxHdr.llid); - break; - } - - /* If the packet was flushed, change the packet status flag to warn host of errors. */ - if (pRxCtx->pduFlushed) - { - switch (pRxCtx->rxState) - { - case LL_ISO_SDU_STATE_CONT: - /* Lost data since last transfer; invalidate packet. */ - pRxCtx->data.unframed.ps = LCTR_PS_INVALID; - break; - case LL_ISO_SDU_STATE_NEW: - /* This may be a fragmented packet with the end fragment, but no way to tell, so process as normal. */ - pRxCtx->data.unframed.ps = (rxHdr.llid == LL_LLID_ISO_UNF_END_PDU) ? LCTR_PS_INVALID : LCTR_PS_LOST; - break; - } - pRxCtx->pduFlushed = FALSE; + continue; } /* Pack isoHdr and queue PDU. */ @@ -384,34 +384,34 @@ void lctrCisRxPendingHandler(void) { uint8_t * pSduBuf = pRxBuf - LCTR_CIS_DATA_PDU_START_OFFSET - HCI_ISO_DL_MAX_LEN; - /* Pack current packet. */ - isoHdr.handle = cisHandle; - isoHdr.tsFlag = ((isoHdr.pb == LCTR_PB_COMP) || (isoHdr.pb == LCTR_PB_FIRST)) ? 1 : 0; - if (isoHdr.tsFlag) + if ((isoHdr.pb == LCTR_PB_COMP) || (isoHdr.pb == LCTR_PB_FIRST)) { - isoHdr.ts = 0xFF; - } - isoHdr.len = pRxBuf[LCTR_ISO_DATA_PDU_LEN_OFFSET]; - /* isoHdr.pktSn = 0; */ + isoHdr.tsFlag = TRUE; + isoHdr.ts = PalBbGetCurrentTime(); - /* LCTR_PB_COMP and LCTR_PB_FIRST will have their headers re-packed in lctrIsoUnframedRxSduPendQueue. */ + pRxCtx->packetSequence++; + } + isoHdr.pktSn = pRxCtx->packetSequence; + + /* LCTR_PB_COMP and LCTR_PB_FIRST will have their headers re-packed in lctrRecombineRxUnframedSdu(). */ uint8_t headerOffset = lctrIsoPackHdr(pSduBuf, &isoHdr); /* Process received buffer for Rx testing purpose. */ + /* TODO: Optimize test packet dataflow. */ if (pCisCtx->rxTestEnabled == TRUE) { lctrIsoProcessRxTestData(pCisCtx, pRxBuf + LL_DATA_HDR_LEN, rxHdr.len); } - /* TODO optimize memory layout */ /* Move payload next to header. */ - if (LCTR_CIS_DATA_PDU_START_OFFSET + LL_ISO_DATA_HDR_LEN > HCI_ISO_HDR_LEN) + if ((LCTR_CIS_DATA_PDU_START_OFFSET + LL_ISO_DATA_HDR_LEN) > HCI_ISO_HDR_LEN) { + /* TODO optimize memory layout */ memmove(pSduBuf + headerOffset , pRxBuf + LL_DATA_HDR_LEN, rxHdr.len); } /* Put onto pending queue until whole SDU is ready to be sent. */ - if (!lctrIsoUnframedRxSduPendQueue(pRxCtx, pSduBuf, cisHandle, rxHdr.len, rxHdr.llid)) + if (!lctrRecombineRxUnframedSdu(pRxCtx, pSduBuf)) { break; } @@ -421,7 +421,8 @@ void lctrCisRxPendingHandler(void) while ((pSduBuf = WsfMsgDeq(&pRxCtx->data.unframed.pendSduQ, &handlerId)) != NULL) { /* Enqueue SDU for processing. */ - if (!lctrIsoRxConnEnq(&pCisCtx->dataPathOutCtx, pCisCtx->cisHandle, pSduBuf)) + if (!lctrIsoRxConnEnq(&pCisCtx->dataPathOutCtx, pCisCtx->cisHandle, + pCisCtx->rxPktCounter - 1, pSduBuf)) { /* The buffer was not freed, so free it now. */ WsfMsgFree(pSduBuf); @@ -437,12 +438,13 @@ void lctrCisRxPendingHandler(void) { pCisCtx->dataPathOutCtx.cfg.hci.numRxPend += lctrAssembleRxFramedSdu(pRxCtx, &pCisCtx->dataPathOutCtx.cfg.hci.rxDataQ, pCisCtx->cisHandle, pRxBuf, cisDataHdr.len); - /* Consume and process packets for iso test mode */ + /* Consume packets if needed */ + lctrIsoHdr_t isoHdr; + /* ISO test mode. */ if (pCisCtx->rxTestEnabled == TRUE) { while (pCisCtx->dataPathOutCtx.cfg.hci.numRxPend) { - lctrIsoHdr_t isoHdr; uint8_t *pTestRxBuf = lctrIsoRxConnDeq(&pCisCtx->dataPathOutCtx); lctrIsoUnpackHdr(&isoHdr, pTestRxBuf); lctrIsoProcessRxTestData(pCisCtx, pTestRxBuf+ HCI_ISO_HDR_LEN + HCI_ISO_DL_MAX_LEN, isoHdr.sduLen); @@ -451,6 +453,19 @@ void lctrCisRxPendingHandler(void) pCisCtx->dataPathOutCtx.cfg.hci.numRxPend--; } } + /* Codec output */ + else if (pCisCtx->dataPathOutCtx.id == LL_ISO_DATA_PATH_VS) + { + while (pCisCtx->dataPathOutCtx.cfg.hci.numRxPend) + { + uint8_t *pSduBuf = lctrIsoRxConnDeq(&pCisCtx->dataPathOutCtx); + lctrIsoUnpackHdr(&isoHdr, pSduBuf); + lctrCodecHdlr.out(pCisCtx->dataPathOutCtx.cfg.codec.streamId, isoHdr.pSdu, isoHdr.sduLen, isoHdr.ts); + WsfMsgFree(pSduBuf); + LctrRxIsoComplete(1); + } + } + lctrCisRxPduFree(pRxBuf); break; } @@ -473,23 +488,21 @@ void lctrCisRxPendingHandler(void) WSF_CS_ENTER(cs); for (unsigned int i = 0; i < pLctrRtCfg->maxCis; i++) { - lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i]; + pCisCtx = &pLctrCisTbl[i]; if (pCisCtx->enabled && + (pCisCtx->dataPathOutCtx.id == LL_ISO_DATA_PATH_HCI) && pCisCtx->dataPathOutCtx.cfg.hci.numRxPend) { - if (pCisCtx->dataPathOutCtx.id == LL_ISO_DATA_PATH_HCI) - { - handle[numHandles] = pCisCtx->cisHandle; - numSdu[numHandles] = pCisCtx->dataPathOutCtx.cfg.hci.numRxPend; - pCisCtx->dataPathOutCtx.cfg.hci.numRxPend = 0; - numHandles++; - } + handle[numHandles] = pCisCtx->cisHandle; + numSdu[numHandles] = pCisCtx->dataPathOutCtx.cfg.hci.numRxPend; + pCisCtx->dataPathOutCtx.cfg.hci.numRxPend = 0; + numHandles++; } } WSF_CS_EXIT(cs); - if (numHandles) + if (lmgrPersistCb.recvIsoPendCback && numHandles) { /* Notify host. */ lmgrPersistCb.recvIsoPendCback(numHandles, handle, numSdu); @@ -551,7 +564,10 @@ void LctrTxIso(uint8_t *pIsoBuf) { LL_TRACE_ERR2("Invalid ISO header: invalid packet length, actLen=%u, maxLen=%u", isoHdr.sduLen, pLctrRtCfg->maxIsoSduLen); WsfMsgFree(pIsoBuf); - lmgrPersistCb.sendCompCback(isoHdr.handle, 1); + if (lmgrPersistCb.sendCompCback) + { + lmgrPersistCb.sendCompCback(isoHdr.handle, 1); + } return; } @@ -559,16 +575,22 @@ void LctrTxIso(uint8_t *pIsoBuf) { LL_TRACE_ERR1("ISO Tx path flow controlled, handle=%u", isoHdr.handle); WsfMsgFree(pIsoBuf); - lmgrPersistCb.sendCompCback(isoHdr.handle, 1); + if (lmgrPersistCb.sendCompCback) + { + lmgrPersistCb.sendCompCback(isoHdr.handle, 1); + } return; } - uint16_t expIsoLen = isoHdr.len - HCI_ISO_DL_MIN_LEN + ((isoHdr.tsFlag) ? HCI_ISO_TS_LEN : 0); + uint16_t expIsoLen = isoHdr.len - HCI_ISO_DL_MIN_LEN - ((isoHdr.tsFlag) ? HCI_ISO_TS_LEN : 0); if (isoHdr.sduLen != expIsoLen) { LL_TRACE_ERR2("Invalid ISO header: packet length mismatch, expSduLen=%u, actSduLen=%u", expIsoLen, isoHdr.sduLen); WsfMsgFree(pIsoBuf); - lmgrPersistCb.sendCompCback(isoHdr.handle, 1); + if (lmgrPersistCb.sendCompCback) + { + lmgrPersistCb.sendCompCback(isoHdr.handle, 1); + } return; } @@ -582,7 +604,10 @@ void LctrTxIso(uint8_t *pIsoBuf) if (!lctrCheckIsCisEstCis(pCisCtx->cisHandle)) { LL_TRACE_ERR1("Invalid ISO handle: link not established cisHandle=%u; dropping packet", isoHdr.handle); - lmgrPersistCb.sendCompCback(isoHdr.handle, 1); + if (lmgrPersistCb.sendCompCback) + { + lmgrPersistCb.sendCompCback(isoHdr.handle, 1); + } WsfMsgFree(pIsoBuf); return; } @@ -593,7 +618,10 @@ void LctrTxIso(uint8_t *pIsoBuf) { LL_TRACE_ERR1("Invalid CIS state: handle=%u does not accept transmissions; dropping packet", isoHdr.handle); WsfMsgFree(pIsoBuf); - lmgrPersistCb.sendCompCback(isoHdr.handle, 1); + if (lmgrPersistCb.sendCompCback) + { + lmgrPersistCb.sendCompCback(isoHdr.handle, 1); + } return; } @@ -620,7 +648,10 @@ void LctrTxIso(uint8_t *pIsoBuf) { LL_TRACE_ERR2("Invalid ISO header: invalid packet length, actLen=%u, maxSdu=%u", isoHdr.sduLen, pBisCtx->pBigCtx->maxSdu); WsfMsgFree(pIsoBuf); - lmgrPersistCb.sendCompCback(isoHdr.handle, 1); + if (lmgrPersistCb.sendCompCback) + { + lmgrPersistCb.sendCompCback(isoHdr.handle, 1); + } return; } @@ -662,7 +693,7 @@ uint8_t *LctrRxIso(void) { lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i]; - if ((pCisCtx->enabled) && + if ((pCisCtx->enabled) && (pCisCtx->dataPathOutCtx.id == LL_ISO_DATA_PATH_HCI) && ((pBuf = lctrIsoRxConnDeq(&pCisCtx->dataPathOutCtx)) != NULL)) { return pBuf; @@ -677,6 +708,7 @@ uint8_t *LctrRxIso(void) (pBisCtx->pBigCtx->role == LL_ROLE_MASTER) && ((pBuf = lctrBisRxIsoSduDeq(pBisCtx)) != NULL)) { + /* Postpone lctrIsoDataRxIncAvailBuf() until client consumes buffer, cf. LctrRxIsoComplete(). */ return pBuf; } } @@ -742,7 +774,37 @@ uint8_t LctrReadIsoTxSync(uint16_t handle, uint16_t *pPktSn, uint32_t *pTs, uint /*************************************************************************************************/ /*! - * \brief Used to identify and enable the isochronous data path between the host and the controller for each connected isochronous stream or broadcast isochronous stream. + * \brief Used to request the Controller to configure the data transport path in a given + * direction between the Controller and the Host. + * + * \param pConfigDataPath Parameters for configure data path. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrConfigureDataPath(LlIsoConfigDataPath_t *pConfigDataPath) +{ + switch (pConfigDataPath->dpId) + { + case LL_ISO_DATA_PATH_DISABLED: + case LL_ISO_DATA_PATH_HCI: + /* No action required. */ + break; + case LL_ISO_DATA_PATH_VS: + /* No action required. */ + break; + default: + LL_TRACE_WARN2("LlConfigureDataPath: unknown data path, dpDir=%u, dpId=%u", pConfigDataPath->dpDir, pConfigDataPath->dpId); + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Used to identify and enable the isochronous data path between the host and the + * controller for each connected isochronous stream or broadcast isochronous stream. * * \param pSetupDataPath Parameters for setup ISO data path. * @@ -751,65 +813,76 @@ uint8_t LctrReadIsoTxSync(uint16_t handle, uint16_t *pPktSn, uint32_t *pTs, uint /*************************************************************************************************/ uint8_t LctrSetupIsoDataPath(LlIsoSetupDataPath_t *pSetupDataPath) { - uint8_t status = LL_SUCCESS; lctrCisCtx_t *pCisCtx; lctrBisCtx_t *pBisCtx; - lctrDataPathCtx_t *pDataPathDir; + lctrDpParams_t dpParam; if ((pCisCtx = lctrFindCisByHandle(pSetupDataPath->handle)) != NULL) { + dpParam.handle = pCisCtx->cisHandle; + dpParam.isoInt = (pCisCtx->role == LL_ROLE_SLAVE) ? pCisCtx->sduIntervalSToM : pCisCtx->sduIntervalMToS; + dpParam.pktCtr = pCisCtx->txPktCounter + 1; + dpParam.dpDir = pSetupDataPath->dpDir; + switch (pSetupDataPath->dpDir) { case LL_ISO_DATA_DIR_INPUT: - pDataPathDir = (lctrDataPathCtx_t *) (&pCisCtx->dataPathInCtx); + dpParam.pDataPathCtx = (lctrDataPathCtx_t *) (&pCisCtx->dataPathInCtx); break; case LL_ISO_DATA_DIR_OUTPUT: - pDataPathDir = (lctrDataPathCtx_t *) (&pCisCtx->dataPathOutCtx); + dpParam.pDataPathCtx = (lctrDataPathCtx_t *) (&pCisCtx->dataPathOutCtx); break; default: LL_TRACE_WARN2("LctrSetupIsoDataPath: handle=%u invalid direction dpDir=%u", pSetupDataPath->handle, pSetupDataPath->dpDir); return LL_ERROR_CODE_CMD_DISALLOWED; } - return lctrSetupIsoDataPath(pSetupDataPath, pDataPathDir); } else if ((pBisCtx = lctrFindBisByHandle(pSetupDataPath->handle)) != NULL) { + dpParam.handle = pBisCtx->handle; + dpParam.isoInt = pBisCtx->pBigCtx->isoInterUsec; + dpParam.pktCtr = (pBisCtx->pBigCtx->eventCounter + 1) * pBisCtx->pBigCtx->bn; + dpParam.dpDir = pSetupDataPath->dpDir; + switch (pSetupDataPath->dpDir) { case LL_ISO_DATA_DIR_INPUT: if (pBisCtx->pBigCtx->role == LL_ROLE_SLAVE) { - status = lctrBisSetDataPath(pBisCtx, pSetupDataPath->dpDir, pSetupDataPath->dpId); + dpParam.pDataPathCtx = (lctrDataPathCtx_t *) (&pBisCtx->roleData.slv.dataPathInCtx); } else { LL_TRACE_WARN1("LctrSetupIsoDataPath: handle=%u invalid input direction for master", pSetupDataPath->handle); - status = LL_ERROR_CODE_CMD_DISALLOWED; + return LL_ERROR_CODE_CMD_DISALLOWED; } break; case LL_ISO_DATA_DIR_OUTPUT: if (pBisCtx->pBigCtx->role == LL_ROLE_MASTER) { - status = lctrBisSetDataPath(pBisCtx, pSetupDataPath->dpDir, pSetupDataPath->dpId); + dpParam.pDataPathCtx = (lctrDataPathCtx_t *) (&pBisCtx->roleData.mst.dataPathOutCtx); } else { LL_TRACE_WARN1("LctrSetupIsoDataPath: handle=%u invalid output direction for slave", pSetupDataPath->handle); - status = LL_ERROR_CODE_CMD_DISALLOWED; + return LL_ERROR_CODE_CMD_DISALLOWED; } break; default: + LL_TRACE_WARN2("LctrSetupIsoDataPath: handle=%u invalid direction dpDir=%u", pSetupDataPath->handle, pSetupDataPath->dpDir); + return LL_ERROR_CODE_CMD_DISALLOWED; break; } } + else { LL_TRACE_WARN1("LctrSetupIsoDataPath: handle=%u not found", pSetupDataPath->handle); - status = LL_ERROR_CODE_UNKNOWN_CONN_ID; + return LL_ERROR_CODE_UNKNOWN_CONN_ID; } - return status; + return lctrIsoSetupDataPath(&dpParam, pSetupDataPath); } /*************************************************************************************************/ @@ -828,18 +901,27 @@ uint8_t LctrRemoveIsoDataPath(uint16_t handle, uint8_t dpDir) uint8_t status = LL_SUCCESS; lctrCisCtx_t *pCisCtx; lctrBisCtx_t *pBisCtx; + lctrDpParams_t dpParam; if ((pCisCtx = lctrFindCisByHandle(handle)) != NULL) { + /* Check to make sure parameters are valid. */ + if ((dpDir & ~(LL_ISO_DATA_PATH_INPUT_BIT | LL_ISO_DATA_PATH_OUTPUT_BIT)) || + (dpDir == 0)) + { + LL_TRACE_WARN2("LctrRemoveIsoDataPath: handle=%u invalid direction dpDir=0x%08x", handle, dpDir); + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + /* Check for validity of parameters before operating on them. */ - if (dpDir | LL_ISO_DATA_PATH_INPUT_BIT) + if (dpDir & LL_ISO_DATA_PATH_INPUT_BIT) { if (pCisCtx->dataPathInCtx.id == LL_ISO_DATA_PATH_DISABLED) { return LL_ERROR_CODE_CMD_DISALLOWED; } } - if (dpDir | LL_ISO_DATA_PATH_OUTPUT_BIT) + if (dpDir & LL_ISO_DATA_PATH_OUTPUT_BIT) { if (pCisCtx->dataPathOutCtx.id == LL_ISO_DATA_PATH_DISABLED) { @@ -847,18 +929,70 @@ uint8_t LctrRemoveIsoDataPath(uint16_t handle, uint8_t dpDir) } } - if (dpDir | LL_ISO_DATA_PATH_INPUT_BIT) + if (dpDir & LL_ISO_DATA_PATH_INPUT_BIT) { + /* Stop input data path. */ + dpParam.handle = pCisCtx->cisHandle; + dpParam.pDataPathCtx = (lctrDataPathCtx_t *)&pCisCtx->dataPathInCtx; + /* Other parameters are unused in data path clearing. */ + lctrIsoInDataPathClear(&dpParam); + pCisCtx->dataPathInCtx.id = LL_ISO_DATA_PATH_DISABLED; } - if (dpDir | LL_ISO_DATA_PATH_OUTPUT_BIT) + if (dpDir & LL_ISO_DATA_PATH_OUTPUT_BIT) { + /* Stop output data path. */ + dpParam.handle = pCisCtx->cisHandle; + dpParam.pDataPathCtx = (lctrDataPathCtx_t *)&pCisCtx->dataPathOutCtx; + /* Other parameters are unused in data path clearing. */ + lctrIsoOutDataPathClear(&dpParam); + pCisCtx->dataPathOutCtx.id = LL_ISO_DATA_PATH_DISABLED; } } else if ((pBisCtx = lctrFindBisByHandle(handle)) != NULL) { - pBisCtx->path = LL_ISO_DATA_PATH_DISABLED; + if (dpDir & LL_ISO_DATA_PATH_INPUT_BIT) + { + if (pBisCtx->roleData.slv.dataPathInCtx.id == LL_ISO_DATA_PATH_DISABLED) + { + return LL_ERROR_CODE_CMD_DISALLOWED; + } + } + if (dpDir & LL_ISO_DATA_PATH_OUTPUT_BIT) + { + if (pBisCtx->roleData.mst.dataPathOutCtx.id == LL_ISO_DATA_PATH_DISABLED) + { + return LL_ERROR_CODE_CMD_DISALLOWED; + } + } + + dpParam.handle = pBisCtx->handle; + + if (pBisCtx->pBigCtx->role == LL_ROLE_MASTER) + { + if (pBisCtx->roleData.mst.dataPathOutCtx.id == LL_ISO_DATA_PATH_DISABLED) + { + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + dpParam.pDataPathCtx = (lctrDataPathCtx_t *)&pBisCtx->roleData.mst.dataPathOutCtx; + /* Other parameters are unused in data path clearing. */ + lctrIsoOutDataPathClear(&dpParam); + pBisCtx->roleData.mst.dataPathOutCtx.id = LL_ISO_DATA_PATH_DISABLED; + } + else + { + if (pBisCtx->roleData.slv.dataPathInCtx.id == LL_ISO_DATA_PATH_DISABLED) + { + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + dpParam.pDataPathCtx = (lctrDataPathCtx_t *)&pBisCtx->roleData.slv.dataPathInCtx; + /* Other parameters are unused in data path clearing. */ + lctrIsoInDataPathClear(&dpParam); + pBisCtx->roleData.slv.dataPathInCtx.id = LL_ISO_DATA_PATH_DISABLED; + } } else { @@ -1100,48 +1234,23 @@ void lctrNotifyHostIsoEventComplete(uint8_t handle, uint32_t evtCtr) /*! * \brief Send Codec SDU data. * - * \param handle Stream ID. + * \param handle ISO Handle. */ /*************************************************************************************************/ -void lctrIsoSendCodecSdu(uint16_t handle) +void lctrIsoSendCodecSdu(uint16_t id, uint32_t pktCtr, uint32_t ts, uint8_t *pData, uint16_t actLen) { - lctrBisCtx_t *pBisCtx; - - if ((pBisCtx = lctrFindBisByHandle(handle)) == NULL) - { - LL_TRACE_WARN1("lctrIsoSendCodecSdu: handle=%u not found", handle); - return; - } - - uint8_t *pSduBuf; - - if ((pSduBuf = WsfMsgAlloc(pLctrRtCfg->maxIsoSduLen + HCI_ISO_DL_MAX_LEN)) == NULL) - { - LL_TRACE_ERR1("!!! Out of memory; dropping input SDU, stream=%u", handle); - return; - } - - uint16_t len; - uint32_t pktCtr; - - WSF_ASSERT(lctrCodecHdlr.in); - if ((len = lctrCodecHdlr.in(handle, pSduBuf + HCI_ISO_HDR_LEN + HCI_ISO_DL_MAX_LEN, - pBisCtx->pBigCtx->maxSdu, &pktCtr)) == 0) - { - LL_TRACE_WARN1("ISO audio stream data not available, stream=%u", handle); - WsfMsgFree(pSduBuf); - return; - } + /* Recover SDU buffer. */ + uint8_t *pSduBuf = pData - HCI_ISO_HDR_LEN - HCI_ISO_DL_MAX_LEN; lctrIsoHdr_t hdr = { - .handle = handle, + .handle = id, .pb = LCTR_PB_COMP, .tsFlag = TRUE, - .len = len, + .len = actLen, .ts = 0, .pktSn = pktCtr, - .sduLen = len, + .sduLen = actLen, .ps = LCTR_PS_VALID }; @@ -1153,37 +1262,42 @@ void lctrIsoSendCodecSdu(uint16_t handle) /*! * \brief Setup ISO data path. * + * \param pDpParam Parameters to set up data path. * \param pSetupDataPath Data path setup parameters. - * \param pDataPathCtx Generic data path context. */ /*************************************************************************************************/ -uint8_t lctrSetupIsoDataPath(LlIsoSetupDataPath_t *pSetupDataPath, lctrDataPathCtx_t *pDataPathCtx) +uint8_t lctrIsoSetupDataPath(lctrDpParams_t *pDpParam, LlIsoSetupDataPath_t *pSetupDataPath) { + uint8_t status = LL_SUCCESS; + switch (pSetupDataPath->dpDir) { case LL_ISO_DATA_DIR_INPUT: { - if (pSetupDataPath->dpId == pDataPathCtx->in.id) + if (pSetupDataPath->dpId == pDpParam->pDataPathCtx->in.id) { + /* No change. */ return LL_SUCCESS; } - /* No teardown needed. */ - pDataPathCtx->in.id = pSetupDataPath->dpId; - /* No setup needed. */ + lctrIsoInDataPathClear(pDpParam); + pDpParam->pDataPathCtx->in.id = pSetupDataPath->dpId; + status = lctrIsoInDataPathSetup(pDpParam, pSetupDataPath); break; } case LL_ISO_DATA_DIR_OUTPUT: { - if (pSetupDataPath->dpId == pDataPathCtx->out.id) + if (pSetupDataPath->dpId == pDpParam->pDataPathCtx->out.id) { + /* No change. */ return LL_SUCCESS; } - lctrIsoOutDataPathClear(&pDataPathCtx->out); - pDataPathCtx->out.id = pSetupDataPath->dpId; - lctrIsoOutDataPathSetup(&pDataPathCtx->out); + lctrIsoOutDataPathClear(pDpParam); + pDpParam->pDataPathCtx->out.id = pSetupDataPath->dpId; + status = lctrIsoOutDataPathSetup(pDpParam, pSetupDataPath); + break; } @@ -1192,5 +1306,5 @@ uint8_t lctrSetupIsoDataPath(LlIsoSetupDataPath_t *pSetupDataPath, lctrDataPathC break; } - return LL_SUCCESS; + return status; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_iso_data.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_iso_data.c index 424a2ee589..30c7ccb077 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_iso_data.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_iso_data.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -69,7 +69,6 @@ static void lctrAssembleCisDataPdu(lctrIsoHdr_t *pIsoHdr, uint8_t *pBuf, uint8_t lctrCisPackDataPduHdr(pBuf, &dataHdr); } - /*************************************************************************************************/ /*! * \brief Initialize the transmit memory resources. @@ -181,7 +180,8 @@ void lctrCisTxDataPduQueue(lctrCisCtx_t *pCisCtx, lctrIsoHdr_t *pIsoHdr, uint8_t { LL_TRACE_ERR1("Failed to allocate transmit buffer descriptor: cisHandle=%u", pIsoHdr->handle); WsfMsgFree(pIsoBuf); - if (pCisCtx->txTestEnabled == FALSE) + if (lmgrPersistCb.sendIsoCompCback && + (pCisCtx->txTestEnabled == FALSE)) { uint16_t handle = pIsoHdr->handle; uint16_t numSdu = 1; @@ -411,15 +411,15 @@ uint8_t lctrCisTxQueueClear(lctrCisCtx_t *pCisCtx) * \return Pointer to the start of the PDU data buffer. */ /*************************************************************************************************/ -uint8_t *lctrCisRxPduAlloc(uint16_t maxRxLen) +uint8_t *lctrCisRxPduAlloc() { /* LCTR_DATA_PDU_MAX_LEN includes LL_DATA_MIC_LEN if required. */ - const uint16_t allocLen = WSF_MAX(BB_FIXED_DATA_PKT_LEN, LCTR_CIS_DATA_PDU_LEN(maxRxLen)) + LCTR_CIS_DATA_PDU_START_OFFSET; + const uint16_t allocLen = LCTR_CIS_DATA_PDU_START_OFFSET + HCI_ISO_DL_MAX_LEN + pLctrRtCfg->maxIsoSduLen + BB_DATA_PDU_TAILROOM; uint8_t *pBuf; /* Include ISO header. */ - if ((pBuf = WsfMsgAlloc(HCI_ISO_DL_MAX_LEN + allocLen)) != NULL) + if ((pBuf = WsfMsgAlloc(allocLen)) != NULL) { /* Return start of data PDU. */ pBuf += LCTR_CIS_DATA_PDU_START_OFFSET + HCI_ISO_DL_MAX_LEN; @@ -454,12 +454,16 @@ void lctrCisRxPduFree(uint8_t *pBuf) /*************************************************************************************************/ void lctrCisRxEnq(uint8_t *pBuf, uint16_t eventCounter, uint16_t cisHandle) { - /* Stamp packet with event counter. */ - pBuf -= LCTR_CIS_DATA_PDU_START_OFFSET; - UINT16_TO_BUF(pBuf, eventCounter); + if (pBuf != NULL) + { + /* Stamp packet with event counter. */ + pBuf -= LCTR_CIS_DATA_PDU_START_OFFSET; + UINT16_TO_BUF(pBuf, eventCounter); + + /* Queue LE Data PDU. */ + WsfMsgEnq(&lmgrIsoCb.rxDataQ, cisHandle, pBuf); + } - /* Queue LE Data PDU. */ - WsfMsgEnq(&lmgrIsoCb.rxDataQ, cisHandle, pBuf); WsfSetEvent(lmgrPersistCb.handlerId, (1 << LCTR_EVENT_CIS_RX_PENDING)); } @@ -497,12 +501,15 @@ uint8_t *lctrCisRxDeq(uint16_t *pCisHandle) * \param pBuf SDU buffer. * * \return TRUE if buffer successfully handled and will be used. - * FALSE if buffer was not handled and needs to be disposed. + * FALSE needs to be disposed. * */ /*************************************************************************************************/ -bool_t lctrIsoRxConnEnq(lctrOutDataPathCtx_t *pOutDataPathCtx, uint16_t handle, uint8_t *pBuf) +bool_t lctrIsoRxConnEnq(lctrOutDataPathCtx_t *pOutDataPathCtx, uint16_t handle, uint32_t pktCtr, uint8_t *pBuf) { + lctrIsoHdr_t isoHdr; + lctrIsoUnpackHdr(&isoHdr, pBuf); + switch (pOutDataPathCtx->id) { case LL_ISO_DATA_PATH_HCI: @@ -513,6 +520,10 @@ bool_t lctrIsoRxConnEnq(lctrOutDataPathCtx_t *pOutDataPathCtx, uint16_t handle, return TRUE; case LL_ISO_DATA_PATH_VS: + WSF_ASSERT(lctrCodecHdlr.out); + lctrCodecHdlr.out(pOutDataPathCtx->cfg.codec.streamId, isoHdr.pSdu, isoHdr.sduLen, isoHdr.ts); + return FALSE; + default: return FALSE; } @@ -533,34 +544,84 @@ uint8_t *lctrIsoRxConnDeq(lctrOutDataPathCtx_t *pOutCtx) { wsfHandlerId_t handle; - if (pOutCtx->id != LL_ISO_DATA_PATH_HCI) - { - return NULL; - } - return WsfMsgDeq(&pOutCtx->cfg.hci.rxDataQ, &handle); } /*************************************************************************************************/ /*! - * \brief Setup a datapath context. + * \brief Setup an input data path context. * - * \param pOutCtx Output datapath context. + * \param pDpParam Data path parameters. + * \param pSetupDataPath Data path setup parameters. + * + * \return Status error code. */ /*************************************************************************************************/ -void lctrIsoOutDataPathSetup(lctrOutDataPathCtx_t *pOutCtx) +uint8_t lctrIsoInDataPathSetup(lctrDpParams_t *pDpParam, LlIsoSetupDataPath_t *pSetupDataPath) { - switch (pOutCtx->id) + lctrInDataPathCtx_t *pInCtx = &pDpParam->pDataPathCtx->in; + + switch (pInCtx->id) { - case LL_ISO_DATA_PATH_HCI: - pOutCtx->cfg.hci.numRxPend = 0; - WSF_QUEUE_INIT(&pOutCtx->cfg.hci.rxDataQ); - break; - case LL_ISO_DATA_PATH_VS: - /* No action. */ + pInCtx->cfg.codec.streamId = pDpParam->handle; + + if (lctrCodecHdlr.start) + { + PalCodecStreamParam_t param = + { + .dir = PAL_CODEC_DIR_INPUT, + .pktCtr = pDpParam->pktCtr, + .codecId = pSetupDataPath->codecId, + .inCback = lctrIsoSendCodecSdu + }; + + if (!lctrCodecHdlr.start(pInCtx->cfg.codec.streamId, ¶m)) + { + LL_TRACE_WARN1("Failed to start the codec, dpId=%u", pInCtx->id); + pInCtx->id = LL_ISO_DATA_PATH_DISABLED; + return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES; + } + } + else + { + LL_TRACE_WARN1("Codec not found, dpId=%u", pInCtx->id); + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } break; + case LL_ISO_DATA_PATH_DISABLED: + case LL_ISO_DATA_PATH_HCI: + /* No action required. */ + break; + + default: + LL_TRACE_WARN1("Unknown Data Path, dpId=%u", pInCtx->id); + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Clear an input data path context. + * + * \param pOutCtx Output data path context. + */ +/*************************************************************************************************/ +void lctrIsoInDataPathClear(lctrDpParams_t *pDpParam) +{ + lctrInDataPathCtx_t *pInCtx = &pDpParam->pDataPathCtx->in; + + switch (pInCtx->id) + { + case LL_ISO_DATA_PATH_VS: + WSF_ASSERT(lctrCodecHdlr.stop); + lctrCodecHdlr.stop(pInCtx->cfg.codec.streamId, PAL_CODEC_DIR_INPUT); + break; + + case LL_ISO_DATA_PATH_HCI: default: /* No action. */ break; @@ -569,19 +630,81 @@ void lctrIsoOutDataPathSetup(lctrOutDataPathCtx_t *pOutCtx) /*************************************************************************************************/ /*! - * \brief Clear a datapath context. + * \brief Setup a data path context. * - * \param pOutCtx Output datapath context. + * \param pDpParam Data path parameters. + * \param pSetupDataPath Data path setup parameters. + * + * \return Status error code. */ /*************************************************************************************************/ -void lctrIsoOutDataPathClear(lctrOutDataPathCtx_t *pOutCtx) +uint8_t lctrIsoOutDataPathSetup(lctrDpParams_t *pDpParam, LlIsoSetupDataPath_t *pSetupDataPath) { + lctrOutDataPathCtx_t *pOutCtx = &pDpParam->pDataPathCtx->out; + + switch (pOutCtx->id) + { + case LL_ISO_DATA_PATH_VS: + pOutCtx->cfg.codec.streamId = pDpParam->handle; + + if (lctrCodecHdlr.start) + { + PalCodecStreamParam_t param = + { + .dir = PAL_CODEC_DIR_OUTPUT, + .pktCtr = pDpParam->pktCtr, + .codecId = pSetupDataPath->codecId + }; + + if (!lctrCodecHdlr.start(pOutCtx->cfg.codec.streamId, ¶m)) + { + LL_TRACE_WARN1("Failed to start the codec, dpId=%u", pOutCtx->id); + pOutCtx->id = LL_ISO_DATA_PATH_DISABLED; + return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES; + } + } + else + { + LL_TRACE_WARN1("Codec not found, dpId=%u", pOutCtx->id); + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + break; + + case LL_ISO_DATA_PATH_HCI: + pOutCtx->cfg.hci.numRxPend = 0; + WSF_QUEUE_INIT(&pOutCtx->cfg.hci.rxDataQ); + break; + + case LL_ISO_DATA_PATH_DISABLED: + /* No action required. */ + break; + + default: + LL_TRACE_WARN1("Unknown Data Path, dpId=%u", pOutCtx->id); + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Clear a data path context. + * + * \param pOutCtx Output data path context. + */ +/*************************************************************************************************/ +void lctrIsoOutDataPathClear(lctrDpParams_t *pDpParam) +{ + lctrOutDataPathCtx_t *pOutCtx = &pDpParam->pDataPathCtx->out; + switch (pOutCtx->id) { case LL_ISO_DATA_PATH_HCI: { uint8_t *pBuf; wsfHandlerId_t handlerId; + while ((pBuf = WsfMsgDeq(&pOutCtx->cfg.hci.rxDataQ, &handlerId)) != NULL) { WsfMsgFree(pBuf); @@ -591,8 +714,20 @@ void lctrIsoOutDataPathClear(lctrOutDataPathCtx_t *pOutCtx) } case LL_ISO_DATA_PATH_VS: - /* No action. */ + { + WSF_ASSERT(lctrCodecHdlr.stop); + lctrCodecHdlr.stop(pOutCtx->cfg.codec.streamId, PAL_CODEC_DIR_OUTPUT); + + uint8_t *pBuf; + wsfHandlerId_t handlerId; + + while ((pBuf = WsfMsgDeq(&pOutCtx->cfg.codec.rxDataQ, &handlerId)) != NULL) + { + WsfMsgFree(pBuf); + lctrIsoDataRxIncAvailBuf(1); + } break; + } default: /* No action. */ @@ -678,11 +813,9 @@ uint8_t *lctrGenerateIsoTestData(uint16_t handle, LlIsoPldType_t pldType, uint16 break; default: - { LL_TRACE_ERR1("Invalid value pldType=%u", pldType); len = 0; break; - } } /* Pack ISO header. */ @@ -810,7 +943,7 @@ uint8_t *lctrTxIsoDataPduAlloc(void) /* Use LL_ISO_PDU_MAX_LEN to ensure use of data buffers located in the large pool. */ if ((pPdu = (uint8_t*)WsfMsgAlloc(allocLen)) == NULL) { - LL_TRACE_WARN1("lctrTxIsoDataPduAlloc: Unable to allocate framed Tx buffer, allocSize=%u", allocLen); + LL_TRACE_WARN1("lctrTxIsoDataPduAlloc: Unable to allocate Tx buffer, allocSize=%u", allocLen); } return pPdu; @@ -841,13 +974,12 @@ uint8_t lctrAssembleTxFramedPdu(lctrIsoalTxCtx_t *pIsoalTxCtx, uint8_t *pPduBuf, /* Set offset of pPduBuf */ pPduBuf += HCI_ISO_HDR_LEN + HCI_ISO_DL_MIN_LEN; - /*** Loop through and pack SDUs. ***/ - + /* Loop through and pack SDUs. */ while (remLen) { uint8_t *pSduBuf = WsfMsgPeek(pSduQ, &handlerId); - /* The buffer is empty, process the completed PDU */ + /* The buffer is empty, process the completed PDU. */ if (pSduBuf == NULL) { break; @@ -855,7 +987,7 @@ uint8_t lctrAssembleTxFramedPdu(lctrIsoalTxCtx_t *pIsoalTxCtx, uint8_t *pPduBuf, lctrIsoHdr_t isoHdr; - /*** Disassemble ISO packet. ***/ + /*** Disassemble ISO packet ***/ lctrIsoUnpackHdr(&isoHdr, pSduBuf); @@ -878,7 +1010,7 @@ uint8_t lctrAssembleTxFramedPdu(lctrIsoalTxCtx_t *pIsoalTxCtx, uint8_t *pPduBuf, segHdrLen += LL_ISO_SEG_TO_LEN; } - /*** Compute segment parameters. ***/ + /*** Compute segment parameters ***/ /* There is enough room for the entire SDU. */ if (remLen >= (isoHdr.sduLen + segHdrLen)) @@ -951,7 +1083,7 @@ uint8_t lctrAssembleTxFramedPdu(lctrIsoalTxCtx_t *pIsoalTxCtx, uint8_t *pPduBuf, * \return Pointer to the start of the ISO Data PDU buffer, NULL if allocation failed. */ /*************************************************************************************************/ -static uint8_t *lctrRxSduAlloc(void) +uint8_t *lctrRxSduAlloc(void) { uint8_t *pSdu; @@ -971,59 +1103,102 @@ static uint8_t *lctrRxSduAlloc(void) * \brief Queue the received SDU into the pending queue. * * \param pRxCtx ISOAL receive context. - * \param pSdu SDU buffer. + * \param pSdu SDU fragment. * \param handle CIS connection handle. - * \param dataLen Data length. - * \param llid Rx LLID. * * \return TRUE if pending queue ready to be sent to host. */ /*************************************************************************************************/ -bool_t lctrIsoUnframedRxSduPendQueue(lctrIsoalRxCtx_t *pRxCtx, uint8_t *pSdu, uint16_t handle, - uint16_t dataLen, uint8_t llid) +bool_t lctrRecombineRxUnframedSdu(lctrIsoalRxCtx_t *pRxCtx, uint8_t *pSduFrag) { - /* Save data for head packet. */ - /* pRxCtx->data.unframed.pendSduIsoHdr.ps = 0; */ /* Should be done in calling function. */ - pRxCtx->data.unframed.curLen += dataLen; + bool_t result = FALSE; - WsfMsgEnq(&pRxCtx->data.unframed.pendSduQ, handle, pSdu); + uint8_t handlerId; + uint8_t *pSdu = WsfMsgPeek(&pRxCtx->data.unframed.pendSduQ, &handlerId); - /* If we received the last PDU, pack the head packet with the packet status and sdu length. */ - if (llid == LL_LLID_ISO_UNF_END_PDU) + if (pSduFrag) { - uint8_t *pHeadPkt; - uint8_t handlerId; - lctrIsoHdr_t isoHdr = {0}; + lctrIsoHdr_t fragHdr; + lctrIsoUnpackHdr(&fragHdr, pSduFrag); - pHeadPkt = WsfMsgPeek(&pRxCtx->data.unframed.pendSduQ, &handlerId); - WSF_ASSERT(pHeadPkt); + switch (fragHdr.pb) + { + case LCTR_PB_COMP: + result = TRUE; + /* Fallthrough */ + case LCTR_PB_FIRST: + if (pSdu) + { + LL_TRACE_ERR1("Previous SDU was not flushed, dropping SDU, handle=%u", fragHdr.handle); - lctrIsoUnpackHdr(&isoHdr, pHeadPkt); - isoHdr.pktSn = pRxCtx->packetSequence++; + pSdu = WsfMsgDeq(&pRxCtx->data.unframed.pendSduQ, &handlerId); + WsfMsgFree(pSdu); + + pSdu = NULL; + } + + /* Store first fragment. */ + pRxCtx->data.unframed.curLen = fragHdr.sduLen; + WsfMsgEnq(&pRxCtx->data.unframed.pendSduQ, fragHdr.handle, pSduFrag); + break; + + case LCTR_PB_LAST: + result = TRUE; + /* Fallthrough */ + case LCTR_PB_CONT: + if (pSdu == NULL) + { + /* Store first fragment. */ + pRxCtx->data.unframed.curLen = fragHdr.len; + WsfMsgEnq(&pRxCtx->data.unframed.pendSduQ, fragHdr.handle, pSduFrag); + + /* Missing first fragment. */ + pRxCtx->data.unframed.ps = LCTR_PS_INVALID; + } + else + { + lctrIsoHdr_t isoHdr; + lctrIsoUnpackHdr(&isoHdr, pSdu); + + /* Append continuation fragment (recombine). */ + memcpy(isoHdr.pSdu + pRxCtx->data.unframed.curLen, fragHdr.pSdu, fragHdr.len); + WsfMsgFree(pSduFrag); + pRxCtx->data.unframed.curLen += fragHdr.len; + } + break; + + default: + break; + } + } + else + { + /* NULL fragment indicates unexpected flush. */ + if (pSdu) + { + /* Complete pending SDU fragment. */ + pRxCtx->data.unframed.ps = LCTR_PS_INVALID; + result = TRUE; + } + } + + if (result && pSdu) + { + /* Update ISO header. */ + lctrIsoHdr_t isoHdr; + lctrIsoUnpackHdr(&isoHdr, pSdu); + isoHdr.pb = LCTR_PB_COMP; + isoHdr.len = pRxCtx->data.unframed.curLen; isoHdr.sduLen = pRxCtx->data.unframed.curLen; isoHdr.ps = pRxCtx->data.unframed.ps; - isoHdr.len -= + HCI_ISO_DL_MAX_LEN; - - /* Reset the packet boundary in case a missed packet leaves it undefined. */ - uint8_t rfu; /* Used to peek into msg queue. */ - if (WsfMsgNPeek(&pRxCtx->data.unframed.pendSduQ, 1, &rfu)) - { - isoHdr.pb = LCTR_PB_FIRST; - } - else - { - isoHdr.pb = LCTR_PB_COMP; - } - - lctrIsoPackHdr(pHeadPkt, &isoHdr); + lctrIsoPackHdr(pSdu, &isoHdr); /* Clean up context */ pRxCtx->data.unframed.curLen = 0; - pRxCtx->data.unframed.ps = 0; - return TRUE; + pRxCtx->data.unframed.ps = LCTR_PS_VALID; } - return FALSE; + return result; } /*************************************************************************************************/ @@ -1044,17 +1219,19 @@ uint8_t lctrAssembleRxFramedSdu(lctrIsoalRxCtx_t *pIsoalRxCtx, wsfQueue_t *pRxQu { uint8_t totalSduQueued = 0; - /* Last PDU was flushed. SDU data is lost and will be flushed. */ + /* Last PDU was flushed. */ if (pIsoalRxCtx->pduFlushed) { + pIsoalRxCtx->pduFlushed = FALSE; + + /* There was a lost SDU due to a fragment being flushed. */ if (pIsoalRxCtx->pPendSduBuf) { /* Flush SDU. */ WsfMsgFree(pIsoalRxCtx->pPendSduBuf); pIsoalRxCtx->pPendSduBuf = NULL; + return 0; } - pIsoalRxCtx->pduFlushed = FALSE; - return 0; } uint8_t *pDataBuf = pIsoBuf + LL_DATA_HDR_LEN; @@ -1160,6 +1337,7 @@ uint8_t lctrAssembleRxFramedSdu(lctrIsoalRxCtx_t *pIsoalRxCtx, wsfQueue_t *pRxQu uint8_t *pIsoHdrBuf = (pIsoalRxCtx->pPendSduBuf); lctrIsoPackHdr(pIsoHdrBuf, &isoHdr); + /* TODO: when adding codec data path, change this to enque or consume based on data path. */ /* Queue SDU. */ WsfMsgEnq(pRxQueue, handle, pIsoalRxCtx->pPendSduBuf); /* lctrIsoDataRxDecAvailBuf(); */ /* Handled in lctrRxSduAlloc. */ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_pc.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_pc.c index 9d1514134a..3bd0b1986b 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_pc.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_pc.c @@ -4,7 +4,7 @@ * * \brief Link layer controller power control implementation file. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,11 +42,10 @@ void LctrPowerControlInit(void) { /* Initialize power control. */ lmgrPersistCb.featuresDefault |= (LL_FEAT_POWER_CHANGE_IND | LL_FEAT_POWER_CONTROL_REQUEST); - lctrPcActTbl[LCTR_PC_MONITOR_AUTO] = lctrAutoPowerMonitorAct; /* Initialize path loss. */ lmgrPersistCb.featuresDefault |= (LL_FEAT_PATH_LOSS_MONITOR); - lctrPcActTbl[LCTR_PC_MONITOR_PATH_LOSS] = lctrPathLossMonitorAct; + lctrPathLossMonitorActFn = lctrPathLossMonitorAct; /* Initialize state machines. */ lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PC] = lctrLlcpExecutePclSm; @@ -209,7 +208,6 @@ uint8_t lctrSetPathLossReportingEnable(uint16_t handle, uint8_t enable) return LL_ERROR_CODE_CMD_DISALLOWED; } - /* If peer Tx power is unavailable, read the peer tx power. */ if (pCtx->peerTxPower == LL_PWR_CTRL_TXPOWER_UNAVAILABLE) { @@ -255,7 +253,7 @@ void lctrNotifyHostPathLossRpt(lctrConnCtx_t *pCtx) const uint16_t handle = LCTR_GET_CONN_HANDLE(pCtx); uint8_t curPathLoss = lctrCalcPathLoss(pCtx); - LlPathLossThresholdEvt_t evt = + LlPathLossThresholdInd_t evt = { .hdr = { @@ -311,7 +309,7 @@ void lctrPathLossMonitorAct(lctrConnCtx_t *pCtx) if (pCtx->pclMonitorParam.pathLoss.curTimeSpent >= pCtx->pclMonitorParam.pathLoss.minTimeSpent) { - LL_TRACE_INFO2("lctrPathLossMonitorAct, New zone entered. newZone=%u, pathLoss=%u", newZone, lctrCalcPathLoss(pCtx)); + LL_TRACE_INFO2("lctrPathLossMonitorAct: new zone entered. newZone=%u, pathLoss=%u", newZone, lctrCalcPathLoss(pCtx)); pCtx->pclMonitorParam.pathLoss.curTimeSpent = 0; pCtx->pclMonitorParam.pathLoss.curZone = newZone; diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_sc.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_sc.c index 7a0f18aa04..9d918715e6 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_sc.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_sc.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,10 +30,18 @@ #include "wsf_assert.h" #include "ll_math.h" #include "wsf_trace.h" -#include "uECC_ll.h" #include "pal_bb_ble.h" #include +#if ENABLE_UECC + #include "uECC_ll.h" +#endif + +#if ENABLE_UECC_TINYCRYPT + #include "tinycrypt/ecc.h" + #include "tinycrypt/ecc_dh.h" +#endif + /*************************************************************************************************/ /*! * \brief Baseband driver ECC service function. @@ -117,6 +125,34 @@ static void lctrReverse(uint8_t *p, uint16_t len) } } +/*************************************************************************************************/ +/*! + * \brief Notify host of key generation. + * + * \param pDhKey Diffie-Hellman key. + */ +/*************************************************************************************************/ +static void lctrNotifyGenerateDhKeyInd(const uint8_t *pDhKey) +{ + LlGenerateDhKeyInd_t evt = + { + .hdr = + { + .param = 0, + .event = LL_GENERATE_DHKEY_CMPL_IND, + .status = LL_SUCCESS + } + }; + + evt.status = lmgrScCb.pubKeyValid ? LL_SUCCESS : LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + memcpy(evt.dhKey, pDhKey, sizeof(evt.dhKey)); + + LL_TRACE_INFO0("### LlEvent ### LL_GENERATE_DHKEY_CMPL_IND, status=LL_SUCCESS"); + + LmgrSendEvent((LlEvt_t *)&evt); +} + +#if ENABLE_UECC /*************************************************************************************************/ /*! * \brief Start generating P-256 key pair. @@ -193,6 +229,7 @@ void lctrGenerateP256KeyPairComplete(uint8_t *pPubKey, uint8_t *pPrivKey) lctrReverse(pPubKey + LL_ECC_KEY_LEN, LL_ECC_KEY_LEN); lctrReverse(pPrivKey, LL_ECC_KEY_LEN); } +#endif /*************************************************************************************************/ /*! @@ -213,12 +250,30 @@ void lctrGenerateDhKeyStart(const uint8_t *pPubKey, const uint8_t *pPrivKey) lctrReverseCopy(privKey, pPrivKey, LL_ECC_KEY_LEN); /* Start shared secret generation. */ +#if ENABLE_UECC uECC_set_rng_ll(lctrRng); uECC_shared_secret_start(pubKey, privKey); lctrScBbDrvEcc(LL_MATH_ECC_OP_GENERATE_DH_KEY); +#endif + +#if ENABLE_UECC_TINYCRYPT + uint8_t dhKey[LL_ECC_KEY_LEN]; + uECC_set_rng(lctrRng); + const struct uECC_Curve_t* pCurve = uECC_secp256r1(); + uECC_shared_secret(pPubKey, pPrivKey, dhKey, pCurve); + + /* Reverse shared secret (to little endian). */ + lctrReverse(dhKey, LL_ECC_KEY_LEN); + + /* Notify host that the key was generated. */ + lctrNotifyGenerateDhKeyInd(dhKey); + + lmgrScCb.eccOpActive = FALSE; +#endif } +#if ENABLE_UECC /*************************************************************************************************/ /*! * \brief Continue generating Diffie-Hellman key. @@ -252,6 +307,7 @@ void lctrGenerateDhKeyComplete(uint8_t *pDhKey) /* Reverse shared secret (to little endian). */ lctrReverse(pDhKey, LL_ECC_KEY_LEN); } +#endif /*************************************************************************************************/ /*! @@ -272,7 +328,14 @@ bool_t lctrValidatePublicKey(const uint8_t *pPubKey, bool_t generateKey) lctrReverseCopy(pubKey, pPubKey, LL_ECC_KEY_LEN); lctrReverseCopy(pubKey + LL_ECC_KEY_LEN, pPubKey + LL_ECC_KEY_LEN, LL_ECC_KEY_LEN); +#if ENABLE_UECC pubKeyValid = (bool_t)uECC_valid_public_key_ll(pubKey); +#endif + +#if ENABLE_UECC_TINYCRYPT + const struct uECC_Curve_t* pCurve = uECC_secp256r1(); + pubKeyValid = (bool_t)uECC_valid_public_key(pubKey, pCurve); +#endif if (!pubKeyValid && generateKey) { @@ -310,33 +373,7 @@ static void lctrNotifyReadLocalP256PubKeyInd(const uint8_t *pPubKey) LmgrSendEvent((LlEvt_t *)&evt); } -/*************************************************************************************************/ -/*! - * \brief Notify host of key generation. - * - * \param pDhKey Diffie-Hellman key. - */ -/*************************************************************************************************/ -static void lctrNotifyGenerateDhKeyInd(const uint8_t *pDhKey) -{ - LlGenerateDhKeyInd_t evt = - { - .hdr = - { - .param = 0, - .event = LL_GENERATE_DHKEY_CMPL_IND, - .status = LL_SUCCESS - } - }; - - evt.status = lmgrScCb.pubKeyValid ? LL_SUCCESS : LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; - memcpy(evt.dhKey, pDhKey, sizeof(evt.dhKey)); - - LL_TRACE_INFO0("### LlEvent ### LL_GENERATE_DHKEY_CMPL_IND, status=LL_SUCCESS"); - - LmgrSendEvent((LlEvt_t *)&evt); -} - +#if ENABLE_UECC /*************************************************************************************************/ /*! * \brief P-256 key pair generation. @@ -388,6 +425,7 @@ static void lctrScGenerateDhKeyContinue(void) lmgrScCb.eccOpActive = FALSE; } } +#endif /*************************************************************************************************/ /*! @@ -409,6 +447,8 @@ uint8_t LctrGenerateP256KeyPair(void) /* Start operation. */ lmgrScCb.eccOpActive = TRUE; + +#if ENABLE_UECC if (lmgrScCb.privKeySet) { lctrGenerateP256PublicKeyStart(lmgrScCb.privKey); @@ -417,6 +457,37 @@ uint8_t LctrGenerateP256KeyPair(void) { lctrGenerateP256KeyPairStart(); } +#endif + +#if ENABLE_UECC_TINYCRYPT + uint8_t pubKey[LL_ECC_KEY_LEN * 2]; + uint8_t privKey[LL_ECC_KEY_LEN]; + + if (lmgrScCb.privKeySet) + { + /* Reverse private key (to big endian). */ + lctrReverseCopy(privKey, lmgrScCb.privKey, LL_ECC_KEY_LEN); + } + else + { + /* Generate private key. */ + lctrRng(privKey, sizeof(privKey)); + } + + uECC_set_rng(lctrRng); + const struct uECC_Curve_t* pCurve = uECC_secp256r1(); + uECC_make_key(pubKey, privKey, pCurve); + + /* Reverse keys (to little endian). */ + lctrReverse(pubKey, LL_ECC_KEY_LEN); + lctrReverse(pubKey + LL_ECC_KEY_LEN, LL_ECC_KEY_LEN); + lctrReverseCopy(lmgrScCb.privKey, privKey, LL_ECC_KEY_LEN); + + /* Notify host that the key was generated. */ + lctrNotifyReadLocalP256PubKeyInd(pubKey); + + lmgrScCb.eccOpActive = FALSE; +#endif return LL_SUCCESS; } @@ -471,23 +542,23 @@ uint8_t LctrGenerateDhKey(const uint8_t *pPubKey, const uint8_t *pPrivKey) uint8_t LctrGenerateDebugDhKey() { const uint8_t privKey[LL_ECC_KEY_LEN] = { - 0xbd, 0x1a, 0x3c, 0xcd, 0xa6, 0xb8, 0x99, 0x58, - 0x99, 0xb7, 0x40, 0xeb, 0x7b, 0x60, 0xff, 0x4a, - 0x50, 0x3f, 0x10, 0xd2, 0xe3, 0xb3, 0xc9, 0x74, - 0x38, 0x5f, 0xc5, 0xa3, 0xd4, 0xf6, 0x49, 0x3f + 0xbd, 0x1a, 0x3c, 0xcd, 0xa6, 0xb8, 0x99, 0x58, + 0x99, 0xb7, 0x40, 0xeb, 0x7b, 0x60, 0xff, 0x4a, + 0x50, 0x3f, 0x10, 0xd2, 0xe3, 0xb3, 0xc9, 0x74, + 0x38, 0x5f, 0xc5, 0xa3, 0xd4, 0xf6, 0x49, 0x3f }; const uint8_t pubKey[LL_ECC_KEY_LEN * 2] = { - /* pubDebugKey_x */ - 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, - 0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef, - 0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e, - 0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20, - /* pubDebuKey_y */ - 0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74, - 0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76, - 0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63, - 0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc + /* pubDebugKey_x */ + 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, + 0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef, + 0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e, + 0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20, + /* pubDebuKey_y */ + 0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74, + 0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76, + 0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63, + 0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc }; /* Allow only one key pair generation at a time. */ @@ -529,8 +600,10 @@ uint8_t LctrSetValidatePublicKeyMode(uint8_t validateMode) /*************************************************************************************************/ void LctrScInit(void) { +#if ENABLE_UECC lctrEventHdlrTbl[LCTR_EVENT_SC_GENERATE_P256_KEY_PAIR] = lctrScGenerateP256KeyPairContinue; lctrEventHdlrTbl[LCTR_EVENT_SC_GENERATE_DHKEY] = lctrScGenerateDhKeyContinue; +#endif lmgrPersistCb.featuresDefault |= LL_FEAT_REMOTE_PUB_KEY_VALIDATION; lmgrScCb.validatePubKeyMode = KEY_VALIDATE_MODE_ALT2; diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_slave_phy.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_slave_phy.c index fcb64785de..27b0e07655 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_slave_phy.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_slave_phy.c @@ -6,7 +6,7 @@ * * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,4 +36,6 @@ void LctrSlvPhyConnInit(void) { /* Add LLCP SM handler. */ lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD] = lctrSlvLlcpExecutePhyUpdateSm; + + lctrSlvCheckEncOverridePhyUpdateFn = lctrSlvCheckEncOverridePhyUpdate; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_slave_ae.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_slave_ae.c index a93a841c7f..aa657363fc 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_slave_ae.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_slave_ae.c @@ -22,6 +22,7 @@ */ /*************************************************************************************************/ +#include "ll_api.h" #include "lctr_pdu_adv_ae.h" #include "lctr_pdu_adv.h" #include "lctr_int_adv_slave.h" @@ -190,11 +191,13 @@ static uint8_t lctrPackExtAdvHeader(lctrAdvSet_t *pAdvSet, uint8_t manExtHdrFlag } if ((manExtHdrFlags & LL_EXT_HDR_ADI_BIT) || - ((optExtHdrFlags & LL_EXT_HDR_ADI_BIT) && (!(pAdvSet->extHdrFlags & LL_EXT_HDR_ADI_BIT)))) + ((optExtHdrFlags & LL_EXT_HDR_ADI_BIT) && + (!(pAdvSet->extHdrFlags & LL_EXT_HDR_ADI_BIT) || (isPeriodic && pAdvSet->perParam.enableAdi)))) { /* Pack AdvDataInfo */ extHdrFlags |= LL_EXT_HDR_ADI_BIT; - UINT16_TO_BSTREAM(pBuf, (pAdvSet->param.advSID << 12) | ((pAdvSet->param.advDID & 0x0FFF) << 0)); + uint8_t did = isPeriodic ? pAdvSet->perParam.advDID : pAdvSet->param.advDID; + UINT16_TO_BSTREAM(pBuf, (pAdvSet->param.advSID << 12) | ((did & 0x0FFF) << 0)); #if (LL_ENABLE_TESTER == TRUE) if ((llTesterCb.extHdr.pduMatchMask & (1 << pPduHdr->pduType)) && @@ -610,6 +613,7 @@ uint8_t lctrPackAuxAdvIndPdu(lctrAdvSet_t *pAdvSet, uint8_t *pPduBuf, lctrAdvDat } /*** Host allowed options ***/ + lctrChooseSetAdvA(&pduHdr, pBle, pAdvSet); lctrChooseSetPeerA(&pduHdr, pBle, pAdvSet); @@ -744,6 +748,11 @@ void lctrPackAuxPtr(lctrAdvSet_t const *pAdvSet, uint32_t offsUsec, uint8_t chId auxOffset = LL_MATH_DIV_300(offsUsec); } + if (auxOffset > LCTR_AUX_PTR_MAX_OFFSET) + { + LL_TRACE_ERR1("AUX Offset exceeds max allowed value: %u", auxOffset); + } + pAuxPtr[0] = chIdx | /* LL Channel */ (ca << 6) | /* CA */ (offsUnits << 7); /* Offset Units */ @@ -932,6 +941,7 @@ uint8_t lctrPackSyncIndPdu(lctrAdvSet_t *pAdvSet, uint8_t *pPduBuf, lctrAdvDataB uint8_t manExtHdrFlags = 0; uint8_t optExtHdrFlags = LL_EXT_HDR_AUX_PTR_BIT | + ((lmgrCb.features & LL_FEAT_PER_ADV_ADI_SUP) ? LL_EXT_HDR_ADI_BIT : 0) | ((pAdvSet->perParam.advEventProp & LL_EXT_HDR_TX_PWR_BIT) ? LL_EXT_HDR_TX_PWR_BIT : 0); return lctrPackExtAdvHeader(pAdvSet, manExtHdrFlags, optExtHdrFlags, diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_conn.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_conn.c index f44df7ffb0..a06fe59a7c 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_conn.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_conn.c @@ -129,6 +129,57 @@ static inline bool_t lctrIsSetMinUsedChanParamValid(lctrMinUsedChanInd_t *pParam return TRUE; } +/*************************************************************************************************/ +/*! + * \brief Check whether the subrate request parameters are valid. + * + * \param pParam Subrate request parameter. + * + * \return TRUE if parameters are valid, FALSE otherwise. + */ +/*************************************************************************************************/ +static inline bool_t lctrIsSubrateReqParamValid(lctrSubrateReq_t *pParam) +{ + if ((pParam->srMin < LCTR_MIN_SUBRATE) || + (pParam->srMin > LCTR_MAX_SUBRATE) || + (pParam->srMax < LCTR_MIN_SUBRATE) || + (pParam->srMax > LCTR_MAX_SUBRATE) || + (pParam->srMin > pParam->srMax) || + (pParam->maxLatency > (LCTR_MAX_SUBRATE - 1)) || + (pParam->contNum > (LCTR_MAX_SUBRATE - 1)) || + (pParam->svt < LL_MIN_SUP_TIMEOUT) || + (pParam->svt > LL_MAX_SUP_TIMEOUT)) + { + return FALSE; + } + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Check whether the subrate indication parameters are valid. + * + * \param pParam Subrate indication parameter. + * + * \return TRUE if parameters are valid, FALSE otherwise. + */ +/*************************************************************************************************/ +static inline bool_t lctrIsSubrateIndParamValid(lctrSubrateInd_t *pParam) +{ + if ((pParam->srFactor < LCTR_MIN_SUBRATE) || + (pParam->srFactor > LCTR_MAX_SUBRATE) || + (pParam->latency > (LCTR_MAX_SUBRATE - 1)) || + (pParam->contNum > (LCTR_MAX_SUBRATE - 1)) || + (pParam->svt < LL_MIN_SUP_TIMEOUT) || + (pParam->svt > LL_MAX_SUP_TIMEOUT)) + { + return FALSE; + } + + return TRUE; +} + /*************************************************************************************************/ /*! * \brief Pack an ACL header. @@ -745,7 +796,7 @@ uint8_t lctrUnpackCisTermPdu(lctrCisTermInd_t *pPdu, const uint8_t *pBuf) /*************************************************************************************************/ static uint8_t lctrUnpackPwrChngIndPdu(lctrPwrChngInd_t *pPdu, const uint8_t *pBuf) { - const uint8_t len = LL_PWR_CHNG_IND_LEN; + const uint8_t len = LL_PWR_CHANGE_IND_LEN; pBuf += 1; /* skip opcode */ BSTREAM_TO_UINT8 (pPdu->phy, pBuf); @@ -800,6 +851,103 @@ static uint8_t lctrUnpackPwrCtrlRspPdu(lctrPwrCtrlRsp_t *pPdu, const uint8_t *pB return len; } + +/*************************************************************************************************/ +/*! + * \brief Unpack a subrate request PDU. + * + * \param pPdu Subrate request PDU. + * \param pBuf Packed packet buffer. + * + * \return PDU length. + */ +/*************************************************************************************************/ +static uint8_t lctrUnpackSubrateReqPdu(lctrSubrateReq_t *pPdu, const uint8_t *pBuf) +{ + const uint8_t len = LL_SUBRATE_REQ_LEN; + + pBuf += 1; /* skip opcode */ + BSTREAM_TO_UINT16(pPdu->srMin, pBuf); + BSTREAM_TO_UINT16(pPdu->srMax, pBuf); + BSTREAM_TO_UINT16(pPdu->maxLatency, pBuf); + BSTREAM_TO_UINT16(pPdu->contNum, pBuf); + BSTREAM_TO_UINT16(pPdu->svt, pBuf); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Unpack a subrate indication PDU. + * + * \param pPdu Subrate indication PDU. + * \param pBuf Packed packet buffer. + * + * \return PDU length. + */ +/*************************************************************************************************/ +static uint8_t lctrUnpackSubrateIndPdu(lctrSubrateInd_t *pPdu, const uint8_t *pBuf) +{ + const uint8_t len = LL_SUBRATE_IND_LEN; + + pBuf += 1; /* skip opcode */ + BSTREAM_TO_UINT16(pPdu->srFactor, pBuf); + BSTREAM_TO_UINT16(pPdu->srBaseEvent, pBuf); + BSTREAM_TO_UINT16(pPdu->latency, pBuf); + BSTREAM_TO_UINT16(pPdu->contNum, pBuf); + BSTREAM_TO_UINT16(pPdu->svt, pBuf); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Unpack a channel reporting indication pdu + * + * \param pPdu Channel reporting indication PDU. + * \param pBuf Packed packet buffer. + * + * \return PDU length. + */ +/*************************************************************************************************/ +static uint8_t lctrUnpackChanRptIndPdu(lctrChanRptInd_t *pPdu, const uint8_t *pBuf) +{ + const uint8_t len = LL_CH_REPORTING_LEN; + + pBuf += 1; /* skip opcode */ + BSTREAM_TO_UINT8 (pPdu->enable, pBuf); + BSTREAM_TO_UINT8 (pPdu->minSpacing, pBuf); + BSTREAM_TO_UINT8 (pPdu->maxDelay, pBuf); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Unpack a channel status indication pdu + * + * \param pPdu Channel status indication PDU. + * \param pBuf Packed packet buffer. + * + * \return PDU length. + */ +/*************************************************************************************************/ +static uint8_t lctrUnpackChanStatusIndPdu(lctrChanStatusInd_t *pPdu, const uint8_t *pBuf) +{ + const uint8_t len = LL_CH_STATUS_LEN; + + uint8_t i = 0; + + pBuf += 1; /* skip opcode */ + for (i = 0; i < (LL_CH_STATUS_LEN - 1); i++) + { + /* Leave channel status map packed, unpack as needed. */ + BSTREAM_TO_UINT8 (pPdu->chanStatusMap[i], pBuf); + } + + return len; +} + /*************************************************************************************************/ /*! * \brief Decode an LE-C channel buffer. @@ -1051,7 +1199,7 @@ uint8_t lctrDecodeCtrlPdu(lctrDataPdu_t *pPdu, const uint8_t *pBuf, uint8_t role return LL_ERROR_CODE_UNKNOWN_LMP_PDU; } break; - case LL_PDU_PWR_CHNG_IND: + case LL_PDU_PWR_CHANGE_IND: if ((lmgrCb.features & LL_FEAT_POWER_CHANGE_IND) == 0) { return LL_ERROR_CODE_UNKNOWN_LMP_PDU; @@ -1081,6 +1229,54 @@ uint8_t lctrDecodeCtrlPdu(lctrDataPdu_t *pPdu, const uint8_t *pBuf, uint8_t role return LL_ERROR_CODE_UNKNOWN_LMP_PDU; } break; + case LL_PDU_SUBRATE_REQ: + if ((lmgrCb.features & LL_FEAT_CONN_SUBRATE) == 0) + { + return LL_ERROR_CODE_UNKNOWN_LMP_PDU; + } + if (lctrUnpackSubrateReqPdu(&pPdu->pld.subrateReq, pBuf) != pPdu->hdr.len) + { + return LL_ERROR_CODE_UNKNOWN_LMP_PDU; + } + if (lctrIsSubrateReqParamValid(&pPdu->pld.subrateReq) == FALSE) + { + return LL_ERROR_CODE_INVALID_LMP_PARAMS; + } + break; + case LL_PDU_SUBRATE_IND: + if ((lmgrCb.features & LL_FEAT_CONN_SUBRATE) == 0) + { + return LL_ERROR_CODE_UNKNOWN_LMP_PDU; + } + if (lctrUnpackSubrateIndPdu(&pPdu->pld.subrateInd, pBuf) != pPdu->hdr.len) + { + return LL_ERROR_CODE_UNKNOWN_LMP_PDU; + } + if (lctrIsSubrateIndParamValid(&pPdu->pld.subrateInd) == FALSE) + { + return LL_ERROR_CODE_INVALID_LMP_PARAMS; + } + break; + case LL_PDU_CH_REPORTING_IND: + if ((lmgrCb.features & LL_FEAT_CHANNEL_CLASSIFICATION) == 0) + { + return LL_ERROR_CODE_UNKNOWN_LMP_PDU; + } + if (lctrUnpackChanRptIndPdu(&pPdu->pld.chanRptInd, pBuf) != pPdu->hdr.len) + { + return LL_ERROR_CODE_UNKNOWN_LMP_PDU; + } + break; + case LL_PDU_CH_STATUS_IND: + if ((lmgrCb.features & LL_FEAT_CHANNEL_CLASSIFICATION) == 0) + { + return LL_ERROR_CODE_UNKNOWN_LMP_PDU; + } + if (lctrUnpackChanStatusIndPdu(&pPdu->pld.chanStatusInd, pBuf) != pPdu->hdr.len) + { + return LL_ERROR_CODE_UNKNOWN_LMP_PDU; + } + break; default: result = LL_ERROR_CODE_UNKNOWN_LMP_PDU; diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_conn.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_conn.h index bb33c728df..569254048c 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_conn.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_conn.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -154,32 +154,32 @@ typedef struct /*! \brief Data length request or response PDU. */ typedef struct { - uint16_t maxRxLen; /*!< Maximum receive length. */ - uint16_t maxRxTime; /*!< Maximum receive time. */ - uint16_t maxTxLen; /*!< Maximum transmit length. */ - uint16_t maxTxTime; /*!< Maximum transmit time. */ + uint16_t maxRxLen; /*!< Maximum receive length. */ + uint16_t maxRxTime; /*!< Maximum receive time. */ + uint16_t maxTxLen; /*!< Maximum transmit length. */ + uint16_t maxTxTime; /*!< Maximum transmit time. */ } lctrDataLen_t; /*! \brief PHY request or response PDU. */ typedef struct { - uint8_t txPhys; /*!< Transmitter PHYs. */ - uint8_t rxPhys; /*!< Receiver PHYs. */ + uint8_t txPhys; /*!< Transmitter PHYs. */ + uint8_t rxPhys; /*!< Receiver PHYs. */ } lctrPhy_t; /*! \brief PHY update indication PDU. */ typedef struct { - uint8_t masterToSlavePhy; /*!< Master-to-slave PHY. */ - uint8_t slaveToMasterPhy; /*!< Slave-to-master PHY. */ - uint16_t instant; /*!< Instant. */ + uint8_t masterToSlavePhy; /*!< Master-to-slave PHY. */ + uint8_t slaveToMasterPhy; /*!< Slave-to-master PHY. */ + uint16_t instant; /*!< Instant. */ } lctrPhyUpdInd_t; /*! \brief Minimum number of used channels indication PDU. */ typedef struct { - uint8_t phys; /*!< Bitmask for the affected PHYs. */ - uint8_t minUsedChan; /*!< Minimum number of used channels. */ + uint8_t phys; /*!< Bitmask for the affected PHYs. */ + uint8_t minUsedChan; /*!< Minimum number of used channels. */ } lctrMinUsedChanInd_t; /*! \brief Periodic sync indication PDU. */ @@ -200,61 +200,81 @@ typedef struct /*! \brief Peer SCA response PDU. */ typedef struct { - uint8_t sca; /*!< Peer SCA. */ + uint8_t sca; /*!< Peer SCA. */ } lctrPeerSca_t; /*! \brief CIS request PDU. */ typedef struct { - uint8_t cigId; /*!< CIG identifier. */ - uint8_t cisId; /*!< CIS identifier. */ - uint8_t phyMToS; /*!< Master to slave PHY. */ - uint8_t phySToM; /*!< Slave to Master PHY. */ - uint8_t framing; /*!< PDU framing type. */ - uint16_t sduSizeMToS; /*!< Maximum SDU size from the master Host. */ - uint16_t sduSizeSToM; /*!< Maximum SDU size from the slave Host. */ - uint32_t sduIntervalMToS; /*!< Time interval between the start of consecutive SDUs from the master Host */ - uint32_t sduIntervalSToM; /*!< Time interval between the start of consecutive SDUs from the master Host */ - uint16_t plMToS; /*!< Master to slave payload. */ - uint16_t plSToM; /*!< Slave to master payload. */ - uint8_t nse; /*!< Number of subevent. */ - uint32_t subIntervUsec; /*!< Contain the time between the start of a subevent and the start of the next subevent, 24 significant bits. */ - uint8_t bnMToS; /*!< Master to slave burst number, 4 significant bits. */ - uint8_t bnSToM; /*!< Slave to master burst number, 4 significant bits. */ - uint8_t ftMToS; /*!< Master to slave flush time. */ - uint8_t ftSToM; /*!< Slave to master flush time. */ - uint16_t isoInterval; /*!< Contain the time between two CIS anchor points in 1.25msec unit. */ - uint32_t cisOffMinUsec; /*!< Contain the minimum time between the CE and the first CIS anchor point. */ - uint32_t cisOffMaxUsec; /*!< Contain the maximum time between the CE and the first CIS anchor point. */ - uint16_t ceRef; /*!< Contain the reference CE where offsets are applied. */ + uint8_t cigId; /*!< CIG identifier. */ + uint8_t cisId; /*!< CIS identifier. */ + uint8_t phyMToS; /*!< Master to slave PHY. */ + uint8_t phySToM; /*!< Slave to Master PHY. */ + uint8_t framing; /*!< PDU framing type. */ + uint16_t sduSizeMToS; /*!< Maximum SDU size from the master Host. */ + uint16_t sduSizeSToM; /*!< Maximum SDU size from the slave Host. */ + uint32_t sduIntervalMToS; /*!< Time interval between the start of consecutive SDUs from the master Host */ + uint32_t sduIntervalSToM; /*!< Time interval between the start of consecutive SDUs from the master Host */ + uint16_t plMToS; /*!< Master to slave payload. */ + uint16_t plSToM; /*!< Slave to master payload. */ + uint8_t nse; /*!< Number of subevent. */ + uint32_t subIntervUsec; /*!< Contain the time between the start of a subevent and the start of the next subevent, 24 significant bits. */ + uint8_t bnMToS; /*!< Master to slave burst number, 4 significant bits. */ + uint8_t bnSToM; /*!< Slave to master burst number, 4 significant bits. */ + uint8_t ftMToS; /*!< Master to slave flush time. */ + uint8_t ftSToM; /*!< Slave to master flush time. */ + uint16_t isoInterval; /*!< Contain the time between two CIS anchor points in 1.25msec unit. */ + uint32_t cisOffMinUsec; /*!< Contain the minimum time between the CE and the first CIS anchor point. */ + uint32_t cisOffMaxUsec; /*!< Contain the maximum time between the CE and the first CIS anchor point. */ + uint16_t ceRef; /*!< Contain the reference CE where offsets are applied. */ } lctrCisReq_t; /*! \brief CIS response PDU. */ typedef struct { - uint32_t cisOffMinUsec; /*!< Contain the minimum time between the CE and the first CIS anchor point. */ - uint32_t cisOffMaxUsec; /*!< Contain the maximum time between the CE and the first CIS anchor point. */ - uint16_t ceRef; /*!< Contain the reference CE where offsets are applied. */ + uint32_t cisOffMinUsec; /*!< Contain the minimum time between the CE and the first CIS anchor point. */ + uint32_t cisOffMaxUsec; /*!< Contain the maximum time between the CE and the first CIS anchor point. */ + uint16_t ceRef; /*!< Contain the reference CE where offsets are applied. */ } lctrCisRsp_t; /*! \brief CIS indication PDU. */ typedef struct { - uint32_t accessAddr; /*!< Contain the access address of the CIS. */ - uint32_t cisOffUsec; /*!< Contain the time from the start of the referenced CE to the first CIS anchor point. */ - uint32_t cigSyncDelayUsec; /*!< CIG synchronization delay in usec. */ - uint32_t cisSyncDelayUsec; /*!< CIG synchronization delay in usec. */ - uint16_t ceRef; /*!< Contain the reference CE where offsets are applied. */ + uint32_t accessAddr; /*!< Contain the access address of the CIS. */ + uint32_t cisOffUsec; /*!< Contain the time from the start of the referenced CE to the first CIS anchor point. */ + uint32_t cigSyncDelayUsec; /*!< CIG synchronization delay in usec. */ + uint32_t cisSyncDelayUsec; /*!< CIG synchronization delay in usec. */ + uint16_t ceRef; /*!< Contain the reference CE where offsets are applied. */ } lctrCisInd_t; /*! \brief CIS terminate PDU. */ typedef struct { - uint8_t cigId; /*!< CIG identifier. */ - uint8_t cisId; /*!< CIS identifier. */ - uint8_t reason; /*!< Reason for termination. */ + uint8_t cigId; /*!< CIG identifier. */ + uint8_t cisId; /*!< CIS identifier. */ + uint8_t reason; /*!< Reason for termination. */ } lctrCisTermInd_t; +/*! \brief Subrate request PDU. */ +typedef struct +{ + uint16_t srMin; /*!< Subrate minimum value. */ + uint16_t srMax; /*!< Subrate maximum value. */ + uint16_t maxLatency; /*!< Maximum latency. */ + uint16_t contNum; /*!< Continuation number. */ + uint16_t svt; /*!< Supervision timeout in 10ms units. */ +} lctrSubrateReq_t; + +/*! \brief Subrate indication PDU. */ +typedef struct +{ + uint16_t srFactor; /*!< Subrate factor. */ + uint16_t srBaseEvent; /*!< Subrate base event. */ + uint16_t latency; /*!< Latency. */ + uint16_t contNum; /*!< Continuation number. */ + uint16_t svt; /*!< Supervision timeout in 10ms units. */ +} lctrSubrateInd_t; + /*! \brief Power control request PDU. */ typedef struct { @@ -281,6 +301,21 @@ typedef struct int8_t txPower; /*!< Local txPower. */ } lctrPwrChngInd_t; +/*! \brief Channel reporting indication PDU. */ +typedef struct +{ + uint8_t enable; /*!< Enable. */ + uint8_t minSpacing; /*!< Minimum spacing. */ + uint8_t maxDelay; /*!< Maximum delay. */ +} lctrChanRptInd_t; + +/*! \brief Channel status indication PDU. */ +typedef struct +{ + uint8_t chanStatusMap[LL_CH_STATUS_LEN - 1]; + /*!< Map of current peer channel status. */ +} lctrChanStatusInd_t; + /*! \brief Data channel control PDU. */ typedef struct { @@ -314,6 +349,11 @@ typedef struct lctrPwrCtrlReq_t pwrCtrlReq; /*!< Power control request. */ lctrPwrCtrlRsp_t pwrCtrlRsp; /*!< Power control response. */ lctrPwrChngInd_t pwrChngInd; /*!< Power change indication. */ + lctrChanRptInd_t chanRptInd; /*!< Channel report indication. */ + lctrChanStatusInd_t chanStatusInd; + /*!< Channel status indication. */ + lctrSubrateReq_t subrateReq; /*!< Subrate request. */ + lctrSubrateInd_t subrateInd; /*!< Subrate indication. */ } pld; /*!< Unpacked PDU payload. */ } lctrDataPdu_t; diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_iso.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_iso.c index e2b8f33a47..f9f3d9acaf 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_iso.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_iso.c @@ -37,9 +37,9 @@ * \return Header length. */ /*************************************************************************************************/ -uint8_t lctrIsoUnpackHdr(lctrIsoHdr_t *pHdr, const uint8_t *pBuf) +uint8_t lctrIsoUnpackHdr(lctrIsoHdr_t *pHdr, uint8_t *pBuf) { - uint8_t len = HCI_ISO_HDR_LEN + HCI_ISO_DL_MIN_LEN; + uint8_t len = HCI_ISO_HDR_LEN; uint16_t field16; @@ -50,21 +50,34 @@ uint8_t lctrIsoUnpackHdr(lctrIsoHdr_t *pHdr, const uint8_t *pBuf) BSTREAM_TO_UINT16(pHdr->len, pBuf); - if (pHdr->tsFlag) + switch (pHdr->pb) { - BSTREAM_TO_UINT32(pHdr->ts, pBuf); - len += HCI_ISO_TS_LEN; - } - else - { - pHdr->ts = 0; - } + case LCTR_PB_COMP: + case LCTR_PB_FIRST: + len += HCI_ISO_DL_MIN_LEN; + if (pHdr->tsFlag) + { + BSTREAM_TO_UINT32(pHdr->ts, pBuf); + len += HCI_ISO_TS_LEN; + } + else + { + pHdr->ts = 0; + } - BSTREAM_TO_UINT16(pHdr->pktSn, pBuf); - BSTREAM_TO_UINT16(field16, pBuf); + BSTREAM_TO_UINT16(pHdr->pktSn, pBuf); + BSTREAM_TO_UINT16(field16, pBuf); - pHdr->sduLen = (field16 >> 0) & 0x0FFF; - pHdr->ps = (field16 >> 14) & 0x03; + pHdr->sduLen = (field16 >> 0) & 0x0FFF; + pHdr->ps = (field16 >> 14) & 0x03; + break; + + default: + pHdr->ts = 0; + pHdr->sduLen = 0; + pHdr->ps = 0; + break; + } pHdr->pSdu = pBuf; diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_iso.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_iso.h index 3888a92ae8..23273ca80a 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_iso.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_iso.h @@ -82,7 +82,7 @@ typedef struct uint16_t pktSn; /*!< Packet sequence number. */ uint16_t sduLen; /*!< SDU length. */ lctrPktStatus_t ps:8; /*!< Packet status. */ - const uint8_t *pSdu; /*!< First byte of ISO SDU. */ + uint8_t *pSdu; /*!< First byte of ISO SDU. */ } lctrIsoHdr_t; /*! \brief ISO SDU descriptor. */ @@ -136,7 +136,7 @@ uint8_t lctrBisPackBigChannelMapInd(uint8_t *pBuf, uint64_t chanMap, uint16_t in uint8_t lctrBisPackBigTerminateInd(uint8_t *pBuf, uint8_t reason, uint16_t instance); /* Unpack */ -uint8_t lctrIsoUnpackHdr(lctrIsoHdr_t *pHdr, const uint8_t *pBuf); +uint8_t lctrIsoUnpackHdr(lctrIsoHdr_t *pHdr, uint8_t *pBuf); uint8_t lctrCisUnpackDataPduHdr(lctrCisDataPduHdr_t *pHdr, const uint8_t *pBuf); uint8_t lctrBisUnpackDataPduHdr(lctrBisDataPduHdr_t *pHdr, const uint8_t *pBuf); uint8_t lctrBisUnpackBigChannelMapInd(uint64_t *pChanMap, uint16_t *pInstance, const uint8_t *pBuf); diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_slave_ae.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_slave_ae.c index bda9c64e0d..3285c1f9be 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_slave_ae.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_slave_ae.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_cis.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_cis.c index 6499914c51..d340eaeb00 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_cis.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_cis.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -60,6 +60,7 @@ static uint8_t lctrRemapEvent(lctrCisCtx_t *pCisCtx, uint8_t event) case LCTR_CONN_MSG_API_DISCONNECT: { + pCisCtx->hostInitTerm = TRUE; lctrCisStoreDisconnectReason(pCisCtx); return LCTR_CIS_MSG_CIS_DISC; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_cis_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_cis_master.c index 1a62568038..a577bf0ee7 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_cis_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_cis_master.c @@ -249,7 +249,12 @@ bool_t lctrMstLlcpExecuteCisEstSm(lctrConnCtx_t *pCtx, uint8_t event) } lctrCisCtx_t *pCisCtx = lctrFindCisByHandle(pCtx->llcpCisHandle); - WSF_ASSERT(pCisCtx != NULL) + if (pCisCtx == NULL) + { + LL_TRACE_WARN1("lctrMstLlcpExecuteCisEstSm: CIS context not found cis_handle=%u", pCtx->llcpCisHandle); + /* TRUE to prevent further processing of this message. */ + return TRUE; + } switch (pCtx->llcpState) { diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn.c index 54baacaf8f..2cbd64e384 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,6 +38,7 @@ #include "lctr_int_conn.h" #include "lctr_int_conn_slave.h" +#include "ll_init_api.h" #include "lmgr_api.h" #include "util/bstream.h" #include "wsf_trace.h" @@ -142,6 +143,24 @@ const lctrLlcpEh_t lctrCmnProcTbl[LCTR_PROC_CMN_TOTAL][LCTR_PROC_CMN_ACT_TOTAL] lctrStorePeerSca, /* LCTR_PROC_CMN_ACT_RECV_REQ */ lctrSendPeerScaRsp, /* LCTR_PROC_CMN_ACT_SEND_RSP */ lctrStorePeerSca, /* LCTR_PROC_CMN_ACT_RECV_RSP */ + }, + /* LCTR_PROC_CMN_CH_CLASS_REPORTING */ + { + NULL, /* LCTR_PROC_CMN_ACT_API_PARAM */ + lctrSendChannelReportingInd, + /* LCTR_PROC_CMN_ACT_SEND_REQ */ + lctrStoreChannelReportingInd, + /* LCTR_PROC_CMN_ACT_RECV_REQ */ + NULL, /* LCTR_PROC_CMN_ACT_SEND_RSP */ + NULL /* LCTR_PROC_CMN_ACT_RECV_RSP */ + }, + /* LCTR_PROC_CMN_CH_STATUS_REPORT */ + { + NULL, /* LCTR_PROC_CMN_ACT_API_PARAM */ + lctrSendChannelStatusInd, /* LCTR_PROC_CMN_ACT_SEND_REQ */ + lctrStoreChannelStatusInd, /* LCTR_PROC_CMN_ACT_RECV_REQ */ + NULL, /* LCTR_PROC_CMN_ACT_SEND_RSP */ + NULL /* LCTR_PROC_CMN_ACT_RECV_RSP */ } }; @@ -270,6 +289,12 @@ static uint8_t lctrGetCmnProcId(lctrConnCtx_t *pCtx, uint8_t event) case LCTR_CONN_LLCP_LENGTH_EXCH: return LCTR_PROC_CMN_DATA_LEN_UPD; + case LCTR_CONN_LLCP_CHANNEL_STATUS: + return LCTR_PROC_CMN_CH_STATUS_REPORT; + + case LCTR_CONN_LLCP_CHANNEL_REPORTING: + return LCTR_PROC_CMN_CH_CLASS_REPORTING; + case LCTR_CONN_LLCP_PROC_CMPL: return pCtx->llcpActiveProc; @@ -304,6 +329,12 @@ static uint8_t lctrGetCmnProcId(lctrConnCtx_t *pCtx, uint8_t event) case LL_PDU_PEER_SCA_RSP: return LCTR_PROC_CMN_REQ_PEER_SCA; + case LL_PDU_CH_REPORTING_IND: + return LCTR_PROC_CMN_CH_CLASS_REPORTING; + + case LL_PDU_CH_STATUS_IND: + return LCTR_PROC_CMN_CH_STATUS_REPORT; + case LL_PDU_UNKNOWN_RSP: switch (lctrDataPdu.pld.unknownRsp.unknownType) { @@ -325,6 +356,19 @@ static uint8_t lctrGetCmnProcId(lctrConnCtx_t *pCtx, uint8_t event) case LL_PDU_LENGTH_RSP: return LCTR_PROC_CMN_DATA_LEN_UPD; + case LL_PDU_PWR_CHANGE_IND: + return LCTR_PROC_PWR_IND; + + case LL_PDU_PWR_CTRL_RSP: + case LL_PDU_PWR_CTRL_REQ: + return LCTR_PROC_PWR_CTRL; + + case LL_PDU_CH_REPORTING_IND: + return LCTR_PROC_CMN_CH_CLASS_REPORTING; + + case LL_PDU_CH_STATUS_IND: + return LCTR_PROC_CMN_CH_STATUS_REPORT; + default: break; } @@ -381,6 +425,8 @@ static uint8_t lctrRemapCmnProcEvent(lctrConnCtx_t *pCtx, uint8_t event) case LCTR_CONN_LLCP_VERSION_EXCH: case LCTR_CONN_LLCP_LENGTH_EXCH: case LCTR_CONN_LLCP_TERM: + case LCTR_CONN_LLCP_CHANNEL_STATUS: + case LCTR_CONN_LLCP_CHANNEL_REPORTING: return LCTR_PROC_CMN_EVT_INT_START; case LCTR_CONN_LLCP_PROC_CMPL: @@ -397,6 +443,8 @@ static uint8_t lctrRemapCmnProcEvent(lctrConnCtx_t *pCtx, uint8_t event) case LL_PDU_SLV_FEATURE_REQ: case LL_PDU_LENGTH_REQ: case LL_PDU_PEER_SCA_REQ: + case LL_PDU_CH_REPORTING_IND: + case LL_PDU_CH_STATUS_IND: return LCTR_PROC_CMN_EVT_RECV_REQ; case LL_PDU_TERMINATE_IND: @@ -541,6 +589,14 @@ static bool_t lctrFeatureAvail(lctrConnCtx_t *pCtx, uint8_t proc, uint8_t event) result = FALSE; } break; + case LCTR_PROC_CMN_CH_CLASS_REPORTING: + case LCTR_PROC_CMN_CH_STATUS_REPORT: + if ((pCtx->usedFeatSet & LL_FEAT_CHANNEL_CLASSIFICATION) == 0) + { + LL_TRACE_WARN1("Requested LL_FEAT_CHANNEL_CLASSIFICATION not available, usedFeatSet=0x%08x", pCtx->usedFeatSet); + result = FALSE; + } + break; case LCTR_PROC_CMN_TERM: default: break; @@ -575,7 +631,14 @@ static void lctrNotifyHostReadRemoteFeatCnf(lctrConnCtx_t *pCtx, uint8_t status) }; uint8_t *pBuf = evt.features; - UINT64_TO_BSTREAM(pBuf, pCtx->usedFeatSet); + if (BT_VER < LL_VER_BT_CORE_SPEC_5_0) + { + UINT64_TO_BSTREAM(pBuf, pCtx->usedFeatSet); + } + else + { + UINT64_TO_BSTREAM(pBuf, pCtx->peerFeatures); + } LL_TRACE_INFO2("### LlEvent ### LL_READ_REMOTE_FEAT_CNF, handle=%u, status=%u", handle, status); diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn_master.c index 0f7f8ab60d..0577cfa569 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn_master.c @@ -53,13 +53,13 @@ enum LCTR_CU_EVENT_HOST_NEG_REPLY, /*!< Received host connection parameter negative reply. */ LCTR_CU_EVENT_PEER_CONN_PARAM_REQ, /*!< Received peer LL_CONN_PARAM_REQ. */ LCTR_CU_EVENT_PEER_CONN_PARAM_RSP, /*!< Received peer LL_CONN_PARAM_RSP. */ - LCTR_CU_EVENT_PEER_REJECT, /*!< Received peer LL_REJECT_IND OR LL_UNKNOWN_RSP. */ + LCTR_CU_EVENT_PEER_REJECT, /*!< Received peer LL_REJECT_IND or LL_UNKNOWN_RSP. */ LCTR_CU_EVENT_INT_PROC_COMP, /*!< Procedure completion event. */ LCTR_CU_EVENT_INT_SKIP_CONN_PARAM, /*!< Skip connection parameter procedure. */ LCTR_CU_EVENT_INT_START_CONN_UPD, /*!< Start pending host connection update procedure. */ LCTR_CU_EVENT_INT_START_CONN_PARAM, /*!< Start pending peer connection parameter procedure. */ LCTR_CU_EVENT_INT_REJECT_CONN_UPD, /*!< Reject connection update procedure. */ - LCTR_CU_EVENT_TOTAL, /*!< Total connection parameter/update states. */ + LCTR_CU_EVENT_TOTAL, /*!< Total connection parameter/update events. */ LCTR_CU_EVENT_INVALID = 0xFF /*!< Invalid event. */ }; @@ -638,14 +638,15 @@ void lctrMstLlcpExecuteSm(lctrConnCtx_t *pCtx, uint8_t event) break; } - if (!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_ENCRYPT] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_ENCRYPT](pCtx, event)) && - !(lctrMstLlcpSmTbl[LCTR_LLCP_SM_PING] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_PING](pCtx, event)) && - !(lctrMstLlcpSmTbl[LCTR_LLCP_SM_CONN_UPD] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_CONN_UPD](pCtx, event)) && - !(lctrMstLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD](pCtx, event)) && - !(lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_EST] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_EST](pCtx, event)) && - !(lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM](pCtx, event)) && - !(lctrMstLlcpSmTbl[LCTR_LLCP_SM_PC] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_PC](pCtx, event)) && - !(lctrMstLlcpSmTbl[LCTR_LLCP_SM_CMN] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_CMN](pCtx, event))) + if (!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_ENCRYPT] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_ENCRYPT](pCtx, event)) && + !(lctrMstLlcpSmTbl[LCTR_LLCP_SM_PING] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_PING](pCtx, event)) && + !(lctrMstLlcpSmTbl[LCTR_LLCP_SM_ENH_CONN_UPD] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_ENH_CONN_UPD](pCtx, event)) && + !(lctrMstLlcpSmTbl[LCTR_LLCP_SM_CONN_UPD] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_CONN_UPD](pCtx, event)) && + !(lctrMstLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD](pCtx, event)) && + !(lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_EST] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_EST](pCtx, event)) && + !(lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM](pCtx, event)) && + !(lctrMstLlcpSmTbl[LCTR_LLCP_SM_PC] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_PC](pCtx, event)) && + !(lctrMstLlcpSmTbl[LCTR_LLCP_SM_CMN] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_CMN](pCtx, event))) { lctrLlcpStatelessEventHandler(pCtx, event); } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn_slave.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn_slave.c index 4d0e7bbc6c..69083a0f91 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn_slave.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn_slave.c @@ -50,10 +50,10 @@ enum LCTR_CU_EVENT_HOST_REPLY, /*!< Received host connection parameter reply. */ LCTR_CU_EVENT_HOST_NEG_REPLY, /*!< Received host connection parameter negative reply. */ LCTR_CU_EVENT_PEER_CONN_UPD_IND, /*!< Received peer LL_CONN_UPD_IND. */ - LCTR_CU_EVENT_PEER_REJECT, /*!< Received peer LL_REJECT_IND OR LL_UNKNOWN_RSP. */ + LCTR_CU_EVENT_PEER_REJECT, /*!< Received peer LL_REJECT_IND or LL_UNKNOWN_RSP. */ LCTR_CU_EVENT_INT_PROC_COMP, /*!< Procedure completion event. */ LCTR_CU_EVENT_INT_START_CONN_UPD, /*!< Start pending connection update procedure. */ - LCTR_CU_EVENT_TOTAL, /*!< Total connection parameter/update states. */ + LCTR_CU_EVENT_TOTAL, /*!< Total connection parameter/update events. */ LCTR_CU_EVENT_INVALID = 0xFF /*!< Invalid event. */ }; @@ -670,14 +670,15 @@ void lctrSlvLlcpExecuteSm(lctrConnCtx_t *pCtx, uint8_t event) break; } - if (!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_ENCRYPT] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_ENCRYPT](pCtx, event)) && - !(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PING] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PING](pCtx, event)) && - !(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CONN_UPD] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CONN_UPD](pCtx, event)) && - !(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD](pCtx, event)) && - !(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_EST] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_EST](pCtx, event)) && - !(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM](pCtx, event)) && - !(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PC] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PC](pCtx, event)) && - !(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CMN] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CMN](pCtx, event)) ) + if (!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_ENCRYPT] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_ENCRYPT](pCtx, event)) && + !(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PING] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PING](pCtx, event)) && + !(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_ENH_CONN_UPD] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_ENH_CONN_UPD](pCtx, event)) && + !(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CONN_UPD] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CONN_UPD](pCtx, event)) && + !(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD](pCtx, event)) && + !(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_EST] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_EST](pCtx, event)) && + !(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM](pCtx, event)) && + !(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PC] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PC](pCtx, event)) && + !(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CMN] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CMN](pCtx, event)) ) { lctrLlcpStatelessEventHandler(pCtx, event); } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_enc_slave.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_enc_slave.c index e60fd8b1c2..d499d02ec4 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_enc_slave.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_enc_slave.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ #include "lctr_int_enc_slave.h" #include "lctr_int_conn.h" #include "lctr_int_conn_slave.h" +#include "lctr_int_slave_phy.h" #include "lmgr_api.h" #include "wsf_trace.h" @@ -428,7 +429,8 @@ static void lctrSlvCheckProcOverride(lctrConnCtx_t *pCtx, uint8_t event) { case LCTR_ENC_EVENT_PEER_ENC_REQ: if (lctrSlvCheckEncOverrideConnParam(pCtx) || - lctrSlvCheckEncOverrideCommonParam(pCtx)) + lctrSlvCheckEncOverrideCommonParam(pCtx) || + ((lctrSlvCheckEncOverridePhyUpdateFn == NULL) || lctrSlvCheckEncOverridePhyUpdateFn(pCtx))) { pCtx->llcpPendMask |= 1 << pCtx->llcpActiveProc; pCtx->llcpActiveProc = LCTR_PROC_ENCRYPT; diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_pc.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_pc.c index 2fbb9dbe31..d817a56af4 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_pc.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_pc.c @@ -34,60 +34,60 @@ /*! \brief Power control LLCP types. */ enum { - LCTR_PC_PROC_IND, /*!< Power Indication process. */ - LCTR_PC_PROC_CTRL, /*!< Power control process. */ + LCTR_PC_PROC_IND, /*!< Power Indication process. */ + LCTR_PC_PROC_CTRL, /*!< Power control process. */ - LCTR_PC_PROC_TOTAL /*!< Total power control procedures. */ + LCTR_PC_PROC_TOTAL /*!< Total power control procedures. */ }; -/*! \brief Common LLCP actions. */ +/*! \brief Power control LLCP actions. */ enum { - LCTR_PROC_CMN_ACT_API_PARAM, /*!< Store host API parameter action. */ - LCTR_PROC_CMN_ACT_SEND_REQ, /*!< Send request action. */ - LCTR_PROC_CMN_ACT_RECV_REQ, /*!< Receive request action. */ - LCTR_PROC_CMN_ACT_SEND_RSP, /*!< Send response action. */ - LCTR_PROC_CMN_ACT_RECV_RSP, /*!< Receive response action. */ - LCTR_PROC_CMN_ACT_TOTAL /*!< Total common procedure actions. */ + LCTR_PC_ACT_API_PARAM, /*!< Store host API parameter action. */ + LCTR_PC_ACT_SEND_REQ, /*!< Send request action. */ + LCTR_PC_ACT_RECV_REQ, /*!< Receive request action. */ + LCTR_PC_ACT_SEND_RSP, /*!< Send response action. */ + LCTR_PC_ACT_RECV_RSP, /*!< Receive response action. */ + LCTR_PC_ACT_TOTAL /*!< Total power control procedure actions. */ }; -/*! \brief Common LLCP events. */ +/*! \brief Power control LLCP events. */ enum { - LCTR_PROC_CMN_EVT_HOST_START, /*!< Host initiated start procedure event. */ - LCTR_PROC_CMN_EVT_INT_START, /*!< LL initiated start procedure event. */ - LCTR_PROC_CMN_EVT_INT_INCOMP, /*!< Complete an interrupted procedure event. */ - LCTR_PROC_CMN_EVT_RECV_IND, /*!< Receive indication event. */ - LCTR_PROC_CMN_EVT_RECV_REQ, /*!< Receive request event. */ - LCTR_PROC_CMN_EVT_RECV_RSP, /*!< Receive response event. */ - LCTR_PROC_CMN_EVT_PROC_COMP, /*!< Procedure completed event. */ - LCTR_PROC_CMN_EVT_REJECT, /*!< Procedure rejected event. */ - LCTR_PROC_CMN_EVT_TOTAL, /*!< Total common procedure events. */ - LCTR_PROC_CMN_EVT_INVALID = 0xFF /*!< Invalid event. */ + LCTR_PC_EVT_HOST_START, /*!< Host initiated start procedure event. */ + LCTR_PC_EVT_INT_START, /*!< LL initiated start procedure event. */ + LCTR_PC_EVT_INT_INCOMP, /*!< Complete an interrupted procedure event. */ + LCTR_PC_EVT_RECV_IND, /*!< Receive indication event. */ + LCTR_PC_EVT_RECV_REQ, /*!< Receive request event. */ + LCTR_PC_EVT_RECV_RSP, /*!< Receive response event. */ + LCTR_PC_EVT_PROC_COMP, /*!< Procedure completed event. */ + LCTR_PC_EVT_REJECT, /*!< Procedure rejected event. */ + LCTR_PC_EVT_TOTAL, /*!< Total power control procedure events. */ + LCTR_PC_EVT_INVALID = 0xFF /*!< Invalid event. */ }; /************************************************************************************************** Global Variables **************************************************************************************************/ -/*! \brief Common procedure state machine action table. */ -const lctrLlcpEh_t lctrPclProcTbl[LCTR_PC_PROC_TOTAL][LCTR_PROC_CMN_ACT_TOTAL] = +/*! \brief Power control procedure state machine action table. */ +const lctrLlcpEh_t lctrPclProcTbl[LCTR_PC_PROC_TOTAL][LCTR_PC_ACT_TOTAL] = { /* LCTR_PROC_PWR_IND */ { - NULL, /* LCTR_PROC_CMN_ACT_API_PARAM */ - NULL, /* LCTR_PROC_CMN_ACT_SEND_REQ */ - lctrStorePeerPowerInd, /* LCTR_PROC_CMN_ACT_RECV_REQ */ - lctrSendPeerPowerRsp, /* LCTR_PROC_CMN_ACT_SEND_RSP */ - NULL /* LCTR_PROC_CMN_ACT_RECV_RSP */ + NULL, /* LCTR_PC_ACT_API_PARAM */ + NULL, /* LCTR_PC_ACT_SEND_REQ */ + lctrStorePeerPowerInd, /* LCTR_PC_ACT_RECV_REQ */ + lctrSendPeerPowerRsp, /* LCTR_PC_ACT_SEND_RSP */ + NULL, /* LCTR_PC_ACT_RECV_RSP */ }, /* LCTR_PROC_PWR_CTRL */ { - lctrStorePowerControlAction, /* LCTR_PROC_CMN_ACT_API_PARAM */ - lctrSendPeerPowerControlReq, /* LCTR_PROC_CMN_ACT_SEND_REQ */ - lctrStorePeerPowerControlReq, /* LCTR_PROC_CMN_ACT_RECV_REQ */ - lctrSendPeerPowerControlRsp, /* LCTR_PROC_CMN_ACT_SEND_RSP */ - lctrStorePeerPowerControlRsp /* LCTR_PROC_CMN_ACT_RECV_RSP */ + lctrStorePowerControlAction, /* LCTR_PC_ACT_API_PARAM */ + lctrSendPeerPowerControlReq, /* LCTR_PC_ACT_SEND_REQ */ + lctrStorePeerPowerControlReq, /* LCTR_PC_ACT_RECV_REQ */ + lctrSendPeerPowerControlRsp, /* LCTR_PC_ACT_SEND_RSP */ + lctrStorePeerPowerControlRsp, /* LCTR_PC_ACT_RECV_RSP */ } }; @@ -156,7 +156,7 @@ static uint8_t lctrGetPclProcId(lctrConnCtx_t *pCtx, uint8_t event) case LCTR_CONN_MSG_RX_LLCP: switch (lctrDataPdu.opcode) { - case LL_PDU_PWR_CHNG_IND: + case LL_PDU_PWR_CHANGE_IND: return LCTR_PROC_PWR_IND; case LL_PDU_PWR_CTRL_REQ: @@ -167,6 +167,16 @@ static uint8_t lctrGetPclProcId(lctrConnCtx_t *pCtx, uint8_t event) case LL_PDU_REJECT_EXT_IND: return pCtx->llcpActiveProc; + case LL_PDU_UNKNOWN_RSP: + switch (lctrDataPdu.pld.unknownRsp.unknownType) + { + case LL_PDU_PWR_CTRL_REQ: + case LL_PDU_PWR_CTRL_RSP: + case LL_PDU_PWR_CHANGE_IND: + return LCTR_PC_EVT_REJECT; + } + break; + default: break; } @@ -195,63 +205,63 @@ static uint8_t lctrGetPclProcId(lctrConnCtx_t *pCtx, uint8_t event) /*************************************************************************************************/ /*! - * \brief Get remapped common LLCP procedure event. + * \brief Get remapped power control LLCP procedure event. * * \param pCtx Connection context. * \param event Subsystem event. * - * \return Common LLCP procedure action ID. + * \return Power control LLCP procedure action ID. * - * This routine remaps events for the common LLCP procedure state machine for optimized + * This routine remaps events for the power control LLCP procedure state machine for optimized * compressed state tables. */ /*************************************************************************************************/ -static uint8_t lctrRemapCmnProcEvent(lctrConnCtx_t *pCtx, uint8_t event) +static uint8_t lctrRemapPcEvent(lctrConnCtx_t *pCtx, uint8_t event) { switch (event) { case LCTR_CONN_MSG_API_PWR_CTRL_REQ: - return LCTR_PROC_CMN_EVT_HOST_START; + return LCTR_PC_EVT_HOST_START; case LCTR_CONN_MSG_RX_LLCP_UNKNOWN: - return LCTR_PROC_CMN_EVT_RECV_REQ; + return LCTR_PC_EVT_RECV_REQ; case LCTR_CONN_MSG_RX_LLCP: switch (lctrDataPdu.opcode) { case LL_PDU_PWR_CTRL_REQ: - return LCTR_PROC_CMN_EVT_RECV_REQ; + return LCTR_PC_EVT_RECV_REQ; - case LL_PDU_PWR_CHNG_IND: - return LCTR_PROC_CMN_EVT_RECV_IND; + case LL_PDU_PWR_CHANGE_IND: + return LCTR_PC_EVT_RECV_IND; case LL_PDU_PWR_CTRL_RSP: - return LCTR_PROC_CMN_EVT_RECV_RSP; + return LCTR_PC_EVT_RECV_RSP; case LL_PDU_UNKNOWN_RSP: case LL_PDU_REJECT_IND: case LL_PDU_REJECT_EXT_IND: - return LCTR_PROC_CMN_EVT_REJECT; + return LCTR_PC_EVT_REJECT; default: - return LCTR_PROC_CMN_EVT_INVALID; + return LCTR_PC_EVT_INVALID; } case LCTR_CONN_LLCP_START_PENDING: if (pCtx->llcpIncompMask) { - return LCTR_PROC_CMN_EVT_INT_INCOMP; + return LCTR_PC_EVT_INT_INCOMP; } else { - return LCTR_PROC_CMN_EVT_INT_START; + return LCTR_PC_EVT_INT_START; } default: break; } - return LCTR_PROC_CMN_EVT_INVALID; + return LCTR_PC_EVT_INVALID; } /*************************************************************************************************/ @@ -314,9 +324,9 @@ static void lctrNotifyHostSuccess(lctrConnCtx_t *pCtx, uint8_t proc) case LCTR_PROC_PWR_CTRL: if (pCtx->readRemoteTxPower) { - lctrNotifyPowerReportInd(pCtx, LL_POWER_REPORT_REASON_READ_REMOTE, - pCtx->reqPhy, pCtx->peerTxPower, pCtx->peerPwrLimits, - pCtx->delta); + lctrNotifyPowerReportInd(pCtx, LL_SUCCESS, LL_POWER_REPORT_REASON_READ_REMOTE, + pCtx->reqPhy, pCtx->peerTxPower, pCtx->peerPwrLimits, + pCtx->delta); pCtx->readRemoteTxPower = FALSE; } break; @@ -341,11 +351,47 @@ static void lctrNotifyHostReject(lctrConnCtx_t *pCtx, uint8_t proc) } pCtx->llcpNotifyMask &= ~(1 << proc); + + uint8_t reason = LL_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE; + + switch (lctrDataPdu.opcode) + { + case LL_PDU_REJECT_IND: + case LL_PDU_REJECT_EXT_IND: + reason = lctrDataPdu.pld.rejInd.reason; + break; + case LL_PDU_UNKNOWN_RSP: + /* Do not transmit another PCL request if the peer does not recognize it. */ + if (proc == LCTR_PROC_PWR_CTRL) + { + pCtx->usedFeatSet &= ~LL_FEAT_POWER_CONTROL_REQUEST; + } + if (proc == LCTR_PROC_PWR_IND) + { + pCtx->usedFeatSet &= ~LL_FEAT_POWER_CHANGE_IND; + } + break; + default: + break; + } + switch (proc) + { + case LCTR_PROC_PWR_CTRL: + if (pCtx->readRemoteTxPower) + { + lctrNotifyPowerReportInd(pCtx, reason, LL_POWER_REPORT_REASON_READ_REMOTE, 0, 0, 0, 0); + } + break; + case LCTR_PROC_PWR_IND: + break; + default: + break; + } } /*************************************************************************************************/ /*! - * \brief Execute common LLCP state machine. + * \brief Execute power control LLCP state machine. * * \param pCtx Connection context. * \param event State machine event. @@ -358,7 +404,37 @@ bool_t lctrLlcpExecutePclSm(lctrConnCtx_t *pCtx, uint8_t event) uint8_t proc; uint8_t llEvent = event; - if ((event = lctrRemapCmnProcEvent(pCtx, event)) == LCTR_PROC_CMN_EVT_INVALID) + /*** State-less events ***/ + + if (event == LCTR_CONN_LLCP_PWR_CTRL_SERVICE) + { + proc = LCTR_PROC_PWR_CTRL; + + if (lctrFeatureAvail(pCtx, proc, event) && + (pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) && + (pCtx->powerMonitorScheme == LCTR_PC_MONITOR_AUTO)) + { + /* Restart timer. */ + WsfTimerStartMs(&pCtx->tmrPowerCtrl, LL_PC_SERVICE_MS); + lctrConnServicePowerMonitor(pCtx); + + /* If CIS is enabled, monitor those power levels if needed. */ + if (lctrCisServicePowerMonitorFn) + { + lctrCisServicePowerMonitorFn(pCtx); + } + } + else + { + WsfTimerStop(&pCtx->tmrPowerCtrl); + } + + return TRUE; + } + + /*** LLCP state machine ***/ + + if ((event = lctrRemapPcEvent(pCtx, event)) == LCTR_PC_EVT_INVALID) { return FALSE; } @@ -375,14 +451,14 @@ bool_t lctrLlcpExecutePclSm(lctrConnCtx_t *pCtx, uint8_t event) switch (event) { - case LCTR_PROC_CMN_EVT_HOST_START: + case LCTR_PC_EVT_HOST_START: pCtx->llcpNotifyMask |= 1 << proc; - lctrExecAction(pCtx, proc, LCTR_PROC_CMN_ACT_API_PARAM); + lctrExecAction(pCtx, proc, LCTR_PC_ACT_API_PARAM); /* Fallthrough */ - case LCTR_PROC_CMN_EVT_INT_START: + case LCTR_PC_EVT_INT_START: if (lctrFeatureAvail(pCtx, proc, event)) { - lctrExecAction(pCtx, proc, LCTR_PROC_CMN_ACT_SEND_REQ); + lctrExecAction(pCtx, proc, LCTR_PC_ACT_SEND_REQ); lctrStartLlcpTimer(pCtx); pCtx->llcpActiveProc = proc; pCtx->cmnState = LCTR_CMN_STATE_BUSY; @@ -394,20 +470,20 @@ bool_t lctrLlcpExecutePclSm(lctrConnCtx_t *pCtx, uint8_t event) } break; - case LCTR_PROC_CMN_EVT_INT_INCOMP: - case LCTR_PROC_CMN_EVT_RECV_IND: - case LCTR_PROC_CMN_EVT_RECV_REQ: + case LCTR_PC_EVT_INT_INCOMP: + case LCTR_PC_EVT_RECV_IND: + case LCTR_PC_EVT_RECV_REQ: if (lctrFeatureAvail(pCtx, proc, event)) { - if (event != LCTR_PROC_CMN_EVT_INT_INCOMP) + if (event != LCTR_PC_EVT_INT_INCOMP) { - lctrExecAction(pCtx, proc, LCTR_PROC_CMN_ACT_RECV_REQ); + lctrExecAction(pCtx, proc, LCTR_PC_ACT_RECV_REQ); } - if (lctrPclProcTbl[lctrGetPclProcSmIndex(proc)][LCTR_PROC_CMN_ACT_SEND_RSP]) + if (lctrPclProcTbl[lctrGetPclProcSmIndex(proc)][LCTR_PC_ACT_SEND_RSP]) { /* Procedure completes; no transition to BUSY. */ - lctrPclProcTbl[lctrGetPclProcSmIndex(proc)][LCTR_PROC_CMN_ACT_SEND_RSP](pCtx); + lctrPclProcTbl[lctrGetPclProcSmIndex(proc)][LCTR_PC_ACT_SEND_RSP](pCtx); } else { @@ -424,9 +500,9 @@ bool_t lctrLlcpExecutePclSm(lctrConnCtx_t *pCtx, uint8_t event) } break; - case LCTR_PROC_CMN_EVT_RECV_RSP: - case LCTR_PROC_CMN_EVT_PROC_COMP: - case LCTR_PROC_CMN_EVT_REJECT: + case LCTR_PC_EVT_RECV_RSP: + case LCTR_PC_EVT_PROC_COMP: + case LCTR_PC_EVT_REJECT: default: /* No action required. */ break; @@ -438,11 +514,11 @@ bool_t lctrLlcpExecutePclSm(lctrConnCtx_t *pCtx, uint8_t event) switch (event) { - case LCTR_PROC_CMN_EVT_HOST_START: - case LCTR_PROC_CMN_EVT_INT_START: + case LCTR_PC_EVT_HOST_START: + case LCTR_PC_EVT_INT_START: if (lctrFeatureAvail(pCtx, proc, event)) { - if (event == LCTR_PROC_CMN_EVT_HOST_START) + if (event == LCTR_PC_EVT_HOST_START) { pCtx->llcpNotifyMask |= 1 << proc; } @@ -452,9 +528,9 @@ bool_t lctrLlcpExecutePclSm(lctrConnCtx_t *pCtx, uint8_t event) LL_TRACE_INFO1("Pending procedure in progress: activeProc=%u", pCtx->llcpActiveProc); pCtx->llcpPendMask |= 1 << proc; } - if (event == LCTR_PROC_CMN_EVT_HOST_START) + if (event == LCTR_PC_EVT_HOST_START) { - lctrExecAction(pCtx, proc, LCTR_PROC_CMN_ACT_API_PARAM); + lctrExecAction(pCtx, proc, LCTR_PC_ACT_API_PARAM); } } else @@ -463,23 +539,23 @@ bool_t lctrLlcpExecutePclSm(lctrConnCtx_t *pCtx, uint8_t event) } break; - case LCTR_PROC_CMN_EVT_RECV_IND: /* Completion from message */ + case LCTR_PC_EVT_RECV_IND: /* Completion from message */ if (proc != pCtx->llcpActiveProc) { if (lctrFeatureAvail(pCtx, proc, event)) { LL_TRACE_WARN1("Procedure collision; pending incomplete request, activeProc=%u", pCtx->llcpActiveProc); - lctrExecAction(pCtx, proc, LCTR_PROC_CMN_ACT_RECV_REQ); + lctrExecAction(pCtx, proc, LCTR_PC_ACT_RECV_REQ); pCtx->llcpIncompMask |= 1 << proc; } break; } /* Fallthrough */ - case LCTR_PROC_CMN_EVT_RECV_RSP: + case LCTR_PC_EVT_RECV_RSP: if (proc == pCtx->llcpActiveProc) { /* Incoming procedure matches the active one. */ - lctrExecAction(pCtx, proc, LCTR_PROC_CMN_ACT_RECV_RSP); + lctrExecAction(pCtx, proc, LCTR_PC_ACT_RECV_RSP); } else if (pCtx->llcpPendMask & (1 << proc)) { @@ -489,7 +565,7 @@ bool_t lctrLlcpExecutePclSm(lctrConnCtx_t *pCtx, uint8_t event) { pCtx->llcpIsOverridden = FALSE; } - lctrExecAction(pCtx, proc, LCTR_PROC_CMN_ACT_RECV_RSP); + lctrExecAction(pCtx, proc, LCTR_PC_ACT_RECV_RSP); lctrNotifyHostSuccess(pCtx, proc); break; } @@ -499,9 +575,9 @@ bool_t lctrLlcpExecutePclSm(lctrConnCtx_t *pCtx, uint8_t event) break; } /* Fallthrough */ - case LCTR_PROC_CMN_EVT_PROC_COMP: /* Completion from CE */ - case LCTR_PROC_CMN_EVT_REJECT: /* Failed completion */ - if (event == LCTR_PROC_CMN_EVT_REJECT) + case LCTR_PC_EVT_PROC_COMP: /* Completion from CE */ + case LCTR_PC_EVT_REJECT: /* Failed completion */ + if (event == LCTR_PC_EVT_REJECT) { lctrNotifyHostReject(pCtx, proc); } @@ -519,12 +595,12 @@ bool_t lctrLlcpExecutePclSm(lctrConnCtx_t *pCtx, uint8_t event) lctrStartPendingLlcp(pCtx); break; - case LCTR_PROC_CMN_EVT_RECV_REQ: + case LCTR_PC_EVT_RECV_REQ: LL_TRACE_WARN1("Procedure collision; pending incomplete request, activeProc=%u", pCtx->llcpActiveProc); - lctrExecAction(pCtx, proc, LCTR_PROC_CMN_ACT_RECV_REQ); + lctrExecAction(pCtx, proc, LCTR_PC_ACT_RECV_REQ); if (lctrFeatureAvail(pCtx, proc, event)) { - lctrPclProcTbl[lctrGetPclProcSmIndex(proc)][LCTR_PROC_CMN_ACT_SEND_RSP](pCtx); + lctrPclProcTbl[lctrGetPclProcSmIndex(proc)][LCTR_PC_ACT_SEND_RSP](pCtx); } else { diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_slave_phy.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_slave_phy.c index a4fc42e106..ef2a96dc40 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_slave_phy.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_slave_phy.c @@ -6,7 +6,7 @@ * * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -96,10 +96,8 @@ static void lctrUpdateDataTime(lctrConnCtx_t *pCtx) switch (pCtx->bleData.chan.txPhy) { case BB_PHY_BLE_1M: - maxTxTime = WSF_MIN(LL_DATA_LEN_TO_TIME_1M(pCtx->effDataPdu.maxTxLen, TRUE), pCtx->effDataPdu.maxTxTime); - break; case BB_PHY_BLE_2M: - maxTxTime = WSF_MIN(LL_DATA_LEN_TO_TIME_2M(pCtx->effDataPdu.maxTxLen, TRUE), pCtx->effDataPdu.maxTxTime); + maxTxTime = WSF_MIN(LL_DATA_LEN_TO_TIME_1M(pCtx->effDataPdu.maxTxLen, TRUE), pCtx->effDataPdu.maxTxTime); break; case BB_PHY_BLE_CODED: maxTxTime = WSF_MIN(LL_DATA_LEN_TO_TIME_CODED_S8(pCtx->effDataPdu.maxTxLen, TRUE), pCtx->effDataPdu.maxTxTime); @@ -109,10 +107,8 @@ static void lctrUpdateDataTime(lctrConnCtx_t *pCtx) switch (pCtx->bleData.chan.rxPhy) { case BB_PHY_BLE_1M: - maxRxTime = WSF_MIN(LL_DATA_LEN_TO_TIME_1M(pCtx->effDataPdu.maxRxLen, TRUE), pCtx->effDataPdu.maxRxTime); - break; case BB_PHY_BLE_2M: - maxRxTime = WSF_MIN(LL_DATA_LEN_TO_TIME_2M(pCtx->effDataPdu.maxRxLen, TRUE), pCtx->effDataPdu.maxRxTime); + maxRxTime = WSF_MIN(LL_DATA_LEN_TO_TIME_1M(pCtx->effDataPdu.maxRxLen, TRUE), pCtx->effDataPdu.maxRxTime); break; case BB_PHY_BLE_CODED: maxRxTime = WSF_MIN(LL_DATA_LEN_TO_TIME_CODED_S8(pCtx->effDataPdu.maxRxLen, TRUE), pCtx->effDataPdu.maxRxTime); @@ -521,7 +517,7 @@ static const lctrActFn_t lctrSlvPhyUpdateActionTbl[LCTR_PU_STATE_TOTAL][LCTR_PU_ lctrActPeerPhyReqWithCollision, /* LCTR_PU_EVENT_PEER_PHY_REQ */ NULL, /* LCTR_PU_EVENT_PEER_REJECT */ /* should never occur; ignore */ NULL, /* LCTR_PU_EVENT_INT_PROC_COMP */ /* should never occur */ - NULL, /* LCTR_PU_EVENT_INT_START_PHY_UPD */ /* should never occur */ + lctrActFlushArq, /* LCTR_PU_EVENT_INT_START_PHY_UPD */ /* occurs on override by other ll procedure */ lctrActStartPhyUpdate /* LCTR_PU_EVENT_ARQ_FLUSHED */ }, { /* LCTR_PU_STATE_HOST_PHY_UPDATE_REQ */ @@ -530,7 +526,7 @@ static const lctrActFn_t lctrSlvPhyUpdateActionTbl[LCTR_PU_STATE_TOTAL][LCTR_PU_ lctrActPeerPhyReqWithCollision, /* LCTR_PU_EVENT_PEER_PHY_REQ */ lctrActPeerRejectPhyReq, /* LCTR_PU_EVENT_PEER_REJECT */ lctrActNotifyHostPhyUpdateNoChange, /* LCTR_PU_EVENT_INT_PROC_COMP */ /* if no change */ - NULL, /* LCTR_PU_EVENT_INT_START_PHY_UPD */ /* should never occur */ + lctrActFlushArq, /* LCTR_PU_EVENT_INT_START_PHY_UPD */ /* occurs on override by other ll procedure */ NULL /* LCTR_PU_EVENT_ARQ_FLUSHED */ /* should never occur (not for this SM) */ }, { /* LCTR_PU_STATE_FLUSH_BEFORE_PHY_RSP */ @@ -577,10 +573,10 @@ static const uint8_t lctrSlvPhyUpdateNextStateTbl[LCTR_PU_STATE_TOTAL][LCTR_PU_E { /* LCTR_PU_STATE_FLUSH_BEFORE_PHY_REQ */ LCTR_PU_STATE_FLUSH_BEFORE_PHY_REQ, /* LCTR_PU_EVENT_HOST_PHY_UPD */ LCTR_PU_STATE_FLUSH_BEFORE_PHY_REQ, /* LCTR_PU_EVENT_PEER_PHY_UPDATE_IND */ /* out of sequence; ignore */ - LCTR_PU_STATE_FLUSH_BEFORE_PHY_RSP, /* LCTR_PU_EVENT_PEER_PHY_REQ */ + LCTR_PU_STATE_FLUSH_BEFORE_PHY_RSP, /* LCTR_PU_EVENT_PEER_PHY_REQ */ LCTR_PU_STATE_FLUSH_BEFORE_PHY_REQ, /* LCTR_PU_EVENT_PEER_REJECT */ /* should never occur; ignore */ LCTR_PU_STATE_FLUSH_BEFORE_PHY_REQ, /* LCTR_PU_EVENT_INT_PROC_COMP */ /* should never occur */ - LCTR_PU_STATE_FLUSH_BEFORE_PHY_REQ, /* LCTR_PU_EVENT_INT_START_PHY_UPD */ /* should never occur */ + LCTR_PU_STATE_FLUSH_BEFORE_PHY_REQ, /* LCTR_PU_EVENT_INT_START_PHY_UPD */ /* occurs on override by other ll procedure */ LCTR_PU_STATE_HOST_PHY_UPDATE_REQ /* LCTR_PU_EVENT_ARQ_FLUSHED */ }, { /* LCTR_PU_STATE_HOST_PHY_UPDATE_REQ */ @@ -589,7 +585,7 @@ static const uint8_t lctrSlvPhyUpdateNextStateTbl[LCTR_PU_STATE_TOTAL][LCTR_PU_E LCTR_PU_STATE_FLUSH_BEFORE_PHY_RSP, /* LCTR_PU_EVENT_PEER_PHY_REQ */ LCTR_PU_STATE_IDLE, /* LCTR_PU_EVENT_PEER_REJECT */ LCTR_PU_STATE_IDLE, /* LCTR_PU_EVENT_INT_PROC_COMP */ /* if no change */ - LCTR_PU_STATE_HOST_PHY_UPDATE_REQ, /* LCTR_PU_EVENT_INT_START_PHY_UPD */ /* should never occur */ + LCTR_PU_STATE_HOST_PHY_UPDATE_REQ, /* LCTR_PU_EVENT_INT_START_PHY_UPD */ /* occurs on override by other ll procedure */ LCTR_PU_STATE_HOST_PHY_UPDATE_REQ /* LCTR_PU_EVENT_ARQ_FLUSHED */ /* should never occur (not for this SM) */ }, { /* LCTR_PU_STATE_FLUSH_BEFORE_PHY_RSP */ @@ -869,3 +865,25 @@ bool_t lctrSlvLlcpExecutePhyUpdateSm(lctrConnCtx_t *pCtx, uint8_t event) return TRUE; } + +/*************************************************************************************************/ +/*! + * \brief Check if encryption can override phy update procedure. + * + * \param pCtx Connection context. + * + * \return TRUE if override possible, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lctrSlvCheckEncOverridePhyUpdate(lctrConnCtx_t *pCtx) +{ + if (pCtx->llcpActiveProc == LCTR_PROC_PHY_UPD) + { + if ((pCtx->phyUpdState == LCTR_PU_STATE_FLUSH_BEFORE_PHY_REQ) || + (pCtx->phyUpdState == LCTR_PU_STATE_HOST_PHY_UPDATE_REQ)) + { + return TRUE; + } + } + return FALSE; +} diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd.c index 0f20089845..8b8ab0d485 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd.c @@ -203,6 +203,7 @@ static void lhciCommonSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t case HCI_OPCODE_NOP: case HCI_OPCODE_LE_MODIFY_SLEEP_CLK_ACC: case HCI_OPCODE_LE_SET_HOST_FEATURE: + case HCI_OPCODE_WRITE_AFH_CHAN_ASSESSMENT_MODE: lhciPackCmdCompleteEvtStatus(pBuf, status); break; @@ -261,6 +262,12 @@ static void lhciCommonSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t UINT16_TO_BSTREAM(pBuf, rxPathComp); break; } + case HCI_OPCODE_READ_AFH_CHAN_ASSESMENT_MODE: + { + pBuf += lhciPackCmdCompleteEvtStatus(pBuf, status); + UINT8_TO_BSTREAM(pBuf, lhciCb.chanAssesmentMode); + break; + } /* --- test --- */ @@ -413,6 +420,17 @@ bool_t lhciCommonDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) case HCI_OPCODE_NOP: paramLen = 1; break; + case HCI_OPCODE_READ_AFH_CHAN_ASSESMENT_MODE: + { + paramLen = LHCI_LEN_READ_AFH_CHAN_ASSESMENT_MODE; + break; + } + case HCI_OPCODE_WRITE_AFH_CHAN_ASSESSMENT_MODE: + { + BSTREAM_TO_UINT8(lhciCb.chanAssesmentMode, pBuf); + paramLen = LHCI_LEN_WRITE_AFH_CHAN_ASSESMENT_MODE; + break; + } /* --- test --- */ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_cis_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_cis_master.c index 8126506cc0..b1a91922f6 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_cis_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_cis_master.c @@ -26,9 +26,9 @@ #include "hci_defs.h" #include "ll_api.h" #include "ll_defs.h" +#include "lmgr_api.h" #include "wsf_msg.h" #include "wsf_math.h" -#include "wsf_trace.h" #include "util/bstream.h" #include @@ -37,7 +37,7 @@ **************************************************************************************************/ uint8_t numCis; /*!< Number of CIS. */ -uint8_t cigID; /*!< Number of CIS. */ +uint8_t cigID; /*!< CIG ID. */ uint16_t cisHandles[LL_MAX_CIS] = {0}; /*!< CIS Handle list. */ /************************************************************************************************** @@ -83,6 +83,7 @@ static uint8_t lhciPackRemoveCigEvt(uint8_t *pBuf, uint8_t status) const uint8_t len = LHCI_LEN_LE_REMOVE_CIG; UINT8_TO_BSTREAM (pBuf, status); + UINT8_TO_BSTREAM (pBuf, cigID); return len; } @@ -155,7 +156,6 @@ bool_t lhciMstCisDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) { case HCI_OPCODE_LE_SET_CIG_PARAMS: { - uint8_t cigId; uint32_t sduIntervalMToS = 0; uint32_t sduIntervalSToM = 0; uint8_t sca; @@ -164,7 +164,7 @@ bool_t lhciMstCisDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) uint16_t transLatMToS; uint16_t transLatSToM; - BSTREAM_TO_UINT8(cigId, pBuf); + BSTREAM_TO_UINT8(cigID, pBuf); BSTREAM_TO_UINT24(sduIntervalMToS, pBuf); BSTREAM_TO_UINT24(sduIntervalSToM, pBuf); BSTREAM_TO_UINT8(sca, pBuf); @@ -189,7 +189,7 @@ bool_t lhciMstCisDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) BSTREAM_TO_UINT8(cisParam[i].rteSToM, pBuf); } - cigParam.cigId = cigId; + cigParam.cigId = cigID; cigParam.sduIntervalMToS = sduIntervalMToS; cigParam.sduIntervalSToM = sduIntervalSToM; cigParam.sca = sca; @@ -206,7 +206,6 @@ bool_t lhciMstCisDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) } case HCI_OPCODE_LE_SET_CIG_PARAMS_TEST: { - uint8_t cigId; uint32_t sduIntervalMToS = 0; uint32_t sduIntervalSToM = 0; uint8_t ftMToS; @@ -216,7 +215,7 @@ bool_t lhciMstCisDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) uint8_t packing; uint8_t framing; - BSTREAM_TO_UINT8(cigId, pBuf); + BSTREAM_TO_UINT8(cigID, pBuf); BSTREAM_TO_UINT24(sduIntervalMToS, pBuf); BSTREAM_TO_UINT24(sduIntervalSToM, pBuf); BSTREAM_TO_UINT8(ftMToS, pBuf); @@ -245,7 +244,7 @@ bool_t lhciMstCisDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) BSTREAM_TO_UINT8(cisParam[i].bnSToM, pBuf); } - cigParam.cigId = cigId; + cigParam.cigId = cigID; cigParam.sduIntervalMToS = sduIntervalMToS; cigParam.sduIntervalSToM = sduIntervalSToM; cigParam.ftMToS = ftMToS; @@ -281,10 +280,8 @@ bool_t lhciMstCisDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) } case HCI_OPCODE_LE_REMOVE_CIG: { - uint8_t cigId; - - BSTREAM_TO_UINT8(cigId, pBuf); - status = LlRemoveCig(cigId); + BSTREAM_TO_UINT8(cigID, pBuf); + status = LlRemoveCig(cigID); paramLen = LHCI_LEN_LE_REMOVE_CIG; diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_iso.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_iso.c index 0073a37187..17b2a2b830 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_iso.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_iso.c @@ -51,6 +51,12 @@ typedef union uint32_t minDly; /*!< Minimum controller delay. */ uint32_t maxDly; /*!< Maximum controller delay. */ } ctrDly; /*!< Read local supported controller delay return parameters. */ + struct + { + uint8_t numCap; /*!< Number of codec capabilities returned. */ + uint8_t capLen; /*!< Capability length. */ + uint8_t cap[32]; /*!< Capability data. */ + } codecCap; /*!< Read local supported controller capabilities return parameters. */ } lhciIsoReturnParam_t; /************************************************************************************************** @@ -224,8 +230,8 @@ static uint8_t lhciPackRemoveDataPathEvt(uint8_t *pBuf, uint8_t status, uint16_t */ /*************************************************************************************************/ static uint8_t lhciPackReadLocalSupportedCodecs(uint8_t *pBuf, uint8_t status, - uint8_t numStd, AudioStdCodecInfo_t stdCodecs[], - uint8_t numVs, AudioVsCodecInfo_t vsCodecs[]) + uint8_t numStd, PalCodecStdInfo_t stdCodecs[], + uint8_t numVs, PalCodecVsInfo_t vsCodecs[]) { uint8_t len = LHCI_LEN_READ_LOCAL_SUP_CODECS; @@ -252,6 +258,276 @@ static uint8_t lhciPackReadLocalSupportedCodecs(uint8_t *pBuf, uint8_t status, return len; } +/*************************************************************************************************/ +/*! + * \brief Read local supported codecs. + * + * \param pNumStd Input is size of \a stdCodecs and output is actual number of standard codecs. + * \param stdCodecs Standard codec info. + * \param pNumVs Input is size of \a vsCodecs and output is actual number of vendor specific codecs. + * \param vsCodecs Vendor specific codec info. + * + * This function is called by HCI when the host invokes HCI_Read_Local_Supported_Codecs. + */ +/*************************************************************************************************/ +static void lhciCodecReadLocalSupportedCodecs(uint8_t *pNumStd, PalCodecStdInfo_t stdCodecs[], + uint8_t *pNumVs, PalCodecVsInfo_t vsCodecs[]) +{ + uint8_t numStd = 0; + uint8_t numVs = 0; + + // FIXME obtain list from pal_codec +#if (CODEC_LC3) + if (*pNumStd > numStd) + { + stdCodecs[numStd].codecId = HCI_ID_LC3; + stdCodecs[numStd].supTrans = (1 << HCI_CODEC_TRANSPORT_CIS) | (1 << HCI_CODEC_TRANSPORT_BIS); + numStd++; + } +#endif + *pNumStd = numStd; + +#if (CODEC_BLUEDROID) + if (*pNumVs > numVs) + { + vsCodecs[numVs].compId = HCI_ID_PACKETCRAFT; + vsCodecs[numVs].codecId = 1; + stdCodecs[numStd].supTrans = (1 << HCI_CODEC_TRANSPORT_CIS) | (1 << HCI_CODEC_TRANSPORT_BIS); + numVs++; + } +#endif +#if (CODEC_OPUS) + if (*pNumVs > numVs) + { + vsCodecs[numVs].compId = HCI_ID_PACKETCRAFT; + vsCodecs[numVs].codecId = 2; + stdCodecs[numStd].supTrans = (1 << HCI_CODEC_TRANSPORT_CIS) | (1 << HCI_CODEC_TRANSPORT_BIS); + numVs++; + } +#endif +#if (CODEC_BV32) + if (*pNumVs > numVs) + { + vsCodecs[numVs].compId = HCI_ID_PACKETCRAFT; + vsCodecs[numVs].codecId = 3; + vsCodecs[numVs].supTrans = (1 << HCI_CODEC_TRANSPORT_CIS) | (1 << HCI_CODEC_TRANSPORT_BIS); + numVs++; + } +#endif + *pNumVs = numVs; +} + +/*************************************************************************************************/ +/*! + * \brief Read local supported codec capabilities. + * + * \param codingFmt Coding format. + * \param compId Company ID. + * \param vsCodecId Vendor specific codec ID. + * \param dir Direction. + * \param transType Transport type. + * \param pCapLen Input is size of \a pCap and output is actual size copied into \a pCap. + * \param pCap Capability buffer return parameter. + * + * \return TRUE if valid, FALSE otherwise. + * + * This function is called by HCI when the host invokes HCI_Read_Local_Supported_Codec_Capabilities. + */ +/*************************************************************************************************/ +static bool_t lhciCodecReadLocalSupportedCodecCapabilities(uint8_t codingFmt, uint16_t compId, uint16_t vsCodecId, PalCodecDir_t dir, uint8_t transType, + uint8_t *pCapLen, uint8_t *pCap) +{ + bool_t valid = FALSE; + const char *pRetCap = NULL; + + /* TODO check if enabled in LL. */ + if ((transType & ((1 << HCI_CODEC_TRANSPORT_CIS) | (1 << HCI_CODEC_TRANSPORT_BIS))) == 0) + { + /* Invalid transport. */ + return FALSE; + } + + // FIXME obtain list from pal_codec + switch (codingFmt) + { + case HCI_ID_LC3: + (void)compId; /* ignored */ + (void)vsCodecId; /* ignored */ + (void)dir; /* either direction is valid */ +#if (CODEC_LC3) + { + static const char cap[] = "LC3:L+R,16kHz"; + pRetCap = cap; + valid = TRUE; + } +#endif + break; + case HCI_ID_VS: + (void)dir; /* either direction is valid */ + if (compId == HCI_ID_PACKETCRAFT) + { +#if (CODEC_BLUEDROID) + if (vsCodecId == 1) + { + static const char cap[] = "SBC:L+R,16kHz"; + pRetCap = cap; + valid = TRUE; + } +#endif +#if (CODEC_OPUS) + if (vsCodecId == 2) + { + static const char cap[] = "Opus:L+R,16kHz"; + pRetCap = cap; + valid = TRUE; + } +#endif +#if (CODEC_BV32) + if (vsCodecId == 3) + { + static const char cap[] = "BV32:mono,16kHz"; + pRetCap = cap; + valid = TRUE; + } +#endif + } + break; + + default: + break; + } + + if (pRetCap && (*pCapLen >= strlen(pRetCap))) + { + strncpy((char *)pCap, pRetCap, *pCapLen); + *pCapLen = sizeof(strlen(pRetCap)); + } + + return valid; +} + +/*************************************************************************************************/ +/*! + * \brief Read local supported codecs. + * + * \param codingFmt Coding format. + * \param compId Company ID. + * \param vsCodecId Vendor specific codec ID. + * \param dir Direction. + * \param transType Transport type. + * \param pMinDly Min_Controller_Delay return value. + * \param pMaxDly Max_Controller_Delay return value. + * + * \return TRUE if valid, FALSE otherwise. + * + * This function is called by HCI when the host invokes HCI_Read_Local_Supported_Controller_Delay. + */ +/*************************************************************************************************/ +static bool_t lhciCodecReadLocalSupportedControllerDelay(uint8_t codingFmt, uint16_t compId, uint16_t vsCodecId, PalCodecDir_t dir, uint8_t transType, + uint32_t *pMinDly, uint32_t *pMaxDly) +{ + bool_t valid = FALSE; + + if ((transType & ((1 << HCI_CODEC_TRANSPORT_CIS) | (1 << HCI_CODEC_TRANSPORT_BIS))) == 0) + { + /* Invalid transport. */ + return FALSE; + } + + switch (codingFmt) + { + case HCI_ID_LC3: +#if (CODEC_LC3) + (void)compId; /* ignored */ + (void)vsCodecId; /* ignored */ + + switch (dir) + { + case PAL_CODEC_DIR_INPUT: + *pMinDly = 5000; /* TODO */ + *pMaxDly = 5000; /* TODO */ + valid = TRUE; + break; + case PAL_CODEC_DIR_OUTPUT: + *pMinDly = 2500; /* TODO */ + *pMaxDly = 2500; /* TODO */ + valid = TRUE; + break; + default: + break; + } +#endif + break; + + case HCI_ID_VS: +#if (CODEC_BLUEDROID) + if (vsCodecId == 1) + { + switch (dir) + { + case PAL_CODEC_DIR_INPUT: + *pMinDly = 1300; + *pMaxDly = 1300; + valid = TRUE; + break; + case PAL_CODEC_DIR_OUTPUT: + *pMinDly = 1140; + *pMaxDly = 1140; + valid = TRUE; + break; + default: + break; + } + } +#endif +#if (CODEC_OPUS) + if (vsCodecId == 2) + { + switch (dir) + { + case PAL_CODEC_DIR_INPUT: + *pMinDly = 5000; /* TODO */ + *pMaxDly = 5000; /* TODO */ + valid = TRUE; + break; + case PAL_CODEC_DIR_OUTPUT: + *pMinDly = 2500; /* TODO */ + *pMaxDly = 2500; /* TODO */ + valid = TRUE; + break; + default: + break; + } + } +#endif +#if (CODEC_BV32) + if (vsCodecId == 3) + { + switch (dir) + { + case PAL_CODEC_DIR_INPUT: + *pMinDly = 5690; + *pMaxDly = 5690; + valid = TRUE; + break; + case PAL_CODEC_DIR_OUTPUT: + *pMinDly = 950; + *pMaxDly = 950; + valid = TRUE; + break; + default: + break; + } + } +#endif + break; + default: + break; + } + + return valid; +} + /*************************************************************************************************/ /*! * \brief Build and send a command complete event packet. @@ -335,11 +611,19 @@ static void lhciIsoSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t pa case HCI_OPCODE_READ_LOCAL_SUP_CODECS: { uint8_t numStdCodecs = LHCI_MAX_CODEC; - AudioStdCodecInfo_t stdCodecs[LHCI_MAX_CODEC]; + PalCodecStdInfo_t stdCodecs[LHCI_MAX_CODEC]; uint8_t numVsCodecs = LHCI_MAX_CODEC; - AudioVsCodecInfo_t vsCodecs[LHCI_MAX_CODEC]; + PalCodecVsInfo_t vsCodecs[LHCI_MAX_CODEC]; - PalCodecReadLocalSupportedCodecs(&numStdCodecs, stdCodecs, + + + + + + + + + lhciCodecReadLocalSupportedCodecs(&numStdCodecs, stdCodecs, &numVsCodecs, vsCodecs); paramLen = lhciPackReadLocalSupportedCodecs(pBuf, status, @@ -353,7 +637,9 @@ static void lhciIsoSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t pa case HCI_OPCODE_READ_LOCAL_SUP_CODEC_CAP: { UINT8_TO_BSTREAM(pBuf, status); - UINT8_TO_BSTREAM(pBuf, 0); /* Num_Codec_Capabilities */ + UINT8_TO_BSTREAM(pBuf, 1); /* Num_Codec_Capabilities always 1 */ + UINT8_TO_BSTREAM(pBuf, pRet->codecCap.capLen); /* Codec_Capability_Length[0] */ + memcpy(pBuf, pRet->codecCap.cap, pRet->codecCap.capLen); /* Codec_Capability[0] */ break; } case HCI_OPCODE_READ_LOCAL_SUP_CONTROLLER_DLY: @@ -499,14 +785,13 @@ bool_t lhciIsoDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) } case HCI_OPCODE_CONFIG_DATA_PATH: { - uint8_t dir; - uint8_t dataPathId; - BSTREAM_TO_UINT8 (dir, pBuf); - BSTREAM_TO_UINT8 (dataPathId, pBuf); - if (!PalCodecConfigureDataPath(dir, dataPathId)) - { - status = HCI_ERR_INVALID_PARAM; - } + LlIsoConfigDataPath_t param; + + BSTREAM_TO_UINT8 (param.dpDir, pBuf); + BSTREAM_TO_UINT8 (param.dpId, pBuf); + BSTREAM_TO_UINT8 (param.vsCfgLen, pBuf); + param.pVsCfg = pBuf; + status = LlConfigureDataPath(¶m); paramLen = LHCI_LEN_CONFIG_DATA_PATH; break; } @@ -530,20 +815,19 @@ bool_t lhciIsoDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) BSTREAM_TO_UINT16(vsCodecId, pBuf); BSTREAM_TO_UINT8 (transType, pBuf); BSTREAM_TO_UINT8 (dir, pBuf); - - if (PalCodecReadLocalSupportedCodecCapabilities(codingFmt, compId, vsCodecId, dir)) + ret.codecCap.capLen = sizeof(ret.codecCap.cap); + if (lhciCodecReadLocalSupportedCodecCapabilities(codingFmt, compId, vsCodecId, dir, transType, + &ret.codecCap.capLen, ret.codecCap.cap)) { - if ((transType & (LL_CODEC_TRANS_CIS_BIT | LL_CODEC_TRANS_BIS_BIT)) == 0) - { - status = HCI_ERR_INVALID_PARAM; - } + ret.codecCap.numCap = 1; } else { + ret.codecCap.numCap = 0; + ret.codecCap.capLen = 0; status = HCI_ERR_INVALID_PARAM; } - - paramLen = LHCI_LEN_READ_LOCAL_SUP_CODEC_CAP; + paramLen = LHCI_LEN_READ_LOCAL_SUP_CODEC_CAP + ret.codecCap.numCap + ret.codecCap.capLen; break; } case HCI_OPCODE_READ_LOCAL_SUP_CONTROLLER_DLY: @@ -559,15 +843,8 @@ bool_t lhciIsoDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) BSTREAM_TO_UINT8 (transType, pBuf); BSTREAM_TO_UINT8 (dir, pBuf); ret.ctrDly.minDly = ret.ctrDly.maxDly = 0; - if (PalCodecReadLocalSupportedControllerDelay(codingFmt, compId, vsCodecId, dir, + if (lhciCodecReadLocalSupportedControllerDelay(codingFmt, compId, vsCodecId, dir, transType, &ret.ctrDly.minDly, &ret.ctrDly.maxDly)) - { - if ((transType & (LL_CODEC_TRANS_CIS_BIT | LL_CODEC_TRANS_BIS_BIT)) == 0) - { - status = HCI_ERR_INVALID_PARAM; - } - } - else { status = HCI_ERR_INVALID_PARAM; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs.c index b63fc09961..9a7e6c2547 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,13 +50,20 @@ #define LHCI_LEN_GET_POOL_STATS_EVT(n) (3 + (sizeof(WsfBufPoolStat_t) * (n))) /*! \brief Get System Statistics command complete event length. */ -/* stackWatermark(uint16_t) + palSysAssertCount(uint16_t) + - * freeMem (uint32_t) + usedMem(uint32_t) + schDelayLoadTotalCount(uint32_t) + - * connMax(uint16_t) + connCtxSize(uint16_t) + csWatermarkUsec(uint16_t) + llHandlerWatermarkUsec(uint16_t) + schHandlerWatermarkUsec(uint16_t) + lhciHandlerWatermarkUsec(uint16_t) + schDelayLoadWatermarkCount(uint16_t) + - * advSetMax(uint16_t) + advSetCtxSize(uint16_t) + - * extScanMax(uint16_t) + extScanCtxSize(uint16_t) + extInitMax(uint16_t) + extInitCtxSize(uint16_t) + perScanMax(uint16_t) + perScanCtxSize(uint16_t) + cigMax(uint16_t) + cigCtxSize(uint16_t) + cisMax(uint16_t) + cisCtxSize(uint16_t) */ +#define LHCI_LEN_GET_SYS_STATS_EVT (2 * sizeof(uint16_t) + 3 * sizeof(uint32_t) + 7 * sizeof(uint16_t) + 2 * sizeof(uint16_t)) -#define LHCI_LEN_GET_SYS_STATS_EVT (2 * sizeof(uint16_t) + 3 * sizeof(uint32_t) + 7 * sizeof(uint16_t) + 2 * sizeof(uint16_t) + 10 * sizeof(uint16_t)) +/*! \brief Get context size command complete event length. */ +#define LHCI_LEN_GET_CONTEXT_SIZES_EVT (2 * 14 * sizeof(uint16_t)) + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/* Reset flag. */ +bool_t lhciResetPending = FALSE; + +/* Bootloader flag. */ +bool_t lhciEnterBootloaderPending = FALSE; /************************************************************************************************** Functions @@ -153,6 +160,9 @@ bool_t lhciCommonVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) case LHCI_OPCODE_VS_GET_SYS_STATS: evtParamLen += LHCI_LEN_GET_SYS_STATS_EVT; break; + case LHCI_OPCODE_VS_GET_CONTEXT_SIZES: + evtParamLen += LHCI_LEN_GET_CONTEXT_SIZES_EVT; + break; case LHCI_OPCODE_VS_GET_TEST_STATS: evtParamLen += sizeof(BbBleDataPktStats_t); break; @@ -167,7 +177,18 @@ bool_t lhciCommonVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) evtParamLen += sizeof(BbBlePduFiltStats_t); break; + /* --- reset --- */ + + case LHCI_OPCODE_VS_SYSTEM_RESET: + lhciResetPending = TRUE; + break; + + case LHCI_OPCODE_VS_ENTER_BOOTLOADER: + lhciEnterBootloaderPending = TRUE; + break; + /* --- default --- */ + default: return FALSE; /* exit dispatcher routine */ } @@ -228,6 +249,10 @@ bool_t lhciCommonVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) UINT16_TO_BSTREAM(pBuf, schHandlerWatermarkUsec); UINT16_TO_BSTREAM(pBuf, lhciHandlerWatermarkUsec); + break; + } + case LHCI_OPCODE_VS_GET_CONTEXT_SIZES: + { uint16_t advSetMax = 0; uint16_t advSetCtxSize; LlGetAdvSetContextSize((uint8_t *)&advSetMax, &advSetCtxSize); @@ -252,18 +277,26 @@ bool_t lhciCommonVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) UINT16_TO_BSTREAM(pBuf, perScanMax); UINT16_TO_BSTREAM(pBuf, perScanCtxSize); - uint16_t cigMax = 0; + uint8_t cigMax = 0; uint16_t cigCtxSize; - LlGetCigContextSize((uint8_t *)&cigMax, &cigCtxSize); + uint8_t cisMax = 0; + uint16_t cisCtxSize; + LlGetCisContextSize(&cigMax, &cigCtxSize, &cisMax, &cisCtxSize); UINT16_TO_BSTREAM(pBuf, cigMax); UINT16_TO_BSTREAM(pBuf, cigCtxSize); - - uint16_t cisMax = 0; - uint16_t cisCtxSize; - LlGetCisContextSize((uint8_t *)&cisMax, &cisCtxSize); UINT16_TO_BSTREAM(pBuf, cisMax); UINT16_TO_BSTREAM(pBuf, cisCtxSize); + uint8_t bigMax = 0; + uint16_t bigCtxSize; + uint8_t bisMax = 0; + uint16_t bisCtxSize; + LlGetBisContextSize(&bigMax, &bigCtxSize, &bisMax, &bisCtxSize); + UINT16_TO_BSTREAM(pBuf, bigMax); + UINT16_TO_BSTREAM(pBuf, bigCtxSize); + UINT16_TO_BSTREAM(pBuf, bisMax); + UINT16_TO_BSTREAM(pBuf, bisCtxSize); + break; } case LHCI_OPCODE_VS_GET_TEST_STATS: diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_iso.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_iso.c index 90731fb38c..3741a9c477 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_iso.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_iso.c @@ -79,6 +79,7 @@ bool_t lhciIsoVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) break; } case LHCI_OPCODE_VS_GET_CIS_STATS: + case LHCI_OPCODE_VS_GET_BIS_STATS: evtParamLen += sizeof(BbBleDataPktStats_t); break; @@ -104,7 +105,6 @@ bool_t lhciIsoVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) UINT32_TO_BSTREAM(pBuf, lhciIsoCb.genPktCnt); UINT32_TO_BSTREAM(pBuf, lhciIsoCb.genOctetCnt); break; - case LHCI_OPCODE_VS_GET_CIS_STATS: { BbBleDataPktStats_t stats; @@ -112,6 +112,13 @@ bool_t lhciIsoVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) memcpy(pBuf, (uint8_t *)&stats, sizeof(stats)); break; } + case LHCI_OPCODE_VS_GET_BIS_STATS: + { + BbBleDataPktStats_t stats; + BbBleGetBisStats(&stats); + memcpy(pBuf, (uint8_t *)&stats, sizeof(stats)); + break; + } /* --- default --- */ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_bis_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_bis_master.c index f5e41fed74..0f924d4fc3 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_bis_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_bis_master.c @@ -23,6 +23,7 @@ /*************************************************************************************************/ #include "lhci_int.h" +#include "lctr_api.h" #include "ll_api.h" #include "util/bstream.h" @@ -159,16 +160,27 @@ bool_t lhciMstBisEncodeEvtPkt(LlEvt_t *pEvt) break; case LL_BIG_INFO_ADV_REPORT_IND: + { + bool_t evtSent = FALSE; + if ((lhciCb.leEvtMsk & ((uint64_t)(HCI_EVT_MASK_LE_BIG_INFO_ADV_RPT_EVT) << LHCI_BYTE_TO_BITS(4))) && (lhciCb.evtMsk & ((uint64_t)(HCI_EVT_MASK_LE_META) << LHCI_BYTE_TO_BITS(7)))) { - if ((pEvtBuf = lhciAllocEvt(HCI_LE_META_EVT, HCI_LEN_LE_BIG_INFO_ADV_REPORT)) != NULL) + if ((lhciCb.numAdvReport < pLctrRtCfg->maxAdvReports) && + ((pEvtBuf = lhciAllocEvt(HCI_LE_META_EVT, HCI_LEN_LE_BIG_INFO_ADV_REPORT)) != NULL)) { lhciPackBigBigInfoAdvReportEvt(pEvtBuf, &pEvt->bigInfoInd); + lhciCb.numAdvReport++; + evtSent = TRUE; } } + if (!evtSent) + { + /* Handle event here even if event cannot be sent. */ + return TRUE; + } break; - + } default: break; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_cis_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_cis_master.c index 953d007225..d96a5798ac 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_cis_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_cis_master.c @@ -6,7 +6,7 @@ * * Copyright (c) 2016-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,41 +33,6 @@ Local Functions **************************************************************************************************/ -/*************************************************************************************************/ -/*! - * \brief Pack a CIS established event packet. - * - * \param pBuf Packed packet buffer. - * \param pEvt CIS established event data. - * - * \return Packet length. - */ -/*************************************************************************************************/ -static uint8_t lhciPackCisEstEvt(uint8_t *pBuf, const LlCisEstInd_t *pEvt) -{ - const uint8_t len = HCI_LEN_LE_CIS_EST; - - UINT8_TO_BSTREAM (pBuf, HCI_LE_CIS_EST_EVT); - UINT8_TO_BSTREAM (pBuf, pEvt->status); - UINT16_TO_BSTREAM (pBuf, pEvt->cisHandle); - UINT24_TO_BSTREAM (pBuf, pEvt->cigSyncDelayUsec); - UINT24_TO_BSTREAM (pBuf, pEvt->cisSyncDelayUsec); - UINT24_TO_BSTREAM (pBuf, pEvt->transLatUsecMToS); - UINT24_TO_BSTREAM (pBuf, pEvt->transLatUsecSToM); - UINT8_TO_BSTREAM (pBuf, pEvt->phyMToS); - UINT8_TO_BSTREAM (pBuf, pEvt->phySToM); - UINT8_TO_BSTREAM (pBuf, pEvt->nse); - UINT8_TO_BSTREAM (pBuf, pEvt->bnMToS); - UINT8_TO_BSTREAM (pBuf, pEvt->bnSToM); - UINT8_TO_BSTREAM (pBuf, pEvt->ftMToS); - UINT8_TO_BSTREAM (pBuf, pEvt->ftSToM); - UINT16_TO_BSTREAM (pBuf, pEvt->maxPduMToS); - UINT16_TO_BSTREAM (pBuf, pEvt->maxPduSToM); - UINT16_TO_BSTREAM (pBuf, pEvt->isoInterval); - - return len; -} - /************************************************************************************************** External Functions **************************************************************************************************/ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_cis_slave.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_cis_slave.c index 45cb477000..63c2dc7cb3 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_cis_slave.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_cis_slave.c @@ -6,7 +6,7 @@ * * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -61,6 +61,41 @@ static uint8_t lhciPackCisReqEvt(uint8_t *pBuf, const LlCisReqInd_t *pEvt) External Functions **************************************************************************************************/ +/*************************************************************************************************/ +/*! + * \brief Pack a CIS established event packet. + * + * \param pBuf Packed packet buffer. + * \param pEvt CIS established event data. + * + * \return Packet length. + */ +/*************************************************************************************************/ +uint8_t lhciPackCisEstEvt(uint8_t *pBuf, const LlCisEstInd_t *pEvt) +{ + const uint8_t len = HCI_LEN_LE_CIS_EST; + + UINT8_TO_BSTREAM (pBuf, HCI_LE_CIS_EST_EVT); + UINT8_TO_BSTREAM (pBuf, pEvt->status); + UINT16_TO_BSTREAM (pBuf, pEvt->cisHandle); + UINT24_TO_BSTREAM (pBuf, pEvt->cigSyncDelayUsec); + UINT24_TO_BSTREAM (pBuf, pEvt->cisSyncDelayUsec); + UINT24_TO_BSTREAM (pBuf, pEvt->transLatUsecMToS); + UINT24_TO_BSTREAM (pBuf, pEvt->transLatUsecSToM); + UINT8_TO_BSTREAM (pBuf, pEvt->phyMToS); + UINT8_TO_BSTREAM (pBuf, pEvt->phySToM); + UINT8_TO_BSTREAM (pBuf, pEvt->nse); + UINT8_TO_BSTREAM (pBuf, pEvt->bnMToS); + UINT8_TO_BSTREAM (pBuf, pEvt->bnSToM); + UINT8_TO_BSTREAM (pBuf, pEvt->ftMToS); + UINT8_TO_BSTREAM (pBuf, pEvt->ftSToM); + UINT16_TO_BSTREAM (pBuf, pEvt->maxPduMToS); + UINT16_TO_BSTREAM (pBuf, pEvt->maxPduSToM); + UINT16_TO_BSTREAM (pBuf, pEvt->isoInterval); + + return len; +} + /*************************************************************************************************/ /*! * \brief LL CIS slave event handler. @@ -87,6 +122,20 @@ bool_t lhciSlvCisEncodeEvtPkt(LlEvt_t *pEvt) } break; + case LL_CIS_EST_IND: + { + if ((lhciCb.leEvtMsk & ((uint64_t)(HCI_EVT_MASK_LE_CIS_EST_EVT) << LHCI_BYTE_TO_BITS(3))) && + (lhciCb.evtMsk & ((uint64_t)(HCI_EVT_MASK_LE_META) << LHCI_BYTE_TO_BITS(7)))) + { + + if ((pEvtBuf = lhciAllocEvt(HCI_LE_META_EVT, HCI_LEN_LE_CIS_EST)) != NULL) + { + lhciPackCisEstEvt(pEvtBuf, &pEvt->cisEstInd); + } + } + break; + } + default: break; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn.c index 8929c53ac2..91c908f71a 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn.c @@ -287,7 +287,7 @@ static uint8_t lhciPackPowerReportEvt(uint8_t *pBuf, const LlPowerReportInd_t *p * \return Packet length. */ /*************************************************************************************************/ -static uint8_t lhciPackPathLossEvt(uint8_t *pBuf, const LlPathLossThresholdEvt_t *pEvt) +static uint8_t lhciPackPathLossEvt(uint8_t *pBuf, const LlPathLossThresholdInd_t *pEvt) { const uint8_t len = HCI_LEN_LE_PATH_LOSS_ZONE; @@ -511,7 +511,7 @@ bool_t lhciConnEncodeEvtPkt(LlEvt_t *pEvt) { if ((pEvtBuf = lhciAllocEvt(HCI_LE_META_EVT, HCI_LEN_LE_PATH_LOSS_ZONE)) != NULL) { - lhciPackPathLossEvt(pEvtBuf, &pEvt->pathLossEvt); + lhciPackPathLossEvt(pEvtBuf, &pEvt->pathLossInd); } } break; diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_enc_slave.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_enc_slave.c index 15336b9e03..c3e89d6b1f 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_enc_slave.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_enc_slave.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,6 +50,28 @@ static uint8_t lhciPackEncChangeEvt(uint8_t *pBuf, const LlEncChangeInd_t *pEvt) return len; } +/*************************************************************************************************/ +/*! + * \brief Pack start encryption event packet [v2]. + * + * \param pBuf Packed packet buffer. + * \param pEvt Encryption change indication data. + * + * \return Packet length. + */ +/*************************************************************************************************/ +static uint8_t lhciPackEncChangeV2Evt(uint8_t *pBuf, const LlEncChangeInd_t *pEvt) +{ + const uint8_t len = HCI_LEN_ENC_CHANGE; + + UINT8_TO_BSTREAM (pBuf, pEvt->status); + UINT16_TO_BSTREAM(pBuf, pEvt->handle); + UINT8_TO_BSTREAM (pBuf, pEvt->enabled); + UINT8_TO_BSTREAM (pBuf, pEvt->encKeySize); + + return len; +} + /*************************************************************************************************/ /*! * \brief Pack key refresh complete event packet. @@ -128,7 +150,15 @@ bool_t lhciSlvEncEncodeEvtPkt(LlEvt_t *pEvt) switch (pEvt->hdr.event) { case LL_ENC_CHANGE_IND: - if (lhciCb.evtMsk & ((uint64_t)(HCI_EVT_MASK_ENC_CHANGE) << LHCI_BYTE_TO_BITS(0))) + if (lhciCb.evtMskPg2 & ((uint64_t)(HCI_EVT_MASK_ENC_CHANGE_V2) << LHCI_BYTE_TO_BITS(3))) + { + if ((pEvtBuf = lhciAllocEvt(HCI_ENC_CHANGE_V2_EVT, HCI_LEN_ENC_CHANGE_V2)) != NULL) + { + pEvt->encChangeInd.encKeySize = 0x01; /* Unused value. */ + lhciPackEncChangeV2Evt(pEvtBuf, &pEvt->encChangeInd); + } + } + else if (lhciCb.evtMsk & ((uint64_t)(HCI_EVT_MASK_ENC_CHANGE) << LHCI_BYTE_TO_BITS(0))) { if ((pEvtBuf = lhciAllocEvt(HCI_ENC_CHANGE_EVT, HCI_LEN_ENC_CHANGE)) != NULL) { diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_pc.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_pc.c index 3c4c5c5709..a07c9d48d2 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_pc.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_pc.c @@ -4,7 +4,7 @@ * * \brief LL HCI event module implementation file. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,7 +63,7 @@ static uint8_t lhciPackPowerReportEvt(uint8_t *pBuf, const LlPowerReportInd_t *p * \return Packet length. */ /*************************************************************************************************/ -static uint8_t lhciPackPathLossEvt(uint8_t *pBuf, const LlPathLossThresholdEvt_t *pEvt) +static uint8_t lhciPackPathLossEvt(uint8_t *pBuf, const LlPathLossThresholdInd_t *pEvt) { const uint8_t len = HCI_LEN_LE_PATH_LOSS_ZONE; @@ -105,7 +105,7 @@ bool_t lhciPclEncodeEvtPkt(LlEvt_t *pEvt) { if ((pEvtBuf = lhciAllocEvt(HCI_LE_META_EVT, HCI_LEN_LE_PATH_LOSS_ZONE)) != NULL) { - lhciPackPathLossEvt(pEvtBuf, &pEvt->pathLossEvt); + lhciPackPathLossEvt(pEvtBuf, &pEvt->pathLossInd); } } break; diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_int.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_int.h index f0f91165e0..e7d3e86951 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_int.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_int.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,6 +50,8 @@ extern "C" { /* --- Controller Group --- */ #define LHCI_LEN_SET_EVENT_MASK_EVT 1 /*!< Set event mask command complete event length. */ #define LHCI_LEN_RESET_EVT 1 /*!< Reset command complete event length. */ +#define LHCI_LEN_READ_AFH_CHAN_ASSESMENT_MODE 2 /*!< Read AFH channel assessment mode command complete event length. */ +#define LHCI_LEN_WRITE_AFH_CHAN_ASSESMENT_MODE 1 /*!< Write AFH channel assesment mode command complete event length. */ #define LHCI_LEN_READ_PWR_LVL_EVT 4 /*!< Read power level command complete event length. */ #define LHCI_LEN_READ_AUTH_PAYLOAD_TO_EVT 5 /*!< Read authenticated payload timeout command complete event length. */ #define LHCI_LEN_WRITE_AUTH_PAYLOAD_TO_EVT 3 /*!< Write authenticated payload timeout command complete event length. */ @@ -144,7 +146,7 @@ extern "C" { /* New in version 5.2 */ #define LHCI_LEN_LE_READ_BUF_SIZE_V2 7 /*!< LE read ISO buffer size command complete event length. */ #define LHCI_LEN_LE_READ_TX_SYNC 12 /*!< LE read ISO Tx sync. */ -#define LHCI_LEN_LE_REMOVE_CIG 1 /*!< LE remove CIG. */ +#define LHCI_LEN_LE_REMOVE_CIG 2 /*!< LE remove CIG. */ #define LHCI_LEN_LE_REJECT_CIS_REQ 1 /*!< LE reject CIS request. */ #define LHCI_LEN_LE_BIG_TERMINATE_SYNC 2 /*!< LE BIG terminate sync. */ #define LHCI_LEN_LE_SETUP_ISO_DATA_PATH 3 /*!< LE setup ISO data path. */ @@ -218,6 +220,7 @@ extern "C" { #define LHCI_OPCODE_VS_GET_PDU_FILT_STATS HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3F4) /*!< Get PDU Filter Statistics opcode. */ #define LHCI_OPCODE_VS_GET_SYS_STATS HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3FA) /*!< Get Memory Statistics opcode. */ +#define LHCI_OPCODE_VS_GET_CONTEXT_SIZES HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3C0) /*!< Get context sizes opcode. */ #define LHCI_OPCODE_VS_GET_ADV_STATS HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3FB) /*!< Get Advertising Statistics opcode. */ #define LHCI_OPCODE_VS_GET_SCAN_STATS HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3FC) /*!< Get Scan Statistics opcode. */ #define LHCI_OPCODE_VS_GET_CONN_STATS HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3FD) /*!< Get Connection Statistics opcode. */ @@ -233,7 +236,8 @@ extern "C" { #define LHCI_OPCODE_VS_GET_ISO_TEST_REPORT HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3D6) /*!< Get ISO Test Report opcode. */ #define LHCI_OPCODE_VS_ENA_ISO_SINK HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3D7) /*!< Enable ISO Packet Sink opcode. */ #define LHCI_OPCODE_VS_ENA_AUTO_GEN_ISO HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3D8) /*!< Enable Auto Generate ISO Packets opcode. */ -#define LHCI_OPCODE_VS_GET_CIS_STATS HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3D9) /*!< Get ISO Connection Statistics opcode. */ +#define LHCI_OPCODE_VS_GET_CIS_STATS HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3D9) /*!< Get CIS Statistics opcode. */ +#define LHCI_OPCODE_VS_GET_BIS_STATS HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3C1) /*!< Get BIS Statistics opcode. */ #define LHCI_OPCODE_VS_GET_AUX_ADV_STATS HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3DA) /*!< Get Auxiliary Advertising Statistics opcode. */ #define LHCI_OPCODE_VS_GET_AUX_SCAN_STATS HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3DB) /*!< Get Auxiliary Scanning Statistics opcode. */ @@ -241,6 +245,8 @@ extern "C" { #define LHCI_OPCODE_VS_SET_CONN_PHY_TX_PWR HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3DD) /*!< Set Connection Phy Tx Power opcode. */ +#define LHCI_OPCODE_VS_SYSTEM_RESET HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3A0) /*!< System reset opcode. */ +#define LHCI_OPCODE_VS_ENTER_BOOTLOADER HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3A1) /*!< Enter bootloader opcode. */ /* Vendor specific event masks. */ #define LHCI_VS_EVT_MASK_SCAN_REPORT_EVT 0x01 /*!< (Byte 0) VS event bit, scan report. */ @@ -255,6 +261,7 @@ extern "C" { enum { LHCI_MSG_PRIV, /*!< Privacy command handler type. Must be before CONN. */ + LHCI_MSG_ECU, /*!< Enhanced connection update command handler type. */ LHCI_MSG_CONN, /*!< Connection command handler type. */ LHCI_MSG_CONN_CS2, /*!< Connection Channel Selection 2 command handler type. */ LHCI_MSG_ENC, /*!< Encryption command handler type. */ @@ -306,6 +313,7 @@ typedef struct wsfQueue_t cmdQ; /*!< Command queue. */ wsfQueue_t evtQ; /*!< Event queue. */ wsfQueue_t isoQ; /*!< ISO queue. */ + lhciCompHandler_t evtCompCback; /*!< Event complete handler. */ bool_t evtTrPending; /*!< Event transport in progress. */ uint8_t supCmds[HCI_SUP_CMD_LEN]; @@ -318,7 +326,6 @@ typedef struct uint64_t evtMsk; /*!< General event mask. */ uint64_t evtMskPg2; /*!< General event mask page 2. */ uint64_t leEvtMsk; /*!< LE specific event mask. */ - lhciCompHandler_t evtCompCback; /*!< Event complete handler. */ uint8_t numScanReqRcvd; /*!< Number of scan request received. */ uint8_t hwErrorCode; /*!< Hardware error code. */ @@ -333,6 +340,8 @@ typedef struct uint32_t genOctetCnt; /*!< Generate ACL octet count. */ uint8_t numAdvReport; /*!< Number of pending advertising reports. */ + + uint8_t chanAssesmentMode; /*!< Channel assesment mode. */ } lhciCb_t; /*! \brief Control block for ISO data generator. */ @@ -425,6 +434,7 @@ bool_t lhciSlvBisDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf); bool_t lhciMstBisDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf); bool_t lhciIsoDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf); bool_t lhciPclDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf); +bool_t lhciEcuDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf); bool_t lhciCommonVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf); bool_t lhciConnVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf); @@ -458,7 +468,7 @@ bool_t lhciSlvBigEncodeEvtPkt(LlEvt_t *pEvt); bool_t lhciMstBisEncodeEvtPkt(LlEvt_t *pEvt); bool_t lhciIsoEncodeEvtPkt(LlEvt_t *pEvt); bool_t lhciPclEncodeEvtPkt(LlEvt_t *pEvt); - +bool_t lhciEcuEncodeEvtPkt(LlEvt_t *pEvt); bool_t lhciSlvVsStdEncodeEvtPkt(LlEvt_t *pEvt); @@ -471,6 +481,20 @@ void lhciPclSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen, /* Command packet. */ uint8_t lhciUnpackConnSpec(LlConnSpec_t *pConnSpec, const uint8_t *pBuf); +/* Common events. */ + +/*************************************************************************************************/ +/*! + * \brief Pack a CIS established event packet. + * + * \param pBuf Packed packet buffer. + * \param pEvt CIS established event data. + * + * \return Packet length. + */ +/*************************************************************************************************/ +uint8_t lhciPackCisEstEvt(uint8_t *pBuf, const LlCisEstInd_t *pEvt); + /*************************************************************************************************/ /*! * \brief Pack an event packet header. diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_main.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_main.c index aa22316670..e3ef767119 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_main.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_main.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,7 +27,7 @@ #include "hci_defs.h" #include "ll_api.h" #include "bb_api.h" -#include "pal_bb.h" +#include "pal_frc.h" #include "wsf_assert.h" #include "wsf_msg.h" #include "util/bstream.h" @@ -92,7 +92,7 @@ void LhciHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) uint32_t startTime; uint32_t endTime; - startTimeValid = PalBbGetTimestamp(NULL); + startTimeValid = PalFrcGetCurrentTime(); if (startTimeValid) { startTime = PalBbGetCurrentTime(); @@ -153,9 +153,9 @@ void LhciHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) lhciPersistCb.evtTrPending = FALSE; ChciTrNeedsService(CHCI_TR_PROT_BLE); - if (lhciCb.evtCompCback) + if (lhciPersistCb.evtCompCback) { - lhciCb.evtCompCback(); + lhciPersistCb.evtCompCback(); } } @@ -173,10 +173,10 @@ void LhciHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) } if (startTimeValid && - PalBbGetTimestamp(NULL)) + PalFrcGetCurrentTime()) { endTime = PalBbGetCurrentTime(); - uint32_t durUsec = BbGetTargetTimeDelta(endTime, startTime); + uint32_t durUsec = PalFrcDeltaUs(endTime, startTime); if (lhciHandlerWatermarkUsec < durUsec) { lhciHandlerWatermarkUsec = durUsec; @@ -238,6 +238,7 @@ void lhciSendComplete(uint8_t type, uint8_t *pBuf) case HCI_LE_DIRECT_ADV_REPORT_EVT: case HCI_LE_EXT_ADV_REPORT_EVT: case HCI_LE_PER_ADV_REPORT_EVT: + case HCI_LE_BIG_INFO_ADV_REPORT_EVT: lhciCb.numAdvReport--; break; case HCI_LE_SCAN_REQ_RCVD_EVT: @@ -348,8 +349,12 @@ bool_t lhciService(uint8_t *pType, uint16_t *pLen, uint8_t **pBuf) /*************************************************************************************************/ void lhciSendHwError(uint8_t code) { - lhciCb.hwErrorCode = code; - WsfSetEvent(lhciPersistCb.handlerId, LHCI_EVT_HW_ERR); + /* Only send once. Host is expected to reset system after first error code. */ + if (lhciCb.hwErrorCode == 0) + { + lhciCb.hwErrorCode = code; + WsfSetEvent(lhciPersistCb.handlerId, LHCI_EVT_HW_ERR); + } } /*************************************************************************************************/ @@ -398,8 +403,9 @@ static void LhciSetDefaultHciSupCmd(uint8_t *pBuf) HCI_SUP_LE_RECEIVER_TEST | /* Rx device */ HCI_SUP_LE_TRANSMITTER_TEST | /* Tx device */ HCI_SUP_LE_TEST_END; /* mandatory */ + pBuf[41] = HCI_SUP_LE_MODIFY_SLEEP_CLK_ACCURACY; pBuf[44] = HCI_SUP_LE_SET_HOST_FEATURE; /* v5.2 */ - pBuf[45] = HCI_SUP_LE_TRANSMITTER_TEST_V4; /* v5.2 */ + pBuf[45] = 0; /* v5.2 */ pBuf[38] = HCI_SUP_LE_READ_TX_POWER; /* mandatory (5.0) */ if (lhciCmdTbl[LHCI_MSG_CONN]) @@ -475,6 +481,8 @@ static void LhciSetDefaultHciSupCmd(uint8_t *pBuf) { pBuf[34] |= HCI_SUP_LE_READ_LOCAL_P256_PUB_KEY | /* Secure connections */ HCI_SUP_LE_GENERATE_DHKEY; /* Secure connections */ + + pBuf[41] |= HCI_SUP_LE_GENERATE_DHKEY_V2; /* Secure connections */ } if (lhciCmdTbl[LHCI_MSG_PHY]) @@ -570,7 +578,7 @@ static void LhciSetDefaultHciSupCmd(uint8_t *pBuf) { pBuf[41] |= HCI_SUP_LE_READ_BUF_SIZE_V2 | /* ISO */ HCI_SUP_LE_READ_ISO_TX_SYNC; /* ISO */ - pBuf[44] |= HCI_SUP_LE_SETUP_ISO_DATA_PATH | /* ISO */ + pBuf[43] |= HCI_SUP_LE_SETUP_ISO_DATA_PATH | /* ISO */ HCI_SUP_LE_REMOVE_ISO_DATA_PATH | /* ISO */ HCI_SUP_LE_REQ_PEER_SCA; /* ISO */ @@ -618,5 +626,5 @@ void LhciInitFinalize(void) /*************************************************************************************************/ void LhciRegisterSendTrCompleteHandler(lhciCompHandler_t compCback) { - lhciCb.evtCompCback = compCback; + lhciPersistCb.evtCompCback = compCback; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init.c index fd9479ae50..6d5900df15 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ #include "ll_api.h" #include "lctr_api.h" #include "lmgr_api.h" -#include "pal_bb.h" +#include "pal_frc.h" #include "wsf_assert.h" #include "wsf_math.h" #include "wsf_msg.h" @@ -57,7 +57,7 @@ void LlGetDefaultRunTimeCfg(LlRtCfg_t *pCfg) { /* Device */ .compId = HCI_ID_PACKETCRAFT, - .implRev = LL_VER_NUM >> 16, + .implRev = LL_VER_NUM, .btVer = LL_VER_BT_CORE_SPEC_4_2, /* Advertiser */ .maxAdvSets = 0, /* Disable extended advertising. */ @@ -92,7 +92,12 @@ void LlGetDefaultRunTimeCfg(LlRtCfg_t *pCfg) .phy2mSup = FALSE, .phyCodedSup = FALSE, .stableModIdxTxSup = FALSE, - .stableModIdxRxSup = FALSE + .stableModIdxRxSup = FALSE, + /* Power control */ + .pcHighThreshold = -50, + .pcLowThreshold = -70, + /* Channel class reporting */ + .chClassIntSpacing = 50 }; *pCfg = defCfg; @@ -118,9 +123,9 @@ void LlInitRunTimeCfg(const LlRtCfg_t *pCfg) WSF_ASSERT(pCfg->maxAdvReports > 0); WSF_ASSERT(pCfg->maxAdvSets <= LL_MAX_ADV_SETS); WSF_ASSERT((pCfg->maxAdvSets == 0) || (pCfg->maxExtAdvDataLen >= LL_ADVBU_MAX_LEN)); - WSF_ASSERT(pCfg->numTxBufs > 0); - WSF_ASSERT(pCfg->numRxBufs > 0); - WSF_ASSERT(pCfg->maxAclLen >= LL_MAX_DATA_LEN_MIN); + WSF_ASSERT((pCfg->maxConn == 0) || pCfg->numTxBufs > 0); + WSF_ASSERT((pCfg->maxConn == 0) || pCfg->numRxBufs > 0); + WSF_ASSERT((pCfg->maxConn == 0) || pCfg->maxAclLen >= LL_MAX_DATA_LEN_MIN); WSF_ASSERT(pCfg->maxConn <= LL_MAX_CONN); WSF_ASSERT(pCfg->dtmRxSyncMs > 0); @@ -180,15 +185,10 @@ void LlHandlerInit(wsfHandlerId_t handlerId) /*************************************************************************************************/ void LlHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) { - bool_t startTimeValid; uint32_t startTime; uint32_t endTime; - startTimeValid = PalBbGetTimestamp(NULL); - if (startTimeValid) - { - startTime = PalBbGetCurrentTime(); - } + startTime = PalFrcGetCurrentTime(); if (event != 0) { @@ -207,16 +207,12 @@ void LlHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) LctrMsgDispatcher((lctrMsgHdr_t *)pMsg); } - if (startTimeValid && - PalBbGetTimestamp(NULL)) + endTime = PalFrcGetCurrentTime(); + uint32_t durUsec = PalFrcDeltaUs(endTime, startTime); + if (llHandlerWatermarkUsec < durUsec) { - endTime = PalBbGetCurrentTime(); - uint32_t durUsec = BbGetTargetTimeDelta(endTime, startTime); - if (llHandlerWatermarkUsec < durUsec) - { - llHandlerWatermarkUsec = durUsec; - LL_TRACE_INFO1("Raised watermark for LlHandler processing, time watermarkUsec=%u", durUsec); - } + llHandlerWatermarkUsec = durUsec; + LL_TRACE_INFO1("Raised watermark for LlHandler processing, time watermarkUsec=%u", durUsec); } } @@ -360,52 +356,62 @@ void LlGetPerScanContextSize(uint8_t *pMaxPerScan, uint16_t *pPerScanCtxSize) /*************************************************************************************************/ /*! - * \brief Get CIG context size. + * \brief Get CIS context size. * * \param pMaxCig Buffer to return the maximum number of CIG. * \param pCigCtxSize Buffer to return the size in bytes of the CIG context. - * - * Return the connection context sizes. - */ -/*************************************************************************************************/ -void LlGetCigContextSize(uint8_t *pMaxCig, uint16_t *pCigCtxSize) -{ - if (pLctrRtCfg) - { - *pMaxCig = pLctrRtCfg->maxCig; - } - else - { - *pMaxCig = 0; - } - - *pCigCtxSize = lmgrPersistCb.cigCtxSize; -} - -/*************************************************************************************************/ -/*! - * \brief Get CIS context size. - * * \param pMaxCis Buffer to return the maximum number of CIS. * \param pCisCtxSize Buffer to return the size in bytes of the CIS context. * * Return the connection context sizes. */ /*************************************************************************************************/ -void LlGetCisContextSize(uint8_t *pMaxCis, uint16_t *pCisCtxSize) +void LlGetCisContextSize(uint8_t *pMaxCig, uint16_t *pCigCtxSize, uint8_t *pMaxCis, uint16_t *pCisCtxSize) { if (pLctrRtCfg) { + *pMaxCig = pLctrRtCfg->maxCig; *pMaxCis = pLctrRtCfg->maxCis; } else { + *pMaxCig = 0; *pMaxCis = 0; } + *pCigCtxSize = lmgrPersistCb.cigCtxSize; *pCisCtxSize = lmgrPersistCb.cisCtxSize; } +/*************************************************************************************************/ +/*! + * \brief Get BIS context size. + * + * \param pMaxBig Buffer to return the maximum number of BIG. + * \param pBigCtxSize Buffer to return the size in bytes of the BIG context. + * \param pMaxBis Buffer to return the maximum number of BIS. + * \param pBisCtxSize Buffer to return the size in bytes of the BIS context. + * + * Return the connection context sizes. + */ +/*************************************************************************************************/ +void LlGetBisContextSize(uint8_t *pMaxBig, uint16_t *pBigCtxSize, uint8_t *pMaxBis, uint16_t *pBisCtxSize) +{ + if (pLctrRtCfg) + { + *pMaxBig = pLctrRtCfg->maxBig; + *pMaxBis = pLctrRtCfg->maxBis; + } + else + { + *pMaxBig = 0; + *pMaxBis = 0; + } + + *pBigCtxSize = lmgrPersistCb.bigCtxSize; + *pBisCtxSize = lmgrPersistCb.bisCtxSize; +} + /*************************************************************************************************/ /*! * \brief Get the LL handler watermark level. diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_iso.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_iso.c index 2a8f3ddaa3..e9aec1f3b8 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_iso.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_iso.c @@ -21,6 +21,7 @@ * limitations under the License. */ /*************************************************************************************************/ + #include "lctr_api_iso.h" #include "lmgr_api.h" #include "lctr_api.h" diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_pc.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_pc.c index 2b31cc085b..584d43ea32 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_pc.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_pc.c @@ -34,6 +34,5 @@ /*************************************************************************************************/ void LlPowerControlInit(void) { - LhciPowerControlInit(); LctrPowerControlInit(); } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main.c index 284369d985..08a7fb9693 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main.c @@ -330,22 +330,27 @@ uint8_t LlSetOpFlags(uint32_t flags, bool_t enable) LL_OP_MODE_FLAG_MST_RETX_AFTER_RX_NACK | LL_OP_MODE_FLAG_MST_IGNORE_CP_RSP | LL_OP_MODE_FLAG_MST_UNCOND_CP_RSP | - LL_OP_MODE_FLAG_REQ_SYM_PHY | LL_OP_MODE_FLAG_ENA_LEN_LLCP_STARTUP | + LL_OP_MODE_FLAG_REQ_SYM_PHY | LL_OP_MODE_FLAG_ENA_FEAT_LLCP_STARTUP | LL_OP_MODE_FLAG_SLV_DELAY_LLCP_STARTUP | + LL_OP_MODE_FLAG_ENA_SLV_LATENCY_WAKEUP | + LL_OP_MODE_FLAG_ENA_SLV_AUX_SCAN_RSP_ADI | LL_OP_MODE_FLAG_ENA_MST_CIS_NULL_PDU | + LL_OP_MODE_FLAG_ENA_SLV_AUX_IND_ADVA | + LL_OP_MODE_FLAG_ENA_ADV_CHAN_RAND | + LL_OP_MODE_FLAG_DIS_POWER_MONITOR | + LL_OP_MODE_FLAG_ENA_ISO_LOST_NOTIFY | + LL_OP_MODE_FLAG_ENA_CH_RPT_LLCP_AFTER_FEAT | + LL_OP_MODE_FLAG_IGNORE_CRC_ERR_TS | + LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2 | + /* diagnostics only */ LL_OP_MODE_FLAG_ENA_ADV_DLY | LL_OP_MODE_FLAG_ENA_SCAN_BACKOFF | LL_OP_MODE_FLAG_ENA_WW | LL_OP_MODE_FLAG_ENA_SLV_LATENCY | - LL_OP_MODE_FLAG_ENA_SLV_LATENCY_WAKEUP | - LL_OP_MODE_FLAG_ENA_SLV_AUX_SCAN_RSP_ADI | - LL_OP_MODE_FLAG_ENA_SLV_AUX_IND_ADVA | - LL_OP_MODE_FLAG_ENA_ADV_CHAN_RAND | - LL_OP_MODE_DISABLE_POWER_MONITOR | LL_OP_MODE_FLAG_ENA_LLCP_TIMER | - LL_OP_MODE_FLAG_IGNORE_CRC_ERR_TS; + LL_OP_MODE_FLAG_ENA_SUBRATE_CE; LL_TRACE_INFO2("### LlApi ### LlSetOpFlags flag=%x enable=%d", flags, enable); @@ -524,7 +529,7 @@ uint8_t LlRemoveDeviceFromWhitelist(uint8_t addrType, bdAddr_t pAddr) /*************************************************************************************************/ uint8_t LlSetHostFeatures(uint8_t bitNum, bool_t bitVal) { - LL_TRACE_INFO2("### LlApi ### LlSetHostFeatures, Bit=%d Value=%d", bitNum, bitVal); + LL_TRACE_INFO2("### LlApi ### LlSetHostFeatures, bit=%d value=%d", bitNum, bitVal); if ((LL_HOST_CONTROLLED_FEAT & (UINT64_C(1) << bitNum)) == 0) { diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_master_ae.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_master_ae.c index 8d0aa0eed5..aafe028f8b 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_master_ae.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_master_ae.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -76,7 +76,8 @@ uint8_t LlSetExtScanParam(uint8_t ownAddrType, uint8_t scanFiltPolicy, uint8_t s { const uint8_t scanFiltPolicyMax = ((lmgrCb.features & LL_FEAT_EXT_SCAN_FILT_POLICY) != 0) ? LL_SCAN_FILTER_WL_OR_RES_INIT : LL_SCAN_FILTER_WL_BIT; const uint8_t ownAddrTypeMax = ((lmgrCb.features & LL_FEAT_PRIVACY) != 0) ? LL_ADDR_RANDOM_IDENTITY : LL_ADDR_RANDOM; - const uint8_t validScanPhys = LL_PHYS_LE_1M_BIT | LL_PHYS_LE_CODED_BIT; + uint8_t supportedPhys = LL_PHYS_LE_1M_BIT; + supportedPhys |= (lmgrCb.features & LL_FEAT_LE_CODED_PHY) ? LL_PHYS_LE_CODED_BIT : 0; LL_TRACE_INFO1("### LlApi ### LlSetExtScanParam, scanPhys=0x%02x", scanPhys); @@ -93,17 +94,17 @@ uint8_t LlSetExtScanParam(uint8_t ownAddrType, uint8_t scanFiltPolicy, uint8_t s } if ((LL_API_PARAM_CHECK == 1) && - ((ownAddrType > ownAddrTypeMax) || - (scanFiltPolicy > scanFiltPolicyMax) || - (scanPhys & ~validScanPhys))) + (scanPhys & ~supportedPhys)) { - return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; } if ((LL_API_PARAM_CHECK == 1) && - ((scanPhys & LL_PHYS_LE_CODED_BIT) && ((lmgrCb.features & LL_FEAT_LE_CODED_PHY) == 0))) + ((ownAddrType > ownAddrTypeMax) || + (scanFiltPolicy > scanFiltPolicyMax) || + (scanPhys == 0))) { - return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; } if (LL_API_PARAM_CHECK == 1) @@ -296,6 +297,7 @@ uint8_t LlPeriodicAdvCreateSync(const LlPerAdvCreateSyncCmd_t *pParam) pMsg->advSID = pParam->advSID; pMsg->filterPolicy = pParam->options & 0x01; pMsg->repDisabled = (pParam->options >> 1) & 0x01; + pMsg->dupFilterEnable = ((pMsg->repDisabled) ? 0 : ((pParam->options >> 2) & 0x01)); pMsg->skip = pParam->skip; pMsg->syncTimeOut = pParam->syncTimeOut; diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_slave_ae.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_slave_ae.c index b644cad744..78b26a08e7 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_slave_ae.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_slave_ae.c @@ -562,7 +562,7 @@ uint8_t LlSetPeriodicAdvData(uint8_t handle, uint8_t op, uint8_t len, const uint } if ((LL_API_PARAM_CHECK == 1) && - (op > LL_ADV_DATA_OP_COMP)) + (op > LL_ADV_DATA_OP_UNCHANGED)) { return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_cis_master.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_cis_master.c index ee19329f82..954d9fa844 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_cis_master.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_cis_master.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -59,8 +59,6 @@ static bool_t LlIsCigParamsValid(LlCisCigParams_t *pCigParam) const uint8_t MAX_NUM_CIS = 0x10; const uint8_t MAX_CIS_ID = 0xEF; const uint16_t MAX_SDU_SIZE = 0x0FFF; - const uint8_t MIN_PHY = 0x01; - const uint8_t MAX_PHY = 0x07; const uint8_t MAX_RTE = 0x0F; if (pCigParam->cigId > MAX_CIG_ID) @@ -133,25 +131,25 @@ static bool_t LlIsCigParamsValid(LlCisCigParams_t *pCigParam) LL_TRACE_INFO0("LlIsCigParamsValid Invalid sduSizeSToM"); return FALSE; } - if ((pCisParam->phyMToS < MIN_PHY) || (pCisParam->phyMToS > MAX_PHY)) + if (pCisParam->phyMToS == 0) { LL_TRACE_INFO0("LlIsCigParamsValid Invalid phyMToS"); return FALSE; } - if ((pCisParam->phySToM < MIN_PHY) || (pCisParam->phySToM > MAX_PHY)) + if (pCisParam->phySToM == 0) { LL_TRACE_INFO0("LlIsCigParamsValid Invalid phySToM"); return FALSE; } if (pCisParam->rteMToS > MAX_RTE) { - LL_TRACE_INFO0("LlIsCigParamsValid Invalid rteMToS"); - return FALSE; + LL_TRACE_WARN0("LlIsCigParamsValid rteMToS out of controller range, setting to max"); + pCisParam->rteMToS = MAX_RTE; } if (pCisParam->rteSToM > MAX_RTE) { - LL_TRACE_INFO0("LlIsCigParamsValid Invalid rteSToM"); - return FALSE; + LL_TRACE_WARN0("LlIsCigParamsValid rteSToM out of controller range, setting to max"); + pCisParam->rteSToM = MAX_RTE; } } @@ -171,6 +169,7 @@ static bool_t LlIsCigPhyParamsValid(LlCisCigParams_t *pCigParam) { for (unsigned int i = 0; i < pCigParam->numCis; i++) { + const uint8_t phyMask = LL_PHYS_LE_1M_BIT | LL_PHYS_LE_2M_BIT | LL_PHYS_LE_CODED_BIT; LlCisCisParams_t *pCisParam = &pCigParam->pCisParam[i]; if (!llValidatePhySupport(pCisParam->phyMToS, pCisParam->phySToM)) @@ -178,6 +177,11 @@ static bool_t LlIsCigPhyParamsValid(LlCisCigParams_t *pCigParam) return FALSE; } + if (((pCisParam->phyMToS & ~phyMask) != 0) || /* reserved bits set in phyMToS */ + ((pCisParam->phySToM & ~phyMask) != 0)) /* reserved bits set in phySToM */ + { + return FALSE; + } if (BB_SYM_PHY_REQ && (pCisParam->phyMToS != pCisParam->phySToM)) @@ -215,8 +219,6 @@ static bool_t LlIsCigTestParamsValid(LlCisCigParamsTest_t *pSetCigParamTest) const uint8_t MAX_CIS_ID = 0xEF; const uint16_t MAX_SDU_SIZE = 0x0FFF; const uint16_t MAX_PDU_SIZE = 0x0FFB; - const uint8_t MIN_PHY = 0x01; - const uint8_t MAX_PHY = 0x07; const uint8_t MAX_BN = 0x0F; if (pSetCigParamTest->cigId > MAX_CIG_ID) @@ -284,11 +286,11 @@ static bool_t LlIsCigTestParamsValid(LlCisCigParamsTest_t *pSetCigParamTest) { return FALSE; } - if ((pCisParam->phyMToS < MIN_PHY) || (pCisParam->phyMToS > MAX_PHY)) + if (pCisParam->phyMToS == 0) { return FALSE; } - if ((pCisParam->phySToM < MIN_PHY) || (pCisParam->phySToM > MAX_PHY)) + if (pCisParam->phySToM == 0) { return FALSE; } @@ -325,6 +327,7 @@ static bool_t LlIsCigPhyTestParamsValid(LlCisCigParamsTest_t *pSetCigParamTest) { for (unsigned int i = 0; i < pSetCigParamTest->numCis; i++) { + const uint8_t phyMask = LL_PHYS_LE_1M_BIT | LL_PHYS_LE_2M_BIT | LL_PHYS_LE_CODED_BIT; LlCisCigCisParamsTest_t *pCisParam = &pSetCigParamTest->pCisParam[i]; if (!llValidatePhySupport(pCisParam->phyMToS, pCisParam->phySToM)) @@ -332,6 +335,12 @@ static bool_t LlIsCigPhyTestParamsValid(LlCisCigParamsTest_t *pSetCigParamTest) return FALSE; } + if (((pCisParam->phyMToS & ~phyMask) != 0) || /* reserved bits set in phyMToS */ + ((pCisParam->phySToM & ~phyMask) != 0)) /* reserved bits set in phySToM */ + { + return FALSE; + } + if (BB_SYM_PHY_REQ && (pCisParam->phyMToS != pCisParam->phySToM)) { @@ -356,26 +365,15 @@ uint8_t LlSetCigParams(LlCisCigParams_t *pCigParam, uint16_t *pCisHandles) { uint8_t status = LL_SUCCESS; - LL_TRACE_INFO1("### LlApi ### LlSetCigParams numCis=%d", pCigParam->numCis); + LL_TRACE_INFO1("### LlApi ### LlSetCigParams numCis=%u", pCigParam->numCis); memset(pCisHandles, 0, pCigParam->numCis * sizeof(uint16_t)); - LL_TRACE_INFO1("### LlApi ### LlSetCigParams cigId=%d", pCigParam->cigId); - LL_TRACE_INFO1("### LlApi ### LlSetCigParams sduIntervalMToS=%d", pCigParam->sduIntervalMToS); - LL_TRACE_INFO1("### LlApi ### LlSetCigParams sduIntervalSToM=%d", pCigParam->sduIntervalSToM); - LL_TRACE_INFO1("### LlApi ### LlSetCigParams sca=%d", pCigParam->sca); - LL_TRACE_INFO1("### LlApi ### LlSetCigParams packing=%d", pCigParam->packing); - LL_TRACE_INFO1("### LlApi ### LlSetCigParams framing=%d", pCigParam->framing); - LL_TRACE_INFO1("### LlApi ### LlSetCigParams transLatMToS=%d", pCigParam->transLatMToS); - LL_TRACE_INFO1("### LlApi ### LlSetCigParams transLatSToM=%d", pCigParam->transLatSToM); - LL_TRACE_INFO1("### LlApi ### LlSetCigParams numCis=%d", pCigParam->numCis); - LL_TRACE_INFO1("### LlApi ### LlSetCigParams cisId=%d", pCigParam->pCisParam[0].cisId); - LL_TRACE_INFO1("### LlApi ### LlSetCigParams sduSizeMToS=%d", pCigParam->pCisParam[0].sduSizeMToS); - LL_TRACE_INFO1("### LlApi ### LlSetCigParams sduSizeSToM=%d", pCigParam->pCisParam[0].sduSizeSToM); - LL_TRACE_INFO1("### LlApi ### LlSetCigParams phyMToS=%d", pCigParam->pCisParam[0].phyMToS); - LL_TRACE_INFO1("### LlApi ### LlSetCigParams phySToM=%d", pCigParam->pCisParam[0].phySToM); - LL_TRACE_INFO1("### LlApi ### LlSetCigParams rteMToS=%d", pCigParam->pCisParam[0].rteMToS); - LL_TRACE_INFO1("### LlApi ### LlSetCigParams rteSToM=%d", pCigParam->pCisParam[0].rteSToM); + LL_TRACE_INFO1("### LlApi ### LlSetCigParams cigId=%u", pCigParam->cigId); + LL_TRACE_INFO1("### LlApi ### LlSetCigParams sduIntervalMToS=%u", pCigParam->sduIntervalMToS); + LL_TRACE_INFO1("### LlApi ### LlSetCigParams sduIntervalSToM=%u", pCigParam->sduIntervalSToM); + LL_TRACE_INFO2("### LlApi ### LlSetCigParams packing=%u, framing=%u", pCigParam->packing, pCigParam->framing); + LL_TRACE_INFO1("### LlApi ### LlSetCigParams numCis=%u", pCigParam->numCis); if ((LL_API_PARAM_CHECK == 1) && (LlIsCigParamsValid(pCigParam) == FALSE)) @@ -413,7 +411,7 @@ uint8_t LlSetCigParamsTest(LlCisCigParamsTest_t *pSetCigParamTest, uint16_t *pCi { uint8_t status = LL_SUCCESS; - LL_TRACE_INFO1("### LlApi ### LlSetCigParamsTest numCis=%d", pSetCigParamTest->numCis); + LL_TRACE_INFO1("### LlApi ### LlSetCigParamsTest numCis=%u", pSetCigParamTest->numCis); memset(pCisHandles, 0, pSetCigParamTest->numCis * sizeof(uint16_t)); @@ -450,7 +448,7 @@ uint8_t LlCreateCis(uint8_t numCis, LlCisCreateCisParams_t *pCreateCisParam) { uint8_t status = LL_SUCCESS; - LL_TRACE_INFO1("### LlApi ### LlCreateCis numCis=%d", numCis); + LL_TRACE_INFO1("### LlApi ### LlCreateCis numCis=%u", numCis); if ((lmgrCb.features & LL_FEAT_ISO_HOST_SUPPORT) == 0) { @@ -492,7 +490,7 @@ uint8_t LlRemoveCig(uint8_t cigId) { uint8_t status = LL_SUCCESS; - LL_TRACE_INFO1("### LlApi ### LlRemoveCig CIG_ID=%d", cigId); + LL_TRACE_INFO1("### LlApi ### LlRemoveCig CIG_ID=%u", cigId); status = LctrRemoveCig(cigId); diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn.c index 9be7e7904e..fcbd435204 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn.c @@ -314,7 +314,8 @@ uint8_t LlSetConnOpFlags(uint16_t handle, uint32_t flags, bool_t enable) LL_OP_MODE_FLAG_ENA_WW | LL_OP_MODE_FLAG_ENA_SLV_LATENCY | LL_OP_MODE_FLAG_ENA_LLCP_TIMER | - LL_OP_MODE_FLAG_IGNORE_CRC_ERR_TS; + LL_OP_MODE_FLAG_IGNORE_CRC_ERR_TS | + LL_OP_MODE_FLAG_ENA_SUBRATE_CE; LL_TRACE_INFO2("### LlApi ### LlSetConnFlags flag=%x enable=%d", flags, enable); @@ -380,6 +381,9 @@ uint8_t LlDisconnect(uint16_t handle, uint8_t reason) pMsg->hdr.event = LCTR_CONN_MSG_API_DISCONNECT; pMsg->reason = reason; + /* Explicitly define a non-cis handle to avoid disconnecting CIS. */ + ((lctrCisDisc_t *) pMsg)->cisHandle = handle; + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); } } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_master_ae.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_master_ae.c index 2dd04fca97..6f9a6124a9 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_master_ae.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_master_ae.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -130,12 +130,6 @@ uint8_t LlExtCreateConn(const LlExtInitParam_t *pInitParam, const LlExtInitScanP return LL_ERROR_CODE_CMD_DISALLOWED; } - if ((LL_API_PARAM_CHECK == 1) && - ((pInitParam->initPhys & ~validInitPhys) || (pInitParam->initPhys == 0))) - { - return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; - } - if ((LL_API_PARAM_CHECK == 1) && ((pInitParam->initPhys & supportedPhys) != pInitParam->initPhys)) { @@ -143,6 +137,12 @@ uint8_t LlExtCreateConn(const LlExtInitParam_t *pInitParam, const LlExtInitScanP return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; } + if ((LL_API_PARAM_CHECK == 1) && + ((pInitParam->initPhys & ~validInitPhys) || (pInitParam->initPhys == 0))) + { + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + if ((LL_API_PARAM_CHECK == 1) && (!llValidateInitiateParams(pInitParam))) { diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_slave.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_slave.c index 1cc0eb5cea..0fbdbdca16 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_slave.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_slave.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,6 +46,18 @@ uint8_t LlReadRemoteFeat(uint16_t handle) if (LctrIsProcActPended(handle, LCTR_CONN_MSG_API_REMOTE_FEATURE) == TRUE) { + + /* The process can already be pended when the connection starts up if + * host sends this command right when connection establishes if + * LL_OP_MODE_FLAG_ENA_FEAT_LLCP_STARTUP is enabled. + */ + if (LctrIsConnHandleEnabled(handle) && + !LctrIsFeatExchHostInit(handle)) + { + LctrSetHostNotifyFeatExch(handle); + return LL_SUCCESS; + } + return LL_ERROR_CODE_CMD_DISALLOWED; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_dtm.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_dtm.c index 95befc6dd9..39e0633011 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_dtm.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_dtm.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -137,8 +137,8 @@ static uint32_t llCalcPacketInterval(uint8_t len, uint8_t phy, uint8_t phyOption break; } - /* ceil((L + 249) / 625) * 625 */ - return LL_MATH_DIV_625(totalTime + 249 + 624) * 625; + /* ceil((t) / 625) * 625 */ + return LL_MATH_DIV_625(totalTime + 624) * 625; } /*************************************************************************************************/ @@ -211,7 +211,7 @@ static inline void llPrbs9Payload(uint8_t *pBuf, uint8_t len) /*************************************************************************************************/ /*! - * \brief Buikld transmit buffer. + * \brief Build transmit buffer. * * \param len Length of test data. * \param pktType Test packet payload type. @@ -408,7 +408,7 @@ static bool_t llTestTxComplete(BbOpDesc_t *pOp, uint8_t status) /*************************************************************************************************/ uint8_t LlEnhancedTxTest(uint8_t rfChan, uint8_t len, uint8_t pktType, uint8_t phy, uint16_t numPkt) { - WSF_CS_INIT(); + WSF_CS_INIT(cs); LL_TRACE_INFO3("### LlApi ### LlTxTest, rfChan=%u, len=%u, pktType=%u", rfChan, len, pktType); @@ -489,7 +489,7 @@ uint8_t LlEnhancedTxTest(uint8_t rfChan, uint8_t len, uint8_t pktType, uint8_t p len = WSF_MIN(len, WSF_MAX(LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN, LL_DTM_MAX_PLD_LEN)); /* Modify operational parameters. */ - WSF_CS_ENTER(); + WSF_CS_ENTER(cs); llTestCb.tx.pduLen = WSF_MIN(len, WSF_MAX(LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN, LL_DTM_MAX_PLD_LEN)); llTestCb.tx.pktType = pktType; llTestCb.tx.chanIdx = llConvertRfChanToChanIdx(rfChan); @@ -515,7 +515,7 @@ uint8_t LlEnhancedTxTest(uint8_t rfChan, uint8_t len, uint8_t pktType, uint8_t p llTestCb.tx.errPattern = 0xFFFFFFFF; llTestCb.tx.errBit = 0; - WSF_CS_EXIT(); + WSF_CS_EXIT(cs); if (llTestCb.state == LL_TEST_STATE_TX) { diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_iso.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_iso.c index b795fddeb6..6fcd872a83 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_iso.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_iso.c @@ -173,9 +173,27 @@ void LlRecvIsoDataComplete(uint8_t numBufs) uint8_t LlReadIsoTxSync(uint16_t handle, uint16_t *pPktSn, uint32_t *pTs, uint32_t *pTimeOffs) { LL_TRACE_INFO1("### LlApi ### LlReadIsoTxSync, handle=%u", handle); + return LctrReadIsoTxSync(handle, pPktSn, pTs, pTimeOffs); } +/*************************************************************************************************/ +/*! + * \brief Used to request the Controller to configure the data transport path in a given + * direction between the Controller and the Host. + * + * \param pConfigDataPath Parameters for configure data path. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlConfigureDataPath(LlIsoConfigDataPath_t *pConfigDataPath) +{ + LL_TRACE_INFO2("### LlApi ### LlConfigureDataPath, dpDir=%u, dpId=%u", pConfigDataPath->dpDir, pConfigDataPath->dpId); + + return LctrConfigureDataPath(pConfigDataPath); +} + /*************************************************************************************************/ /*! * \brief Used to identify and enable the isochronous data path between the host and the diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_past.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_past.c index b41f7b9c01..727287c13d 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_past.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_past.c @@ -6,7 +6,7 @@ * * Copyright (c) 2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,7 +35,7 @@ * \brief Enable or disable reports for the periodic advertising sync. * * \param syncHandle Periodic sync handle. - * \param enable 1 to enable reports, 0 to disable reports. + * \param enable Enable settings. * * \return Status error code. * @@ -65,7 +65,7 @@ uint8_t LlSetPeriodicAdvRcvEnable(uint16_t syncHandle, uint8_t enable) return LL_ERROR_CODE_UNKNOWN_ADV_ID; } - LctrMstPerSetRcvEnable (syncHandle, (bool_t)enable); + LctrMstPerSetRcvEnable(syncHandle, enable); return LL_SUCCESS; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main.c index 966106a9ca..54d0e53c6e 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,27 +63,36 @@ void LmgrSetDefaults(void) lmgrCb.features = lmgrPersistCb.featuresDefault; lmgrCb.opModeFlags = - /* LL_OP_MODE_FLAG_ENA_VER_LLCP_STARTUP | */ /* disabled */ - /* LL_OP_MODE_FLAG_SLV_REQ_IMMED_ACK | */ /* disabled */ - /* LL_OP_MODE_FLAG_BYPASS_CE_GUARD | */ /* disabled */ - /* LL_OP_MODE_FLAG_MST_RETX_AFTER_RX_NACK | */ /* disabled */ - /* LL_OP_MODE_FLAG_MST_IGNORE_CP_RSP | */ /* disabled */ - /* LL_OP_MODE_FLAG_MST_UNCOND_CP_RSP | */ /* disabled */ - /* LL_OP_MODE_FLAG_REQ_SYM_PHY | */ /* disabled */ - /* LL_OP_MODE_FLAG_ENA_FEAT_LLCP_STARTUP | */ /* disabled */ - /* LL_OP_MODE_FLAG_SLV_DELAY_LLCP_STARTUP | */ /* disabled */ - LL_OP_MODE_FLAG_ENA_SLV_LATENCY_WAKEUP | + /* LL_OP_MODE_FLAG_ENA_VER_LLCP_STARTUP | */ /* disabled */ + /* LL_OP_MODE_FLAG_SLV_REQ_IMMED_ACK | */ /* disabled */ + /* LL_OP_MODE_FLAG_BYPASS_CE_GUARD | */ /* disabled */ + /* LL_OP_MODE_FLAG_MST_RETX_AFTER_RX_NACK | */ /* disabled */ + /* LL_OP_MODE_FLAG_MST_IGNORE_CP_RSP | */ /* disabled */ + /* LL_OP_MODE_FLAG_MST_UNCOND_CP_RSP | */ /* disabled */ LL_OP_MODE_FLAG_ENA_LEN_LLCP_STARTUP | + /* LL_OP_MODE_FLAG_REQ_SYM_PHY | */ /* disabled */ + /* LL_OP_MODE_FLAG_ENA_FEAT_LLCP_STARTUP | */ /* disabled. */ + /* LL_OP_MODE_FLAG_SLV_DELAY_LLCP_STARTUP | */ /* disabled */ + LL_OP_MODE_FLAG_ENA_SLV_LATENCY_WAKEUP | + LL_OP_MODE_FLAG_ENA_SLV_AUX_SCAN_RSP_ADI | + LL_OP_MODE_FLAG_ENA_MST_CIS_NULL_PDU | + /* LL_OP_MODE_FLAG_ENA_SLV_AUX_IND_ADVA | */ /* disabled */ + LL_OP_MODE_FLAG_ENA_ADV_CHAN_RAND | + /* LL_OP_MODE_FLAG_DIS_POWER_MONITOR | */ /* disabled */ + /* LL_OP_MODE_FLAG_ENA_BIS_RECV_DUP | */ /* disabled */ + /* LL_OP_MODE_FLAG_ENA_ISO_LOST_NOTIFY | */ + LL_OP_MODE_FLAG_ENA_CH_RPT_LLCP_AFTER_FEAT | + /* LL_OP_MODE_FLAG_IGNORE_CRC_ERR_TS | */ /* disabled */ + /* LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2 | */ /* disabled */ + + /* diagnostics only */ LL_OP_MODE_FLAG_ENA_ADV_DLY | LL_OP_MODE_FLAG_ENA_SCAN_BACKOFF | LL_OP_MODE_FLAG_ENA_WW | LL_OP_MODE_FLAG_ENA_SLV_LATENCY | - LL_OP_MODE_FLAG_ENA_SLV_AUX_SCAN_RSP_ADI | - LL_OP_MODE_FLAG_ENA_MST_CIS_NULL_PDU | - /* LL_OP_MODE_FLAG_ENA_SLV_AUX_IND_ADVA | */ /* disabled */ - LL_OP_MODE_FLAG_ENA_ADV_CHAN_RAND | - /* LL_OP_MODE_DISABLE_POWER_MONITOR | */ /* disabled */ - LL_OP_MODE_FLAG_ENA_LLCP_TIMER; + LL_OP_MODE_FLAG_ENA_LLCP_TIMER | + LL_OP_MODE_FLAG_ENA_SUBRATE_CE | + 0; lmgrCb.chanClass = LL_CHAN_DATA_ALL; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_conn.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_conn.c index 74b2e09fe8..58ba70d466 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_conn.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_conn.c @@ -56,4 +56,10 @@ void LmgrConnInit(void) lmgrConnCb.syncMode = LL_SYNC_TRSF_MODE_OFF; lmgrConnCb.syncSkip = 0; lmgrConnCb.syncTimeout = LL_SYNC_MIN_TIMEOUT; + + lmgrConnCb.defSrMin = 1; + lmgrConnCb.defSrMax = 1; + lmgrConnCb.defMaxLatency = 0; + lmgrConnCb.defContNum = 0; + lmgrConnCb.defSvt = LL_MAX_SUP_TIMEOUT; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_ble.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_ble.c index 0c12985f63..3e181b5667 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_ble.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_ble.c @@ -311,11 +311,6 @@ void SchBleCalcAdvOpDuration(BbOpDesc_t *pBod, uint8_t fragLen) minDurUsec = LL_EXT_ADVB_MAX_TIME_2M; break; case BB_PHY_BLE_CODED: - /* Setting min & max duration differently to avoid conflict with other BOD's. */ - /* Min = 3.8ms for normal size(up to 50 bytes) */ - /* Max = 17.4ms for maximum size(up to 255 bytes) */ - /* When RX data size is larger than 50 bytes, it may stomp on the next high priority BOD's. */ - /* TODO: We need HW support(Radio interrupt when packet header is received) to properly fix the problem. */ minDurUsec = LL_EXT_ADVB_NORMAL_TIME_S8; pBod->maxDurUsec = LL_EXT_ADVB_MAX_TIME_S8; break; diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_int_rm.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_int_rm.h index 72342806fb..7600c728f9 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_int_rm.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_int_rm.h @@ -65,7 +65,7 @@ extern "C" { typedef struct { uint8_t handle; /*!< Reservation handle. */ - bool_t commIntUsed; /*!< Reservation is controlled by common interval. */ + bool_t cmdInterUsed; /*!< Reservation is controlled by common interval. */ uint8_t offsetBit; /*!< Offset bit location. */ uint32_t interUsec; /*!< Interval in microseconds. */ uint32_t durUsec; /*!< Duration in microseconds. */ @@ -80,7 +80,7 @@ typedef struct uint8_t offsetDepth; /*!< Offset depth from common interval. */ uint8_t indexUncommon; /*!< Index of uncommon reservations. */ uint32_t rmStatus; /*!< Reservation status. */ - uint32_t commonInt; /*!< Common interval. */ + uint32_t cmnInter; /*!< Common interval. */ uint32_t rsvnInterUsec[SCH_RM_MAX_RSVN]; /*!< Reserved intervals indexed by handle. */ schRmRsvn_t rsvn[SCH_RM_MAX_RSVN]; /*!< Reservation info for each handle. */ } SchRmCb_t; diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_rm.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_rm.c index 812d7ce88f..a2270354f8 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_rm.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_rm.c @@ -51,7 +51,6 @@ * :..3 : 3 : 3 : 3: :3 : 3 : 3 : 3 : 3: * |---------|---------|---------|---------|---------|---------|---------|---------|---------|---------| * 0 1 2 3 4 5 6 7 8 9 10-ms - * */ /*************************************************************************************************/ @@ -72,7 +71,7 @@ WSF_CT_ASSERT((SCH_RM_MAX_RSVN <= 32)); #define SCH_RM_MAX_RSVN_BINS ((sizeof(schRmRsvnRatio)/sizeof(schRmRsvnRatio[0])) - 1) /*! \brief Maximum number of attempts to add reservation. */ -#define SCH_RM_ADD_MAX_ATTEMPTS 3 +#define SCH_RM_ADD_MAX_ATTEMPTS 4 /************************************************************************************************** Global Variables @@ -283,13 +282,13 @@ uint8_t schRmIntCalculateDepth(uint32_t intLarge, uint32_t intSmall) static bool_t schRmIntAddRmOffset(uint8_t handle, uint8_t depth, uint32_t interUsec, uint32_t durUsec) { bool_t updated = FALSE; - uint32_t offsetUnitUs = schRmCb.commonInt >> schRmCb.offsetDepth; + uint32_t offsetUnitUs = schRmCb.cmnInter >> schRmCb.offsetDepth; uint32_t tmpRmStatus = schRmCb.rmStatus; uint8_t numBitsPerRes = 1; /* Number of bit offsets to be occupied by the reservation. */ uint8_t x, y, z, numBitsOn; WSF_ASSERT(schRmCb.offsetDepth >= depth); - WSF_ASSERT(durUsec < schRmCb.commonInt); + WSF_ASSERT(durUsec < schRmCb.cmnInter); /* If duration is 12ms while offset unit is 5ms, the reservation will occupy 3 consecutive offset bits. */ while (durUsec >= offsetUnitUs) @@ -346,13 +345,13 @@ static bool_t schRmIntAddRmOffset(uint8_t handle, uint8_t depth, uint32_t interU } schRmCb.rsvn[handle].offsetBit = x; - schRmCb.rsvn[handle].commIntUsed = TRUE; + schRmCb.rsvn[handle].cmdInterUsed = TRUE; updated = TRUE; - LL_TRACE_INFO2("schRmIntAddRmOffset, handle = %u, offsetDepth = %u", handle, schRmCb.offsetDepth); - LL_TRACE_INFO1(" rmStatus = 0x%x", schRmCb.rmStatus); - LL_TRACE_INFO1(" commonInt = %u", schRmCb.commonInt); - LL_TRACE_INFO1(" offsetBit = %u", schRmCb.rsvn[handle].offsetBit); + LL_TRACE_INFO2("schRmIntAddRmOffset, handle=%u, offsetDepth=%u", handle, schRmCb.offsetDepth); + LL_TRACE_INFO1(" rmStatus=0x%x", schRmCb.rmStatus); + LL_TRACE_INFO1(" cmnInter=%u", schRmCb.cmnInter); + LL_TRACE_INFO1(" offsetBit=%u", schRmCb.rsvn[handle].offsetBit); break; } } @@ -374,7 +373,7 @@ static bool_t schRmIntIncOffsetDepth(uint8_t depth) uint8_t y, z, handle; uint8_t numBitsPerRes, rsvnDepth; uint32_t durUsec; - uint32_t offsetUnitUs = schRmCb.commonInt >> (schRmCb.offsetDepth + depth); + uint32_t offsetUnitUs = schRmCb.cmnInter >> (schRmCb.offsetDepth + depth); /* Check if the offsetDepth will be valid after the increase. */ if (offsetUnitUs < SCH_RM_MIN_OFFSET_UNIT_US) @@ -389,19 +388,19 @@ static bool_t schRmIntIncOffsetDepth(uint8_t depth) /* rmStatus b'11 becomes b'00010001, when depth is 2. */ for (handle = 0; handle < SCH_RM_MAX_RSVN; handle++) { - if (schRmCb.rsvn[handle].commIntUsed) + if (schRmCb.rsvn[handle].cmdInterUsed) { numBitsPerRes = 1; /* Number of bit offsets to be occupied by the reservation. */ durUsec = schRmCb.rsvn[handle].durUsec; - WSF_ASSERT(durUsec < schRmCb.commonInt); + WSF_ASSERT(durUsec < schRmCb.cmnInter); - if (schRmCb.commonInt == schRmCb.rsvn[handle].interUsec) + if (schRmCb.cmnInter == schRmCb.rsvn[handle].interUsec) { rsvnDepth = 0; } else { - rsvnDepth = schRmIntCalculateDepth(schRmCb.commonInt, schRmCb.rsvn[handle].interUsec); + rsvnDepth = schRmIntCalculateDepth(schRmCb.cmnInter, schRmCb.rsvn[handle].interUsec); WSF_ASSERT(rsvnDepth > 0); } @@ -476,7 +475,7 @@ static void schRmIntCheckDecOffsetDepth(void) /* Update database according to the new offsetDepth. */ for (handle = 0; handle < SCH_RM_MAX_RSVN; handle++) { - if (schRmCb.rsvn[handle].commIntUsed) + if (schRmCb.rsvn[handle].cmdInterUsed) { schRmCb.rsvn[handle].offsetBit >>= 1; @@ -507,11 +506,11 @@ static void schRmIntRemoveRmOffset(uint8_t handle) uint8_t x, y, depth; uint8_t numBitsPerRes = 1; /* Number of consecutive offset bits occupied by the reservation. */ uint32_t durUsec; - uint32_t offsetUnitUs = schRmCb.commonInt >> schRmCb.offsetDepth; + uint32_t offsetUnitUs = schRmCb.cmnInter >> schRmCb.offsetDepth; - if (schRmCb.rsvn[handle].commIntUsed) + if (schRmCb.rsvn[handle].cmdInterUsed) { - WSF_ASSERT(schRmCb.rsvn[handle].durUsec < schRmCb.commonInt); + WSF_ASSERT(schRmCb.rsvn[handle].durUsec < schRmCb.cmnInter); /* Check how many continuous bit offsets were occupied by this reservation. */ durUsec = schRmCb.rsvn[handle].durUsec; @@ -522,7 +521,7 @@ static void schRmIntRemoveRmOffset(uint8_t handle) } /* The interval of this handle must be equal to or smaller than the common interval. */ - if (schRmCb.commonInt == schRmCb.rsvn[handle].interUsec) + if (schRmCb.cmnInter == schRmCb.rsvn[handle].interUsec) { for (y = 0; y < numBitsPerRes; y++) { @@ -531,7 +530,7 @@ static void schRmIntRemoveRmOffset(uint8_t handle) } else { - depth = schRmIntCalculateDepth(schRmCb.commonInt, schRmCb.rsvn[handle].interUsec); + depth = schRmIntCalculateDepth(schRmCb.cmnInter, schRmCb.rsvn[handle].interUsec); if (depth) { @@ -545,7 +544,7 @@ static void schRmIntRemoveRmOffset(uint8_t handle) } } - schRmCb.rsvn[handle].commIntUsed = FALSE; + schRmCb.rsvn[handle].cmdInterUsed = FALSE; /* Adjust offsetDepth if necessary. */ schRmIntCheckDecOffsetDepth(); @@ -553,13 +552,13 @@ static void schRmIntRemoveRmOffset(uint8_t handle) /* All the reservations are removed. */ if (schRmCb.rmStatus == 0) { - schRmCb.commonInt = 0; + schRmCb.cmnInter = 0; schRmCb.offsetDepth = 0; } - LL_TRACE_INFO2("schRmIntRemoveRmOffset, handle = %u, offsetDepth = %u", handle, schRmCb.offsetDepth); - LL_TRACE_INFO1(" rmStatus = 0x%x", schRmCb.rmStatus); - LL_TRACE_INFO1(" commonInt = %u", schRmCb.commonInt); + LL_TRACE_INFO2("schRmIntRemoveRmOffset, handle=%u, offsetDepth=%u", handle, schRmCb.offsetDepth); + LL_TRACE_INFO1(" rmStatus=0x%x", schRmCb.rmStatus); + LL_TRACE_INFO1(" cmnInter=%u", schRmCb.cmnInter); } else { @@ -567,7 +566,7 @@ static void schRmIntRemoveRmOffset(uint8_t handle) { /* Uncommon handle by reservation manager. */ schRmCb.indexUncommon--; - LL_TRACE_INFO2("schRmIntRemoveRmOffset, deleted uncommon index %u, Handle = %u", schRmCb.indexUncommon, handle); + LL_TRACE_INFO2("schRmIntRemoveRmOffset, deleted uncommon index %u, handle=%u", schRmCb.indexUncommon, handle); } } } @@ -586,7 +585,7 @@ static void schRmIntIncCommInterval(uint8_t depth) WSF_ASSERT(depth > 0); - schRmCb.commonInt = schRmCb.commonInt << depth; + schRmCb.cmnInter = schRmCb.cmnInter << depth; /* Reconstruct rmStatus as to the new common interval. */ schRmCb.rmStatus = 0; @@ -608,7 +607,7 @@ static void schRmIntIncCommInterval(uint8_t depth) /*************************************************************************************************/ /*! - * \brief Handle Adding resource manager offset for the specified handle. + * \brief Handle adding resource manager offset for the specified handle. * * \param handle Client defined reservation handle. * \param newInterUsec Interval of the reservation in microseconds. @@ -624,18 +623,18 @@ static bool_t schRmIntHandleAddRmOffset(uint8_t handle, uint32_t newInterUsec, u /* Let's assume all connections are with common multiples. */ /* Will add function later to determine if 2 intervals are with common intervals. */ - if (schRmCb.commonInt == 0) + if (schRmCb.cmnInter == 0) { - schRmCb.commonInt = newInterUsec; + schRmCb.cmnInter = newInterUsec; schRmCb.indexUncommon = 0; - schRmCb.offsetDepth = 0; /* Offset unit is same as commonInt. */ + schRmCb.offsetDepth = 0; /* Offset unit is same as cmnInter. */ schRmCb.rmStatus = 0x01; /* 100 percent reserved. */ schRmCb.rsvn[handle].offsetBit = 0; - schRmCb.rsvn[handle].commIntUsed = TRUE; + schRmCb.rsvn[handle].cmdInterUsed = TRUE; schRmCb.refHandle = handle; } - else if (schRmCb.commonInt == newInterUsec) + else if (schRmCb.cmnInter == newInterUsec) { while (status == TRUE) { @@ -656,9 +655,9 @@ static bool_t schRmIntHandleAddRmOffset(uint8_t handle, uint32_t newInterUsec, u } } } - else if (schRmCb.commonInt < newInterUsec) /* new interval is multiple of commonInt. */ + else if (schRmCb.cmnInter < newInterUsec) /* new interval is multiple of cmnInter. */ { - uint8_t depth = schRmIntCalculateDepth(newInterUsec, schRmCb.commonInt); + uint8_t depth = schRmIntCalculateDepth(newInterUsec, schRmCb.cmnInter); if (depth) { @@ -687,12 +686,12 @@ static bool_t schRmIntHandleAddRmOffset(uint8_t handle, uint32_t newInterUsec, u { /* Uncommon handle by reservation manager. */ schRmCb.indexUncommon++; - LL_TRACE_INFO2("Adding uncommon index %u, Handle = %u", schRmCb.indexUncommon, handle); + LL_TRACE_INFO2("Adding uncommon index %u, handle=%u", schRmCb.indexUncommon, handle); } } - else if (schRmCb.commonInt > newInterUsec) + else if (schRmCb.cmnInter > newInterUsec) { - uint8_t depth = schRmIntCalculateDepth(schRmCb.commonInt, newInterUsec); + uint8_t depth = schRmIntCalculateDepth(schRmCb.cmnInter, newInterUsec); if (depth) { @@ -725,7 +724,7 @@ static bool_t schRmIntHandleAddRmOffset(uint8_t handle, uint32_t newInterUsec, u { /* Uncommon handle by reservation manager. */ schRmCb.indexUncommon++; - LL_TRACE_INFO2("Adding uncommon index %u, Handle = %u", schRmCb.indexUncommon, handle); + LL_TRACE_INFO2("Adding uncommon index %u, handle=%u", schRmCb.indexUncommon, handle); } } @@ -737,7 +736,7 @@ static bool_t schRmIntHandleAddRmOffset(uint8_t handle, uint32_t newInterUsec, u } else { - LL_TRACE_WARN2("schRmIntHandleAddRmOffset, Add RM failed, Handle = %u, Interval = %u", handle, newInterUsec); + LL_TRACE_WARN2("schRmIntHandleAddRmOffset, Add RM failed, handle=%u, interval=%u", handle, newInterUsec); } return status; @@ -959,11 +958,15 @@ void SchRmRemove(uint8_t handle) uint32_t SchRmGetOffsetUsec(uint32_t defOffsUsec, uint8_t handle, uint32_t refTime) { uint32_t rmRefTime = refTime; - uint32_t offsUsec, targetTime; - uint32_t offsetUnitUs = schRmCb.commonInt >> schRmCb.offsetDepth; + uint32_t targetTime, offsUsec; + uint32_t offsetUnitUs = schRmCb.cmnInter >> schRmCb.offsetDepth; + /* Out of sequence. */ WSF_ASSERT(schRmCb.numRsvn); + /* Ensure no division by 0. */ + WSF_ASSERT(schRmCb.rsvn[handle].interUsec > 0); + if (schRmCb.numRsvn <= 1) { /* We do not have reference anchor point yet for the 1st reservation. */ @@ -977,20 +980,22 @@ uint32_t SchRmGetOffsetUsec(uint32_t defOffsUsec, uint8_t handle, uint32_t refTi rmRefTime = schRmCb.rsvn[schRmCb.refHandle].refTimeCb(schRmCb.refHandle, NULL); } - if ((schRmCb.commonInt != 0) && (schRmCb.rsvn[handle].commIntUsed == TRUE)) + if ((schRmCb.cmnInter != 0) && (schRmCb.rsvn[handle].cmdInterUsed == TRUE)) { + uint32_t rmOffsUsec; + /* Time of Offset bit n = rmRefTime + offsetUnit * n. */ - offsUsec = offsetUnitUs * schRmCb.rsvn[handle].offsetBit; - if (offsUsec == 0) + rmOffsUsec = offsetUnitUs * schRmCb.rsvn[handle].offsetBit; + if (rmOffsUsec == 0) { - offsUsec += schRmCb.rsvn[handle].interUsec; + rmOffsUsec = schRmCb.rsvn[handle].interUsec; } - targetTime = rmRefTime + offsUsec; + targetTime = rmRefTime + rmOffsUsec; + offsUsec = BbGetTargetTimeDelta(targetTime, refTime); - LL_TRACE_INFO2("SchRmGetOffsetUsec, handle = %u, refHandle = %u", handle, schRmCb.refHandle); - LL_TRACE_INFO1(" refTime = %u", refTime); - LL_TRACE_INFO1(" targetTime = %u", targetTime); + LL_TRACE_INFO2("SchRmGetOffsetUsec, handle=%u, refhandle=%u", handle, schRmCb.refHandle); + LL_TRACE_INFO1(" rmOffsUsec=%u", rmOffsUsec); } else { @@ -1009,7 +1014,7 @@ uint32_t SchRmGetOffsetUsec(uint32_t defOffsUsec, uint8_t handle, uint32_t refTi /* Find the duration of BOD of the handle which occupies the offset bit. */ for (unsigned int i = 0; i < SCH_RM_MAX_RSVN; i++) { - if ((schRmCb.rsvn[i].offsetBit == offsetBit) && (schRmCb.rsvn[i].commIntUsed == TRUE)) + if ((schRmCb.rsvn[i].offsetBit == offsetBit) && (schRmCb.rsvn[i].cmdInterUsed == TRUE)) { if (schRmCb.rsvn[i].refTimeCb != NULL) { @@ -1021,24 +1026,31 @@ uint32_t SchRmGetOffsetUsec(uint32_t defOffsUsec, uint8_t handle, uint32_t refTi /* Place the uncommon handle away from each common ones to avoid conflicts. */ targetTime = rmRefTime + (offsetBit * offsetUnitUs) + uncommonOffsetUs; + offsUsec = BbGetTargetTimeDelta(targetTime, refTime); - LL_TRACE_INFO2("SchRmGetOffsetUsec, uncommon handle = %u, refHandle = %u", handle, schRmCb.refHandle); - LL_TRACE_INFO1(" refTime = %u", rmRefTime); - LL_TRACE_INFO1(" targetTime = %u", targetTime); + LL_TRACE_INFO2("SchRmGetOffsetUsec, uncommonHandle=%u, refHandle=%u", handle, schRmCb.refHandle); } - /* Time to return has to be future from refTime. */ - while (BbGetTargetTimeDelta(targetTime, refTime) == 0) + /* Ensure "targetTime > refTime". */ + if (offsUsec == 0) { - targetTime += schRmCb.rsvn[handle].interUsec; + unsigned int numInter = 1; + + if (schRmCb.rsvn[handle].interUsec) /* Protect against division by 0. */ + { + numInter = (BbGetTargetTimeDelta(refTime, targetTime) / schRmCb.rsvn[handle].interUsec) + 1; + } + + targetTime += numInter * schRmCb.rsvn[handle].interUsec; + offsUsec = BbGetTargetTimeDelta(targetTime, refTime); } - /* 0 < targetTime <= interval */ - while (BbGetTargetTimeDelta(targetTime, refTime) > schRmCb.rsvn[handle].interUsec) + if (schRmCb.rsvn[handle].interUsec) /* Protect against division by 0. */ { - targetTime -= schRmCb.rsvn[handle].interUsec; + /* Ensure "offset <= interval". */ + offsUsec %= schRmCb.rsvn[handle].interUsec; } - LL_TRACE_INFO1(" offsUsec = %u", (targetTime - refTime)); - return BbGetTargetTimeDelta(targetTime, refTime); + LL_TRACE_INFO1(" targetTime=%u", (refTime + offsUsec)); + return offsUsec; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/bb/bb_main.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/bb/bb_main.c index 9c90edbab8..effb043f93 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/bb/bb_main.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/bb/bb_main.c @@ -6,7 +6,7 @@ * * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -202,7 +202,7 @@ void BbExecuteBod(BbOpDesc_t *pBod) WSF_ASSERT(pBod->protId < BB_PROT_NUM); /* TODO: Removed this assert as it spuriously seems to be taken. */ - /* WSF_ASSERT(!bbCb.pOpInProgress); */ + /* WSF_ASSERT(bbCb.pOpInProgress == NULL); */ bbCb.pOpInProgress = pBod; bbCb.termBod = FALSE; @@ -228,11 +228,6 @@ void BbExecuteBod(BbOpDesc_t *pBod) { bbCb.prot[pBod->protId].execOpCback(pBod); } - - if (bbCb.termBod) - { - bbCb.pOpInProgress = NULL; - } } /*************************************************************************************************/ @@ -247,12 +242,12 @@ void BbCancelBod(void) BbOpDesc_t * const pBod = bbCb.pOpInProgress; WSF_ASSERT(pBod->protId < BB_PROT_NUM); + + bbCb.pOpInProgress = NULL; if (bbCb.prot[pBod->protId].cancelOpCback != NULL) { bbCb.prot[pBod->protId].cancelOpCback(pBod); } - - bbCb.pOpInProgress = NULL; } } @@ -402,7 +397,7 @@ uint32_t BbAdjustTime(uint32_t dueUsec) /*************************************************************************************************/ /*! - * \brief Get Delta between target and reference time. Only valid if target time is in the future. + * \brief Get delta between target and reference time. Only valid if target time is in the future. * * \param targetUsec Target time in microseconds. * \param refUsec Reference time in microseconds. diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/chci/chci_tr.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/chci/chci_tr.c index 27152d6f84..4eee74deb3 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/chci/chci_tr.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/chci/chci_tr.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -98,7 +98,6 @@ typedef struct uint16_t wrBufOffs; /*!< Write data buffer offset. */ uint16_t wrBufLen; /*!< Write data buffer length. */ uint8_t *pWrBuf; /*!< Write data buffer. */ - bool_t wrBufComp; /*!< Write buffer completed. */ } chciTrCtrlBlk_t; /*! \brief Send handler. */ @@ -376,8 +375,7 @@ static void chciTxComplete(void) } else { - /* Completion handled in task context, i.e. ChciTrService(). */ - chciTrCb.wrBufComp = TRUE; + chciTrSendComplete(); } } @@ -426,7 +424,6 @@ static void chciTrWrite(uint8_t prot, uint8_t type, uint16_t len, uint8_t *pData /* Initiate Tx operation. */ PalUartWriteData(PAL_UART_ID_CHCI, chciTrCb.pWrBuf, chciTrCb.wrBufOffs); - PalSysSetBusy(); #endif #if (CHCI_TR_CUSTOM == 1) @@ -628,25 +625,3 @@ void chciTrRecv(uint8_t prot, uint8_t type, uint8_t *pBuf) /* Free buffer that cannot be handled. */ WsfMsgFree(pBuf); } - -/*************************************************************************************************/ -/*! - * \brief Service the transport device. - * - * \return TRUE if work pending, FALSE if no work is pending. - */ -/*************************************************************************************************/ -bool_t ChciTrService(void) -{ -#if (CHCI_TR_UART == 1) - if (chciTrCb.wrBufComp) - { - chciTrCb.wrBufComp = FALSE; - chciTrSendComplete(); - PalSysSetIdle(); - return TRUE; - } -#endif - - return FALSE; -} diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_int.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_int.h index b687c8d0f0..8d4561345c 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_int.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_int.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 ARM Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,8 +40,11 @@ extern "C" { /*! \brief Maximum span of scheduler elements. Half of the boundary time. */ #define SCH_MAX_SPAN ((BbGetBbTimerBoundaryUs() >> 1) + 1) -/*! \brief Typical time needed for loading BOD. */ -#define SCH_LOAD_DELAY_US 300 +/*! \brief Delay in microseconds to start timer. */ +#define SCH_TIMER_DELAY_US 10 + +/*! \brief Event queue size, must be multiple of ^2. */ +#define SCH_EVT_Q_SIZE 4 /************************************************************************************************** Constants @@ -50,8 +53,10 @@ extern "C" { /*! \brief Scheduler states. */ typedef enum { - SCH_STATE_IDLE, /*!< Scheduler idle. */ - SCH_STATE_EXEC /*!< Scheduler executing BOD. */ + SCH_STATE_IDLE, /*!< Scheduler idle state. */ + SCH_STATE_LOAD, /*!< Scheduler load delay state. */ + SCH_STATE_EXECUTE, /*!< Scheduler execute in progress state. */ + SCH_STATE_UNLOAD /*!< Scheduler unload state (BOD completion). */ } schState_t; /************************************************************************************************** @@ -61,17 +66,21 @@ typedef enum /*! \brief Scheduler control block. */ typedef struct { - schState_t state:8; /*!< Current scheduler state. */ - uint8_t eventSetFlagCount; /*!< Scheduler event set count. */ - wsfHandlerId_t handlerId; /*!< System event handler ID. */ + schState_t state:8; /*!< Current scheduler state. */ + wsfHandlerId_t handlerId; /*!< System event handler ID. */ - BbOpDesc_t *pHead; /*!< Head element of scheduled list of BOD. */ - BbOpDesc_t *pTail; /*!< Tail element of scheduled list of BOD. */ + struct + { + size_t prodIdx; /*!< Producer index, must be atomic size. */ + size_t consIdx; /*!< Consumer index, must be atomic size. */ + uint8_t events[SCH_EVT_Q_SIZE]; + /*!< Circular queue of events. */ + } eventQ; /*!< Lock-free event queue. */ + + BbOpDesc_t *pHead; /*!< Head element of scheduled list of BOD. */ + BbOpDesc_t *pTail; /*!< Tail element of scheduled list of BOD. */ uint16_t schHandlerWatermarkUsec; /*!< Statistics: Handler duration watermark in microseconds. */ - uint16_t delayLoadWatermarkCount; /*!< Statistics: Delay loading watermark count. */ - uint16_t delayLoadCount; /*!< Statistics: Delay loading count. */ - uint32_t delayLoadTotalCount; /*!< Statistics: Delay loading total count. */ } SchCtrlBlk_t; /************************************************************************************************** @@ -84,11 +93,8 @@ extern SchCtrlBlk_t schCb; Function Declarations **************************************************************************************************/ -/* Load */ -bool_t schTryCurTailLoadNext(void); -bool_t schTryLoadHead(void); - -/* List management */ +void schSetBodStartEvent(void); +void schSetBodAbortEvent(void); void schRemoveHead(void); /*************************************************************************************************/ @@ -107,36 +113,6 @@ static inline bool_t schDueTimeInFuture(BbOpDesc_t *pBod) return (BbGetTargetTimeDelta(pBod->dueUsec, curTime) > 0); } - -/*************************************************************************************************/ -/*! - * \brief Return the time between now and the BOD to be executed. - * - * \param pBod Target BOD. - * - * \return usec. - */ -/*************************************************************************************************/ -static inline uint32_t schGetTimeToExecBod(BbOpDesc_t *pBod) -{ - uint32_t result = 0; - - const uint32_t curTime = PalBbGetCurrentTime(); - - result = BbGetTargetTimeDelta(pBod->dueUsec, curTime); - - if (result >= SCH_LOAD_DELAY_US) - { - result -= SCH_LOAD_DELAY_US; - } - else - { - result = 0; - } - - return result; -} - #ifdef __cplusplus }; #endif diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_list.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_list.c index 0b53e3741a..d886e740cf 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_list.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_list.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,15 +48,9 @@ /*! \brief Is BOD[a] due time after BOD[b] completion time. */ #define SCH_IS_DUE_AFTER(a, b) (BbGetTargetTimeDelta(SCH_END_TIME(b), ((a)->dueUsec)) == 0) -/*! \brief Minimum time in microseconds to start scheduler timer. */ -#define SCH_MIN_TIMER_USEC 200 - -/*! \brief Margin in microseconds to cancel a BOD. */ -#define SCH_CANCEL_MARGIN_USEC 15 - #ifndef SCH_TRACE_ENABLE /*! \brief Enable scheduler trace. */ -#define SCH_TRACE_ENABLE FALSE +#define SCH_TRACE_ENABLE FALSE #endif #if SCH_TRACE_ENABLE @@ -74,11 +68,10 @@ /*! \brief Warning trace with 1 parameters. */ #define SCH_TRACE_WARN1(msg, var1) #endif -/*! \brief Maximum allowed number of deleted BOD due to conflicts. */ -#define SCH_MAX_DELETE_BOD 8 + #ifndef SCH_CHECK_LIST_INTEGRITY /*! \brief Check list requirements upon insertions and removals. */ -#define SCH_CHECK_LIST_INTEGRITY FALSE +#define SCH_CHECK_LIST_INTEGRITY FALSE #endif #if (SCH_CHECK_LIST_INTEGRITY) @@ -127,30 +120,6 @@ static inline bool_t SchCheckIsInserted(BbOpDesc_t *pBod) return FALSE; } -/*************************************************************************************************/ -/*! - * \brief Is BOD due within next BOD if not already started. - * - * \param pBod Target BOD. - * - * \return TRUE if BOD is cancelable, FALSE otherwise. - */ -/*************************************************************************************************/ -static inline bool_t SchEnoughTimeToCancel(BbOpDesc_t *pBod) -{ - bool_t result = FALSE; - - const uint32_t curTime = PalBbGetCurrentTime(); - const uint32_t delta = BbGetTargetTimeDelta(pBod->dueUsec, curTime); - - if (delta >= BbGetSchSetupDelayUs()) - { - result = TRUE; - } - - return result; -} - /*************************************************************************************************/ /*! * \brief Check and return the status of whether it is ok to cancel the head BOD. @@ -160,26 +129,7 @@ static inline bool_t SchEnoughTimeToCancel(BbOpDesc_t *pBod) /*************************************************************************************************/ static inline bool_t schCheckCancelHead(void) { - bool_t result = FALSE; -#if SCH_TIMER_REQUIRED == TRUE - if (schCb.state == SCH_STATE_IDLE) - { - result = SchEnoughTimeToCancel(schCb.pHead); - } - else - { - /* If head BOD is executing, it can't be canceled. */ - result = FALSE; - } -#else - /* For platforms without sch timer, cancel the head. */ - if ((result = SchEnoughTimeToCancel(schCb.pHead)) == TRUE) - { - BbCancelBod(); - schCb.state = SCH_STATE_IDLE; - } -#endif - return result; + return (schCb.state != SCH_STATE_EXECUTE); } /*************************************************************************************************/ @@ -329,88 +279,6 @@ static void schRemoveMiddle(BbOpDesc_t *pBod) } } -/*************************************************************************************************/ -/*! - * \brief Remove item from list for conflict. - * - * \param pBod Element to remove. - * - * \return Return TRUE if removed successfully, FALSE if item not in the list or could not be - * removed. - * - * Remove item from list. - */ -/*************************************************************************************************/ -static bool_t schRemoveForConflict(BbOpDesc_t *pBod) -{ - if (schCb.pHead == NULL) - { - return FALSE; - } - - bool_t result = FALSE; - -#if SCH_TIMER_REQUIRED == FALSE - if (schCb.pHead == pBod) - { - if ((result = SchEnoughTimeToCancel(pBod)) == TRUE) - { - /* Stop timer for canceled BOD. */ - PalTimerStop(); - - schRemoveHead(); - - if (schCb.pHead) - { - PalTimerStart(schGetTimeToExecBod(schCb.pHead)); - } - schCb.state = SCH_STATE_IDLE; - result = TRUE; - } - } -#else - if (schCb.pHead == pBod) - { - if (schCb.state == SCH_STATE_IDLE && (result = SchEnoughTimeToCancel(pBod)) == TRUE) - { - /* Stop timer for canceled BOD. */ - PalTimerStop(); - - schRemoveHead(); - - if (schCb.pHead) - { - PalTimerStart(schGetTimeToExecBod(schCb.pHead)); - } - result = TRUE; - } - } - else if (schCb.pHead->pNext == pBod && schCb.state == SCH_STATE_EXEC) - { - if ((result = SchEnoughTimeToCancel(pBod)) == TRUE) - { - /* Stop timer for next BOD. */ - PalTimerStop(); - - schRemoveMiddle(pBod); - - if (schCb.pHead->pNext) - { - PalTimerStart(schGetTimeToExecBod(schCb.pHead->pNext)); - } - result = TRUE; - } - } -#endif - else - { - schRemoveMiddle(pBod); - result = TRUE; - } - - return result; -} - /*************************************************************************************************/ /*! * \brief Check whether the conflict between BODs is resolvable. @@ -422,7 +290,7 @@ static bool_t schRemoveForConflict(BbOpDesc_t *pBod) * \return TRUE if conflict is resolvable, FALSE otherwise. */ /*************************************************************************************************/ -static bool_t SchIsBodResolvable(BbOpDesc_t *pItem, BbOpDesc_t *pTgt, BbConflictAct_t conflictCback) +static bool_t SchIsBodConflictResolvable(BbOpDesc_t *pItem, BbOpDesc_t *pTgt, BbConflictAct_t conflictCback) { bool_t result = FALSE; @@ -454,6 +322,10 @@ static bool_t SchIsBodResolvable(BbOpDesc_t *pItem, BbOpDesc_t *pTgt, BbConflict * \param pItem Item to insert. * \param pTgt Target position. * + * \note Atypical modification to the head element occurs for conflict only. This routine + * will attempt to remove and modify the head element in order for the a new BOD + * to be inserted correctly in time order. + * * \note Resolve the conflict between the pItem and pTgt. It is possible that * there is a conflict between the pItem and BODs after pTgt. But these conflict * resolutions will be delayed until the BODs are executed. @@ -461,77 +333,85 @@ static bool_t SchIsBodResolvable(BbOpDesc_t *pItem, BbOpDesc_t *pTgt, BbConflict * \return TRUE if \a pItem is inserted, FALSE for no change. */ /*************************************************************************************************/ -static bool_t SchResolveConflict(BbOpDesc_t *pItem, BbOpDesc_t *pTgt) +static bool_t schResolveConflict(BbOpDesc_t *pItem, BbOpDesc_t *pTgt) { - bool_t result = FALSE; - BbOpDesc_t *pCur = pTgt; - int numDeletedBod = 0; - BbOpDesc_t *pDeleted[SCH_MAX_DELETE_BOD]; - WSF_ASSERT(pTgt); WSF_ASSERT(pItem); - while (TRUE) + /* List of aborted BODs. */ + BbOpDesc_t *pRemHead = pTgt; + BbOpDesc_t *pRemTail = pTgt; + + if (pTgt == schCb.pHead) { - if (numDeletedBod == SCH_MAX_DELETE_BOD) + while (schCb.pHead) { - result = FALSE; - break; - } - - pDeleted[numDeletedBod++] = pCur; - - if ((pCur->pNext == NULL) || /* pCur is the tail. */ - (SCH_IS_DONE_BEFORE(pItem, pCur->pNext))) /* Only conflict with pCur. */ - { - /* Remove only 1 conflicting BOD. */ - result = schRemoveForConflict(pCur); - break; - } - else - { - /* Remove all conflicting BODs until it fails. */ - if ((result = schRemoveForConflict(pCur)) == FALSE) + if (SCH_IS_DONE_BEFORE(pItem, schCb.pHead)) { + /* No more conflicts. */ break; } + + pRemTail = schCb.pHead; + schRemoveHead(); + + /* Return to IDLE since old BOD at head was removed. */ + schCb.state = SCH_STATE_IDLE; } - /* Traverse to the next BOD. */ - pCur = pCur->pNext; - } - - if (result == TRUE) - { - if (pCur->pNext) + /* Insert new BOD. */ + if (schCb.pHead) { - schInsertBefore(pItem, pCur->pNext); - } - else if (pTgt->pPrev) - { - schInsertAfter(pItem, pTgt->pPrev); + schInsertBefore(pItem, schCb.pHead); } else { - /* Insert at head. */ schInsertToEmptyList(pItem); } - - /* Call abort callback for all removed BODs. */ - for (int i = 0; i < numDeletedBod; i++) - { - if (pDeleted[i]->abortCback) - { - pDeleted[i]->abortCback(pDeleted[i]); - } - } } else { - LL_TRACE_WARN0("!!! Could not remove existing BOD"); + /* Linkage may change with every loop; use BOD prior to target as start reference. */ + BbOpDesc_t *pStart = pTgt->pPrev; + + while (pStart->pNext) + { + if (SCH_IS_DONE_BEFORE(pItem, pStart->pNext)) + { + /* No more conflicts. */ + break; + } + + pRemTail = pStart->pNext; + schRemoveMiddle(pStart->pNext); + } + + /* Insert new BOD. */ + schInsertAfter(pItem, pStart); } - return result; + /* Now that the new BOD is inserted, the removed BODs may be aborted. Insertion of the + * higher priority BOD must occur first such that the abort() callbacks can manipulate + * the BOD list appropriately. */ + while (TRUE) + { + /* Store next BOD since aborting may adjust linkage. */ + BbOpDesc_t *pCur = pRemHead; + pRemHead = pRemHead->pNext; + + if (pCur->abortCback) + { + pCur->abortCback(pCur); + } + + if (pCur == pRemTail) + { + /* End of removal list. */ + break; + } + } + + return TRUE; } /*************************************************************************************************/ @@ -561,13 +441,13 @@ static bool_t SchIsConflictResolvable(BbOpDesc_t *pItem, BbOpDesc_t *pTgt, BbCon (SCH_IS_DONE_BEFORE(pItem, pCur->pNext))) /* Only conflict with pCur. */ { /* Only 1 conflicting BOD. */ - result = SchIsBodResolvable(pItem, pCur, conflictCback); + result = SchIsBodConflictResolvable(pItem, pCur, conflictCback); break; } else { /* Check all conflicting BODs. */ - if ((result = SchIsBodResolvable(pItem, pCur, conflictCback)) == FALSE) + if ((result = SchIsBodConflictResolvable(pItem, pCur, conflictCback)) == FALSE) { break; } @@ -579,65 +459,6 @@ static bool_t SchIsConflictResolvable(BbOpDesc_t *pItem, BbOpDesc_t *pTgt, BbCon return result; } -/*************************************************************************************************/ -/*! - * \brief Try to load or add scheduler timer for inserted item if possible. - * - * \param pBod Inserted BOD. - */ -/*************************************************************************************************/ -static inline void SchInsertTryLoadBod(BbOpDesc_t *pBod) -{ - uint32_t execTimeUsec = schGetTimeToExecBod(pBod); - - WSF_ASSERT(pBod); - WSF_ASSERT(schCb.pHead); - - /* If inserted BOD is head. */ - if (pBod == schCb.pHead) - { - /* At this moment, head BOD should not be loaded. */ - WSF_ASSERT(schCb.state == SCH_STATE_IDLE); - if (execTimeUsec >= SCH_MIN_TIMER_USEC) - { - /* If HEAD BOD due time is not close, add scheduler timer to load it in the future. - * Always stop existing timer first for simplicity. - */ - PalTimerStop(); - PalTimerStart(execTimeUsec); - } - else - { - /* Send scheduler load event. */ - SchLoadHandler(); - } - } -#if SCH_TIMER_REQUIRED == TRUE - /* If head is executing and inserted BOD is the second one in the list, - * we might need to add scheduler timer or do curtail load. - */ - else if (pBod == schCb.pHead->pNext && schCb.state == SCH_STATE_EXEC) - { - /* At this moment, head BOD should be in the past. */ - WSF_ASSERT(schGetTimeToExecBod(schCb.pHead) < SCH_MIN_TIMER_USEC); - - if (execTimeUsec >= SCH_MIN_TIMER_USEC) - { - /* If BOD due time is not close, add scheduler timer to load it in the future. - * Always stop existing timer first for simplicity. - */ - PalTimerStop(); - PalTimerStart(execTimeUsec); - } - else - { - /* Send scheduler load event. */ - SchLoadHandler(); - } - } -#endif -} - /*************************************************************************************************/ /*! * \brief Insert item into BOD list at the next available opportunity. @@ -674,8 +495,13 @@ void SchInsertNextAvailable(BbOpDesc_t *pBod) { WSF_ASSERT(pBod != pCur); - /* Only update due time when pCur ends in the future. */ - if (!SCH_IS_DONE_BEFORE(pCur, pBod)) + if ((pCur == schCb.pHead) && + (pCur->maxDurUsec > 0)) + { + /* Allow current head BOD to complete naturally. */ + pBod->dueUsec = pCur->dueUsec + pCur->maxDurUsec + BbGetSchSetupDelayUs(); + } + else { pBod->dueUsec = SCH_END_TIME(pCur); } @@ -691,7 +517,11 @@ void SchInsertNextAvailable(BbOpDesc_t *pBod) } } - SchInsertTryLoadBod(pBod); + if (pBod == schCb.pHead) + { + /* Restart the scheduler since the head element is modified. */ + schSetBodStartEvent(); + } } /*************************************************************************************************/ @@ -733,24 +563,31 @@ bool_t SchInsertAtDueTime(BbOpDesc_t *pBod, BbConflictAct_t conflictCback) while (TRUE) { - WSF_ASSERT(pBod != pCur); - if (SCH_IS_DONE_BEFORE(pBod, pCur)) /* BOD is due and done before pCur(no overlap), try to insert before. */ + if (SCH_IS_DONE_BEFORE(pBod, pCur)) /* pBod is due and done before pCur with no overlap. */ { - if (pCur == schCb.pHead) + if ((pCur == schCb.pHead) && + (!schCheckCancelHead())) { - (void) schCheckCancelHead(); + /* Cannot modify head. */ + break; } - /* Insert before head case. */ + schInsertBefore(pBod, pCur); result = TRUE; break; } - else if (!SCH_IS_DONE_BEFORE(pCur, pBod)) /* pCur has overlap with pBod, check priority and resolve BOD. */ + else if (!SCH_IS_DONE_BEFORE(pCur, pBod)) /* pCur has overlap with pBod, check priority and resolve conflict. */ { + if ((pCur == schCb.pHead) && + (!schCheckCancelHead())) + { + /* Cannot modify head. */ + break; + } + if ((result = SchIsConflictResolvable(pBod, pCur, conflictCback)) == TRUE) { - /* Resolve conflict here otherwise delay conflict resolution when BOD is executed. */ - result = SchResolveConflict(pBod, pCur); + result = schResolveConflict(pBod, pCur); } break; } @@ -766,9 +603,14 @@ bool_t SchInsertAtDueTime(BbOpDesc_t *pBod, BbConflictAct_t conflictCback) } } - if (result) + if (result && + (pBod == schCb.pHead)) { - SchInsertTryLoadBod(pBod); + /* Halt execution of previous head BOD. */ + PalTimerStop(); + + /* Restart the scheduler since the head element is modified. */ + schSetBodStartEvent(); } return result; @@ -798,14 +640,14 @@ bool_t SchInsertEarlyAsPossible(BbOpDesc_t *pBod, uint32_t min, uint32_t max) bool_t result = FALSE; - const uint32_t dueOrigin = pBod->dueUsec; + uint32_t dueOrigin = pBod->dueUsec; /* Try inserting at minimum interval. */ pBod->dueUsec += min; if (!schDueTimeInFuture(pBod)) { - if (max != SCH_MAX_SPAN) + if (max < SCH_MAX_SPAN) { /* Reset due time origin. */ pBod->dueUsec = dueOrigin; @@ -813,8 +655,9 @@ bool_t SchInsertEarlyAsPossible(BbOpDesc_t *pBod, uint32_t min, uint32_t max) } else { - /* With SCH_MAX_SPAN, this function will insert the BOD regardless of the current due. */ + /* When max=SCH_MAX_SPAN, this function will insert the BOD regardless of the current due. */ pBod->dueUsec = PalBbGetCurrentTime() + BbGetSchSetupDelayUs(); + dueOrigin = pBod->dueUsec; } } @@ -877,9 +720,11 @@ bool_t SchInsertEarlyAsPossible(BbOpDesc_t *pBod, uint32_t min, uint32_t max) } } - if (result) + if (result && + (pBod == schCb.pHead)) { - SchInsertTryLoadBod(pBod); + /* Restart the scheduler since the head element is modified. */ + schSetBodStartEvent(); } if (!result) @@ -991,9 +836,11 @@ bool_t SchInsertLateAsPossible(BbOpDesc_t *pBod, uint32_t min, uint32_t max) } } - if (result) + if (result && + (pBod == schCb.pHead)) { - SchInsertTryLoadBod(pBod); + /* Restart the scheduler since the head element is modified. */ + schSetBodStartEvent(); } if (!result) @@ -1007,108 +854,58 @@ bool_t SchInsertLateAsPossible(BbOpDesc_t *pBod, uint32_t min, uint32_t max) /*************************************************************************************************/ /*! - * \brief Remove BOD from list. + * \brief Request BOD removal from list. * * \param pBod Element to remove. * - * \return Return TRUE if removed successfully, FALSE if item not in the list or there is not enough time to cancel. - * - * Remove item from list. + * Request BOD removal from list. Request will require BOD list manipulation in the SchHandler() . */ /*************************************************************************************************/ -bool_t SchRemove(BbOpDesc_t *pBod) +void SchRemove(BbOpDesc_t *pBod) { WSF_ASSERT(pBod); if (!SchCheckIsInserted(pBod)) { - LL_TRACE_WARN0("No such BOD to remove"); - return FALSE; + LL_TRACE_WARN1("Remove failed, BOD not found, pBod=0x%08x", pBod); + return; } - bool_t result = FALSE; - -#if SCH_TIMER_REQUIRED == FALSE if (schCb.pHead == pBod) { - if ((result = SchEnoughTimeToCancel(pBod)) == TRUE) - { - /* Stop timer for canceled BOD. */ - PalTimerStop(); - - /* Call callback after removing from list. */ - schRemoveHead(); - - if (schCb.pHead) - { - PalTimerStart(schGetTimeToExecBod(schCb.pHead)); - } - - schCb.state = SCH_STATE_IDLE; - result = TRUE; - } - else + switch (schCb.state) { + case SCH_STATE_EXECUTE: + /* Gracefully complete BOD before removal. */ BbSetBodTerminateFlag(); - } - } -#else - if (schCb.pHead == pBod) - { - if (schCb.state == SCH_STATE_IDLE && (result = SchEnoughTimeToCancel(pBod)) == TRUE) - { - /* Stop timer for canceled BOD. */ - PalTimerStop(); + break; - /* Call callback after removing from list. */ + case SCH_STATE_LOAD: + schSetBodAbortEvent(); + break; + + default: schRemoveHead(); - - if (schCb.pHead) + if (pBod->abortCback) { - PalTimerStart(schGetTimeToExecBod(schCb.pHead)); + pBod->abortCback(pBod); } - result = TRUE; - } - else - { - BbSetBodTerminateFlag(); + break; } } - else if (schCb.pHead->pNext == pBod && schCb.state == SCH_STATE_EXEC) - { - if ((result = SchEnoughTimeToCancel(pBod)) == TRUE) - { - /* Stop timer for next BOD. */ - PalTimerStop(); - - schRemoveMiddle(pBod); - - if (schCb.pHead->pNext) - { - PalTimerStart(schGetTimeToExecBod(schCb.pHead->pNext)); - } - result = TRUE; - } - } -#endif + /* TODO Consider resetting the curtail timer. */ else { /* Call callback after removing from list. */ schRemoveMiddle(pBod); - result = TRUE; - } - - if (result) - { if (pBod->abortCback) { pBod->abortCback(pBod); } - SCH_TRACE_INFO1("--| SchRemove |-- pBod=0x%08x", (uint32_t)pBod); - SCH_TRACE_INFO1("--| |-- .dueUsec=%u", pBod->dueUsec); } - return result; + SCH_TRACE_INFO1("--| SchRemove |-- pBod=0x%08x", (uint32_t)pBod); + SCH_TRACE_INFO1("--| |-- .dueUsec=%u", pBod->dueUsec); } /*************************************************************************************************/ @@ -1125,9 +922,8 @@ void SchReload(BbOpDesc_t *pBod) if ((schCb.pHead == pBod) && schCheckCancelHead()) { - PalTimerStop(); - - SchInsertTryLoadBod(pBod); + /* Restart the scheduler since the head element is modified. */ + schSetBodStartEvent(); } } @@ -1138,22 +934,15 @@ void SchReload(BbOpDesc_t *pBod) * \param pBod Element to be cancelled * * \return TRUE if BOD can be cancelled, FALSE otherwise. - * - * Check if BOD can be cancelled. */ /*************************************************************************************************/ bool_t SchIsBodCancellable(BbOpDesc_t *pBod) { - WSF_ASSERT(pBod); - - bool_t result = FALSE; - const uint32_t curTime = PalBbGetCurrentTime(); - const uint32_t delta = BbGetTargetTimeDelta(pBod->dueUsec, curTime); - - if (delta >= (uint32_t)(BbGetSchSetupDelayUs() + SCH_CANCEL_MARGIN_USEC)) + if ((schCb.pHead != pBod) || + schCheckCancelHead()) { - result = TRUE; + return TRUE; } - return result; + return FALSE; } diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_main.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_main.c index a29178a957..07e3d320dc 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_main.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_main.c @@ -32,15 +32,38 @@ Constants **************************************************************************************************/ +#ifndef SCH_ENABLE_CURTAIL +/*! \brief Enable curtail feature. */ +#define SCH_ENABLE_CURTAIL FALSE +#endif + +#ifndef SCH_ENABLE_DEBUG +/*! \brief Enable scheduler debug statements. */ +#define SCH_ENABLE_DEBUG FALSE +#endif + /*! \brief Scheduler task events. */ enum { - SCH_EVENT_BOD_COMPLETE = (1 << 0), /*!< BOD completion event. */ - SCH_EVENT_BOD_ABORT = (1 << 1), /*!< BOD abort event. */ - SCH_EVENT_BOD_CURTAIL = (1 << 2), /*!< BOD curtail event. */ - SCH_EVENT_BOD_LOAD = (1 << 3), /*!< BOD load event. */ + SCH_EVENT_BOD_EXECUTE, /*!< BOD execute event. */ + SCH_EVENT_BOD_COMPLETE, /*!< BOD completion event. */ + SCH_EVENT_BOD_ABORT, /*!< BOD abort event. */ + SCH_EVENT_BOD_RELOAD /*!< BOD reload event. */ }; +#if SCH_ENABLE_DEBUG +#define SCH_DBG_TRACE_INFO0(m) LL_TRACE_INFO0(m) +#define SCH_DBG_TRACE_INFO1(m, v1) LL_TRACE_INFO1(m, v1) +#include "sch_debug.h" +#define SCH_DBG_TRACE_EVENT(e) schTraceEventTriggered(PalBbGetCurrentTime(), schCb.state, e) +#define SCH_DBG_TRACE_STATE(t, e) schTraceStateEvent(t, schCb.state, e) +#else +#define SCH_DBG_TRACE_INFO0(m) +#define SCH_DBG_TRACE_INFO1(m, v1) +#define SCH_DBG_TRACE_EVENT(e) +#define SCH_DBG_TRACE_STATE(t, e) +#endif + /************************************************************************************************** Global Variables **************************************************************************************************/ @@ -48,123 +71,208 @@ enum /*! \brief Scheduler control block. */ SchCtrlBlk_t schCb; +/************************************************************************************************** + Functions +**************************************************************************************************/ + /*************************************************************************************************/ /*! - * \brief BOD completion handler. + * \brief Push an event to the event queue. + * + * \param event Event ID. */ /*************************************************************************************************/ -static void schBodCompHandler(void) +static inline void schEventEnqueue(uint8_t event) { - WsfSetEvent(schCb.handlerId, SCH_EVENT_BOD_COMPLETE); - schCb.eventSetFlagCount++; + /* Use volatile to create memory barrier. */ + volatile uint32_t prodIdx = (schCb.eventQ.prodIdx + 1) & (SCH_EVT_Q_SIZE - 1); + + /* Queue must never be full. */ + WSF_ASSERT(prodIdx != schCb.eventQ.consIdx); + + schCb.eventQ.events[schCb.eventQ.prodIdx] = event; + schCb.eventQ.prodIdx = prodIdx; + + /* Signal the SM to run. */ + WsfSetEvent(schCb.handlerId, /* not used */ 1); } /*************************************************************************************************/ /*! - * \brief BOD abortion handler. + * \brief Dequeue an event from the event queue. + * + * \param pEvent Event ID return value. */ /*************************************************************************************************/ -static void schBodAbortHandler(void) +static inline bool_t schEventDequeue(uint8_t *pEvent) { - WsfSetEvent(schCb.handlerId, SCH_EVENT_BOD_ABORT); - schCb.eventSetFlagCount++; -} - -/*************************************************************************************************/ -/*! - * \brief BOD curtail handler. - */ -/*************************************************************************************************/ -static void schBodCurtailHandler(void) -{ - WsfSetEvent(schCb.handlerId, SCH_EVENT_BOD_CURTAIL); - schCb.eventSetFlagCount++; -} - -/*************************************************************************************************/ -/*! - * \brief BOD load handler. - */ -/*************************************************************************************************/ -static void schBodLoadHandler(void) -{ - BbOpDesc_t* pNextBod = schCb.pHead; - - if (schCb.eventSetFlagCount) + if (schCb.eventQ.consIdx == schCb.eventQ.prodIdx) { - WSF_ASSERT(pNextBod); - /* Delay loading after event flag is cleared. */ - WsfSetEvent(schCb.handlerId, SCH_EVENT_BOD_LOAD); - schCb.delayLoadCount++; - schCb.delayLoadTotalCount++; - if (schCb.delayLoadCount > schCb.delayLoadWatermarkCount) - { - schCb.delayLoadWatermarkCount = schCb.delayLoadCount; - } + /* Queue empty. */ + return FALSE; + } + /* Use volatile to create memory barrier. */ + volatile uint32_t consIdx = (schCb.eventQ.consIdx + 1) & (SCH_EVT_Q_SIZE - 1); + + *pEvent = schCb.eventQ.events[schCb.eventQ.consIdx]; + schCb.eventQ.consIdx = consIdx; + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Start the BOD operation loop. + */ +/*************************************************************************************************/ +void schSetBodStartEvent(void) +{ + switch (schCb.state) + { + case SCH_STATE_LOAD: + PalTimerStop(); + /* Fallthrough */ + case SCH_STATE_IDLE: + SCH_DBG_TRACE_EVENT(SCH_EVENT_BOD_RELOAD); + + schEventEnqueue(SCH_EVENT_BOD_RELOAD); + break; + + case SCH_STATE_UNLOAD: + /* No action required; next head element loaded by SchHandler(). */ return; - } - /* Try load head if scheduler is idle. */ - if (schCb.state == SCH_STATE_IDLE) + default: + LL_TRACE_WARN1("Unexpected scheduler state for event=SCH_EVENT_BOD_RELOAD, pBod=0x%08x", schCb.pHead); + break; + } +} + +/*************************************************************************************************/ +/*! + * \brief Set the BOD abort event. + */ +/*************************************************************************************************/ +void schSetBodAbortEvent(void) +{ + switch (schCb.state) { - if (!schTryLoadHead()) - { - /* Head load failed. */ - schBodAbortHandler(); - } - /* Move to next BOD. */ - pNextBod = pNextBod->pNext; + case SCH_STATE_LOAD: + case SCH_STATE_EXECUTE: + SCH_DBG_TRACE_EVENT(SCH_EVENT_BOD_ABORT); + + PalTimerStop(); + schEventEnqueue(SCH_EVENT_BOD_ABORT); + break; + + default: + LL_TRACE_WARN1("Unexpected scheduler state for event=SCH_EVENT_BOD_ABORT, pBod=0x%08x", schCb.pHead); + break; } -#if SCH_TIMER_REQUIRED == TRUE - /* If head is executed, check cur tail operation is needed or not. */ - else +} + +/*************************************************************************************************/ +/*! + * \brief Set the BOD execute event. + */ +/*************************************************************************************************/ +static void schSetBodExecuteEvent(void) +{ + switch (schCb.state) { - /* Head BOD and next BOD must exist. */ - WSF_ASSERT(schCb.pHead); - WSF_ASSERT(schCb.pHead->pNext); - pNextBod = pNextBod->pNext; + case SCH_STATE_LOAD: + SCH_DBG_TRACE_EVENT(SCH_EVENT_BOD_EXECUTE); - /* Skip curtail load if next BOD has same or lower priority than current BOD. */ - if ((pNextBod->reschPolicy) >= (schCb.pHead->reschPolicy)) - { - /* Delay loading until idle state. */ - WsfSetEvent(schCb.handlerId, SCH_EVENT_BOD_LOAD); - schCb.delayLoadCount++; - schCb.delayLoadTotalCount++; - if (schCb.delayLoadCount > schCb.delayLoadWatermarkCount) - { - schCb.delayLoadWatermarkCount = schCb.delayLoadCount; - } - return; - } + schEventEnqueue(SCH_EVENT_BOD_EXECUTE); + break; - if (!schTryCurTailLoadNext()) - { - /* Curtail load failed. */ - schBodAbortHandler(); - } - /* Move to the next next BOD. */ - pNextBod = pNextBod->pNext; +#if SCH_ENABLE_CURTAIL + case SCH_STATE_EXECUTE: + SCH_DBG_TRACE_EVENT(SCH_EVENT_BOD_COMPLETE); + + schEventEnqueue(SCH_EVENT_BOD_COMPLETE); + break; +#endif + + default: + LL_TRACE_WARN1("Unexpected scheduler state for timer completion, pBod=0x%08x", schCb.pHead); + break; + } +} + +/*************************************************************************************************/ +/*! + * \brief Set the BOD complete event. + */ +/*************************************************************************************************/ +static void schSetBodCompleteEvent(void) +{ + switch (schCb.state) + { + case SCH_STATE_EXECUTE: + SCH_DBG_TRACE_EVENT(SCH_EVENT_BOD_COMPLETE); + + schEventEnqueue(SCH_EVENT_BOD_COMPLETE); + break; + + default: + LL_TRACE_WARN1("Unexpected scheduler state for event=SCH_EVENT_BOD_COMPLETE, pBod=0x%08x", schCb.pHead); + break; + } +} + +/*************************************************************************************************/ +/*! + * \brief Calculate the execute delay time of a BOD. + * + * \param pBod Target BOD. + * + * \return Time in microseconds when the given BOD should execute. + */ +/*************************************************************************************************/ +static inline bool_t schCalcExecuteDelayUsec(BbOpDesc_t *pBod, uint32_t *pExecTime) +{ + const uint32_t curTime = PalBbGetCurrentTime(); + const uint32_t setupDelayUsec = BbGetSchSetupDelayUs(); + + uint32_t deltaUsec = BbGetTargetTimeDelta(pBod->dueUsec, curTime); + + if (deltaUsec < (setupDelayUsec + SCH_TIMER_DELAY_US)) + { + /* Inadequate delta to start timer. */ + return FALSE; } - /* If pNextBod exists, it should start scheduler timer. */ + *pExecTime = pBod->dueUsec - setupDelayUsec; + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Enable curtail event. + */ +/*************************************************************************************************/ +static void schEnableCurtailEvent(void) +{ +#if SCH_ENABLE_CURTAIL + BbOpDesc_t* pNextBod = schCb.pHead->pNext; + + /* Check curtail operation is needed. */ if (pNextBod) { - uint32_t execTimeUsec = schGetTimeToExecBod(pNextBod); + /* Only enable curtail if current BOD is lower priority than next. */ + if (schCb.pHead->reschPolicy < pNextBod->reschPolicy) + { + uint32_t execDlyUsec; - if (execTimeUsec) - { - /* Always stop existing timer first for simplicity. */ - PalTimerStop(); - PalTimerStart(execTimeUsec); - } - else - { - /* If this happens, it means there's something wrong with the scheduler list. */ - LL_TRACE_WARN0("Next BOD overlaps with current BOD"); - /* Send scheduler load event. */ - SchLoadHandler(); + schCalcExecuteDelayUsec(pNextBod, &execDlyUsec); + + if (execDlyUsec) + { + PalTimerStart(execDlyUsec); + } } } #endif @@ -172,12 +280,63 @@ static void schBodLoadHandler(void) /*************************************************************************************************/ /*! - * \brief Scheduler load handler. + * \brief Execute head BOD. */ /*************************************************************************************************/ -void SchLoadHandler(void) +static void schExecuteHeadBod(void) { - WsfSetEvent(schCb.handlerId, SCH_EVENT_BOD_LOAD); + BbOpDesc_t *pBod = schCb.pHead; + + if (schDueTimeInFuture(pBod) || (pBod->recoverable == TRUE)) + { + /* Setup BB services. */ + BbExecuteBod(pBod); + + if (BbGetBodTerminateFlag() == FALSE) + { + /* BOD executed successfully. */ + schEnableCurtailEvent(); + } + else + { + LL_TRACE_WARN1("!!! BOD terminated on startup, pBod=0x%08x", pBod); + schSetBodCompleteEvent(); + } + } + else + { + LL_TRACE_ERR1("!!! BOD in the past, execution aborted, pBod=0x%08x", pBod); + LL_TRACE_ERR1("!!! dueUsec=%u", pBod->dueUsec); + LL_TRACE_ERR1("!!! curTime=%u", PalBbGetCurrentTime()); + schSetBodAbortEvent(); + } +} + +/*************************************************************************************************/ +/*! + * \brief Delay BOD load. + * + * \return TRUE if load is delayed, FALSE if load is immediate. + */ +/*************************************************************************************************/ +static bool_t schDelayBodLoad(void) +{ + BbOpDesc_t* pBod = schCb.pHead; + WSF_ASSERT(pBod); + + uint32_t execTime; + + if (schCalcExecuteDelayUsec(pBod, &execTime)) + { + /* Delay BOD load. */ + PalTimerStart(execTime); + + return TRUE; + } + else + { + return FALSE; + } } /*************************************************************************************************/ @@ -189,7 +348,7 @@ void SchInit(void) { memset(&schCb, 0, sizeof(schCb)); SchReset(); - PalTimerInit(schBodLoadHandler); + PalTimerInit(schSetBodExecuteEvent); } /*************************************************************************************************/ @@ -209,7 +368,7 @@ void SchHandlerInit(wsfHandlerId_t handlerId) schCb.handlerId = handlerId; - BbRegister(schBodCompHandler); + BbRegister(schSetBodCompleteEvent); } /*************************************************************************************************/ @@ -223,8 +382,6 @@ void SchReset(void) schCb.pHead = NULL; schCb.pTail = NULL; schCb.schHandlerWatermarkUsec = 0; - schCb.delayLoadWatermarkCount = 0; - schCb.delayLoadTotalCount = 0; } /*************************************************************************************************/ @@ -238,81 +395,147 @@ void SchReset(void) void SchHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) { /* Unused parameters */ + (void)event; (void)pMsg; /* Assume scheduler clock started. */ uint32_t startTime = PalBbGetCurrentTime(); - while (event != 0) + uint8_t schEvent; + + while (schEventDequeue(&schEvent)) { BbOpDesc_t *pBod = schCb.pHead; - - if (!pBod) + if (pBod == NULL) { - schCb.eventSetFlagCount = 0; + LL_TRACE_ERR0(" !!! SCH SM !!! out of sequence with pHead=NULL"); schCb.state = SCH_STATE_IDLE; - return; + break; } - if (event & SCH_EVENT_BOD_COMPLETE) + SCH_DBG_TRACE_STATE(startTime, schEvent); + + switch (schCb.state) { - WSF_ASSERT(schCb.state == SCH_STATE_EXEC); - WSF_ASSERT(schCb.eventSetFlagCount); + case SCH_STATE_LOAD: + switch (schEvent) + { + case SCH_EVENT_BOD_EXECUTE: + schCb.state = SCH_STATE_EXECUTE; + schExecuteHeadBod(); + break; - /*** Complete current BOD ***/ + case SCH_EVENT_BOD_RELOAD: + schCb.state = SCH_STATE_LOAD; + if (!schDelayBodLoad()) + { + /* Load BOD immediately. */ + schSetBodExecuteEvent(); + } + break; + case SCH_EVENT_BOD_ABORT: + schRemoveHead(); + + schCb.state = SCH_STATE_UNLOAD; + if (pBod->abortCback) + { + pBod->abortCback(pBod); + } + + if (schCb.pHead) + { + schCb.state = SCH_STATE_LOAD; + if (!schDelayBodLoad()) + { + /* Load BOD immediately. */ + schSetBodExecuteEvent(); + } + } + break; + + default: + LL_TRACE_ERR1(" !!! SCH SM !!! Unexpected scheduler event for pBod=0x%08x", pBod); + break; + } + break; + + case SCH_STATE_EXECUTE: + switch (schEvent) + { + case SCH_EVENT_BOD_COMPLETE: + schRemoveHead(); + + schCb.state = SCH_STATE_UNLOAD; + if (pBod->endCback) + { + pBod->endCback(pBod); + } + + if (schCb.pHead) + { + schCb.state = SCH_STATE_LOAD; + if (!schDelayBodLoad()) + { + /* Load BOD immediately. */ + schSetBodExecuteEvent(); + } + } + break; + + case SCH_EVENT_BOD_ABORT: + schRemoveHead(); + + schCb.state = SCH_STATE_UNLOAD; + if (pBod->abortCback) + { + pBod->abortCback(pBod); + } + + if (schCb.pHead) + { + schCb.state = SCH_STATE_LOAD; + if (!schDelayBodLoad()) + { + /* Load BOD immediately. */ + schSetBodExecuteEvent(); + } + } + break; + + default: + LL_TRACE_ERR1("Unexpected scheduler event for pBod=0x%08x", pBod); + break; + } + break; + + case SCH_STATE_IDLE: + switch (schEvent) + { + case SCH_EVENT_BOD_RELOAD: + schCb.state = SCH_STATE_LOAD; + SCH_DBG_TRACE_INFO0(" *** SCH SM *** scheduler loop started"); + if (!schDelayBodLoad()) + { + /* Load BOD immediately. */ + schSetBodExecuteEvent(); + } + break; + + default: + LL_TRACE_ERR1("Unexpected scheduler for pBod=0x%08x", pBod); + break; + } + break; + + default: + break; + } + + if (schCb.pHead == NULL) + { + SCH_DBG_TRACE_INFO0(" *** SCH SM *** scheduler loop terminated"); schCb.state = SCH_STATE_IDLE; - schRemoveHead(); - if (pBod->endCback) - { - pBod->endCback(pBod); - } - schCb.eventSetFlagCount--; - -#if SCH_TIMER_REQUIRED == FALSE - schBodLoadHandler(); -#endif - event &= ~SCH_EVENT_BOD_COMPLETE; - } - - else if (event & SCH_EVENT_BOD_ABORT) - { - WSF_ASSERT(schCb.state == SCH_STATE_IDLE); - WSF_ASSERT(schCb.eventSetFlagCount); - - /*** Abort current BOD ***/ - - schRemoveHead(); - if (pBod->abortCback) - { - pBod->abortCback(pBod); - } - schCb.eventSetFlagCount--; - -#if SCH_TIMER_REQUIRED == FALSE - schBodLoadHandler(); -#endif - event &= ~SCH_EVENT_BOD_ABORT; - } - - else if (event & SCH_EVENT_BOD_CURTAIL) - { - WSF_ASSERT(schCb.eventSetFlagCount); - - /*** Complete previous BOD ***/ - schRemoveHead(); - if (pBod->endCback) - { - pBod->endCback(pBod); - } - schCb.eventSetFlagCount--; - event &= ~SCH_EVENT_BOD_CURTAIL; - } - - else if (event & SCH_EVENT_BOD_LOAD) - { - schBodLoadHandler(); - event &= ~SCH_EVENT_BOD_LOAD; } } @@ -324,120 +547,6 @@ void SchHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) } } -/*************************************************************************************************/ -/*! - * \brief Load BOD if not already started. - * - * \param pBod BOD description. - * - * \return TRUE if loaded, FALSE otherwise. - */ -/*************************************************************************************************/ -static bool_t schLoadBod(BbOpDesc_t *pBod) -{ - bool_t loaded = FALSE; - - if (schDueTimeInFuture(pBod)) - { - /* Setup BB services. */ - BbExecuteBod(pBod); - schCb.delayLoadCount = 0; - - if (!BbGetBodTerminateFlag()) - { - loaded = TRUE; - } - else - { - LL_TRACE_WARN1("!!! BOD terminated on startup, pBod=0x%08x", pBod); - - if (schCb.eventSetFlagCount) - { - /* Termination or failure is scheduled to complete at next task event. */ - loaded = TRUE; - } - - BbCancelBod(); - } - } - else - { - /* This might occur due to the delay of conflict resolution. */ - LL_TRACE_ERR1("!!! Head element in the past, pBod=0x%08x", pBod); - } - - return loaded; -} - -/*************************************************************************************************/ -/*! - * \brief Load next BOD by curtailing the executed head BOD first. - * - * \return TRUE if curtail loading succeeded. - */ -/*************************************************************************************************/ -bool_t schTryCurTailLoadNext(void) -{ - bool_t loaded = TRUE; - - /* It should only be called when scheduler is in execute state. */ - WSF_ASSERT(schCb.state == SCH_STATE_EXEC); - /* Head BOD and next BOD must exist. */ - WSF_ASSERT(schCb.pHead); - WSF_ASSERT(schCb.pHead->pNext); - - if (schCb.pHead->pNext) - { - /* Hard stop head BOD and load next BOD. */ - BbCancelBod(); - schBodCurtailHandler(); - - schCb.state = SCH_STATE_EXEC; - - /* Try load next BOD. */ - if (!(schLoadBod(schCb.pHead->pNext))) - { - schCb.state = SCH_STATE_IDLE; - loaded = FALSE; - } - } - - return loaded; -} - -/*************************************************************************************************/ -/*! - * \brief Try to load head BOD if not already started. - * - * \return TRUE if load succeeded. - */ -/*************************************************************************************************/ -bool_t schTryLoadHead(void) -{ - bool_t loaded = TRUE; - - /* It should only be called when scheduler is in idle state. */ - WSF_ASSERT(schCb.state == SCH_STATE_IDLE); - -#if SCH_TIMER_REQUIRED == TRUE - /* Head BOD must exist. */ - WSF_ASSERT(schCb.pHead); -#endif - - if (schCb.pHead) - { - schCb.state = SCH_STATE_EXEC; - - if (!schLoadBod(schCb.pHead)) - { - schCb.state = SCH_STATE_IDLE; - loaded = FALSE; - } - } - - return loaded; -} - /*************************************************************************************************/ /*! * \brief Get the scheduler handler watermark level. @@ -449,27 +558,3 @@ uint16_t SchStatsGetHandlerWatermarkUsec(void) { return schCb.schHandlerWatermarkUsec; } - -/*************************************************************************************************/ -/*! - * \brief Get the scheduler handler watermark level. - * - * \return Watermark level in microseconds. - */ -/*************************************************************************************************/ -uint16_t SchStatsGetDelayLoadWatermarkCount(void) -{ - return schCb.delayLoadWatermarkCount; -} - -/*************************************************************************************************/ -/*! - * \brief Get the scheduler handler watermark level. - * - * \return Watermark level in microseconds. - */ -/*************************************************************************************************/ -uint32_t SchStatsGetDelayLoadTotalCount(void) -{ - return schCb.delayLoadTotalCount; -} diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/arduino_primo.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/arduino_primo.h index 2e462c17d7..2cd6ce6b7b 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/arduino_primo.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/arduino_primo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016 - 2019, Nordic Semiconductor ASA + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/boards.c b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/boards.c index 4c7fe5d25d..e5dc311599 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/boards.c +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/boards.c @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016 - 2019, Nordic Semiconductor ASA + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/boards.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/boards.h index 35421d23ad..2b4f3ebba3 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/boards.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/boards.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA + * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA * * All rights reserved. * @@ -67,6 +67,8 @@ #include "pca10056.h" #elif defined(BOARD_PCA10100) #include "pca10100.h" +#elif defined(BOARD_PCA10112) + #include "pca10112.h" #elif defined(BOARD_PCA20020) #include "pca20020.h" #elif defined(BOARD_PCA10059) @@ -88,6 +90,10 @@ #endif +#if defined (SHIELD_BSP_INC) + #include STRINGIFY(SHIELD_BSP_INC.h) +#endif + #ifdef __cplusplus extern "C" { #endif @@ -329,21 +335,26 @@ uint32_t bsp_board_button_idx_to_pin(uint32_t button_idx); BSP_BUTTON_6_MASK | BSP_BUTTON_7_MASK) +/* This macro is supporting only P0 and should not be used if LEDs are on other ports. */ #define LEDS_OFF(leds_mask) do { ASSERT(sizeof(leds_mask) == 4); \ NRF_GPIO->OUTSET = (leds_mask) & (LEDS_MASK & LEDS_INV_MASK); \ NRF_GPIO->OUTCLR = (leds_mask) & (LEDS_MASK & ~LEDS_INV_MASK); } while (0) +/* This macro is supporting only P0 and should not be used if LEDs are on other ports. */ #define LEDS_ON(leds_mask) do { ASSERT(sizeof(leds_mask) == 4); \ NRF_GPIO->OUTCLR = (leds_mask) & (LEDS_MASK & LEDS_INV_MASK); \ NRF_GPIO->OUTSET = (leds_mask) & (LEDS_MASK & ~LEDS_INV_MASK); } while (0) +/* This macro is supporting only P0 and should not be used if LEDs are on other ports. */ #define LED_IS_ON(leds_mask) ((leds_mask) & (NRF_GPIO->OUT ^ LEDS_INV_MASK) ) +/* This macro is supporting only P0 and should not be used if LEDs are on other ports. */ #define LEDS_INVERT(leds_mask) do { uint32_t gpio_state = NRF_GPIO->OUT; \ ASSERT(sizeof(leds_mask) == 4); \ NRF_GPIO->OUTSET = ((leds_mask) & ~gpio_state); \ NRF_GPIO->OUTCLR = ((leds_mask) & gpio_state); } while (0) +/* This macro is supporting only P0 and should not be used if LEDs are on other ports. */ #define LEDS_CONFIGURE(leds_mask) do { uint32_t pin; \ ASSERT(sizeof(leds_mask) == 4); \ for (pin = 0; pin < 32; pin++) \ diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/nrf6310.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/nrf6310.h index bd52945873..c950a205c6 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/nrf6310.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/nrf6310.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2012 - 2019, Nordic Semiconductor ASA + * Copyright (c) 2012 - 2020, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10000.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10000.h index 01fe58ba2c..d0c4aac9b2 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10000.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10000.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2012 - 2019, Nordic Semiconductor ASA + * Copyright (c) 2012 - 2020, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10001.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10001.h index 9c7f228d6a..be80e50c4d 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10001.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10001.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2012 - 2019, Nordic Semiconductor ASA + * Copyright (c) 2012 - 2020, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10003.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10003.h index 3562fd80f8..1f4e816473 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10003.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10003.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA + * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10028.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10028.h index bd365db6c4..63dac68973 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10028.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10028.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA + * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10031.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10031.h index b8c6d6976f..edb554c956 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10031.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10031.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA + * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10036.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10036.h index 6aaddc5eca..f2e6088541 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10036.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10036.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA + * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10040.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10040.h index 597ff69c6e..49df0a4eab 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10040.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10040.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA + * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10056.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10056.h index 8689dc00cd..62fb58a307 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10056.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10056.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016 - 2019, Nordic Semiconductor ASA + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10059.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10059.h index 711edd428b..3a0d6f251d 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10059.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10059.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017 - 2019, Nordic Semiconductor ASA + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10100.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10100.h index c44fb1bfc6..da35cde09d 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10100.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10100.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019, Nordic Semiconductor ASA + * Copyright (c) 2019 - 2020, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca20006.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca20006.h index e8e3d68dc2..18d04d7248 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca20006.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca20006.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA + * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca20020.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca20020.h index 4d3a906503..5855ebf404 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca20020.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca20020.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017 - 2019, Nordic Semiconductor ASA + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/wt51822.h b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/wt51822.h index 53cfbecffa..315832c8f1 100644 --- a/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/wt51822.h +++ b/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/wt51822.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA + * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/CHANGES.md b/connectivity/FEATURE_BLE/libraries/cordio_stack/CHANGES.md new file mode 100644 index 0000000000..2928967c9c --- /dev/null +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/CHANGES.md @@ -0,0 +1,82 @@ +Change Log +r21.04 + +Improvements: + +FW-3921 Deprecate power management API +FW-4022 DM should allow setting of local identity address + +Defects fixed: + +FW-4018 ATT signed write doesn't take CSRK authentication into account + +Known limitations: + +FW-3700 Generic Level Set may not use specified steps +FW-3708 Inadequate smooth state transition +FW-3710 Missing bindings +FW-3920 Mesh demo app - problem with Provisioner Server +FW-3929 Some GATT service characteristics security requirements may not match GATT service specs + +r21.02 + +Improvements: + +FW-3828 Implement VC and MIC Services and Profiles +FW-3830 Host Isochronous Data Path +FW-3947 ISO Host HCI improvements and support for BIS +FW-4016 DM assert reply on event id instead of event routing table size + +Defects fixed: + +FW-3928 GATT Profile service characteristics require no authentication +FW-3957 Linux int-to-pointer-cast and pointer-to-int-cast warnings reported with WDXS and EFS +FW-3977 Host terminal button log is wrong +FW-3985 ATT server blocks partial write to any fixed length attribute from offset zero +FW-4014 Missing Medc profile documentation in usage.md +FW-4017 DM Adv APIs use pointer to Adv Data instead of copying actual data + +Known limitations: + +FW-3434 Mesh Apps should update database hash if they change services +FW-3700 Generic Level Set may not use specified steps +FW-3920 Mesh demo app - problem with Provisioner Server +FW-3929 Some GATT service characteristics security requirements may not match GATT service specs +FW-3950 DM Ext Scan misses final fragments when receiving interleaved AUX ADV segments + +r20.12 + +Improvements: + +FW-3385 Non-blocking scheme for PAL flash +FW-3728 Packetcraft Audio Cape for PCA10056 +FW-3838 Token monitor utility script +FW-3863 FOTA with Nordic secure bootloader integration +FW-3864 Write flash between radio events on nRF52840 +FW-3865 Nordic secure bootloader updates firmware from internal flash +FW-3867 FOTA client profile +FW-3907 ITM SWO trace diagnostics + +Defects fixed: + +FW-3841 Timer may expire early +FW-3844 ATT silently ignores opcode 0x3F received from PTS +FW-3852 Multiple EATT calls in same task context fail +FW-3855 HCI LE create CIS function doesn't index handles correctly +FW-3892 'Encryption key is ready' flag not reset when DHKeyCheck fails +FW-3933 Allow advertising data to be updated while advertising enabled +FW-3934 attsCsfTable indexed using Connection Handle instead of Connection ID +FW-3944 ConnId used directly as index into ATT table +FW-3945 DM Adv and CTE states set after HCI commands invoked +FW-3946 Assert seen when L2CAP sends ACL data while HCI packets being fragmented +FW-3948 ATTS assert for total number of ATT bearers checks against sizeof(uint8_t) + +Known limitations: + +FW-3019 Mesh app does not build with USE_EXACTLE=0 +FW-3434 Mesh Apps should update database hash if they change services +FW-3700 Generic Level Set may not use specified steps +FW-3920 Mesh demo app - problem with Provisioner Server +FW-3928 GATT Profile service characteristics require no authentication +FW-3950 DM Ext Scan misses final fragments when receiving interleaved AUX ADV segments + diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/CMakeLists.txt b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/CMakeLists.txt index 3be9fea405..bf8c844945 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/CMakeLists.txt +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/CMakeLists.txt @@ -12,6 +12,7 @@ target_include_directories(mbed-ble-cordio sources/stack/hci sources/stack/l2c sources/stack/smp + ../../TARGET_CORDIO_LL/stack/controller/include/ble ) target_sources(mbed-ble-cordio diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/att_api.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/att_api.h index a0649f26c0..59cf6a670e 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/att_api.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/att_api.h @@ -6,7 +6,7 @@ * * Copyright (c) 2009-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -162,7 +162,7 @@ typedef struct uint8_t authoriz; /*!< \brief Authorization required */ uint8_t secLevel; /*!< \brief Security level required */ uint8_t numChans; /*!< \brief Number of enhanced l2cap channels per connection */ - uint8_t *pPriorityTbl; /*!< \brief Min priority required for each channel */ + const uint8_t *pPriorityTbl; /*!< \brief Min channel priority table. Set NULL to map priority to L2CAP channel index. */ } eattCfg_t; /*! @@ -758,6 +758,19 @@ void AttsCccSet(dmConnId_t connId, uint8_t idx, uint16_t value); /*************************************************************************************************/ uint16_t AttsCccEnabled(dmConnId_t connId, uint8_t idx); +/*************************************************************************************************/ +/*! + * \brief Check if a client characteristic configuration descriptor is enabled and if + * the characteristic's security level has been met. + * + * \param connId DM connection ID. + * \param handle Attribute handle of CCC descriptor. + * + * \return Value of the descriptor if security level is met, otherwise zero. + */ +/*************************************************************************************************/ +uint16_t AttsCccEnabledByHandle(dmConnId_t connId, uint16_t handle); + /*************************************************************************************************/ /*! * \brief Get number of CCC entries in table. @@ -793,12 +806,12 @@ void AttsContinueWriteReq(dmConnId_t connId, uint16_t handle, uint8_t status); * * \param connId DM connection ID. * \param pCsrk Pointer to data signing key (CSRK). - * \param authenticated True if CSRK is authenticated and false otherwise. + * \param authen Whether CSRK was received on authenticated connection. * * \return None. */ /*************************************************************************************************/ -void AttsSetCsrk(dmConnId_t connId, uint8_t *pCsrk, bool_t authenticated); +void AttsSetCsrk(dmConnId_t connId, uint8_t *pCsrk, bool_t authen); /*************************************************************************************************/ /*! diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/att_defs.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/att_defs.h index 8fea47d94f..ad591e053d 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/att_defs.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/att_defs.h @@ -113,10 +113,6 @@ extern "C" { */ /**@{*/ #define ATT_ERR_VALUE_RANGE 0x80 /*!< \brief Value out of range */ -#define ATT_ERR_INVALID_CHANGE_CTR 0x80 /*!< \brief Invalid change counter */ -#define ATT_ERR_OPCODE_NOT_SUPPORTED 0x81 /*!< \brief Opcode out of range */ -#define ATT_ERR_MUTE_DISABLE 0x82 /*!< \brief Mute disable */ -#define ATT_ERR_VALUE_RANGE_x83 0x83 /*!< \brief Value out of range 0x83 */ /**@}*/ /** \name ATT HCI Error Status diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/att_uuid.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/att_uuid.h index 5896a1c9ba..42f9f5f7a1 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/att_uuid.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/att_uuid.h @@ -6,7 +6,7 @@ * * Copyright (c) 2011-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -70,8 +70,16 @@ extern "C" { #define ATT_UUID_PULSE_OXIMITER_SERVICE 0x1822 /*!< \brief Pulse Oximeter Service */ #define ATT_UUID_MESH_PRV_SERVICE 0x1827 /*!< \brief Mesh Provisioning Service */ #define ATT_UUID_MESH_PROXY_SERVICE 0x1828 /*!< \brief Mesh Proxy Service */ -#define ATT_UUID_CONSTANT_TONE_SERVICE 0x7F7F /*!< \brief Constant Tone Extension */ - +#define ATT_UUID_AUDIO_INPUT_CTRL_SERVICE 0x1843 /*!< \brief Audio Input Control Service */ +#define ATT_UUID_VOLUME_CTRL_SERVICE 0x1844 /*!< \brief Volume Control Service */ +#define ATT_UUID_VOLUME_OFFSET_CTRL_SERVICE 0x1845 /*!< \brief Volume Offset Control Service */ +#define ATT_UUID_CONSTANT_TONE_SERVICE 0x184A /*!< \brief Constant Tone Extension */ +#define ATT_UUID_MICROPHONE_CTRL_SERVICE 0x8FD4 /*!< \brief Microphone Control Service */ +#define ATT_UUID_PUB_AUDIO_CAP_SERVICE 0x8FD9 /*!< \brief Published Audio Capability Service */ +#define ATT_UUID_AUDIO_STRM_CTRL_SERVICE 0x8FDA /*!< \brief Audio Stream Control Service */ +#define ATT_UUID_BCAST_AUDIO_SCAN_SERVICE 0x8FDB /*!< \brief Broadcast Audio Scan Service */ +#define ATT_UUID_BASIC_AUDIO_ANNC_SERVICE 0x8FDC /*!< \brief Basic Audio Announcement Service */ +#define ATT_UUID_BCAST_AUDIO_ANNC_SERVICE 0x8FDD /*!< \brief Broadcast Audio Announcement Service */ /**@}*/ /** \name GATT UUIDs @@ -210,12 +218,36 @@ extern "C" { #define ATT_UUID_CLIENT_SUPPORTED_FEATURES 0x2B29 /*!< \brief Client Supported Features */ #define ATT_UUID_DATABASE_HASH 0x2B2A /*!< \brief Database Hash */ #define ATT_UUID_SERVER_SUPPORTED_FEATURES 0x2B3A /*!< \brief Server Supported Features */ -#define ATT_UUID_CTE_ENABLE 0x7F80 /*!< \brief Constant Tone Extension enable */ -#define ATT_UUID_CTE_MIN_LEN 0x7F81 /*!< \brief Constant Tone Extension minimum length */ -#define ATT_UUID_CTE_TX_CNT 0x7F82 /*!< \brief Constant Tone Extension transmit count */ -#define ATT_UUID_CTE_TX_DURATION 0x7F83 /*!< \brief Constant Tone Extension transmit duration */ -#define ATT_UUID_CTE_INTERVAL 0x7F84 /*!< \brief Constant Tone Extension interval */ -#define ATT_UUID_CTE_PHY 0x7F85 /*!< \brief Constant Tone Extension PHY */ +#define ATT_UUID_AIC_INPUT_STATE 0x2B77 /*!< \brief Audio Input Control Input State */ +#define ATT_UUID_AIC_GAIN_SETTING_ATTR 0x2B78 /*!< \brief Audio Input Control Gain Setting Attributes */ +#define ATT_UUID_AIC_INPUT_TYPE 0x2B79 /*!< \brief Audio Input Control Input Type */ +#define ATT_UUID_AIC_INPUT_STATUS 0x2B7A /*!< \brief Audio Input Control Input Status */ +#define ATT_UUID_AIC_AUDIO_INPUT_CTRL 0x2B7B /*!< \brief Audio Input Control Audio Input Control */ +#define ATT_UUID_AIC_AUDIO_INPUT_DESC 0x2B7C /*!< \brief Audio Input Control Audio Input Description */ +#define ATT_UUID_VOLUME_STATE 0x2B7D /*!< \brief Volume Control State */ +#define ATT_UUID_VOLUME_CONTROL_POINT 0x2B7E /*!< \brief Volume Control Point */ +#define ATT_UUID_VOLUME_FLAGS 0x2B7F /*!< \brief Volume Control Flags */ +#define ATT_UUID_VOLUME_OFFSET_STATE 0x2B80 /*!< \brief Volume Offset State */ +#define ATT_UUID_AUDIO_LOCATION 0x2B81 /*!< \brief Audio Location */ +#define ATT_UUID_VOLUME_OFFSET_CONTROL_PT 0x2B82 /*!< \brief Volume Offset Control Point */ +#define ATT_UUID_AUDIO_OUT_DESC 0x2B83 /*!< \brief Audio Output Description */ +#define ATT_UUID_CTE_ENABLE 0x2BAD /*!< \brief Constant Tone Extension enable */ +#define ATT_UUID_CTE_MIN_LEN 0x2BAE /*!< \brief Constant Tone Extension minimum length */ +#define ATT_UUID_CTE_TX_CNT 0x2BAF /*!< \brief Constant Tone Extension transmit count */ +#define ATT_UUID_CTE_TX_DURATION 0x2BB0 /*!< \brief Constant Tone Extension transmit duration */ +#define ATT_UUID_CTE_INTERVAL 0x2BB1 /*!< \brief Constant Tone Extension interval */ +#define ATT_UUID_CTE_PHY 0x2BB2 /*!< \brief Constant Tone Extension PHY */ +#define ATT_UUID_MC_MUTE 0x8FE1 /*!< \brief Microphone Control Mute */ +#define ATT_UUID_SNK_PAC 0x8F96 /*!< \brief Sink PAC */ +#define ATT_UUID_SNK_AUDIO_LOC 0x8F97 /*!< \brief Sink audio locations */ +#define ATT_UUID_SRC_PAC 0x8F98 /*!< \brief Source PAC */ +#define ATT_UUID_SRC_AUDIO_LOC 0x8F99 /*!< \brief Source audio locations */ +#define ATT_UUID_AUDIO_CONT_AVAIL 0x8F9A /*!< \brief Audio content availability */ +#define ATT_UUID_SUP_AUDIO_CONT 0x8F9B /*!< \brief Supported audio content */ +#define ATT_UUID_ASE 0x8F9C /*!< \brief Audio Stream Endpoint (ASE) */ +#define ATT_UUID_ASE_CP 0x8F9D /*!< \brief Audio Stream Endpoint (ASE) Control Point */ +#define ATT_UUID_BAS_CP 0x8F9E /*!< \brief Broadcast Audio Scan (BAS) Control Point */ +#define ATT_UUID_BCAST_RX_STATE 0x8F9F /*!< \brief Broadcast Receive State */ /**@}*/ /** \name GATT Unit UUIDs @@ -381,7 +413,7 @@ extern const uint8_t attNwaSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Network Ava extern const uint8_t attWdsSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Watchdog Service */ extern const uint8_t attHrsSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Heart Rate Service */ extern const uint8_t attPassSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Phone Alert Status Service */ -extern const uint8_t attBasSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Battery Service */ +extern const uint8_t attBattSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Battery Service */ extern const uint8_t attBpsSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Blood Pressure Service */ extern const uint8_t attAnsSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Alert Notification Service */ extern const uint8_t attHidSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Human Interface Device Service */ @@ -392,7 +424,15 @@ extern const uint8_t attMprvSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Mesh Provis extern const uint8_t attMprxSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Mesh Proxy Service */ extern const uint8_t attWssSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Weight scale service */ extern const uint8_t attCteSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Constant Tone Extension service */ - +extern const uint8_t attAicsSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Audio Input Control service */ +extern const uint8_t attMicsSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Microphone Control service */ +extern const uint8_t attVcsSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Volume Control service */ +extern const uint8_t attVocsSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Volume Offset Control service */ +extern const uint8_t attPacSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Audio capability service */ +extern const uint8_t attAscSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Audio Stream Endpoint Service */ +extern const uint8_t attBasSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Broadcast Audio Scan Service */ +extern const uint8_t attBscAaSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Basic Audio Announcement Service */ +extern const uint8_t attBcstAaSvcUuid[ATT_16_UUID_LEN]; /*!< \brief Broadcast Audio Announcement Service */ /**@}*/ /** \name GATT UUID Variables @@ -536,7 +576,30 @@ extern const uint8_t attCteTxDurChUuid[ATT_16_UUID_LEN]; /*!< \brief Constant To extern const uint8_t attCteIntChUuid[ATT_16_UUID_LEN]; /*!< \brief Constant Tone Extension interval */ extern const uint8_t attCtePhyChUuid[ATT_16_UUID_LEN]; /*!< \brief Constant Tone Extension PHY */ extern const uint8_t attSsfChUuid[ATT_16_UUID_LEN]; /*!< \brief Server supported features */ - +extern const uint8_t attAicsStChUuid[ATT_16_UUID_LEN]; /*!< \brief Audio Input Control input status */ +extern const uint8_t attAicsGsaChUuid[ATT_16_UUID_LEN]; /*!< \brief Audio Input Control gain settings attributes */ +extern const uint8_t attAicsItChUuid[ATT_16_UUID_LEN]; /*!< \brief Audio Input Control input type */ +extern const uint8_t attAicsStatChUuid[ATT_16_UUID_LEN]; /*!< \brief Audio Input Control input status */ +extern const uint8_t attAicsAicChUuid[ATT_16_UUID_LEN]; /*!< \brief Audio Input Control audio input control point */ +extern const uint8_t attAicsAidhUuid[ATT_16_UUID_LEN]; /*!< \brief Audio Input Control audio input description */ +extern const uint8_t attMicsMuteChUuid[ATT_16_UUID_LEN]; /*!< \brief Microphone Control mute */ +extern const uint8_t attVcsStateChUuid[ATT_16_UUID_LEN]; /*!< \brief Volume Control state */ +extern const uint8_t attVcsCpChUuid[ATT_16_UUID_LEN]; /*!< \brief Volume Control Point */ +extern const uint8_t attVcsFlagsChUuid[ATT_16_UUID_LEN]; /*!< \brief Volume Control flags */ +extern const uint8_t attVocsStateChUuid[ATT_16_UUID_LEN];/*!< \brief Volume Offset Control state */ +extern const uint8_t attVocsLocChUuid[ATT_16_UUID_LEN]; /*!< \brief Volume Offset Control audio location */ +extern const uint8_t attVocsCpChUuid[ATT_16_UUID_LEN]; /*!< \brief Volume Offset Control control point */ +extern const uint8_t attVocsDescChUuid[ATT_16_UUID_LEN]; /*!< \brief Volume Offset Control description */ +extern const uint8_t attSnkPacChUuid[ATT_16_UUID_LEN]; /*!< \brief Sink PAC */ +extern const uint8_t attSnkAudLocChUuid[ATT_16_UUID_LEN];/*!< \brief Sink audio locations */ +extern const uint8_t attSrcPacChUuid[ATT_16_UUID_LEN]; /*!< \brief Source PAC */ +extern const uint8_t attSrcAudLocChUuid[ATT_16_UUID_LEN];/*!< \brief Source audio locations */ +extern const uint8_t attAudCntAvChUuid[ATT_16_UUID_LEN]; /*!< \brief Audio Content Availability */ +extern const uint8_t attSupAudCntChUuid[ATT_16_UUID_LEN];/*!< \brief Supported Audio Content */ +extern const uint8_t attAseChUuid[ATT_16_UUID_LEN]; /*!< \brief Audio Stream Endpoint (ASE) */ +extern const uint8_t attAseCpChUuid[ATT_16_UUID_LEN]; /*!< \brief Audio Stream Endpoint (ASE) Control Point */ +extern const uint8_t attBasCpChUuid[ATT_16_UUID_LEN]; /*!< \brief Broadcast Audio Scan (BAS) Control Point */ +extern const uint8_t attBcRxStateChUuid[ATT_16_UUID_LEN];/*!< \brief Broadcast Receive State */ /**@}*/ /*! \} */ /* STACK_ATT_API */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/dm_api.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/dm_api.h index 04271c308f..2d0d1adf16 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/dm_api.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/dm_api.h @@ -6,7 +6,7 @@ * * Copyright (c) 2016-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -143,6 +143,9 @@ extern "C" { /*! \brief Unknown Connected Isochronous Stream (CIS) ID or other error */ #define DM_CIS_ID_NONE 0xFF + +/*! \brief Unknown Broadcast Isochronous Group (BIG) handle or other error */ +#define DM_BIG_HANDLE_NONE 0xFF /**@}*/ /** \name GAP Address Type @@ -473,6 +476,13 @@ enum #define DM_ADV_HANDLE_DEFAULT 0 /**@}*/ +/** \name DM ISO data path directions +* Number of ISO data path directions +*/ +/**@{*/ +#define DM_ISO_NUM_DIR 2 +/**@}*/ + /** \name DM Callback Events * Events handled by the DM state machine. */ @@ -626,6 +636,12 @@ typedef union dmSecCsrk_t csrk; /*!< \brief CSRK */ } dmSecKey_t; +/*! \brief Broadcast_Code data type. */ +typedef struct +{ + uint8_t code[HCI_BC_LEN]; /*!< \brief Broadcast_Code */ +} dmSecBcastCode_t; + /*! \brief Data type for \ref DM_SEC_PAIR_CMPL_IND. */ typedef struct { @@ -734,6 +750,24 @@ typedef struct uint8_t advHandle; /*!< \brief Advertising handle */ } dmPerAdvSetStopEvt_t; +/*! \brief Data structure for \ref DM_ISO_DATA_PATH_SETUP_IND. */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< \brief Event header. */ + uint8_t status; /*!< \brief Status. */ + uint16_t handle; /*!< \brief Connection handle of the CIS or BIS. */ + uint8_t dpDir; /*!< \brief Data path direction being set up. */ +} dmSetupIsoDataPathEvt_t; + +/*! \brief Data structure for \ref DM_ISO_DATA_PATH_REMOVE_IND. */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< \brief Event header. */ + uint8_t status; /*!< \brief Status. */ + uint16_t handle; /*!< \brief Connection handle of the CIS or BIS. */ + uint8_t directionBits; /*!< \brief Data path directions being removed. */ +} dmRemoveIsoDataPathEvt_t; + /*! \brief Data structure for \ref DM_L2C_CMD_REJ_IND. */ typedef struct { @@ -833,8 +867,8 @@ typedef union HciLeCisEstEvt_t cisOpen; /*!< \brief handles \ref DM_CIS_OPEN_IND */ hciDisconnectCmplEvt_t cisClose; /*!< \brief handles \ref DM_CIS_CLOSE_IND */ HciLeReqPeerScaCmplEvt_t_t reqPeerSca; /*!< \brief handles \ref DM_REQ_PEER_SCA_IND */ - hciLeSetupIsoDataPathCmdCmplEvt_t isoDataPathSetup; /*!< \brief handles \ref DM_ISO_DATA_PATH_SETUP_IND */ - hciLeRemoveIsoDataPathCmdCmplEvt_t isoDataPathRemove; /*!< \brief handles \ref DM_ISO_DATA_PATH_REMOVE_IND */ + dmSetupIsoDataPathEvt_t isoDataPathSetup; /*!< \brief handles \ref DM_ISO_DATA_PATH_SETUP_IND */ + dmRemoveIsoDataPathEvt_t isoDataPathRemove; /*!< \brief handles \ref DM_ISO_DATA_PATH_REMOVE_IND */ hciConfigDataPathCmdCmplEvt_t dataPathConfig; /*!< \brief handles \ref DM_DATA_PATH_CONFIG_IND */ hciReadLocalSupCodecsCmdCmplEvt_t readLocalSupCodecs; /*!< \brief handles \ref DM_READ_LOCAL_SUP_CODECS_IND */ hciReadLocalSupCodecCapCmdCmplEvt_t readLocalSupCodecCap; /*!< \brief handles \ref DM_READ_LOCAL_SUP_CODEC_CAP_IND */ @@ -846,9 +880,9 @@ typedef union HciLeBigSyncLostEvt_t bigSyncLost; /*!< \brief handles \ref DM_BIG_SYNC_LOST_IND */ HciLeBigTermSyncCmplEvt_t bigSyncStop; /*!< \brief handles \ref DM_BIG_SYNC_STOP_IND */ HciLeBigInfoAdvRptEvt_t bigInfoAdvRpt; /*!< \brief handles \ref DM_BIG_INFO_ADV_REPORT_IND */ - #if MBED_CONF_CORDIO_ROUTE_UNHANDLED_COMMAND_COMPLETE_EVENTS +#if MBED_CONF_CORDIO_ROUTE_UNHANDLED_COMMAND_COMPLETE_EVENTS hciUnhandledCmdCmplEvt_t unhandledCmdCmplEvt; - #endif +#endif dmL2cCmdRejEvt_t l2cCmdRej; /*!< \brief handles \ref DM_L2C_CMD_REJ_IND */ /* common header used by DM_ERROR_IND */ hciHwErrorEvt_t hwError; /*!< \brief handles \ref DM_HW_ERROR_IND */ @@ -864,9 +898,15 @@ typedef struct uint8_t peerConfirm[SMP_CONFIRM_LEN]; /*!< \brief Confirm value of the peer device */ } dmSecLescOobCfg_t; -/*! \brief Callback type. */ +/*! \brief DM callback type. */ typedef void (*dmCback_t)(dmEvt_t *pDmEvt); +/*! \brief DM Setup ISO data path callback type. */ +typedef void (*dmIsoDataPathSetupCback_t)(HciIsoSetupDataPath_t *pDataPathParam); + +/*! \brief DM Remove ISO data path callback type. */ +typedef void (*dmIsoDataPathRemoveCback_t)(uint16_t handle, uint8_t directionBits); + /************************************************************************************************** Function Declarations **************************************************************************************************/ @@ -1654,13 +1694,16 @@ void DmScanSetAddrType(uint8_t addrType); * \param pAdvAddr Advertiser address. * \param skip Number of periodic advertising packets that can be skipped after * successful receive. - * \param syncTimeout Synchronization timeout. + * \param syncTimeout Synchronization timeout, in the units of 10ms. + * \param syncCteType Whether to only synchronize to periodic advertising with certain types + * of Constant Tone Extension (0 indicates that the presence or absence of + * a Constant Tone Extension is irrelevant). * * \return Sync indentifier. */ /*************************************************************************************************/ dmSyncId_t DmSyncStart(uint8_t advSid, uint8_t advAddrType, const uint8_t *pAdvAddr, uint16_t skip, - uint16_t syncTimeout); + uint16_t syncTimeout, uint8_t syncCteType); /*************************************************************************************************/ /*! @@ -1742,7 +1785,7 @@ void DmBigSyncStart(uint8_t bigHandle, uint16_t syncHandle, uint8_t mse, uint16_ /*! * \brief Stop synchronizing or cancel the process of synchronizing to the Broadcast Isochronous * Group (BIG) identified by the handle. - * + * * \note The command also terminates the reception of BISes in the BIG specified in \ref * DmBigSyncStart, destroys the associated connection handles of the BISes in the BIG * and removes the data paths for all BISes in the BIG. @@ -1900,7 +1943,8 @@ void DmPastSetInfoTrsf(dmConnId_t connId, uint16_t serviceData, uint8_t advHandl * \param syncTimeout Maximum permitted time between successful receives. If this time is * exceeded, synchronization is lost. * \param cteType Whether to only synchronize to periodic advertising with certain - * types of Constant Tone Extension. + * types of Constant Tone Extension (0 indicates that the presence or + * absence of a Constant Tone Extension is irrelevant). * * \return None. */ @@ -1919,7 +1963,8 @@ void DmPastConfig(dmConnId_t connId, uint8_t mode, uint16_t skip, uint16_t syncT * \param syncTimeout Maximum permitted time between successful receives. If this time is * exceeded, synchronization is lost. * \param cteType Whether to only synchronize to periodic advertising with certain - * types of Constant Tone Extension. + * types of Constant Tone Extension (0 indicates that the presence or + * absence of a Constant Tone Extension is irrelevant). * * \return None. */ @@ -2418,7 +2463,7 @@ void DmCisCigSetSca(uint8_t cigId, uint8_t sca); * \return None. */ /*************************************************************************************************/ -void DmCisCigSetPackingFraming(uint8_t cigId, uint8_t packing, uint32_t framing); +void DmCisCigSetPackingFraming(uint8_t cigId, uint8_t packing, uint8_t framing); /*************************************************************************************************/ /*! @@ -2436,7 +2481,7 @@ void DmCisCigSetTransLatInterval(uint8_t cigId, uint16_t transLatMToS, uint16_t /*************************************************************************************************/ /*! - * \brief Set the parameters of one or more Connected Isochronous Streams (CISes) that are + * \brief Set the parameters of one or more Connected Isochronous Streams (CISes) that are * associated with the given Connected Isochronous Group (CIG). * * \param cigId CIG identifier. @@ -2450,7 +2495,7 @@ void DmCisCigConfig(uint8_t cigId, dmConnId_t numCis, HciCisCisParams_t *pCisPar /*************************************************************************************************/ /*! - * \brief Remove all the Connected Isochronous Streams (CISes) associated with the given + * \brief Remove all the Connected Isochronous Streams (CISes) associated with the given * Connected Isochronous Group (CIG). * * \param cigId CIG identifier. @@ -2462,17 +2507,17 @@ void DmCisCigRemove(uint8_t cigId); /*************************************************************************************************/ /*! - * \brief Create one or more Connected Isochronous Streams (CISes) using the connections + * \brief Create one or more Connected Isochronous Streams (CISes) using the connections * identified by the ACL connection handles. * * \param numCis Total number of CISes to be created. * \param pCisHandle List of connection handles of CISes. - * \param pAclHandle List of connection handles of ACLs. + * \param pConnId List of DM connection identifiers. * * \return None. */ /*************************************************************************************************/ -void DmCisOpen(uint8_t numCis, uint16_t *pCisHandle, uint16_t *pAclHandle); +void DmCisOpen(uint8_t numCis, uint16_t *pCisHandle, dmConnId_t *pConnId); /*************************************************************************************************/ /*! @@ -2511,6 +2556,31 @@ void DmCisReject(uint16_t handle, uint8_t reason); /*************************************************************************************************/ void DmCisClose(uint16_t handle, uint8_t reason); +/*************************************************************************************************/ +/*! + * \brief For internal use only. Find the Connected Isochronous Stream (CIS) ID with matching + * handle. + * + * \param handle CIS connection handle. + * + * \return CIS identifier or DM_CIS_ID_NONE if error. + */ +/*************************************************************************************************/ +uint8_t DmCisIdByHandle(uint16_t handle); + +/*************************************************************************************************/ +/*! + * \brief For internal use only. Find the Connected Isochronous Stream (CIS) handle with matching + * CIG and CIS identifiers. + * + * \param handle CIG ID. + * \param handle CIS ID. + * + * \return CIS connection handle or DM_CONN_HCI_HANDLE_NONE if error. + */ +/*************************************************************************************************/ +uint16_t DmCisHandleById(uint8_t cigId, uint8_t cisId); + /*************************************************************************************************/ /*! * \brief For internal use only. Return TRUE if the Connected Isochronous Stream (CIS) @@ -2523,6 +2593,41 @@ void DmCisClose(uint16_t handle, uint8_t reason); /*************************************************************************************************/ bool_t DmCisConnInUse(uint16_t handle); +/*************************************************************************************************/ +/*! + * \brief For internal use only. Return the CIS connection role indicating master or slave. + * + * \param handle CIS connection handle. + * + * \return CIS connection role. + */ +/*************************************************************************************************/ +uint8_t DmCisConnRole(uint16_t handle); + +/*************************************************************************************************/ +/*! + * \brief For internal use only. Return TRUE if Connected Isochronous Group (CIG) is in use. + * + * \param cigId CIG identifier. + * + * \return TRUE if CIG is in use, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t DmCisCigInUse(uint8_t cigId); + +/*************************************************************************************************/ +/*! + * \brief For internal use only. Return TRUE if the Connected Isochronous Stream (CIS) + * connection is in use. + * + * \param cigId CIG identifier. + * \param cisId CIS identifier. + * + * \return TRUE if the CIS connection is in use, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t DmCisInUse(uint8_t cigId, uint8_t cisId); + /**@}*/ /** \name DM BIS Functions @@ -2541,7 +2646,7 @@ void DmBisSlaveInit(void); /*************************************************************************************************/ /*! - * \brief Start a Broadcast Isochronous Group (BIG) with one or more Broadcast Isochronous + * \brief Start a Broadcast Isochronous Group (BIG) with one or more Broadcast Isochronous * Streams (BISes). * * \param bigHandle CIG identifier. @@ -2550,7 +2655,7 @@ void DmBisSlaveInit(void); * \param sduInterUsec Interval, in microseconds, of BIG SDUs. * \param maxSdu Maximum size of SDU * \param mtlMs Maximum time, in milliseconds, for transmitting SDU. - * \param rtn Retransmitted number. + * \param rtn Retransmission number. * * \return None. */ @@ -2660,6 +2765,21 @@ uint8_t DmBigGetSecLevel(uint16_t handle); /*************************************************************************************************/ void DmIsoInit(void); +/*************************************************************************************************/ +/*! + * \brief Register CIS, BIS and setup callbacks for the HCI ISO data path. + * + * \param cisCback CIS data callback function (may be NULL). + * \param bisCback BIS data callback function (may be NULL). + * \param setupCback ISO data path setup callback function (NULL when the codec in the LL). + * \param removeCback ISO data path remove callback function (NULL when the codec in the LL). + * + * \return None. + */ + /*************************************************************************************************/ +void DmIsoRegister(hciIsoCback_t cisCback, hciIsoCback_t bisCback, + dmIsoDataPathSetupCback_t setupCback, dmIsoDataPathRemoveCback_t removeCback); + /*************************************************************************************************/ /*! * \brief Setup the isochronous data path between the Host and the Controller for an established @@ -2733,6 +2853,15 @@ void DmReadLocalSupCodecCap(HciReadLocalSupCodecCaps_t *pCodecParam); /*************************************************************************************************/ void DmReadLocalSupCtrDly(HciReadLocalSupControllerDly_t *pDelayParam); +/*************************************************************************************************/ +/*! + * \brief Send ISO Data packet. + * + * \param pIsoParam ISO data packet parameters. + */ +/*************************************************************************************************/ +void DmSendIsoData(uint16_t handle, uint16_t len, uint8_t *pData, bool_t useTs, uint32_t ts); + /**@}*/ /** \name DM PHY Control Functions @@ -3039,13 +3168,13 @@ void DmSecSetLocalIrk(uint8_t *pIrk); /*! * \brief This function sets the local identity address used by the device. * - * \param pAddr Pointer to the address. - * \param type Type of the address. + * \param identityAddr Local identity address. + * \param addrType Local identity address type. * * \return None. */ -/*************************************************************************************************/ -void DmSecSetLocalIdentityAddr(const uint8_t *pAddr, uint8_t type); + /*************************************************************************************************/ +void DmSecSetLocalIdentityAddr(const bdAddr_t identityAddr, uint8_t addrType); /*************************************************************************************************/ /*! @@ -3369,7 +3498,7 @@ uint8_t *DmSecGetLocalIdentityAddr(void); /*************************************************************************************************/ /*! * \brief For internal use only. This function gets the local identity address type used by the - * device. + * device. * * \return The identity address type. */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/eatt_api.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/eatt_api.h index 15dcee8bf3..ede234acbe 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/eatt_api.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/eatt_api.h @@ -166,6 +166,9 @@ void EattsHandleValueNtfZeroCpy(dmConnId_t connId, uint8_t priority, uint16_t ha * \brief Initialize the Enhanced ATT Server. * * \return None + * + * \note EattInit must be called after the ATT task is created and before calling EattsInit + * and/or EattcInit. */ /*************************************************************************************************/ void EattsInit(); @@ -398,6 +401,9 @@ void EattcReadMultVarLenReq(dmConnId_t connId, uint8_t priority, uint8_t numHand * \brief Initialize the Enhanced ATT Client. * * \return None + * + * \note EattInit must be called after the ATT task is created and before calling EattsInit + * and/or EattcInit. */ /*************************************************************************************************/ void EattcInit(); @@ -441,6 +447,9 @@ uint8_t EattGetNumChannelsInUse(dmConnId_t connId); * \brief Initialize the Enhanced ATT subsystem. * * \return None + * + * \note EattInit must be called after the ATT task is created and before calling EattsInit + * and/or EattcInit. */ /*************************************************************************************************/ void EattInit(uint8_t roleBits); diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/hci_api.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/hci_api.h index 5aa513e016..dfb427bc05 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/hci_api.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/hci_api.h @@ -6,7 +6,7 @@ * * Copyright (c) 2009-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -130,11 +130,24 @@ extern "C" { #define HCI_LE_BIG_SYNC_LOST_CBACK_EVT 83 /*!< \brief LE BIG sync lost */ #define HCI_LE_BIG_TERM_SYNC_CMPL_CBACK_EVT 84 /*!< \brief LE BIG terminate sync complete */ #define HCI_LE_BIG_INFO_ADV_REPORT_CBACK_EVT 85 /*!< \brief LE BIG Info advertising report */ + #if MBED_CONF_CORDIO_ROUTE_UNHANDLED_COMMAND_COMPLETE_EVENTS #define HCI_UNHANDLED_CMD_CMPL_CBACK_EVT 86 /*!< \brief Unhandled event */ #endif + +#define HCI_LE_MAX_CBACK_EVT HCI_LE_BIG_INFO_ADV_REPORT_CBACK_EVT + /*!< \brief Max callback event ID number */ /**@}*/ +/*! \brief HCI calculate SDU header length. */ +#define HCI_GET_SDU_HDR_LEN(useTs) (HCI_ISO_HDR_LEN + (useTs ? HCI_ISO_DL_MAX_LEN : HCI_ISO_DL_MIN_LEN)) + +/*! \brief HCI Get base of SDU data buffer. */ +#define HCI_GET_SDU_PAYLOAD_BUF(pHdrBuf, useTs) (pHdrBuf + HCI_GET_SDU_HDR_LEN(useTs)) + +/*! \brief HCI Get base of SDU Header buffer. */ +#define HCI_GET_SDU_HDR_BUF(pDataBuf, useTs) (pDataBuf - HCI_GET_SDU_HDR_LEN(useTs)) + /************************************************************************************************** Data Types **************************************************************************************************/ @@ -840,7 +853,7 @@ typedef struct { wsfMsgHdr_t hdr; /*!< \brief Event header. */ uint8_t status; /*!< \brief Status. */ - uint8_t handle; /*!< \brief Connection handle of the CIS or BIS. */ + uint16_t handle; /*!< \brief Connection handle of the CIS or BIS. */ } hciLeSetupIsoDataPathCmdCmplEvt_t; /*! \brief LE remove ISO data path command complete event */ @@ -848,7 +861,7 @@ typedef struct { wsfMsgHdr_t hdr; /*!< \brief Event header. */ uint8_t status; /*!< \brief Status. */ - uint8_t handle; /*!< \brief Connection handle of the CIS or BIS. */ + uint16_t handle; /*!< \brief Connection handle of the CIS or BIS. */ } hciLeRemoveIsoDataPathCmdCmplEvt_t; /*! \brief Config data path command complete event */ @@ -992,7 +1005,7 @@ typedef union hciLeConnCteReqEnableCmdCmplEvt_t leConnCteReqEnableCmdCmpl; /*!< \brief LE connection CTE request enable command complete. */ hciLeConnCteRspEnableCmdCmplEvt_t leConnCteRspEnableCmdCmpl; /*!< \brief LE connection CTE response enable command complete. */ hciLeReadAntennaInfoCmdCmplEvt_t leReadAntennaInfoCmdCmpl; /*!< \brief LE read antenna information command complete. */ - hciLeSetCigParamsCmdCmplEvt_t leSetCigParamsCmdCmpl; /*!< \brief LE set CIG parameters command complete. */ + hciLeSetCigParamsCmdCmplEvt_t leSetCigParamsCmdCmpl; /*!< \brief LE set CIG parameters command complete. */ hciLeRemoveCigCmdCmplEvt_t leRemoveCigCmdCmpl; /*!< \brief LE remove CIG command complete. */ HciLeCisEstEvt_t leCisEst; /*!< \brief LE CIS established. */ HciLeCisReqEvt_t leCisReq; /*!< \brief LE CIS request. */ @@ -1125,7 +1138,7 @@ typedef struct uint32_t sduInterUsec; /*!< \brief Interval, in microseconds, of BIG SDUs. */ uint16_t maxSdu; /*!< \brief Maximum size of an SDU. */ uint16_t mtlMs; /*!< \brief Maximum time in milliseconds. */ - uint8_t rtn; /*!< \brief Retransmitted number. */ + uint8_t rtn; /*!< \brief Retransmission number. */ uint8_t phys; /*!< \brief Transmitter PHYs of packets. */ uint8_t packing; /*!< \brief Sequential or Interleaved packing. */ uint8_t framing; /*!< \brief Unframed or Framed. */ @@ -1315,7 +1328,7 @@ void HciAclRegister(hciAclCback_t aclCback, hciFlowCback_t flowCback); * \return None. */ /*************************************************************************************************/ -void HciIsoRegister(hciAclCback_t isoCback, hciFlowCback_t flowCback); +void HciIsoRegister(hciIsoCback_t isoCback, hciFlowCback_t flowCback); /*************************************************************************************************/ /*! diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/hci_core.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/hci_core.h index c165c07205..922071c989 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/hci_core.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/hci_core.h @@ -6,7 +6,7 @@ * * Copyright (c) 2009-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ #define HCI_CORE_H #include "hci_core_ps.h" +#include "hci_core_iso.h" #include "wsf_queue.h" #include "wsf_os.h" #include "hci_api.h" @@ -61,27 +62,27 @@ typedef struct uint8_t outBufs; /*!< \brief Outstanding ACL buffers sent to controller */ } hciCoreConn_t; -/*! \brief Per-connection structure for OSI packet accounting */ -typedef struct -{ - uint16_t handle; /*!< \brief Connection handle */ -} hciCoreCis_t; - /*! \brief Main control block for dual-chip implementation */ typedef struct { hciCoreConn_t conn[DM_CONN_MAX]; /*!< \brief Connection structures */ - hciCoreCis_t cis[DM_CIS_MAX]; /*!< \brief CIS structures */ + hciCoreCig_t *pCig; /*!< \biref CIG structures */ + hciCoreCis_t *pCis; /*!< \brief CIS structures */ + hciCoreBig_t *pBig; /*!< \brief BIG structures */ + hciCoreBis_t *pBis; /*!< \brief BIS structures */ uint8_t leStates[HCI_LE_STATES_LEN]; /*!< \brief Controller LE supported states */ bdAddr_t bdAddr; /*!< \brief Bluetooth device address */ wsfQueue_t aclQueue; /*!< \brief HCI ACL TX queue */ hciCoreConn_t *pConnRx; /*!< \brief Connection struct for current transport RX packet */ uint16_t maxRxAclLen; /*!< \brief Maximum reassembled RX ACL packet length */ uint16_t bufSize; /*!< \brief Controller ACL data buffer size */ + uint16_t isoBufSize; /*!< \brief ISO buffer size. */ uint8_t aclQueueHi; /*!< \brief Disable flow when this many ACL buffers queued */ uint8_t aclQueueLo; /*!< \brief Enable flow when this many ACL buffers queued */ uint8_t availBufs; /*!< \brief Current avail ACL data buffers */ + uint8_t availIsoBufs; /*!< \brief Current available ISO data buffers. */ uint8_t numBufs; /*!< \brief Controller number of ACL data buffers */ + uint8_t isoNumBufs; /*!< \brief Number of ISO buffers. */ uint8_t whiteListSize; /*!< \brief Controller white list size */ uint8_t numCmdPkts; /*!< \brief Controller command packed count */ uint64_t leSupFeat; /*!< \brief Controller LE supported features */ @@ -170,39 +171,6 @@ void hciCoreConnClose(uint16_t handle); /*************************************************************************************************/ hciCoreConn_t *hciCoreConnByHandle(uint16_t handle); -/*************************************************************************************************/ -/*! - * \brief Perform internal processing on HCI CIS connection open. - * - * \param handle Connection handle. - * - * \return None. - */ -/*************************************************************************************************/ -void hciCoreCisOpen(uint16_t handle); - -/*************************************************************************************************/ -/*! - * \brief Perform internal processing on HCI CIS connection close. - * - * \param handle Connection handle. - * - * \return None. - */ -/*************************************************************************************************/ -void hciCoreCisClose(uint16_t handle); - -/*************************************************************************************************/ -/*! - * \brief Get a CIS connection structure by handle - * - * \param handle Connection handle. - * - * \return Pointer to CIS connection structure or NULL if not found. - */ -/*************************************************************************************************/ -hciCoreCis_t *hciCoreCisByHandle(uint16_t handle); - /*************************************************************************************************/ /*! * \brief Send ACL data to transport. diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/hci_core_iso.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/hci_core_iso.h new file mode 100644 index 0000000000..55292efbdd --- /dev/null +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/hci_core_iso.h @@ -0,0 +1,397 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief HCI core ISO interfaces. + * + * Copyright (c) 2019-2021 Packetcraft, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_CORE_ISO_H +#define HCI_CORE_ISO_H + +#include "hci_core_ps.h" +#include "wsf_queue.h" +#include "wsf_os.h" +#include "hci_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief ISO Function table indicies. */ +enum +{ + HCI_CORE_CIS, /*!< \brief HCI core for CIS. */ + HCI_CORE_BIS, /*!< \brief HCI core for BIS. */ + + HCI_CORE_TOTAL_ISO_TYPES /*!< \brief Total number of HCI core types. */ +}; + +/*! \brief Get ISO header length. */ +#define HCI_GET_ISO_DATA_HDR_LEN(pIsoHdr) (HCI_ISO_HDR_LEN + (((pIsoHdr)->tsFlag) ? HCI_ISO_DL_MAX_LEN : HCI_ISO_DL_MIN_LEN) + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief Data structure for unpacked ISO data packet. */ +typedef struct +{ + uint8_t *pData; /*!< Beginning of data buffer. */ + + /* ISO Header. */ + uint16_t handle; /*!< ISO Handle. */ + uint8_t pb; /*!< Packet boundary. */ + bool_t tsFlag; /*!< Timestamp flag. */ + uint16_t isoLen; /*!< ISO data load length. */ + + /* Data load. */ + uint32_t ts; /*!< Timestamp (If exists). */ + uint16_t sn; /*!< Packet sequence number. */ + uint16_t sduLen; /*!< SDU Length. */ + uint8_t ps; /*!< Packet status. */ + uint8_t *pIsoSdu; /*!< ISO SDU buffer. */ +} hciIsoDataPkt_t; + +/*! \brief Data structure for transmit control. */ +typedef struct +{ + uint8_t outBufs; /*!< \brief Currently outgoing buffers. */ + bool_t fragmenting; /*!< \brief Currently fragmenting. */ + hciIsoDataPkt_t *pCurPkt; /*!< \brief Currently transmitting ISO packet if fragmenting. */ + + wsfQueue_t sduQueue; /*!< \brief Queue of SDUs to be transmitted. */ +} hciIsoTxCb_t; + +/*! \brief CIG structure to account for CIS. */ +typedef struct +{ + uint8_t cigId; /*!< \brief CIG ID. */ + uint8_t cisCount; /*!< \brief Number of CIS handles in the CIG. */ + uint8_t activeCis; /*!< \brief Current active CISes on this CIG. */ + uint8_t role; /*!< \brief Role of CIG. */ + uint16_t cisHandles[HCI_MAX_CIS_COUNT]; /*!< \brief Associated CIS handles. */ +} hciCoreCig_t; + +/*! \brief CIS control block. */ +typedef struct +{ + uint16_t handle; /*!< \brief Connection handle */ + hciIsoTxCb_t txCb; /*!< \brief Transmit control block. */ + hciCoreCig_t *pCig; /*!< \brief Associated CIG. */ +} hciCoreCis_t; + +/*! \brief BIG structure to account for BIS. */ +typedef struct +{ + uint8_t bigId; /*!< \brief BIG identifier. */ + uint8_t bigCount; /*!< \brief Number of BIG handles in the BIG. */ + uint8_t activeBis; /*!< \brief Number of active BISes on this BIG. */ + uint8_t role; /*!< \brief Role of BIG. */ + uint16_t bigHandles[HCI_MAX_BIS_COUNT]; /*!< \brief Associated BIS handles. */ +} hciCoreBig_t; + +/*! \brief BIS structure for packet handling. */ +typedef struct +{ + uint16_t handle; /*!< \brief Connection handle. */ + hciCoreBig_t *pBig; /*!< \brief Associated BIG. */ + + /*! \brief role specific data. */ + union + { + struct + { + hciIsoTxCb_t txCb; /*!< \brief Transmit control block. */ + } slv; /*!< \brief Slave specific role data. */ + /* struct mst; */ /*!< \brief Master specific role data. */ + } roleData; +} hciCoreBis_t; + +/*! \brief ISO Rx reassembly function signature. */ +typedef uint8_t *(*hciIsoReassembleCb_t)(uint8_t *pData); + +/*! \brief ISO Tx complete call back function signature. */ +typedef void (*hciIsoTxReadyCb_t)(uint8_t bufs); + +/*! \brief ISO open group function signature. */ +typedef void (*hciIsoGroupOpenCb_t)(uint8_t id, uint8_t count, uint16_t *pHandles, uint8_t role); + +/*! \brief ISO close group function signature. */ +typedef void (*hciIsoGroupCloseCb_t)(uint8_t id); + +/*! \brief ISO open function signature. */ +typedef void (*hciCoreIsoConnOpenClose_t)(uint16_t handle); + +/*! \brief ISO get control block function signature. */ +typedef void *(*hciCoreIsoFindByHandle_t)(uint16_t handle); + +/* ISO connection open and close, and get a control block function interface */ +typedef struct +{ + hciCoreIsoConnOpenClose_t connClose; + hciCoreIsoConnOpenClose_t connOpen; + hciCoreIsoFindByHandle_t findByHandle; + hciIsoGroupOpenCb_t groupOpen; + hciIsoGroupCloseCb_t groupClose; +} isoFcnIf_t; + +/* \brief ISO component function interface table. */ +extern isoFcnIf_t *isoFcnIfTbl[HCI_CORE_TOTAL_ISO_TYPES]; + +/*! \brief CIG control blocks. */ +extern hciCoreCig_t hciCoreCig[HCI_MAX_CIG_COUNT]; + +/*! \brief CIS control blocks. */ +extern hciCoreCis_t hciCoreCis[HCI_MAX_CIS_COUNT]; + +/*! \brief BIG control blocks. */ +extern hciCoreBig_t hciCoreBig[HCI_MAX_BIG_COUNT]; + +/*! \brief BIS control blocks. */ +extern hciCoreBis_t hciCoreBis[HCI_MAX_BIS_COUNT]; + +/*! \brief ISO reassemble Rx packet function. */ +extern hciIsoReassembleCb_t hciIsoReassembleCb; + +/*! \brief ISO Tx complete datapath handler function. */ +extern hciIsoTxReadyCb_t hciIsoTxReadyCb; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/**************************************************************************************************/ +/*! + * \brief Initialize HCI ISO resources. + * + * \return None. + */ +/*************************************************************************************************/ +void HciCoreIsoInit(void); + +/*************************************************************************************************/ +/*! + * \brief Allocate a Big connection structure. + * + * \param BigId Big identifier. + * \param bisCount Count of BIS associated with this Big. + * \param pBisHandles List of BIS handles asoociated with this Big. + * \param role Role of Big. + * + * \return None. + */ +/*************************************************************************************************/ +void hciCoreBigOpen(uint8_t bigId, uint8_t bigCount, uint16_t *pBigHandles, uint8_t role); + +/*************************************************************************************************/ +/*! + * \brief Free a Big connection structure. + * + * \param BigId Big identifier. + */ +/*************************************************************************************************/ +void hciCoreBigClose(uint8_t bigId); + +/*************************************************************************************************/ +/*! + * \brief Perform internal processing on HCI BIS open. + * + * \param handle Connection handle. + * + * \return None. + */ +/*************************************************************************************************/ +void hciCoreBisOpen(uint16_t handle); + +/*************************************************************************************************/ +/*! + * \brief Perform internal processing on HCI BIS close. + * + * \param handle Connection handle. + * + * \return None. + */ +/*************************************************************************************************/ +void hciCoreBisClose(uint16_t handle); + +/*************************************************************************************************/ +/*! + * \brief Get a BIS structure by handle + * + * \param handle Connection handle. + * + * \return Pointer to BIS connection structure or NULL if not found. + */ +/*************************************************************************************************/ +void* hciCoreBisByHandle(uint16_t handle); + +/*************************************************************************************************/ +/*! + * \brief Open CIG. + * + * \param cigId CIG identifier. + * \param numCis Number of CIS in this CIG. + * \param pCisHandles Handle list of CIS in this CIG. + * \param role Role of CIG. + * + * \return None. + */ +/*************************************************************************************************/ +void hciCoreCigOpen(uint8_t cigId, uint8_t numCis, uint16_t *pCisHandles, uint8_t role); + +/*************************************************************************************************/ +/*! + * \brief Close CIG context. + * + * \param cigId CIG identifier. + * + * \return None. + */ +/*************************************************************************************************/ +void hciCoreCigClose(uint8_t cigId); + +/*************************************************************************************************/ +/*! + * \brief Open CIS. + * + * \param handle Connection handle. + * + * \return None. + */ +/*************************************************************************************************/ +void hciCoreCisOpen(uint16_t handle); + +/*************************************************************************************************/ +/*! + * \brief Close CIS. + * + * \param handle Connection handle. + * + * \return None. + */ +/*************************************************************************************************/ +void hciCoreCisClose(uint16_t handle); + +/*************************************************************************************************/ +/*! + * \brief Get a CIS connection structure by handle + * + * \param handle Connection handle. + * + * \return Pointer to CIS connection structure or NULL if not found. + */ +/*************************************************************************************************/ +void* hciCoreCisByHandle(uint16_t handle); + +/**************************************************************************************************/ +/*! + * \brief Initialize HCI ISO common resources. + * + * \return None. + */ +/*************************************************************************************************/ +void hciCoreIsoCommonInit(void); + +/*************************************************************************************************/ +/*! + * \brief Send ISO data. + * + * \param handle ISO Handle to send data to. + * \param len Length of data. + * \param pData Data buffer. + * + * \return TRUE if data was succefully sent. FALSE if not. + */ +/*************************************************************************************************/ +bool_t hciSendIsoData(uint16_t handle, uint16_t len, uint8_t *pData, bool_t useTs, uint32_t ts); + +/*************************************************************************************************/ +/*! + * \brief Unpack an ISO header. + * + * \param pData Packet buffer. + * \param pIsoPkt Unpacked packet header. + * + * \return None. + */ +/*************************************************************************************************/ +void hciCoreUnpackIsoDataPkt(uint8_t *pData, hciIsoDataPkt_t *pIsoPkt); + +/*************************************************************************************************/ +/*! + * \brief Pack a ISO data packet into data buffer for Tx. + * + * \param pData Data buffer. + * \param pIsoPkt ISO Packet. + * + * \return total bytes used by ISO Header. + */ +/*************************************************************************************************/ +uint8_t hciCorePackIsoDataPkt(uint8_t *pBuf, hciIsoDataPkt_t *pIsoPkt); + +/*************************************************************************************************/ +/*! + * \brief Reassembled Rx ISO packet. + * + * \param pData Data buffer. + * + * \return Reassembled packet if finished reassembling. NULL if packet is still pending reassembly. + */ +/*************************************************************************************************/ +uint8_t *hciCoreIsoReassembly(uint8_t *pData); + +/*************************************************************************************************/ +/*! + * \brief Service TX Datapath. + * + * \param bufs Freed buffers. + * + * \return None. + */ +/*************************************************************************************************/ +void hciCoreIsoTxReady(uint8_t bufs); + +/*************************************************************************************************/ +/*! + * \brief Close Tx control block. + * + * \param pTxCb Tx control block. + * \param handle ISO handle. + */ +/*************************************************************************************************/ +void hciCoreClearIsoTxCb(hciIsoTxCb_t *pTxCb, uint16_t handle); + +/*************************************************************************************************/ +/*! + * \brief Get ISO buffer size. + * + * \param len Length of ISO data. + * + * \return ISO buffer size. + */ +/*************************************************************************************************/ +uint16_t HciGetIsoBufSize(uint16_t len); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_CORE_ISO_H */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/hci_tr.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/hci_tr.h index 243f2e4c70..ff9a794351 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/hci_tr.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/hci_tr.h @@ -6,7 +6,7 @@ * * Copyright (c) 2009-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/common/hci_core.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/common/hci_core.c index fe9a1f0cba..f43b98cc0a 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/common/hci_core.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/common/hci_core.c @@ -6,7 +6,7 @@ * * Copyright (c) 2009-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ #include #include "wsf_types.h" +#include "wsf_math.h" #include "wsf_msg.h" #include "wsf_trace.h" #include "wsf_assert.h" @@ -57,7 +58,18 @@ #endif /************************************************************************************************** - Local Variables + Local Functions +**************************************************************************************************/ + +static void hciCoreIsoNullOpenCloseFunction(uint16_t handle); +static void *hciCoreNullFindByHandleFunction(uint16_t handle); +static uint8_t *hciCoreNullAssembleIsoFunction(uint8_t *pData); +static void hciCoreNullOpenGroupFunction(uint8_t id, uint8_t count, uint16_t *pHandles, uint8_t role); +static void hciCoreNullCloseGroupFUnction(uint8_t id); +static void hciCoreNullIsoTxReady(uint8_t bufs); + +/************************************************************************************************** + Global Variables **************************************************************************************************/ /* Event mask */ @@ -142,9 +154,28 @@ uint64_t hciLeSupFeatCfg = HCI_LE_SUP_FEAT_STABLE_MOD_IDX_TRANSMITTER | /* Stable Modulation Index - Transmitter supported */ HCI_LE_SUP_FEAT_STABLE_MOD_IDX_RECEIVER; /* Stable Modulation Index - Receiver supported */ -/************************************************************************************************** - Global Variables -**************************************************************************************************/ +/* Default ISO function inteface */ +static const isoFcnIf_t isoFcnDefault = +{ + hciCoreIsoNullOpenCloseFunction, + hciCoreIsoNullOpenCloseFunction, + hciCoreNullFindByHandleFunction, + hciCoreNullOpenGroupFunction, + hciCoreNullCloseGroupFUnction +}; + +/* Component function interface table indexed ISO type */ +isoFcnIf_t *isoFcnIfTbl[HCI_CORE_TOTAL_ISO_TYPES] = +{ + (isoFcnIf_t *) &isoFcnDefault, /* HCI_CORE_CIS */ + (isoFcnIf_t *) &isoFcnDefault, /* HCI_CORE_BIS */ +}; + +/* Assembling received ISO data */ +hciIsoReassembleCb_t hciIsoReassembleCb = hciCoreNullAssembleIsoFunction; + +/* Servicing ISO TX data path */ +hciIsoTxReadyCb_t hciIsoTxReadyCb = hciCoreNullIsoTxReady; /* Control block */ hciCoreCb_t hciCoreCb; @@ -309,120 +340,6 @@ void hciCoreConnClose(uint16_t handle) hciCoreConnFree(handle); } -/*************************************************************************************************/ -/*! - * \brief Allocate a CIS connection structure. - * - * \param handle Connection handle. - * - * \return None. - */ -/*************************************************************************************************/ -static void hciCoreCisAlloc(uint16_t handle) -{ - uint8_t i; - hciCoreCis_t *pCis = hciCoreCb.cis; - - /* find available connection struct */ - for (i = DM_CIS_MAX; i > 0; i--, pCis++) - { - if (pCis->handle == HCI_HANDLE_NONE) - { - /* allocate and initialize */ - pCis->handle = handle; - - return; - } - } - - HCI_TRACE_WARN0("HCI cis struct alloc failure"); -} - -/*************************************************************************************************/ -/*! - * \brief Free a CIS connection structure. - * - * \param handle Connection handle. - * - * \return None. - */ -/*************************************************************************************************/ -static void hciCoreCisFree(uint16_t handle) -{ - uint8_t i; - hciCoreCis_t *pCis = hciCoreCb.cis; - - /* find connection struct */ - for (i = DM_CIS_MAX; i > 0; i--, pCis++) - { - if (pCis->handle == handle) - { - /* free structure */ - pCis->handle = HCI_HANDLE_NONE; - - return; - } - } - - HCI_TRACE_WARN1("hciCoreCisFree handle not found:%u", handle); -} - -/*************************************************************************************************/ -/*! - * \brief Get a CIS connection structure by handle - * - * \param handle Connection handle. - * - * \return Pointer to CIS connection structure or NULL if not found. - */ -/*************************************************************************************************/ -hciCoreCis_t *hciCoreCisByHandle(uint16_t handle) -{ - uint8_t i; - hciCoreCis_t *pCis = hciCoreCb.cis; - - /* find available connection struct */ - for (i = DM_CIS_MAX; i > 0; i--, pCis++) - { - if (pCis->handle == handle) - { - return pCis; - } - } - - return NULL; -} - -/*************************************************************************************************/ -/*! - * \brief Perform internal processing on HCI CIS connection open. - * - * \param handle Connection handle. - * - * \return None. - */ -/*************************************************************************************************/ -void hciCoreCisOpen(uint16_t handle) -{ - /* allocate CIS connection structure */ - hciCoreCisAlloc(handle); -} - -/*************************************************************************************************/ -/*! - * \brief Perform internal processing on HCI CIS connection close. - * - * \param handle Connection handle. - * - * \return None. - */ -/*************************************************************************************************/ -void hciCoreCisClose(uint16_t handle) -{ - /* free CIS connection structure */ - hciCoreCisFree(handle); -} - /*************************************************************************************************/ /*! * \brief Send ACL data to transport. @@ -469,15 +386,7 @@ void hciCoreTxReady(uint8_t bufs) uint16_t len; hciCoreConn_t *pConn; - /* increment available buffers, with ceiling */ - if (bufs > 0) - { - hciCoreCb.availBufs += bufs; - if (hciCoreCb.availBufs > hciCoreCb.numBufs) - { - hciCoreCb.availBufs = hciCoreCb.numBufs; - } - } + hciCoreCb.availBufs = WSF_MIN(hciCoreCb.availBufs + bufs, hciCoreCb.numBufs); /* service ACL data queue and send as many buffers as we can */ while (hciCoreCb.availBufs > 0) @@ -822,11 +731,6 @@ void HciCoreInit(void) hciCoreCb.conn[i].handle = HCI_HANDLE_NONE; } - for (i = 0; i < DM_CIS_MAX; i++) - { - hciCoreCb.cis[i].handle = HCI_HANDLE_NONE; - } - hciCoreCb.maxRxAclLen = HCI_MAX_RX_ACL_LEN; hciCoreCb.aclQueueHi = HCI_ACL_QUEUE_HI; hciCoreCb.aclQueueLo = HCI_ACL_QUEUE_LO; @@ -953,8 +857,8 @@ void HciSendAclData(uint8_t *pData) /* look up connection structure */ if ((pConn = hciCoreConnByHandle(handle)) != NULL) { - /* if queue empty and buffers available */ - if (WsfQueueEmpty(&hciCoreCb.aclQueue) && hciCoreCb.availBufs > 0) + /* if queue empty, buffers available and no HCI fragmentation in progress */ + if (WsfQueueEmpty(&hciCoreCb.aclQueue) && (hciCoreCb.availBufs > 0) && (pConn->fragmenting == FALSE)) { /* send data */ hciCoreTxAclStart(pConn, len, pData); @@ -984,3 +888,94 @@ void HciSendAclData(uint8_t *pData) HCI_TRACE_WARN1("HciSendAclData discarding buffer, handle=%u", handle); } } + +/************************************************************************************************** + ISO EMPTY FUNCTIONS +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Default empty function for closing ISO control blocks. + * + * \param handle ISO handle + * + * \return None. + */ +/*************************************************************************************************/ +static void hciCoreIsoNullOpenCloseFunction(uint16_t handle) +{ + return; +} + +/*************************************************************************************************/ +/*! + * \brief Default empty function for finding ISO handle. + * + * \param handle ISO handle + * + * \return Pointer to CIS connection structure or NULL if not found. + */ +/*************************************************************************************************/ +static void *hciCoreNullFindByHandleFunction(uint16_t handle) +{ + return NULL; +} + +/*************************************************************************************************/ +/*! + * \brief Default empty function for opening a ISO group + * + * \param id Group identifier. + * \param count Count of handles associated. + * \param pHandles Associated handles. + * \param role Role of group. + * + */ +/*************************************************************************************************/ +static void hciCoreNullOpenGroupFunction(uint8_t id, uint8_t count, uint16_t *pHandles, uint8_t role) +{ + return; +} + +/*************************************************************************************************/ +/*! + * \brief Default empty function for closing a ISO group + * + * \param id Group identifier. + * + */ +/*************************************************************************************************/ +static void hciCoreNullCloseGroupFUnction(uint8_t id) +{ + return; +} +/*************************************************************************************************/ +/*! + * \brief Default empty function for assembling received ISO data. + * + * \param handle ISO handle + * + * \return pointer to ISO packet to send, or NULL if no packet to send. + */ +/*************************************************************************************************/ +static uint8_t *hciCoreNullAssembleIsoFunction(uint8_t *pData) +{ + /* discard buffer */ + WsfMsgFree(pData); + + return NULL; +} + +/*************************************************************************************************/ +/*! + * \brief Default empty function for servicing the ISO TX data path. + * + * \param handle ISO handle + * + * \return None. + */ +/*************************************************************************************************/ +static void hciCoreNullIsoTxReady(uint8_t bufs) +{ + return; +} diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_cmd_bis.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_cmd_bis.c index 6f9ec7d069..c228396b25 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_cmd_bis.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_cmd_bis.c @@ -4,7 +4,7 @@ * * \brief HCI Broadcast Isochronous Stream (BIS) command module. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,7 +31,7 @@ /*************************************************************************************************/ /*! - * \brief HCI LE create BGS command. + * \brief HCI LE create BIG command. * * \param pCreateBis Create BIG parameters. * diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_cmd_cis.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_cmd_cis.c index e78a247822..6f4bac6d87 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_cmd_cis.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_cmd_cis.c @@ -4,7 +4,7 @@ * * \brief HCI Connected Isochronous Stream (CIS) command module. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,8 @@ #include "hci_cmd.h" #include "hci_api.h" #include "hci_main.h" +#include "hci_core_iso.h" +#include "hci_defs.h" /*************************************************************************************************/ /*! @@ -94,10 +96,10 @@ void HciLeCreateCisCmd(uint8_t numCis, HciCisCreateCisParams_t *pCreateCisParam) p = pBuf + HCI_CMD_HDR_LEN; UINT8_TO_BSTREAM(p, numCis); - for (; numCis > 0; numCis--, pCreateCisParam++) + for (uint8_t i = 0; i < numCis; i++) { - UINT16_TO_BSTREAM(p, *pCreateCisParam->pCisHandle); - UINT16_TO_BSTREAM(p, *pCreateCisParam->pAclHandle); + UINT16_TO_BSTREAM(p, pCreateCisParam->pCisHandle[i]); + UINT16_TO_BSTREAM(p, pCreateCisParam->pAclHandle[i]); } hciCmdSend(pBuf); diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_cmd_cte.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_cmd_cte.c index 8011183f9f..9ef87d48b9 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_cmd_cte.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_cmd_cte.c @@ -1,4 +1,4 @@ -/*************************************************************************************************/ +/*************************************************************************************************/ /*! * \file * diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_core_ps.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_core_ps.c index 0730013ce6..3a34697628 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_core_ps.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_core_ps.c @@ -6,7 +6,7 @@ * * Copyright (c) 2009-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ * limitations under the License. * * This module implements core platform-dependent HCI features for transmit data path, receive - * data path, the “optimization” API, and the main event handler. This module contains separate + * data path, the 'optimization' API, and the main event handler. This module contains separate * implementations for dual chip and single chip. */ /*************************************************************************************************/ @@ -39,6 +39,8 @@ #include "hci_api.h" #include "hci_main.h" +#include "mbed_wsf_trace.h" + /*************************************************************************************************/ /*! * \brief HCI core initialization. @@ -65,9 +67,14 @@ void hciCoreNumCmplPkts(uint8_t *pMsg) uint8_t numHandles; uint16_t bufs; uint16_t handle; + uint8_t availBufs = 0; hciCoreConn_t *pConn; + uint8_t isoAvailBufs = 0; + hciCoreCis_t *pCis; + hciCoreBis_t *pBis; + /* parse number of handles */ BSTREAM_TO_UINT8(numHandles, pMsg); @@ -96,10 +103,39 @@ void hciCoreNumCmplPkts(uint8_t *pMsg) (*hciCb.flowCback)(handle, FALSE); } } + + else if ((pCis = isoFcnIfTbl[HCI_CORE_CIS]->findByHandle(handle)) != NULL) + { + pCis->txCb.outBufs -= (uint8_t) bufs; + + isoAvailBufs += (uint8_t) bufs; + + /* TODO: Flow control callback once CIS fragmentation is implemented. */ + } + + else if ((pBis = isoFcnIfTbl[HCI_CORE_BIS]->findByHandle(handle)) != NULL) + { + if (pBis->pBig->role == HCI_ROLE_MASTER) + { + /* Should not happen, but protect the master role data. */ + HCI_TRACE_WARN1("BIS Master received NUM_CMPL_PKTS evt. Handle=%d", pBis->handle); + isoAvailBufs += (uint8_t) bufs; + return; + } + + pBis->roleData.slv.txCb.outBufs -= (uint8_t) bufs; + + isoAvailBufs += (uint8_t) bufs; + + /* TODO: Flow control callback once BIS fragmentation is implemented. */ + } } - /* service TX data path */ + /* service ACL TX data path */ hciCoreTxReady(availBufs); + + /* service ISO TX datapath */ + hciIsoTxReadyCb(isoAvailBufs); } /*************************************************************************************************/ @@ -193,16 +229,11 @@ void HciCoreHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) /* Handle ISO data */ else { - if (hciCb.isoCback) + if ((pBuf = hciIsoReassembleCb(pBuf)) != NULL) { /* Call ISO callback; client will free buffer */ hciCb.isoCback(pBuf); } - else - { - /* free buffer */ - WsfMsgFree(pBuf); - } } } } diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_core_ps.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_core_ps.h index 41f07e8c25..ca05edfada 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_core_ps.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_core_ps.h @@ -24,12 +24,12 @@ #ifndef HCI_CORE_PS_H #define HCI_CORE_PS_H +#include "wsf_types.h" + #ifdef __cplusplus extern "C" { #endif -#include "wsf_types.h" - /************************************************************************************************** Function Declarations **************************************************************************************************/ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_evt.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_evt.c index fd708ea2dd..2e22c55080 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_evt.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/hci/dual_chip/hci_evt.c @@ -6,7 +6,7 @@ * * Copyright (c) 2009-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,7 @@ #include "hci_evt.h" #include "hci_cmd.h" #include "hci_core.h" +#include "hci_core_iso.h" #ifdef WSF_DETOKEN_TRACE #include "wsf_detoken.h" @@ -54,6 +55,17 @@ /* Length of fixed parameters in each individual report */ #define HCI_LE_ADV_REPORT_INDIV_LEN 10 +/* Size of different fields in LE create BIG complete and LE BIG sync established events */ +#define HCI_LE_BIG_SYNC_DELAY_SIZE 3 /* Size of sync delay field */ +#define HCI_LE_BIG_TRANS_LAT_SIZE 3 /* Size of tranport latency field */ +#define HCI_LE_BIG_PHY_SIZE 1 /* Size of PHY field */ +#define HCI_LE_BIG_NSE_SIZE 1 /* Size of NSE field */ +#define HCI_LE_BIG_BN_SIZE 1 /* Size of BN field */ +#define HCI_LE_BIG_PTO_SIZE 1 /* Size of PTO field */ +#define HCI_LE_BIG_IRC_SIZE 1 /* Size of IRC field */ +#define HCI_LE_BIG_MAX_PDU_SIZE 2 /* Size of max PDU field */ +#define HCI_LE_BIG_ISO_INT_SIZE 2 /* Size of ISO interval field */ + /************************************************************************************************** Data Types **************************************************************************************************/ @@ -124,6 +136,7 @@ static void hciEvtParseLeSetConnCteTxParamsCmdCmpl(hciEvt_t *pMsg, uint8_t *p, u static void hciEvtParseLeConnCteReqEnableCmdCmpl(hciEvt_t *pMsg, uint8_t *p, uint8_t len); static void hciEvtParseLeConnCteRspEnableCmdCmpl(hciEvt_t *pMsg, uint8_t *p, uint8_t len); static void hciEvtParseLeReadAntennaInfoCmdCmpl(hciEvt_t *pMsg, uint8_t *p, uint8_t len); +#if HCI_VER_BT >= HCI_VER_BT_CORE_SPEC_5_2 static void hciEvtParseLeCisEst(hciEvt_t *pMsg, uint8_t *p, uint8_t len); static void hciEvtParseLeCisReq(hciEvt_t *pMsg, uint8_t *p, uint8_t len); static void hciEvtParseLeReqPeerScaCmpl(hciEvt_t *pMsg, uint8_t *p, uint8_t len); @@ -141,6 +154,7 @@ static void hciEvtParseLeBigSyncEst(hciEvt_t *pMsg, uint8_t *p, uint8_t len); static void hciEvtParseLeBigSyncLost(hciEvt_t *pMsg, uint8_t *p, uint8_t len); static void hciEvtParseLeBigTermSyncCmpl(hciEvt_t *pMsg, uint8_t *p, uint8_t len); static void hciEvtParseLeBigInfoAdvRpt(hciEvt_t *pMsg, uint8_t *p, uint8_t len); +#endif // HCI_VER_BT_CORE_SPEC_5_2 /************************************************************************************************** Local Variables @@ -329,44 +343,12 @@ static const uint8_t hciEvtCbackLen[] = sizeof(HciLeBigSyncLostEvt_t), sizeof(HciLeBigTermSyncCmplEvt_t), sizeof(HciLeBigInfoAdvRptEvt_t) -#endif +#endif // HCI_VER_BT_CORE_SPEC_5_2 }; /* Global event statistics. */ static hciEvtStats_t hciEvtStats = {0}; - -/*************************************************************************************************/ -/*! - * \brief Parse an HCI event. - * - * \param pMsg Pointer to output event message structure. - * \param p Pointer to input HCI event parameter byte stream. - * \param len Parameter byte stream length. - * - * \return None. - */ -/*************************************************************************************************/ -static void hciEvtParseLeConnCmpl(hciEvt_t *pMsg, uint8_t *p, uint8_t len) -{ - BSTREAM_TO_UINT8(pMsg->leConnCmpl.status, p); - BSTREAM_TO_UINT16(pMsg->leConnCmpl.handle, p); - BSTREAM_TO_UINT8(pMsg->leConnCmpl.role, p); - BSTREAM_TO_UINT8(pMsg->leConnCmpl.addrType, p); - BSTREAM_TO_BDA(pMsg->leConnCmpl.peerAddr, p); - BSTREAM_TO_UINT16(pMsg->leConnCmpl.connInterval, p); - BSTREAM_TO_UINT16(pMsg->leConnCmpl.connLatency, p); - BSTREAM_TO_UINT16(pMsg->leConnCmpl.supTimeout, p); - BSTREAM_TO_UINT8(pMsg->leConnCmpl.clockAccuracy, p); - - /* zero out unused fields */ - memset(pMsg->leConnCmpl.localRpa, 0, BDA_ADDR_LEN); - memset(pMsg->leConnCmpl.peerRpa, 0, BDA_ADDR_LEN); - - pMsg->hdr.param = pMsg->leConnCmpl.handle; - pMsg->hdr.status = pMsg->leConnCmpl.status; -} - #ifndef CORDIO_RPA_SWAP_WORKAROUND #define CORDIO_RPA_SWAP_WORKAROUND 0 #endif @@ -391,6 +373,37 @@ static bool_t isAddressInvalid(uint8_t *p) } #endif // CORDIO_RPA_SWAP_WORKAROUND +/*************************************************************************************************/ +/*! + * \brief Parse an HCI event. + * + * \param pMsg Pointer to output event message structure. + * \param p Pointer to input HCI event parameter byte stream. + * \param len Parameter byte stream length. + * + * \return None. + */ +/*************************************************************************************************/ +static void hciEvtParseLeConnCmpl(hciEvt_t *pMsg, uint8_t *p, uint8_t len) +{ + BSTREAM_TO_UINT8(pMsg->leConnCmpl.status, p); + BSTREAM_TO_UINT16(pMsg->leConnCmpl.handle, p); + BSTREAM_TO_UINT8(pMsg->leConnCmpl.role, p); + BSTREAM_TO_UINT8(pMsg->leConnCmpl.addrType, p); + BSTREAM_TO_BDA(pMsg->leConnCmpl.peerAddr, p); + BSTREAM_TO_UINT16(pMsg->leConnCmpl.connInterval, p); + BSTREAM_TO_UINT16(pMsg->leConnCmpl.connLatency, p); + BSTREAM_TO_UINT16(pMsg->leConnCmpl.supTimeout, p); + BSTREAM_TO_UINT8(pMsg->leConnCmpl.clockAccuracy, p); + + /* zero out unused fields */ + memset(pMsg->leConnCmpl.localRpa, 0, BDA_ADDR_LEN); + memset(pMsg->leConnCmpl.peerRpa, 0, BDA_ADDR_LEN); + + pMsg->hdr.param = pMsg->leConnCmpl.handle; + pMsg->hdr.status = pMsg->leConnCmpl.status; +} + /*************************************************************************************************/ /*! * \brief Parse an HCI event. @@ -408,21 +421,9 @@ static void hciEvtParseLeEnhancedConnCmpl(hciEvt_t *pMsg, uint8_t *p, uint8_t le BSTREAM_TO_UINT16(pMsg->leConnCmpl.handle, p); BSTREAM_TO_UINT8(pMsg->leConnCmpl.role, p); BSTREAM_TO_UINT8(pMsg->leConnCmpl.addrType, p); - -#if CORDIO_RPA_SWAP_WORKAROUND - if (isAddressInvalid(p)) { - memset(pMsg->leConnCmpl.peerRpa, 0x00, BDA_ADDR_LEN); - p += BDA_ADDR_LEN; - BSTREAM_TO_BDA(pMsg->leConnCmpl.localRpa, p); - BSTREAM_TO_BDA(pMsg->leConnCmpl.peerAddr, p); - } else -#endif // CORDIO_RPA_SWAP_WORKAROUND - { - BSTREAM_TO_BDA(pMsg->leConnCmpl.peerAddr, p); - BSTREAM_TO_BDA(pMsg->leConnCmpl.localRpa, p); - BSTREAM_TO_BDA(pMsg->leConnCmpl.peerRpa, p); - } - + BSTREAM_TO_BDA(pMsg->leConnCmpl.peerAddr, p); + BSTREAM_TO_BDA(pMsg->leConnCmpl.localRpa, p); + BSTREAM_TO_BDA(pMsg->leConnCmpl.peerRpa, p); BSTREAM_TO_UINT16(pMsg->leConnCmpl.connInterval, p); BSTREAM_TO_UINT16(pMsg->leConnCmpl.connLatency, p); BSTREAM_TO_UINT16(pMsg->leConnCmpl.supTimeout, p); @@ -1901,6 +1902,7 @@ static void hciEvtParseLeReadAntennaInfoCmdCmpl(hciEvt_t *pMsg, uint8_t *p, uint pMsg->hdr.status = pMsg->leReadAntennaInfoCmdCmpl.status; } +#if HCI_VER_BT >= HCI_VER_BT_CORE_SPEC_5_2 /*************************************************************************************************/ /*! * \brief Process an HCI LE CIS established event. @@ -2022,7 +2024,7 @@ static void hciEvtParseLeSetCigParamsCmdCmpl(hciEvt_t *pMsg, uint8_t *p, uint8_t */ /*************************************************************************************************/ static void hciEvtParseLeRemoveCigCmdCmpl(hciEvt_t *pMsg, uint8_t *p, uint8_t len) -{ +{ BSTREAM_TO_UINT8(pMsg->leRemoveCigCmdCmpl.status, p); BSTREAM_TO_UINT8(pMsg->leRemoveCigCmdCmpl.cigId, p); @@ -2042,9 +2044,9 @@ static void hciEvtParseLeRemoveCigCmdCmpl(hciEvt_t *pMsg, uint8_t *p, uint8_t le */ /*************************************************************************************************/ static void hciEvtParseLeSetupIsoDataPathCmdCmpl(hciEvt_t *pMsg, uint8_t *p, uint8_t len) -{ +{ BSTREAM_TO_UINT8(pMsg->leSetupIsoDataPathCmdCmpl.status, p); - BSTREAM_TO_UINT8(pMsg->leSetupIsoDataPathCmdCmpl.handle, p); + BSTREAM_TO_UINT16(pMsg->leSetupIsoDataPathCmdCmpl.handle, p); pMsg->hdr.status = pMsg->leSetupIsoDataPathCmdCmpl.status; pMsg->hdr.param = pMsg->leSetupIsoDataPathCmdCmpl.handle; @@ -2062,9 +2064,9 @@ static void hciEvtParseLeSetupIsoDataPathCmdCmpl(hciEvt_t *pMsg, uint8_t *p, uin */ /*************************************************************************************************/ static void hciEvtParseLeRemoveIsoDataPathCmdCmpl(hciEvt_t *pMsg, uint8_t *p, uint8_t len) -{ +{ BSTREAM_TO_UINT8(pMsg->leRemoveIsoDataPathCmdCmpl.status, p); - BSTREAM_TO_UINT8(pMsg->leRemoveIsoDataPathCmdCmpl.handle, p); + BSTREAM_TO_UINT16(pMsg->leRemoveIsoDataPathCmdCmpl.handle, p); pMsg->hdr.status = pMsg->leRemoveIsoDataPathCmdCmpl.status; pMsg->hdr.param = pMsg->leRemoveIsoDataPathCmdCmpl.handle; @@ -2082,7 +2084,7 @@ static void hciEvtParseLeRemoveIsoDataPathCmdCmpl(hciEvt_t *pMsg, uint8_t *p, ui */ /*************************************************************************************************/ static void hciEvtParseConfigDataPathCmdCmpl(hciEvt_t *pMsg, uint8_t *p, uint8_t len) -{ +{ BSTREAM_TO_UINT8(pMsg->configDataPathCmdCmpl.status, p); pMsg->hdr.status = pMsg->configDataPathCmdCmpl.status; @@ -2198,7 +2200,7 @@ static void hciEvtParseReadLocalSupCodecCapCmdCmpl(hciEvt_t *pMsg, uint8_t *p, u */ /*************************************************************************************************/ static void hciEvtParseReadLocalSupCtrDlyCmdCmpl(hciEvt_t *pMsg, uint8_t *p, uint8_t len) -{ +{ BSTREAM_TO_UINT8(pMsg->readLocalSupCtrDlyCmdCmpl.status, p); BSTREAM_TO_UINT24(pMsg->readLocalSupCtrDlyCmdCmpl.minDly, p); BSTREAM_TO_UINT24(pMsg->readLocalSupCtrDlyCmdCmpl.maxDly, p); @@ -2239,7 +2241,7 @@ static void hciEvtParseLeCreateBigCmpl(hciEvt_t *pMsg, uint8_t *p, uint8_t len) { BSTREAM_TO_UINT16(pMsg->leCreateBigCmpl.bisHandle[i], p); } - + if (numBis > HCI_MAX_BIS_COUNT) { /* ignore remaining BIS handles */ @@ -2383,6 +2385,114 @@ static void hciEvtParseLeBigInfoAdvRpt(hciEvt_t *pMsg, uint8_t *p, uint8_t len) pMsg->hdr.param = pMsg->leBigInfoAdvRpt.syncHandle; } +/*************************************************************************************************/ +/*! + * \brief Process an HCI LE set CIG parameters command complete event. + * + * \param p Pointer to input HCI event parameter byte stream. + * \param len Parameter byte stream length. + * + * \return None. + */ +/*************************************************************************************************/ +static void hciEvtProcessLeSetCigParamCmdCmpl(uint8_t *p, uint8_t len) +{ + uint8_t cigId; + uint8_t numCis; + uint16_t cisHandle[HCI_MAX_CIS_COUNT]; + + BSTREAM_TO_UINT8(cigId, p); + BSTREAM_TO_UINT8(numCis, p); + + if (numCis > HCI_MAX_CIS_COUNT) + { + numCis = HCI_MAX_CIS_COUNT; + } + + for (uint8_t i = 0; i < numCis; i++) + { + BSTREAM_TO_UINT16(cisHandle[i], p); + } + + isoFcnIfTbl[HCI_CORE_CIS]->groupOpen(cigId, numCis, cisHandle, HCI_ROLE_MASTER); +} +#endif // HCI_VER_BT_CORE_SPEC_5_2 + +/*************************************************************************************************/ +/*! + * \brief Process an HCI LE create BIG complete event. + * + * \param p Pointer to input HCI event parameter byte stream. + * \param len Parameter byte stream length. + * + * \return None. + */ +/*************************************************************************************************/ +static void hciEvtProcessLeCreateBigCmpl(uint8_t *p, uint8_t len) +{ + uint8_t bigHandle; + uint8_t numBis; + uint16_t bisHandle[HCI_MAX_BIS_COUNT]; + + BSTREAM_TO_UINT8(bigHandle, p); /* BIG Handle. */ + + /* skip over these fields */ + p += HCI_LE_BIG_SYNC_DELAY_SIZE + HCI_LE_BIG_TRANS_LAT_SIZE + HCI_LE_BIG_PHY_SIZE + HCI_LE_BIG_NSE_SIZE + + HCI_LE_BIG_BN_SIZE + HCI_LE_BIG_PTO_SIZE + HCI_LE_BIG_IRC_SIZE + HCI_LE_BIG_MAX_PDU_SIZE + + HCI_LE_BIG_ISO_INT_SIZE; + + BSTREAM_TO_UINT8(numBis, p); + + if (numBis > HCI_MAX_BIS_COUNT) + { + numBis = HCI_MAX_BIS_COUNT; + } + + for (uint8_t i = 0; i < numBis; i++) + { + BSTREAM_TO_UINT16(bisHandle[i], p); + } + + isoFcnIfTbl[HCI_CORE_BIS]->groupOpen(bigHandle, numBis, bisHandle, HCI_ROLE_SLAVE); +} + +/*************************************************************************************************/ +/*! + * \brief Process an HCI LE BIG sync established event. + * + * \param p Pointer to input HCI event parameter byte stream. + * \param len Parameter byte stream length. + * + * \return None. + */ +/*************************************************************************************************/ +static void hciEvtProcessLeBigSyncEst(uint8_t *p, uint8_t len) +{ + uint8_t bigHandle; + uint8_t numBis; + uint16_t bisHandle[HCI_MAX_BIS_COUNT]; + + BSTREAM_TO_UINT8(bigHandle, p); /* BIG Handle. */ + + /* skip over these fields */ + p += HCI_LE_BIG_TRANS_LAT_SIZE + HCI_LE_BIG_NSE_SIZE + HCI_LE_BIG_BN_SIZE + HCI_LE_BIG_PTO_SIZE + + HCI_LE_BIG_IRC_SIZE + HCI_LE_BIG_MAX_PDU_SIZE + HCI_LE_BIG_ISO_INT_SIZE; + + BSTREAM_TO_UINT8(numBis, p); + + if (numBis > HCI_MAX_BIS_COUNT) + { + numBis = HCI_MAX_BIS_COUNT; + } + + for (uint8_t i = 0; i < numBis; i++) + { + BSTREAM_TO_UINT16(bisHandle[i], p); + } + + isoFcnIfTbl[HCI_CORE_BIS]->groupOpen(bigHandle, numBis, bisHandle, HCI_ROLE_MASTER); +} + /*************************************************************************************************/ /*! * \brief Process HCI command status event with failure status. @@ -2625,14 +2735,33 @@ void hciEvtProcessCmdCmpl(uint8_t *p, uint8_t len) #if HCI_VER_BT >= HCI_VER_BT_CORE_SPEC_5_2 case HCI_OPCODE_LE_SET_CIG_PARAMS: + if (*p == HCI_SUCCESS) + { + /* Skip status. */ + hciEvtProcessLeSetCigParamCmdCmpl(p + 1, len - 1); + } cbackEvt = HCI_LE_SET_CIG_PARAMS_CMD_CMPL_CBACK_EVT; break; +#endif case HCI_OPCODE_LE_REMOVE_CIG: + if (*p == HCI_SUCCESS) + { + uint8_t *pBuf = p + 1; + uint8_t cigId; + BSTREAM_TO_UINT8(cigId, pBuf); + isoFcnIfTbl[HCI_CORE_CIS]->groupClose(cigId); + } cbackEvt = HCI_LE_REMOVE_CIG_CMD_CMPL_CBACK_EVT; break; case HCI_OPCODE_LE_BIG_TERMINATE_SYNC: + if (*p == HCI_SUCCESS) + { + uint8_t bigId; + BYTES_TO_UINT16(bigId, (p + 1)); + isoFcnIfTbl[HCI_CORE_BIS]->groupClose(bigId); + } cbackEvt = HCI_LE_BIG_TERM_SYNC_CMPL_CBACK_EVT; break; @@ -2659,7 +2788,6 @@ void hciEvtProcessCmdCmpl(uint8_t *p, uint8_t len) case HCI_OPCODE_READ_LOCAL_SUP_CONTROLLER_DLY: cbackEvt = HCI_READ_LOCAL_SUP_CTR_DLY_CMD_CMPL_CBACK_EVT; break; -#endif default: /* test for vendor specific command completion OGF. */ @@ -2741,6 +2869,7 @@ void hciEvtProcessMsg(uint8_t *pEvt) uint8_t cbackEvt = 0; hciEvt_t *pMsg; uint16_t handle; + uint8_t bigHandle; hciEvtCback_t cback = hciCb.evtCback; /* parse HCI event header */ @@ -2895,11 +3024,12 @@ void hciEvtProcessMsg(uint8_t *pEvt) #if HCI_VER_BT >= HCI_VER_BT_CORE_SPEC_5_2 case HCI_LE_CIS_EST_EVT: - /* if CIS connection created successfully */ if (*pEvt == HCI_SUCCESS) { BYTES_TO_UINT16(handle, (pEvt + 1)); - hciCoreCisOpen(handle); + + /* allocate CIS connection structure */ + isoFcnIfTbl[HCI_CORE_CIS]->connOpen(handle); } cbackEvt = HCI_LE_CIS_EST_CBACK_EVT; break; @@ -2907,22 +3037,43 @@ void hciEvtProcessMsg(uint8_t *pEvt) case HCI_LE_CIS_REQ_EVT: cbackEvt = HCI_LE_CIS_REQ_CBACK_EVT; break; +#endif case HCI_LE_CREATE_BIG_CMPL_EVT: + if (*pEvt == HCI_SUCCESS) + { + /* Skip status. */ + hciEvtProcessLeCreateBigCmpl(pEvt + 1, len - 1); + } cbackEvt = HCI_LE_CREATE_BIG_CMPL_CBACK_EVT; break; case HCI_LE_TERMINATE_BIG_CMPL_EVT: + { + bigHandle = *pEvt; + + isoFcnIfTbl[HCI_CORE_BIS]->groupClose(bigHandle); cbackEvt = HCI_LE_TERM_BIG_CMPL_CBACK_EVT; break; + } case HCI_LE_BIG_SYNC_EST_EVT: + if (*pEvt == HCI_SUCCESS) + { + /* Skip status. */ + hciEvtProcessLeBigSyncEst(pEvt + 1, len - 1); + } cbackEvt = HCI_LE_BIG_SYNC_EST_CBACK_EVT; break; case HCI_LE_BIG_SYNC_LOST_EVT: + { + bigHandle = *pEvt; + + isoFcnIfTbl[HCI_CORE_BIS]->groupClose(bigHandle); cbackEvt = HCI_LE_BIG_SYNC_LOST_CBACK_EVT; break; + } case HCI_LE_REQ_PEER_SCA_CMPLT_EVT: cbackEvt = HCI_LE_REQ_PEER_SCA_CBACK_EVT; @@ -2931,7 +3082,6 @@ void hciEvtProcessMsg(uint8_t *pEvt) case HCI_LE_BIG_INFO_ADV_REPORT_EVT: cbackEvt = HCI_LE_BIG_INFO_ADV_REPORT_CBACK_EVT; break; -#endif default: break; @@ -2944,7 +3094,7 @@ void hciEvtProcessMsg(uint8_t *pEvt) /* if disconnect is for CIS connection */ BYTES_TO_UINT16(handle, (pEvt + 1)); #if HCI_VER_BT >= HCI_VER_BT_CORE_SPEC_5_2 - if (hciCoreCisByHandle(handle) != NULL) + if ((isoFcnIfTbl[HCI_CORE_CIS]->findByHandle(handle) != NULL)) { cbackEvt = HCI_CIS_DISCONNECT_CMPL_CBACK_EVT; } @@ -3041,7 +3191,7 @@ void hciEvtProcessMsg(uint8_t *pEvt) else if (cbackEvt == HCI_CIS_DISCONNECT_CMPL_CBACK_EVT) { BYTES_TO_UINT16(handle, (pEvt + 1)); - hciCoreCisClose(handle); + isoFcnIfTbl[HCI_CORE_CIS]->connClose(handle); } #endif } diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/sec/common/sec_ecc_debug.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/sec/common/sec_ecc_debug.c index e146af4f5d..e8e2496fc3 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/sec/common/sec_ecc_debug.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/sec/common/sec_ecc_debug.c @@ -155,5 +155,5 @@ void SecEccInit() } -#endif /* SEC_ECC_CFG */ + #endif /* SEC_ECC_CFG */ #endif /* defined(SEC_ECC_CFG) */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_eatt.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_eatt.c index 330d9efe93..cb79a0fd4d 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_eatt.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_eatt.c @@ -70,6 +70,15 @@ eattCb_t eattCb; eattChanCb_t eattChanCb[DM_CONN_MAX][EATT_CONN_CHAN_MAX]; #endif +/* Default component function inteface */ +const eattFcnIf_t eattFcnDefault = +{ + attEmptyL2cCocDataCback, + attEmptyL2cCocCback, + (attMsgHandler_t) attEmptyHandler, + attEmptyConnCback +}; + /************************************************************************************************** External Variables **************************************************************************************************/ @@ -415,7 +424,16 @@ static void eattL2cEnChanInd(l2cCocEnConnectInd_t *pMsg) pChanCb->cid = pMsg->cidList[i]; pChanCb->peerMtu = pMsg->mtu; pChanCb->localMtu = pEattCfg->mtu; - pChanCb->priority = pEattCfg->pPriorityTbl[slot - 1]; + + if (pEattCfg->pPriorityTbl) + { + pChanCb->priority = pEattCfg->pPriorityTbl[slot - 1]; + } + else + { + pChanCb->priority = slot; + } + pChanCb->inUse = TRUE; eattUpdateMtu(connId, slot); @@ -551,34 +569,39 @@ static void eattL2cDataCnf(l2cCocDataCnf_t *pMsg) { attCcb_t *pCcb = attCcbByConnId((dmConnId_t) pMsg->hdr.param); - if (pCcb) + /* verify connection is open */ + if (pCcb && pCcb->connId != DM_CONN_ID_NONE) { uint8_t slot = eattGetSlotId((dmConnId_t) pMsg->hdr.param, pMsg->cid); if (slot != ATT_BEARER_SLOT_INVALID) { - /* verify connection is open */ - if (pCcb && pCcb->connId != DM_CONN_ID_NONE) + EATT_TRACE_INFO2("eattL2cDataCnf: slot: %d, status %d", slot, pMsg->hdr.status); + + if (pMsg->hdr.status == L2C_COC_DATA_ERR_OVERFLOW) { - if (pMsg->hdr.event == L2C_CTRL_FLOW_DISABLE_IND) + for (uint8_t i = 0; i < EATT_CONN_CHAN_MAX; i++) { /* flow disabled */ - pCcb->sccb[slot].control |= ATT_CCB_STATUS_FLOW_DISABLED; + pCcb->sccb[i].control |= ATT_CCB_STATUS_FLOW_DISABLED; } - else + } + else + { + for (uint8_t i = 0; i < EATT_CONN_CHAN_MAX; i++) { /* flow enabled */ - pCcb->sccb[slot].control &= ~ATT_CCB_STATUS_FLOW_DISABLED; + pCcb->sccb[i].control &= ~ATT_CCB_STATUS_FLOW_DISABLED; + } - /* call server control callback */ + /* call server control callback */ + (*attCb.pEnServer->l2cCocCnf)((l2cCocEvt_t*) pMsg); + + /* check flow again; could be changed recursively */ + if (!(pCcb->sccb[slot].control & ATT_CCB_STATUS_FLOW_DISABLED)) + { + /* call client control callback */ (*attCb.pEnClient->l2cCocCnf)((l2cCocEvt_t*) pMsg); - - /* check flow again; could be changed recursively */ - if (!(pCcb->sccb[slot].control & ATT_CCB_STATUS_FLOW_DISABLED)) - { - /* call client control callback */ - (*attCb.pEnClient->l2cCocCnf)((l2cCocEvt_t*) pMsg); - } } } } @@ -681,7 +704,7 @@ void EattEstablishChannels(dmConnId_t connId) { eattConnCb_t *pCcb = eattGetConnCb(connId); - EATT_TRACE_INFO1("EattEstablishChannels: connId: %#x", connId); + EATT_TRACE_INFO1("EattEstablishChannels: connId: 0x%x", connId); if (pCcb) { @@ -895,11 +918,40 @@ static void eattL2cDataReq(attCcb_t *pCcb, uint8_t slot, uint16_t len, uint8_t * WsfMsgFree(pPacket); } +/*************************************************************************************************/ +/*! + * \brief Empty l2c coc callback for ATT. + * + * \param pMsg L2CAP coc event message. + * + * \return None. + */ +/*************************************************************************************************/ +void attEmptyL2cCocDataCback(l2cCocEvt_t *pMsg) +{ + l2cCocDataInd_t *pDataInd = &pMsg->dataInd; + dmConnId_t connId = (dmConnId_t) pDataInd->hdr.param; + uint8_t slot = eattGetSlotId(connId, pDataInd->cid); + attCcb_t *pCcb = attCcbByConnId(connId); + + /* get connection control block for this connId, ignore packet if not found */ + if (pCcb) + { + /* parse opcode */ + uint8_t opcode = *(pDataInd->pData); + + attSendOpNotSupportedErr(pCcb, slot, opcode); + } +} + /*************************************************************************************************/ /*! * \brief Initialize the Enhanced ATT subsystem. * * \return None + * + * \note EattInit must be called after the ATT task is created and before calling EattsInit + * and/or EattcInit. */ /*************************************************************************************************/ void EattInit(uint8_t roleBits) @@ -927,6 +979,9 @@ void EattInit(uint8_t roleBits) /* Register functions with ATT control block */ attCb.eattHandler = eattHandler; attCb.eattL2cDataReq = eattL2cDataReq; + + attCb.pEnServer = &eattFcnDefault; + attCb.pEnClient = &eattFcnDefault; /* Set the channel control blocks in the connection control blocks */ #if EATT_CONN_CHAN_MAX > 0 diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_eatt.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_eatt.h index 8927fa5746..3c63e98066 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_eatt.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_eatt.h @@ -76,6 +76,7 @@ uint8_t eattGetSlotId(dmConnId_t connId, uint16_t cid); eattConnCb_t *eattGetConnCb(dmConnId_t connId); void eattHandler(wsfMsgHdr_t *pMsg); void eattExecCallback(dmConnId_t connId, uint8_t event, uint8_t status); +void attEmptyL2cCocDataCback(l2cCocEvt_t *pMsg); #ifdef __cplusplus }; diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_main.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_main.c index e21a307666..a675a05906 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_main.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_main.c @@ -64,7 +64,7 @@ const attFcnIf_t attFcnDefault = }; /* Default component function inteface */ -const eattFcnIf_t eattFcnDefault = +const eattFcnIf_t attEattFcnDefault = { attEmptyL2cCocCback, attEmptyL2cCocCback, @@ -249,9 +249,7 @@ void attEmptyConnCback(attCcb_t *pCcb, dmEvt_t *pDmEvt) /*! * \brief Empty l2c coc callback for ATT. * - * \param handle The connection handle. - * \param len The length of the L2CAP payload data in pPacket. - * \param pPacket A buffer containing the packet. + * \param pMsg L2CAP coc event message. * * \return None. */ @@ -274,7 +272,16 @@ void attEmptyL2cCocCback(l2cCocEvt_t *pMsg) /*************************************************************************************************/ void attEmptyDataCback(uint16_t handle, uint16_t len, uint8_t *pPacket) { - return; + attCcb_t *pCcb = attCcbByHandle(handle); + + /* get connection control block for this handle, ignore packet if not found */ + if (pCcb) + { + /* parse opcode */ + uint8_t opcode = *(pPacket + L2C_PAYLOAD_START); + + attSendOpNotSupportedErr(pCcb, ATT_BEARER_SLOT_ID, opcode); + } } /*************************************************************************************************/ @@ -361,6 +368,61 @@ void attSetMtu(attCcb_t *pCcb, uint8_t slot, uint16_t peerMtu, uint16_t localMtu } } +/*************************************************************************************************/ +/*! + * \brief Send an error response PDU. + * + * \param handle The connection handle. + * \param opcode Opcode of the request that generated this error. + * \param attHandle Attribute handle in request, if applicable. + * \param reason Error reason. + * + * \return None. + */ +/*************************************************************************************************/ +void attErrRsp(attCcb_t *pCcb, uint8_t slot, uint8_t opcode, uint16_t attHandle, uint8_t reason) +{ + uint8_t *pBuf; + uint8_t *p; + + /* allocate buffer */ + if ((pBuf = attMsgAlloc(L2C_PAYLOAD_START + ATT_ERR_RSP_LEN)) != NULL) + { + p = pBuf + L2C_PAYLOAD_START; + UINT8_TO_BSTREAM(p, ATT_PDU_ERR_RSP); + UINT8_TO_BSTREAM(p, opcode); + UINT16_TO_BSTREAM(p, attHandle); + UINT8_TO_BSTREAM(p, reason); + + attL2cDataReq(pCcb, slot, ATT_ERR_RSP_LEN, pBuf); + } +} + +/*************************************************************************************************/ +/*! + * \brief Handle a not supported opcode, sending an error if necessary. + * + * \param pCcb Pointer to control block. + * \param slot ATT bearer slot. + * \param opcode Opcode. + * + * \return None. + */ +/*************************************************************************************************/ +void attSendOpNotSupportedErr(attCcb_t *pCcb, uint8_t slot, uint8_t opcode) +{ + if (opcode & ATT_PDU_MASK_COMMAND) + { + ATT_TRACE_WARN1("ATTC subsystem not registered for opcode: 0x%02x - Command bit set - Ingnoring command", opcode); + return; + } + + ATT_TRACE_WARN1("ATTC subsystem not registered for opcode: 0x%02x", opcode); + + /* Send error */ + attErrRsp(pCcb, slot, opcode, 0, ATT_ERR_NOT_SUP); +} + /*************************************************************************************************/ /*! * \brief Execute application callback function. @@ -484,8 +546,8 @@ void AttHandlerInit(wsfHandlerId_t handlerId) /* initialize control block */ attCb.pClient = &attFcnDefault; attCb.pServer = &attFcnDefault; - attCb.pEnServer = &eattFcnDefault; - attCb.pEnClient = &eattFcnDefault; + attCb.pEnServer = &attEattFcnDefault; + attCb.pEnClient = &attEattFcnDefault; /* Register with L2C */ L2cRegister(L2C_CID_ATT, attL2cDataCback, attL2cCtrlCback); diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_main.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_main.h index cdb6f524ba..9d5f8820eb 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_main.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_main.h @@ -78,6 +78,7 @@ extern "C" { #define ATT_CCB_STATUS_TX_TIMEOUT (1<<2) /* ATT transaction timed out */ #define ATT_CCB_STATUS_RSP_PENDING (1<<3) /* ATTS write rsp pending */ #define ATT_CCB_STATUS_CNF_PENDING (1<<4) /* ATTC confirm pending */ +#define ATT_CCB_STATUS_CONTEXT_LOCK (1<<5) /* Slot held until API is processed in ATT */ /* Number of ATT bearers */ #define ATT_BEARER_MAX (EATT_CONN_CHAN_MAX + 1) @@ -190,6 +191,9 @@ void attL2cDataReq(attCcb_t *pCcb, uint8_t slot, uint16_t len, uint8_t *pPacket) uint16_t attMsgParam(dmConnId_t connId, uint8_t slot); void attDecodeMsgParam(uint16_t param, dmConnId_t *pConnId, uint8_t *pSlot); +void attErrRsp(attCcb_t *pCcb, uint8_t slot, uint8_t opcode, uint16_t attHandle, uint8_t reason); +void attSendOpNotSupportedErr(attCcb_t *pCcb, uint8_t slot, uint8_t opcode); + #ifdef __cplusplus }; #endif diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_uuid.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_uuid.c index 52cda51039..b062b35261 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_uuid.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/att_uuid.c @@ -6,7 +6,7 @@ * * Copyright (c) 2011-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,7 +46,7 @@ const uint8_t attNwaSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_NET const uint8_t attWdsSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_WATCHDOG_SERVICE)}; const uint8_t attHrsSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_HEART_RATE_SERVICE)}; const uint8_t attPassSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_PHONE_ALERT_SERVICE)}; -const uint8_t attBasSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_BATTERY_SERVICE)}; +const uint8_t attBattSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_BATTERY_SERVICE)}; const uint8_t attBpsSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_BLOOD_PRESSURE_SERVICE)}; const uint8_t attAnsSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_ALERT_NOTIF_SERVICE)}; const uint8_t attHidSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_HID_SERVICE)}; @@ -57,6 +57,15 @@ const uint8_t attMprvSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_MES const uint8_t attMprxSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_MESH_PROXY_SERVICE)}; const uint8_t attWssSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_WEIGHT_SCALE_SERVICE)}; const uint8_t attCteSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_CONSTANT_TONE_SERVICE)}; +const uint8_t attAicsSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_AUDIO_INPUT_CTRL_SERVICE)}; +const uint8_t attMicsSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_MICROPHONE_CTRL_SERVICE)}; +const uint8_t attVcsSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_VOLUME_CTRL_SERVICE)}; +const uint8_t attVocsSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_VOLUME_OFFSET_CTRL_SERVICE)}; +const uint8_t attPacSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_PUB_AUDIO_CAP_SERVICE)}; +const uint8_t attAscSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_AUDIO_STRM_CTRL_SERVICE)}; +const uint8_t attBasSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_BCAST_AUDIO_SCAN_SERVICE)}; +const uint8_t attBscAaSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_BASIC_AUDIO_ANNC_SERVICE)}; +const uint8_t attBcstAaSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_BCAST_AUDIO_ANNC_SERVICE)}; /*! GATT UUIDs */ const uint8_t attPrimSvcUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_PRIMARY_SERVICE)}; @@ -100,7 +109,7 @@ const uint8_t attRtiChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_REF const uint8_t attTbChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_TIME_BROADCAST)}; const uint8_t attTucpChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_TIME_UPDATE_CP)}; const uint8_t attTusChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_TIME_UPDATE_STATE)}; -const uint8_t attGlmChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_GLUCOSE_MEAS)}; +const uint8_t attGlmChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_GLUCOSE_MEAS)}; const uint8_t attBlChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_BATTERY_LEVEL)}; const uint8_t attBpsChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_BATTERY_POWER_STATE)}; const uint8_t attBlsChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_BATTERY_LEVEL_STATE)}; @@ -189,3 +198,27 @@ const uint8_t attCteTxDurChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_CTE const uint8_t attCteIntChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_CTE_INTERVAL)}; const uint8_t attCtePhyChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_CTE_PHY)}; const uint8_t attSsfChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_SERVER_SUPPORTED_FEATURES)}; +const uint8_t attAicsStChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_AIC_INPUT_STATE)}; +const uint8_t attAicsGsaChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_AIC_GAIN_SETTING_ATTR)}; +const uint8_t attAicsItChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_AIC_INPUT_TYPE)}; +const uint8_t attAicsStatChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_AIC_INPUT_STATUS)}; +const uint8_t attAicsAicChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_AIC_AUDIO_INPUT_CTRL)}; +const uint8_t attAicsAidhUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_AIC_AUDIO_INPUT_DESC)}; +const uint8_t attMicsMuteChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_MC_MUTE)}; +const uint8_t attVcsStateChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_VOLUME_STATE)}; +const uint8_t attVcsCpChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_VOLUME_CONTROL_POINT)}; +const uint8_t attVcsFlagsChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_VOLUME_FLAGS)}; +const uint8_t attVocsStateChUuid[ATT_16_UUID_LEN] ={UINT16_TO_BYTES(ATT_UUID_VOLUME_OFFSET_STATE)}; +const uint8_t attVocsLocChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_AUDIO_LOCATION)}; +const uint8_t attVocsCpChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_VOLUME_OFFSET_CONTROL_PT)}; +const uint8_t attVocsDescChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_AUDIO_OUT_DESC)}; +const uint8_t attSnkPacChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_SNK_PAC)}; +const uint8_t attSnkAudLocChUuid[ATT_16_UUID_LEN] ={UINT16_TO_BYTES(ATT_UUID_SNK_AUDIO_LOC)}; +const uint8_t attSrcPacChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_SRC_PAC)}; +const uint8_t attSrcAudLocChUuid[ATT_16_UUID_LEN] ={UINT16_TO_BYTES(ATT_UUID_SRC_AUDIO_LOC)}; +const uint8_t attAudCntAvChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_AUDIO_CONT_AVAIL)}; +const uint8_t attSupAudCntChUuid[ATT_16_UUID_LEN] ={UINT16_TO_BYTES(ATT_UUID_SUP_AUDIO_CONT)}; +const uint8_t attAseChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_ASE)}; +const uint8_t attAseCpChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_ASE_CP)}; +const uint8_t attBasCpChUuid[ATT_16_UUID_LEN] = {UINT16_TO_BYTES(ATT_UUID_BAS_CP)}; +const uint8_t attBcRxStateChUuid[ATT_16_UUID_LEN] ={UINT16_TO_BYTES(ATT_UUID_BCAST_RX_STATE)}; \ No newline at end of file diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/attc_eatt.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/attc_eatt.c index 45305ddb59..3e7dac6984 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/attc_eatt.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/attc_eatt.c @@ -77,27 +77,41 @@ static uint8_t eattcGetFreeSlot(dmConnId_t connId, uint8_t priority, uint16_t da if (pEattCcb) { - uint8_t i; - - for (i = 0; i < EATT_CONN_CHAN_MAX; i++) + if (pEattCfg->pPriorityTbl) { - attcCcb_t *pCcb; - uint8_t slot = i + 1; + uint8_t i; - if ((pCcb = attcCcbByConnId(connId, slot))) + for (i = 0; i < EATT_CONN_CHAN_MAX; i++) { + uint8_t slot = i + 1; eattChanCb_t *pChanCb = &pEattCcb->pChanCb[i]; - + if (pChanCb->inUse && (pChanCb->priority >= priority) && (pChanCb->localMtu >= dataLen)) { - if (pCcb->outReq.hdr.event == ATTC_MSG_API_NONE) + attcCcb_t *pCcb = attcCcbByConnId(connId, slot); + attCcb_t *pAttCcb = attCcbByConnId(connId); + + if (pAttCcb && !(pAttCcb->sccb[slot].control & ATT_CCB_STATUS_CONTEXT_LOCK)) { - EATT_TRACE_INFO1("eattcGetFreeSlot: allocating slot: %#x", slot); - return slot; + if (pCcb && (pCcb->outReq.hdr.event == ATTC_MSG_API_NONE)) + { + EATT_TRACE_INFO1("eattcGetFreeSlot: allocating slot: 0x%x", slot); + + /* Reserve the slot until the API function is processed in the ATT */ + pAttCcb->sccb[slot].control |= ATT_CCB_STATUS_CONTEXT_LOCK; + + return slot; + } } } } } + else + { + /* If pEattCfg->pPriorityTbl is NULL, the priority parameter is the L2CAP channel index for this connection. */ + WSF_ASSERT(priority < EATT_CONN_CHAN_MAX); + return priority + 1; + } } return ATT_BEARER_SLOT_ID; @@ -149,7 +163,7 @@ static void eattcL2cCocDataInd(l2cCocEvt_t *pEvt) /* else unknown opcode */ else { - ATT_TRACE_WARN1("eattc unknown opcode 0x%02x", opcode); + attSendOpNotSupportedErr(pCcb->pMainCcb, pCcb->slot, opcode); } } else @@ -262,7 +276,7 @@ void eattcSendMsg(dmConnId_t connId, uint8_t priority, uint16_t handle, uint8_t /* allocate message buffer */ if ((pMsg = WsfMsgAlloc(sizeof(attcApiMsg_t))) != NULL) { - EATT_TRACE_INFO2("eattcSendMsg: sending event: %#x slot: %#x", msgId, slot); + EATT_TRACE_INFO2("eattcSendMsg: sending event: 0x%x slot: 0x%x", msgId, slot); /* set parameters */ pMsg->hdr.param = connId; @@ -275,6 +289,16 @@ void eattcSendMsg(dmConnId_t connId, uint8_t priority, uint16_t handle, uint8_t /* send message */ WsfMsgSend(attCb.handlerId, pMsg); } + else + { + attCcb_t *pAttCcb = attCcbByConnId(connId); + + /* Release the slot */ + if (pAttCcb) + { + pAttCcb->sccb[slot].control &= ~ATT_CCB_STATUS_CONTEXT_LOCK; + } + } } else { diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/attc_main.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/attc_main.c index e3e5f43b17..5ce54100e1 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/attc_main.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/attc_main.c @@ -515,7 +515,7 @@ static void attcDataCback(uint16_t handle, uint16_t len, uint8_t *pPacket) /* else unknown opcode */ else { - ATT_TRACE_WARN1("attc unknown opcode 0x%02x", opcode); + attSendOpNotSupportedErr(pCcb->pMainCcb, pCcb->slot, opcode); } } @@ -591,9 +591,9 @@ static void attcConnCback(attCcb_t *pCcb, dmEvt_t *pDmEvt) } /* free any req on deck */ - if (attcCb.onDeck[pCcb->connId - 1].hdr.event != ATTC_MSG_API_NONE) + if (attcCb.onDeck[pCcb->connId-1].hdr.event != ATTC_MSG_API_NONE) { - attcReqClear(pCcb->connId, &attcCb.onDeck[pCcb->connId - 1], status); + attcReqClear(pCcb->connId, &attcCb.onDeck[pCcb->connId-1], status); } for (i = 0; i < ATT_BEARER_MAX; i++) @@ -611,6 +611,7 @@ static void attcConnCback(attCcb_t *pCcb, dmEvt_t *pDmEvt) /* initialize other control block variables */ pCcb->sccb[i].control &= ~ATT_CCB_STATUS_FLOW_DISABLED; pCcb->sccb[i].control &= ~ATT_CCB_STATUS_CNF_PENDING; + pCcb->sccb[i].control &= ~ATT_CCB_STATUS_CONTEXT_LOCK; /* pass to connection close callback for signed data */ if (attcCb.pSign != NULL) @@ -637,7 +638,7 @@ void attcMsgCback(attcApiMsg_t *pMsg) { attcCcb_t *pCcb; - ATT_TRACE_INFO2("attcMsgCback: msg: %#x slot: %#x", pMsg->hdr.event, pMsg->slot); + ATT_TRACE_INFO2("attcMsgCback: msg: 0x%x slot: 0x%x", pMsg->hdr.event, pMsg->slot); /* if signed data event */ if ((pMsg->hdr.event >= ATTC_MSG_API_SIGNED_WRITE_CMD) && (pMsg->hdr.event <= ATTC_MSG_CMAC_CMPL)) @@ -666,13 +667,16 @@ void attcMsgCback(attcApiMsg_t *pMsg) return; } + /* Release the EATT context lock */ + pCcb->pMainCcb->sccb[pMsg->slot].control &= ~ATT_CCB_STATUS_CONTEXT_LOCK; + /* if an API request to send packet (non-signed) */ if (pMsg->hdr.event <= ATTC_MSG_API_READ_MULT_VAR) { /* verify no API request already waiting on deck, in progress, or no pending write command already for this handle */ if (((pCcb->slot == ATT_BEARER_SLOT_ID) && - (attcCb.onDeck[pCcb->connId - 1].hdr.event != ATTC_MSG_API_NONE)) || + (attcCb.onDeck[pCcb->connId-1].hdr.event != ATTC_MSG_API_NONE)) || (pCcb->outReq.hdr.event > ATTC_MSG_API_MTU) || ((pMsg->hdr.event == ATTC_MSG_API_WRITE_CMD) && attcPendWriteCmd(pCcb, pMsg->handle))) @@ -686,7 +690,7 @@ void attcMsgCback(attcApiMsg_t *pMsg) if ((pCcb->slot == ATT_BEARER_SLOT_ID) && (pCcb->outReq.hdr.event == ATTC_MSG_API_MTU)) { /* put request "on deck" for processing later */ - attcCb.onDeck[pCcb->connId - 1] = *pMsg; + attcCb.onDeck[pCcb->connId-1] = *pMsg; } /* otherwise ready to send; set up request */ else @@ -706,9 +710,9 @@ void attcMsgCback(attcApiMsg_t *pMsg) } /* else free any req on deck */ else if ((pCcb->slot == ATT_BEARER_SLOT_ID) & - (attcCb.onDeck[pCcb->connId - 1].hdr.event != ATTC_MSG_API_NONE)) + (attcCb.onDeck[pCcb->connId-1].hdr.event != ATTC_MSG_API_NONE)) { - attcReqClear(pCcb->connId, &attcCb.onDeck[pCcb->connId - 1], ATT_ERR_CANCELLED); + attcReqClear(pCcb->connId, &attcCb.onDeck[pCcb->connId-1], ATT_ERR_CANCELLED); } } /* else if timeout */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/attc_proc.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/attc_proc.c index 0f87518a91..9b63aeaeda 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/attc_proc.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/attc_proc.c @@ -410,13 +410,13 @@ void attcProcRsp(attcCcb_t *pCcb, uint16_t len, uint8_t *pPacket) } /* else if api is on deck */ else if ((pCcb->slot == ATT_BEARER_SLOT_ID) && - (attcCb.onDeck[pCcb->connId - 1].hdr.event != ATTC_MSG_API_NONE)) + (attcCb.onDeck[pCcb->connId-1].hdr.event != ATTC_MSG_API_NONE)) { /* set up and send request */ - attcSetupReq(pCcb, &attcCb.onDeck[pCcb->connId - 1]); + attcSetupReq(pCcb, &attcCb.onDeck[pCcb->connId-1]); /* clear on deck */ - attcCb.onDeck[pCcb->connId - 1].hdr.event = ATTC_MSG_API_NONE; + attcCb.onDeck[pCcb->connId-1].hdr.event = ATTC_MSG_API_NONE; } } } diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/attc_sign.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/attc_sign.c index 9ce745243a..5d2cbb8ece 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/attc_sign.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/attc_sign.c @@ -178,7 +178,7 @@ static void attcSignMsgCback(attcCcb_t *pCcb, attcSignMsg_t *pMsg) /* verify no API request already waiting on deck or in progress, * and no signed write already in progress */ - if ((attcCb.onDeck[pCcb->connId - 1].hdr.event != ATTC_MSG_API_NONE) || + if ((attcCb.onDeck[pCcb->connId-1].hdr.event != ATTC_MSG_API_NONE) || (pCcb->outReq.hdr.event > ATTC_MSG_API_MTU) || (attcSignCbByConnId((dmConnId_t) pMsg->hdr.param) != NULL)) { @@ -238,7 +238,7 @@ static void attcSignMsgCback(attcCcb_t *pCcb, attcSignMsg_t *pMsg) pCcb->pMainCcb->sccb[ATT_BEARER_SLOT_ID].control & ATT_CCB_STATUS_FLOW_DISABLED) { /* put request "on deck" for processing later */ - attcCb.onDeck[pCcb->connId - 1] = pCb->msg; + attcCb.onDeck[pCcb->connId-1] = pCb->msg; } /* otherwise ready to send */ else diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_ccc.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_ccc.c index 3f230970d8..63878c8b98 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_ccc.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_ccc.c @@ -6,7 +6,7 @@ * * Copyright (c) 2011-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -442,6 +442,34 @@ uint16_t AttsCccEnabled(dmConnId_t connId, uint8_t idx) return AttsCccGet(connId, idx); } +/*************************************************************************************************/ +/*! + * \brief Check if a client characteristic configuration descriptor is enabled and if + * the characteristic's security level has been met. + * + * \param connId DM connection ID. + * \param handle Attribute handle of CCC descriptor. + * + * \return Value of the descriptor if security level is met, otherwise zero. + */ +/*************************************************************************************************/ +uint16_t AttsCccEnabledByHandle(dmConnId_t connId, uint16_t handle) +{ + attsCccSet_t *pSet; + uint8_t i; + + /* find handle in handle array */ + for (pSet = attsCccCb.pSet, i = 0; i < attsCccCb.setLen; i++, pSet++) + { + if (pSet->handle == handle) + { + return AttsCccEnabled(connId, i); + } + } + + return 0; +} + /*************************************************************************************************/ /*! * \brief Get number of CCC entries in table. diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_csf.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_csf.c index 89b022cb06..04efcb12ed 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_csf.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_csf.c @@ -6,7 +6,7 @@ * * Copyright (c) 2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -355,7 +355,8 @@ uint8_t AttsCsfWriteFeatures(dmConnId_t connId, uint16_t offset, uint16_t valueL */ (void)offset; - if (valueLen > ATT_CSF_LEN) + /* sanity check on length */ + if (valueLen < ATT_CSF_LEN) { return ATT_ERR_LENGTH; } diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_eatt.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_eatt.c index f0d42a6afe..d2475386e9 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_eatt.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_eatt.c @@ -67,39 +67,117 @@ static const eattFcnIf_t attsFcnIf = extern attsProcFcn_t attsProcFcnTbl[]; extern const uint8_t attsMinPduLen[]; +/*************************************************************************************************/ +/*! + * \brief Check if application callback is pending for indication or a given notification, or + * the maximum number of simultaneous notifications has been reached. + * + * \param pCcb ATTS ind control block. + * \param opcode Operation opcode. + * \param handle Attribute handle. + * + * \return TRUE if app callback's pending or max number of simultaneous notifications reached. + * FALSE, otherwise. + */ +/*************************************************************************************************/ +static bool_t eattsPendIndNtfHandle(attsCcb_t *pCcb, uint8_t opcode, uint16_t handle) +{ + uint8_t pendNtfs; + uint8_t i; + + /* if indication */ + if (opcode == ATT_PDU_VALUE_IND) + { + /* see if callback pending for indication */ + return (pCcb->pendIndHandle == ATT_HANDLE_NONE) ? FALSE : TRUE; + } + + /* initialize number of notification callbacks pending */ + pendNtfs = 0; + + for (i = 0; i < ATT_NUM_SIMUL_NTF; i++) + { + /* if callback pending for notification */ + if (pCcb->pendNtfHandle[i] != ATT_HANDLE_NONE) + { + if (opcode == ATT_PDU_MULT_VALUE_NTF) + { + /* Multiple value notification not used with pending notifications. */ + return TRUE; + } + + /* if callback pending for this handle */ + if (pCcb->pendNtfHandle[i] == handle) + { + /* callback pending for this notification */ + return TRUE; + } + + pendNtfs++; + } + } + + /* no callback is pending for this notification but see if the maximum number of simultaneous + notifications has been reached */ + return (pendNtfs < ATT_NUM_SIMUL_NTF) ? FALSE : TRUE; +} + /*************************************************************************************************/ /*! * \brief Get a channel for transmission of an EATT server message. * - * \param connId DM connection ID. - * \param priority Operation priority. - * \param dataLen Length of value data. + * \param connId DM connection ID. + * \param priority Operation priority. + * \param dataLen Length of value data. + * \param opcode Operation opcode. + * \param handle Attribute handle. * * \return Slot ID */ /*************************************************************************************************/ -static uint8_t eattsGetFreeSlot(dmConnId_t connId, uint8_t priority, uint16_t dataLen) +static uint8_t eattsGetFreeSlot(dmConnId_t connId, uint8_t priority, uint16_t dataLen, + uint8_t opcode, uint16_t handle) { - eattConnCb_t *pCcb = eattGetConnCb(connId); - attCcb_t *pAttCcb = attCcbByConnId(connId); + eattConnCb_t *pEattCcb = eattGetConnCb(connId); - if (pCcb && pAttCcb) + if (pEattCcb) { - uint8_t i; - - for (i = 0; i < EATT_CONN_CHAN_MAX; i++) + if (pEattCfg->pPriorityTbl) { - eattChanCb_t *pChanCb = &pCcb->pChanCb[i]; + uint8_t i; - if (pChanCb->inUse && (pChanCb->priority >= priority) && (pChanCb->localMtu >= dataLen)) + for (i = 0; i < EATT_CONN_CHAN_MAX; i++) { - if (!(pAttCcb->sccb[i].control & ATT_CCB_STATUS_RSP_PENDING)) + uint8_t slot = i + 1; + eattChanCb_t *pChanCb = &pEattCcb->pChanCb[i]; + + if (pChanCb->inUse && (pChanCb->priority >= priority) && (pChanCb->localMtu >= dataLen)) { - EATT_TRACE_INFO1("eattsGetFreeSlot: allocating slot: %#x", i + 1); - return i + 1; + attsCcb_t *pAttsCcb = attsCcbByConnId(connId, slot); + attCcb_t *pAttCcb = attCcbByConnId(connId); + + if (pAttCcb && !(pAttCcb->sccb[slot].control & ATT_CCB_STATUS_RSP_PENDING) && + !(pAttCcb->sccb[slot].control & ATT_CCB_STATUS_CONTEXT_LOCK)) + { + if (pAttsCcb && !(eattsPendIndNtfHandle(pAttsCcb, opcode, handle))) + { + EATT_TRACE_INFO1("eattsGetFreeSlot: allocating slot: 0x%x", slot); + + /* Reserve the slot until the API function is processed in the ATT */ + pAttCcb->sccb[slot].control |= ATT_CCB_STATUS_CONTEXT_LOCK; + + return slot; + } + } } } } + else + { + /* If pEattCfg->pPriorityTbl is NULL, the priority parameter is the L2CAP channel index for this connection. */ + WSF_ASSERT(priority < EATT_CONN_CHAN_MAX); + return priority + 1; + } } return ATT_BEARER_SLOT_ID; @@ -179,11 +257,13 @@ static void eattsL2cCocDataInd(l2cCocEvt_t *pEvt) #if defined(ATTS_ERROR_TEST) && (ATTS_ERROR_TEST == TRUE) if (attCb.errTest != ATT_SUCCESS) { - attsErrRsp(pAttCcb, ATT_BEARER_SLOT_ID, opcode, attHandle, attCb.errTest); + attErrRsp(pAttCcb, ATT_BEARER_SLOT_ID, opcode, attHandle, attCb.errTest); return; } #endif + EATT_TRACE_INFO2("eattsL2cCocDataInd: slot: 0x%x, method: %d", slot, method); + /* if no error process request */ if (!err) { @@ -217,7 +297,7 @@ static void eattsL2cCocDataInd(l2cCocEvt_t *pEvt) if (err && (opcode != ATT_PDU_MTU_REQ) && (opcode != ATT_PDU_VALUE_CNF) && ((opcode & ATT_PDU_MASK_COMMAND) == 0)) { - attsErrRsp(pAttCcb, slot, opcode, attHandle, err); + attErrRsp(pAttCcb, slot, opcode, attHandle, err); } } } @@ -311,7 +391,7 @@ void EattsMultiValueNtf(dmConnId_t connId, uint8_t priority, uint16_t numTuples, WsfTaskLock(); - slot = eattsGetFreeSlot(connId, priority, valueLen + ATT_MULT_VALUE_NTF_BUF_LEN); + slot = eattsGetFreeSlot(connId, priority, valueLen + ATT_MULT_VALUE_NTF_BUF_LEN, ATT_PDU_MULT_VALUE_NTF, 0); WsfTaskUnlock(); @@ -364,6 +444,14 @@ void EattsMultiValueNtf(dmConnId_t connId, uint8_t priority, uint16_t numTuples, if (!msgSent) { + attCcb_t *pAttCcb = attCcbByConnId(connId); + + /* Release the slot */ + if (pAttCcb) + { + pAttCcb->sccb[slot].control &= ~ATT_CCB_STATUS_CONTEXT_LOCK; + } + /* Failed to send the packet, release the slot. */ attExecCallback(connId, ATTS_MULT_VALUE_CNF, 0, ATT_ERR_MEMORY, 0); } @@ -391,7 +479,7 @@ void EattsMultiValueNtf(dmConnId_t connId, uint8_t priority, uint16_t numTuples, void EattsHandleValueInd(dmConnId_t connId, uint8_t priority, uint16_t handle, uint16_t valueLen, uint8_t *pValue) { - uint8_t slot = eattsGetFreeSlot(connId, priority, valueLen); + uint8_t slot = eattsGetFreeSlot(connId, priority, valueLen, ATT_PDU_VALUE_IND, handle); attsHandleValueIndNtf(connId, handle, slot, valueLen, pValue, ATT_PDU_VALUE_IND, FALSE); } @@ -411,7 +499,7 @@ void EattsHandleValueInd(dmConnId_t connId, uint8_t priority, uint16_t handle, u void EattsHandleValueNtf(dmConnId_t connId, uint8_t priority, uint16_t handle, uint16_t valueLen, uint8_t *pValue) { - uint8_t slot = eattsGetFreeSlot(connId, priority, valueLen); + uint8_t slot = eattsGetFreeSlot(connId, priority, valueLen, ATT_PDU_VALUE_NTF, handle); attsHandleValueIndNtf(connId, handle, slot, valueLen, pValue, ATT_PDU_VALUE_NTF, FALSE); } @@ -434,7 +522,7 @@ void EattsHandleValueNtf(dmConnId_t connId, uint8_t priority, uint16_t handle, u void EattsHandleValueIndZeroCpy(dmConnId_t connId, uint8_t priority, uint16_t handle, uint16_t valueLen, uint8_t *pValue) { - uint8_t slot = eattsGetFreeSlot(connId, priority, valueLen); + uint8_t slot = eattsGetFreeSlot(connId, priority, valueLen, ATT_PDU_VALUE_IND, handle); attsHandleValueIndNtf(connId, handle, slot, valueLen, pValue, ATT_PDU_VALUE_IND, TRUE); } @@ -457,7 +545,7 @@ void EattsHandleValueIndZeroCpy(dmConnId_t connId, uint8_t priority, uint16_t ha void EattsHandleValueNtfZeroCpy(dmConnId_t connId, uint8_t priority, uint16_t handle, uint16_t valueLen, uint8_t *pValue) { - uint8_t slot = eattsGetFreeSlot(connId, priority, valueLen); + uint8_t slot = eattsGetFreeSlot(connId, priority, valueLen, ATT_PDU_VALUE_NTF, handle); attsHandleValueIndNtf(connId, handle, slot, valueLen, pValue, ATT_PDU_VALUE_NTF, TRUE); } @@ -496,7 +584,7 @@ void EattsContinueWriteReq(dmConnId_t connId, uint8_t slot, uint16_t handle, uin if (status) { - attsErrRsp(pCcb, slot, ATT_PDU_WRITE_REQ, handle, status); + attErrRsp(pCcb, slot, ATT_PDU_WRITE_REQ, handle, status); } else { diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_ind.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_ind.c index 803f1fefb2..0670e993bd 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_ind.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_ind.c @@ -314,6 +314,9 @@ static void attsIndMsgCback(attsApiMsg_t *pMsg) return; } + /* Release the EATT context lock */ + pCcb->pMainCcb->sccb[pMsg->slot].control &= ~ATT_CCB_STATUS_CONTEXT_LOCK; + /* verify no API message already pending */ if (attsPendIndNtfHandle(pCcb, pMsg->pPkt)) { @@ -499,10 +502,21 @@ void attsHandleValueIndNtf(dmConnId_t connId, uint16_t handle, uint8_t slot, uin } /* if packet wasn't sent and it's a zero-copy packet */ - if (!pktSent && zeroCpy) + if (!pktSent) { - /* free packet buffer provided */ - AttMsgFree(pValue, opcode); + attCcb_t *pAttCcb = attCcbByConnId(connId); + + /* Release the slot */ + if (pAttCcb) + { + pAttCcb->sccb[slot].control &= ~ATT_CCB_STATUS_CONTEXT_LOCK; + } + + if (zeroCpy) + { + /* free packet buffer provided */ + AttMsgFree(pValue, opcode); + } } } @@ -561,9 +575,6 @@ void AttsIndInit(void) uint8_t i, j; attsCcb_t *pCcb; - /* Number of slots times channels cannot excede 0xFF */ - WSF_ASSERT(((ATT_BEARER_MAX) * DM_CONN_MAX) > sizeof(uint8_t)) - /* Initialize control block CCBs */ for (i = 0; i < DM_CONN_MAX; i++) { diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_main.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_main.c index fa38787f1d..9356716935 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_main.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_main.c @@ -196,7 +196,7 @@ static void attsDataCback(uint16_t handle, uint16_t len, uint8_t *pPacket) if (attCb.errTest != ATT_SUCCESS) { BYTES_TO_UINT16(attHandle, pPacket + L2C_PAYLOAD_START + ATT_HDR_LEN); - attsErrRsp(pCcb->pMainCcb, ATT_BEARER_SLOT_ID, opcode, attHandle, attCb.errTest); + attErrRsp(pCcb->pMainCcb, ATT_BEARER_SLOT_ID, opcode, attHandle, attCb.errTest); return; } #endif @@ -234,7 +234,7 @@ static void attsDataCback(uint16_t handle, uint16_t len, uint8_t *pPacket) if (err && (opcode != ATT_PDU_MTU_REQ) && (opcode != ATT_PDU_VALUE_CNF) && ((opcode & ATT_PDU_MASK_COMMAND) == 0)) { - attsErrRsp(pCcb->pMainCcb, ATT_BEARER_SLOT_ID, opcode, attHandle, err); + attErrRsp(pCcb->pMainCcb, ATT_BEARER_SLOT_ID, opcode, attHandle, err); } } @@ -267,6 +267,8 @@ static void attsConnCback(attCcb_t *pCcb, dmEvt_t *pDmEvt) { WsfTimerStop(&pAttsCb->idleTimer); } + + pCcb->sccb[i].control &= ~ATT_CCB_STATUS_CONTEXT_LOCK; } } @@ -323,36 +325,6 @@ static void attsL2cCtrlCback(wsfMsgHdr_t *pMsg) (*attsCb.pInd->ctrlCback)(pMsg); } -/*************************************************************************************************/ -/*! - * \brief Send an error response PDU. - * - * \param handle The connection handle. - * \param opcode Opcode of the request that generated this error. - * \param attHandle Attribute handle in request, if applicable. - * \param reason Error reason. - * - * \return None. - */ -/*************************************************************************************************/ -void attsErrRsp(attCcb_t *pCcb, uint8_t slot, uint8_t opcode, uint16_t attHandle, uint8_t reason) -{ - uint8_t *pBuf; - uint8_t *p; - - /* allocate buffer */ - if ((pBuf = attMsgAlloc(L2C_PAYLOAD_START + ATT_ERR_RSP_LEN)) != NULL) - { - p = pBuf + L2C_PAYLOAD_START; - UINT8_TO_BSTREAM(p, ATT_PDU_ERR_RSP); - UINT8_TO_BSTREAM(p, opcode); - UINT16_TO_BSTREAM(p, attHandle); - UINT8_TO_BSTREAM(p, reason); - - attL2cDataReq(pCcb, slot, ATT_ERR_RSP_LEN, pBuf); - } -} - /*************************************************************************************************/ /*! * \brief Clear the prepared write queue. @@ -366,7 +338,7 @@ void attsClearPrepWrites(attsCcb_t *pCcb) { void *pBuf; - while ((pBuf = WsfQueueDeq(&attsCb.prepWriteQueue[pCcb->connId - 1])) != NULL) + while ((pBuf = WsfQueueDeq(&attsCb.prepWriteQueue[pCcb->connId-1])) != NULL) { WsfBufFree(pBuf); } @@ -492,12 +464,12 @@ void attsCheckPendDbHashReadRsp(void) } else { - attsErrRsp(pCcb, ATT_BEARER_SLOT_ID, ATT_PDU_READ_TYPE_REQ, pCcb->pPendDbHashRsp->startHandle, ATT_ERR_NOT_FOUND); + attErrRsp(pCcb, ATT_BEARER_SLOT_ID, ATT_PDU_READ_TYPE_REQ, pCcb->pPendDbHashRsp->startHandle, ATT_ERR_NOT_FOUND); } } else { - attsErrRsp(pCcb, ATT_BEARER_SLOT_ID, ATT_PDU_READ_TYPE_REQ, pCcb->pPendDbHashRsp->startHandle, ATT_ERR_RESOURCES); + attErrRsp(pCcb, ATT_BEARER_SLOT_ID, ATT_PDU_READ_TYPE_REQ, pCcb->pPendDbHashRsp->startHandle, ATT_ERR_RESOURCES); } /* Free pending state information. */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_main.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_main.h index 72927bc4e4..7127888922 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_main.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_main.h @@ -135,7 +135,7 @@ extern attsCb_t attsCb; attsCcb_t *attsCcbByConnId(dmConnId_t connId, uint8_t slot); attsCcb_t *attsCcbByHandle(uint16_t handle, uint8_t slot); -void attsErrRsp(attCcb_t *pCcb, uint8_t slot, uint8_t opcode, uint16_t attHandle, uint8_t reason); +void attErrRsp(attCcb_t *pCcb, uint8_t slot, uint8_t opcode, uint16_t attHandle, uint8_t reason); void attsClearPrepWrites(attsCcb_t *pCcb); bool_t attsUuidCmp(attsAttr_t *pAttr, uint8_t uuidLen, uint8_t *pUuid); bool_t attsUuid16Cmp(uint8_t *pUuid16, uint8_t uuidLen, uint8_t *pUuid); diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_proc.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_proc.c index 455950e73b..d18c49255b 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_proc.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_proc.c @@ -251,7 +251,7 @@ void attsProcMtuReq(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) if (features & ATTS_CSF_EATT_BEARER) { /* Client set the EATT supported feature. MTU Exchange not permitted */ - attsErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_MTU_REQ, 0, ATT_ERR_NOT_SUP); + attErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_MTU_REQ, 0, ATT_ERR_NOT_SUP); } else { @@ -404,7 +404,7 @@ void attsProcFindInfoReq(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) } else { - attsErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_FIND_INFO_REQ, startHandle, err); + attErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_FIND_INFO_REQ, startHandle, err); } } @@ -480,7 +480,7 @@ void attsProcReadReq(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) if (err) { - attsErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_READ_REQ, handle, err); + attErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_READ_REQ, handle, err); } } @@ -584,6 +584,6 @@ void attsProcReadMultiVarReq(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) if (err) { - attsErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_READ_MULT_VAR_REQ, handle, err); + attErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_READ_MULT_VAR_REQ, handle, err); } } diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_read.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_read.c index 4e168d0525..547c81e9c8 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_read.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_read.c @@ -242,7 +242,7 @@ void attsProcReadBlobReq(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) if (err) { - attsErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_READ_BLOB_REQ, handle, err); + attErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_READ_BLOB_REQ, handle, err); } } @@ -370,7 +370,7 @@ void attsProcFindTypeReq(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) } else { - attsErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_FIND_TYPE_REQ, startHandle, err); + attErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_FIND_TYPE_REQ, startHandle, err); } } @@ -461,7 +461,7 @@ void attsProcReadTypeReq(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) } else { - attsErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_READ_TYPE_REQ, startHandle, ATT_ERR_RESOURCES); + attErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_READ_TYPE_REQ, startHandle, ATT_ERR_RESOURCES); } return; @@ -558,7 +558,7 @@ void attsProcReadTypeReq(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) } else { - attsErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_READ_TYPE_REQ, startHandle, err); + attErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_READ_TYPE_REQ, startHandle, err); } } @@ -670,7 +670,7 @@ void attsProcReadMultReq(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) WsfMsgFree(pBuf); } - attsErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_READ_MULT_REQ, handle, err); + attErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_READ_MULT_REQ, handle, err); } } @@ -833,6 +833,6 @@ void attsProcReadGroupTypeReq(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) } else { - attsErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_READ_GROUP_TYPE_REQ, startHandle, err); + attErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_READ_GROUP_TYPE_REQ, startHandle, err); } } diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_sign.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_sign.c index ce0e54b963..b78c408369 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_sign.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_sign.c @@ -6,7 +6,7 @@ * * Copyright (c) 2011-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -57,9 +57,9 @@ typedef struct attsSignBuf_tag typedef struct { uint32_t signCounter; /* sign counter for this connection */ - uint8_t *pCsrk; /* signing key for this connection */ + uint8_t *pCsrk; /* signing key (CSRK) for this connection */ + bool_t authen; /* TRUE if CSRK was received on authenticated connection */ attsSignBuf_t *pBuf; /* current data being processed */ - bool_t authenticated; /* Indicate if the CSRK is authenticated or not */ } attsSignCcb_t; /* ATTS signed PDU control block */ @@ -93,6 +93,54 @@ static attsSignCcb_t *attsSignCcbByConnId(dmConnId_t connId) return &attsSignCb.ccb[connId - 1]; } +/*************************************************************************************************/ +/*! + * \brief Perform required permission and security checks for a signed write command. + * + * \param connId Connection ID. + * \param handle Attribute handle. + * \param permissions Attribute permissions. + * \param pSignCcb Pointer to ATTS signed PDU connection control block. + * + * \return ATT_SUCCESS if successful or error code on failure. + */ +/*************************************************************************************************/ +static uint8_t attsSignedWritePermissions(dmConnId_t connId, uint16_t handle, uint8_t permissions, + attsSignCcb_t *pSignCcb) +{ + /* verify write permissions */ + if ((permissions & (ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC)) != + (ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC)) + { + return ATT_ERR_WRITE; + } + + /* if peer CSRK not present */ + if (pSignCcb->pCsrk == NULL) + { + return ATT_ERR_AUTH; + } + + /* check if signed write required with authenticated key but key not authenticated */ + if ((permissions & ATTS_PERMIT_WRITE_AUTH) && (pSignCcb->authen == FALSE)) + { + return ATT_ERR_AUTH; + } + + /* authorization check */ + if (permissions & ATTS_PERMIT_WRITE_AUTHORIZ) + { + if (attsCb.authorCback == NULL) + { + return ATT_ERR_AUTHOR; + } + + return (*attsCb.authorCback)(connId, ATTS_PERMIT_WRITE, handle); + } + + return ATT_SUCCESS; +} + /*************************************************************************************************/ /*! * \brief Start processing of data for signed write. @@ -159,6 +207,12 @@ static void attsProcSignedWrite(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) uint16_t handle; uint16_t writeLen; + /* signed write should not be received on encrypted link */ + if (DmConnSecLevel(pCcb->connId) > DM_SEC_LEVEL_NONE) + { + return; + } + /* parse handle, calculate write length */ p = pPacket + L2C_PAYLOAD_START + ATT_HDR_LEN; BSTREAM_TO_UINT16(handle, p); @@ -169,9 +223,9 @@ static void attsProcSignedWrite(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) { /* verify signed write is permitted */ if ((pAttr->settings & ATTS_SET_ALLOW_SIGNED) == 0) - { - return; - } + { + return; + } /* verify that csrk is present */ if (attsSignCcbByConnId(pCcb->pMainCcb->connId)->pCsrk == NULL) { @@ -180,13 +234,13 @@ static void attsProcSignedWrite(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) /* verify basic permissions */ if ((pAttr->permissions & (ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC)) == 0) - { - return; - } + { + return; + } /* verify authentication */ if ((pAttr->permissions & ATTS_PERMIT_WRITE_AUTH) && - (attsSignCcbByConnId(pCcb->pMainCcb->connId)->authenticated == 0)) + (attsSignCcbByConnId(pCcb->pMainCcb->connId)->authen == 0)) { return; } @@ -194,33 +248,33 @@ static void attsProcSignedWrite(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) /* Note: authorization not verified at this stage as it is reserved for lesc writes; authorization occurs latter when the write cb is called */ - /* verify write length, fixed length */ + /* verify write length, fixed length */ if (((pAttr->settings & ATTS_SET_VARIABLE_LEN) == 0) && - (writeLen != pAttr->maxLen)) - { - return; - } + (writeLen != pAttr->maxLen)) + { + return; + } - /* verify write length, variable length */ + /* verify write length, variable length */ if (((pAttr->settings & ATTS_SET_VARIABLE_LEN) != 0) && - (writeLen > pAttr->maxLen)) - { - return; - } + (writeLen > pAttr->maxLen)) + { + return; + } /* allocate buffer to store packet and parameters */ if ((pBuf = WsfBufAlloc(sizeof(attsSignBuf_t) - 1 + len)) != NULL) - { + { /* initialize buffer */ pBuf->pCcb = pCcb->pMainCcb; pBuf->handle = handle; pBuf->writeLen = writeLen; pBuf->connId = pCcb->connId; memcpy(pBuf->packet, (pPacket + L2C_PAYLOAD_START), len); - + /* check if a signed write is already in progress */ pSignCcb = attsSignCcbByConnId(pCcb->connId); - + if (pSignCcb->pBuf != NULL) { /* signed write in progress; queue packet */ @@ -230,9 +284,9 @@ static void attsProcSignedWrite(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) { /* start signed data processing */ attsSignedWriteStart(pSignCcb, pBuf); - } - } - } + } + } + } } /*************************************************************************************************/ @@ -359,15 +413,17 @@ void AttsSignInit(void) * * \param connId DM connection ID. * \param pCsrk Pointer to data signing key (CSRK). - * \param authenticated True if CSRK is authenticated and false otherwise. + * \param authen Whether CSRK was received on authenticated connection. * * \return None. */ /*************************************************************************************************/ -void AttsSetCsrk(dmConnId_t connId, uint8_t *pCsrk, bool_t authenticated) +void AttsSetCsrk(dmConnId_t connId, uint8_t *pCsrk, bool_t authen) { - attsSignCcbByConnId(connId)->pCsrk = pCsrk; - attsSignCcbByConnId(connId)->authenticated = authenticated; + attsSignCcb_t *pSignCcb = attsSignCcbByConnId(connId); + + pSignCcb->pCsrk = pCsrk; + pSignCcb->authen = authen; } /*************************************************************************************************/ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_write.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_write.c index 64d9c6d187..a8824de104 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_write.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/att/atts_write.c @@ -6,7 +6,7 @@ * * Copyright (c) 2009-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -145,8 +145,7 @@ void attsProcWrite(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) { /* err has been set; fail */ } - /* verify write length within max length, fixed size writes within size must be allowed - * as described in CORE SPECIFICATION Version 5.2, Vol 3, Part F, 3.4.5.1 */ + /* verify write length */ else if (writeLen > pAttr->maxLen) { err = ATT_ERR_LENGTH; @@ -157,6 +156,7 @@ void attsProcWrite(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) if ((pAttr->settings & ATTS_SET_WRITE_CBACK) && (pGroup->writeCback != NULL)) { + /* call write callback */ err = (*pGroup->writeCback)(pCcb->pMainCcb->connId, handle, opcode, 0, writeLen, pPacket, pAttr); } @@ -207,7 +207,7 @@ void attsProcWrite(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) } else { - attsErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_WRITE_REQ, handle, err); + attErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_WRITE_REQ, handle, err); } } } @@ -265,7 +265,7 @@ void attsProcPrepWriteReq(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) err = ATT_ERR_LENGTH; } /* verify prepare write queue limit not reached */ - else if (WsfQueueCount(&attsCb.prepWriteQueue[pCcb->connId - 1]) >= pAttCfg->numPrepWrites) + else if (WsfQueueCount(&attsCb.prepWriteQueue[pCcb->connId-1]) >= pAttCfg->numPrepWrites) { err = ATT_ERR_QUEUE_FULL; } @@ -275,7 +275,7 @@ void attsProcPrepWriteReq(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) err = ATT_ERR_RESOURCES; } else if ((pAttr->settings & ATTS_SET_WRITE_CBACK) && - (pGroup->writeCback != NULL)) + (pGroup->writeCback != NULL)) { err = (*pGroup->writeCback)(pCcb->connId, handle, ATT_PDU_PREP_WRITE_REQ, 0, writeLen, pPacket, pAttr); @@ -288,7 +288,7 @@ void attsProcPrepWriteReq(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) pPrep->handle = handle; pPrep->offset = offset; memcpy(pPrep->packet, pPacket, writeLen); - WsfQueueEnq(&attsCb.prepWriteQueue[pCcb->connId - 1], pPrep); + WsfQueueEnq(&attsCb.prepWriteQueue[pCcb->connId-1], pPrep); /* allocate response buffer */ if ((pBuf = attMsgAlloc(L2C_PAYLOAD_START + ATT_PREP_WRITE_RSP_LEN + writeLen)) != NULL) @@ -306,7 +306,7 @@ void attsProcPrepWriteReq(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) if (err) { - attsErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_PREP_WRITE_REQ, handle, err); + attErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_PREP_WRITE_REQ, handle, err); } } @@ -342,7 +342,7 @@ void attsProcExecWriteReq(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) else if (*pPacket == ATT_EXEC_WRITE_ALL) { /* iterate over prepare write queue and verify offset and length */ - for (pPrep = attsCb.prepWriteQueue[pCcb->connId - 1].pHead; pPrep != NULL; pPrep = pPrep->pNext) + for (pPrep = attsCb.prepWriteQueue[pCcb->connId-1].pHead; pPrep != NULL; pPrep = pPrep->pNext) { /* find attribute */ if ((pAttr = attsFindByHandle(pPrep->handle, &pGroup)) != NULL) @@ -371,7 +371,7 @@ void attsProcExecWriteReq(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) if (err == ATT_SUCCESS) { /* for each buffer */ - while ((pPrep = WsfQueueDeq(&attsCb.prepWriteQueue[pCcb->connId - 1])) != NULL) + while ((pPrep = WsfQueueDeq(&attsCb.prepWriteQueue[pCcb->connId-1])) != NULL) { /* write buffer */ if ((err = attsExecPrepWrite(pCcb, pPrep)) != ATT_SUCCESS) @@ -394,7 +394,7 @@ void attsProcExecWriteReq(attsCcb_t *pCcb, uint16_t len, uint8_t *pPacket) /* send response or error response */ if (err) { - attsErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_EXEC_WRITE_REQ, 0, err); + attErrRsp(pCcb->pMainCcb, pCcb->slot, ATT_PDU_EXEC_WRITE_REQ, 0, err); } else { @@ -441,7 +441,7 @@ void AttsContinueWriteReq(dmConnId_t connId, uint16_t handle, uint8_t status) if (status) { - attsErrRsp(pCcb, ATT_BEARER_SLOT_ID, ATT_PDU_WRITE_REQ, handle, status); + attErrRsp(pCcb, ATT_BEARER_SLOT_ID, ATT_PDU_WRITE_REQ, handle, status); } else { diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/cfg/cfg_stack.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/cfg/cfg_stack.c index eb394de956..46eceada32 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/cfg/cfg_stack.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/cfg/cfg_stack.c @@ -64,7 +64,6 @@ l2cCfg_t *pL2cCfg = (l2cCfg_t *) &l2cCfg; /************************************************************************************************** ATT **************************************************************************************************/ - #if MBED_CONF_CORDIO_DESIRED_ATT_MTU < ATT_DEFAULT_MTU || MBED_CONF_CORDIO_DESIRED_ATT_MTU > ATT_MAX_MTU #error "CORDIO_CFG_DESIRED_ATT_MTU value is outside valid range" #endif @@ -94,7 +93,7 @@ const eattCfg_t eattCfg = FALSE, /* Authorization required */ DM_SEC_LEVEL_NONE, /* Security level required */ 0, /* Number of enhanced l2cap channels per connection */ - NULL /* Channel priority table */ + NULL /* Min channel priority table. Set NULL to map priority to L2CAP channel index. */ }; /* Configuration pointer */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/cfg/cfg_stack.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/cfg/cfg_stack.h index 5612481547..1ef0d87d57 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/cfg/cfg_stack.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/cfg/cfg_stack.h @@ -39,7 +39,7 @@ extern "C" { /*! \brief Stack release version label */ #define STACK_VERSION ((const char *)"Packetcraft Host v5.2\n") /*! \brief Stack release version number */ -#define STACK_VER_NUM 1366 +#define STACK_VER_NUM 21015 /************************************************************************************************** HCI @@ -159,9 +159,9 @@ extern "C" { #define ATT_NUM_SIMUL_NTF 1 #endif -/* Maximum number of EATT channels per DM connection */ +/* Maximum number of EATT channels per DM connection. Set to zero if EATT is not required. */ #ifndef EATT_CONN_CHAN_MAX -#define EATT_CONN_CHAN_MAX 2 +#define EATT_CONN_CHAN_MAX 0 #endif /**@}*/ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_adv.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_adv.c index 933092c0ee..1c26a6a049 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_adv.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_adv.c @@ -6,7 +6,7 @@ * * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -124,7 +124,7 @@ void DmAdvConfig(uint8_t advHandle, uint8_t advType, uint8_t peerAddrType, uint8 WSF_ASSERT(advHandle < DM_NUM_ADV_SETS); - if ((pMsg = WsfMsgAlloc(sizeof(dmAdvApiConfig_t))) != NULL) + if ((pMsg = WsfMsgAlloc(sizeof(dmAdvApiSetData_t))) != NULL) { pMsg->hdr.event = DM_ADV_MSG_API_CONFIG; pMsg->advType = advType; diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_adv_ae.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_adv_ae.c index ea32b7118d..077ba89b9e 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_adv_ae.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_adv_ae.c @@ -6,7 +6,7 @@ * * Copyright (c) 2016-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_adv_leg.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_adv_leg.c index e832906899..f49b782cd4 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_adv_leg.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_adv_leg.c @@ -6,7 +6,7 @@ * * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -166,7 +166,7 @@ void dmAdvActStart(dmAdvMsg_t *pMsg) { DM_TRACE_INFO1("dmAdvActStart: state: %d", dmAdvCb.advState[DM_ADV_HANDLE_DEFAULT]); - if (dmAdvCb.advState[DM_ADV_HANDLE_DEFAULT] == DM_ADV_STATE_IDLE) + if (dmAdvCb.advState[DM_ADV_HANDLE_DEFAULT] == DM_ADV_STATE_IDLE) { /* if doing directed advertising ignore the request */ if ((dmAdvCb.advType[DM_ADV_HANDLE_DEFAULT] == DM_ADV_CONN_DIRECT) || @@ -444,9 +444,6 @@ void dmAdvStartDirected(uint8_t advType, uint16_t duration, uint8_t addrType, ui /* if not advertising */ if (dmAdvCb.advState[DM_ADV_HANDLE_DEFAULT] == DM_ADV_STATE_IDLE) { - /* start advertising */ - HciLeSetAdvEnableCmd(TRUE); - /* store advertising info */ dmAdvCb.advState[DM_ADV_HANDLE_DEFAULT] = (advType == DM_ADV_CONN_DIRECT) ? \ DM_ADV_STATE_STARTING_DIRECTED : DM_ADV_STATE_STARTING; @@ -454,6 +451,9 @@ void dmAdvStartDirected(uint8_t advType, uint16_t duration, uint8_t addrType, ui dmAdvCb.advDuration[DM_ADV_HANDLE_DEFAULT] = duration; BdaCpy(dmAdvCb.peerAddr[DM_ADV_HANDLE_DEFAULT], pAddr); dmAdvCb.peerAddrType[DM_ADV_HANDLE_DEFAULT] = addrType; + + /* start advertising */ + HciLeSetAdvEnableCmd(TRUE); } } diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_bis_master.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_bis_master.c index 2c6ba3ee49..6f86d98f84 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_bis_master.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_bis_master.c @@ -4,7 +4,7 @@ * * \brief DM Broadcast Isochronous Stream (BIS) management for master. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -473,6 +473,8 @@ void dmBisSmActBigSyncEst(dmBigSyncCb_t *pBigSyncCb, dmBisMsg_t *pMsg) pBigSyncCb->bisHandle[i] = pMsg->bigSyncEst.bisHandle[i]; } + /* TODO: create BIS HCI context. */ + pMsg->hdr.event = DM_BIG_SYNC_EST_IND; (*dmCb.cback)((dmEvt_t *) pMsg); } @@ -511,6 +513,8 @@ void dmBisSmActBigSyncLost(dmBigSyncCb_t *pBigSyncCb, dmBisMsg_t *pMsg) /* reset BIG sync cb */ dmBigSyncCbInit(pBigSyncCb); + /* TODO: clear BIS HCI context. */ + pMsg->hdr.event = DM_BIG_SYNC_LOST_IND; (*dmCb.cback)((dmEvt_t *) pMsg); } @@ -604,25 +608,7 @@ static void dmBisReset(void) /*************************************************************************************************/ static void dmBisHciHandler(hciEvt_t *pEvent) { - dmBigSyncCb_t *pBigSyncCb; - - /* handle special case for BIGInfo advertising report event */ - if (pEvent->hdr.event == HCI_LE_BIG_INFO_ADV_REPORT_CBACK_EVT) - { - /* if periodic advertising sync has been established */ - if (DmSyncEnabled(pEvent->hdr.param)) - { - /* store sync info */ - DmSyncSetEncrypt(pEvent->hdr.param, pEvent->leBigInfoAdvRpt.encrypt); - - pEvent->hdr.event = DM_BIG_INFO_ADV_REPORT_IND; - (*dmCb.cback)((dmEvt_t *) pEvent); - } - - return; - } - - pBigSyncCb = dmBigSyncCbByHandle((uint8_t) pEvent->hdr.param); + dmBigSyncCb_t *pBigSyncCb = dmBigSyncCbByHandle((uint8_t) pEvent->hdr.param); /* handle special cases for BIG sync established event */ if (pEvent->hdr.event == HCI_LE_BIG_SYNC_EST_CBACK_EVT) @@ -713,7 +699,7 @@ void DmBigSyncStart(uint8_t bigHandle, uint16_t syncHandle, uint8_t mse, uint16_ /*! * \brief Stop synchronizing or cancel the process of synchronizing to the Broadcast Isochronous * Group (BIG) identified by the handle. - * + * * \note The command also terminates the reception of BISes in the BIG specified in \ref * DmBigSyncStart, destroys the associated connection handles of the BISes in the BIG * and removes the data paths for all BISes in the BIG. diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_bis_slave.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_bis_slave.c index c3fb5cfef3..d9e1849dcd 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_bis_slave.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_bis_slave.c @@ -4,7 +4,7 @@ * * \brief DM Broadcast Isochronous Stream (BIS) management for slave. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -103,7 +103,7 @@ typedef struct uint32_t sduInterval; /*!< \brief Interval, in microseconds, of BIG SDUs. */ uint16_t maxSdu; /*!< \brief Maximum size of SDU. */ uint16_t mtlMs; /*!< \brief Maximum time, in milliseconds, for transmitting SDU. */ - uint8_t rtn; /*!< \brief Retransmitted number. */ + uint8_t rtn; /*!< \brief Retransmission number. */ } dmBisApiBigStart_t; /* Data structure for DM_BIS_MSG_API_BIG_STOP */ @@ -651,6 +651,7 @@ static void dmBisMsgHandler(wsfMsgHdr_t *pMsg) * \param sduInterval Interval, in microseconds, of BIG SDUs. * \param maxSdu Maximum size of SDU. * \param mtlMs Maximum time, in milliseconds, for transmitting SDU. + * \param rtn Retransmission number. * * \return None. */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_cis.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_cis.c index a9ec7af2f9..fd60925adc 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_cis.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_cis.c @@ -262,8 +262,6 @@ dmCisCcb_t *dmCisCcbById(uint8_t cigId, uint8_t cisId) } } - DM_TRACE_INFO2("dmCisCcbById not found cigId:%d cisId:%d", cigId, cisId); - return NULL; } @@ -575,7 +573,7 @@ void DmCisClose(uint16_t handle, uint8_t reason) * \brief For internal use only. Find the Connected Isochronous Stream (CIS) ID with matching * handle. * - * \param handle CIS identifer. + * \param handle CIS connection handle. * * \return CIS identifier or DM_CIS_ID_NONE if error. */ @@ -592,6 +590,29 @@ uint8_t DmCisIdByHandle(uint16_t handle) return DM_CIS_ID_NONE; } +/*************************************************************************************************/ +/*! + * \brief For internal use only. Find the Connected Isochronous Stream (CIS) handle with matching + * CIG and CIS identifiers. + * + * \param handle CIG ID. + * \param handle CIS ID. + * + * \return CIS connection handle or DM_CONN_HCI_HANDLE_NONE if error. + */ +/*************************************************************************************************/ +uint16_t DmCisHandleById(uint8_t cigId, uint8_t cisId) +{ + dmCisCcb_t *pCcb; + + if ((pCcb = dmCisCcbById(cigId, cisId)) != NULL) + { + return pCcb->cisHandle; + } + + return DM_CONN_HCI_HANDLE_NONE; +} + /*************************************************************************************************/ /*! * \brief For internal use only. Return TRUE if the Connected Isochronous Stream (CIS) @@ -614,6 +635,27 @@ bool_t DmCisConnInUse(uint16_t handle) return FALSE; } +/*************************************************************************************************/ +/*! + * \brief For internal use only. Return the CIS connection role indicating master or slave. + * + * \param handle CIS connection handle. + * + * \return CIS connection role. + */ +/*************************************************************************************************/ +uint8_t DmCisConnRole(uint16_t handle) +{ + dmCisCcb_t *pCcb; + + if ((pCcb = dmCisCcbByHandle(handle)) != NULL) + { + return pCcb->role; + } + + return DM_ROLE_SLAVE; +} + /*************************************************************************************************/ /*! * \brief For internal use only. Return TRUE if Connected Isochronous Group (CIG) is in use. diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_cis.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_cis.h index 3995226fb3..4a10c99e9d 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_cis.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_cis.h @@ -164,7 +164,7 @@ typedef struct wsfMsgHdr_t hdr; /*!< Message Header */ uint8_t numCis; /*!< Total number of CISes to be created */ uint16_t *pCisHandle; /*!< List of connection handles of CISes */ - uint16_t *pAclHandle; /*!< List of connection handles of ACLs */ + dmConnId_t *pConnId; /*!< List of DM connection identifiers */ } dmCisApiOpen_t; /*! Data structure for DM_CIS_MSG_API_CLOSE */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_cis_master.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_cis_master.c index 29517978fb..0e589a8ab1 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_cis_master.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_cis_master.c @@ -504,6 +504,7 @@ static void dmCisCigSmActRemoveFailed(dmCisCigCb_t *pCigCb, dmCisMsg_t *pMsg) static void dmCisSmActOpen(dmCisCcb_t *pCcb, dmCisMsg_t *pMsg) { dmCisApiOpen_t *pOpen = &pMsg->apiOpen; + uint16_t aclHandle[DM_CIS_MAX]; uint8_t status = HCI_SUCCESS; /* if the previous create CIS isn't pending or hasn't been cancelled */ @@ -514,9 +515,9 @@ static void dmCisSmActOpen(dmCisCcb_t *pCcb, dmCisMsg_t *pMsg) dmConnCcb_t *pConnCcb; /* if the ACL connection handle doesn't exist */ - if ((pConnCcb = dmConnCcbByHandle(pOpen->pAclHandle[i])) == NULL) + if ((pConnCcb = dmConnCcbById(pOpen->pConnId[i])) == NULL) { - DM_TRACE_WARN1("dmCisSmActOpen: ACL handle not found (handle:%d)", pOpen->pAclHandle[i]); + DM_TRACE_WARN1("dmCisSmActOpen: ACL connection id not found (connId:%d)", pOpen->pConnId[i]); status = HCI_ERR_UNKNOWN_HANDLE; break; } @@ -536,6 +537,9 @@ static void dmCisSmActOpen(dmCisCcb_t *pCcb, dmCisMsg_t *pMsg) status = HCI_ERR_UNKNOWN_HANDLE; break; } + + /* save ACL handle */ + aclHandle[i] = pConnCcb->handle; } } else @@ -548,7 +552,7 @@ static void dmCisSmActOpen(dmCisCcb_t *pCcb, dmCisMsg_t *pMsg) { HciCisCreateCisParams_t createCisParam; - createCisParam.pAclHandle = pOpen->pAclHandle; + createCisParam.pAclHandle = aclHandle; createCisParam.pCisHandle = pOpen->pCisHandle; /* create CIS */ @@ -562,7 +566,7 @@ static void dmCisSmActOpen(dmCisCcb_t *pCcb, dmCisMsg_t *pMsg) if ((pCisCcb = dmCisCcbByHandle(pOpen->pCisHandle[i])) != NULL) { pCisCcb->state = pCcb->state; - pCisCcb->aclHandle = pOpen->pAclHandle[i]; + pCisCcb->aclHandle = aclHandle[i]; } } } @@ -760,18 +764,18 @@ void DmCisCigRemove(uint8_t cigId) * * \param numCis Total number of CISes to be created. * \param pCisHandle List of connection handles of CISes. - * \param pAclHandle List of connection handles of ACLs. + * \param pConnId List of DM connection identifiers. * * \return None. */ /*************************************************************************************************/ -void DmCisOpen(uint8_t numCis, uint16_t *pCisHandle, uint16_t *pAclHandle) +void DmCisOpen(uint8_t numCis, uint16_t *pCisHandle, dmConnId_t *pConnId) { dmCisApiOpen_t *pMsg; WSF_ASSERT((numCis > 0 ) && (numCis <= DM_CIS_MAX)); - if ((pMsg = WsfMsgAlloc(sizeof(dmCisApiOpen_t) + (numCis * 2 * sizeof(uint16_t)))) != NULL) + if ((pMsg = WsfMsgAlloc(sizeof(dmCisApiOpen_t) + (numCis * (sizeof(uint16_t) + sizeof(dmConnId_t))))) != NULL) { pMsg->hdr.event = DM_CIS_MSG_API_OPEN; pMsg->hdr.param = pCisHandle[0]; @@ -780,8 +784,8 @@ void DmCisOpen(uint8_t numCis, uint16_t *pCisHandle, uint16_t *pAclHandle) pMsg->pCisHandle = (uint16_t *) (pMsg + 1); memcpy(pMsg->pCisHandle, pCisHandle, (numCis * sizeof(uint16_t))); - pMsg->pAclHandle = (uint16_t *) (pMsg->pCisHandle + numCis); - memcpy(pMsg->pAclHandle, pAclHandle, (numCis * sizeof(uint16_t))); + pMsg->pConnId = (dmConnId_t *) (pMsg->pCisHandle + numCis); + memcpy(pMsg->pConnId, pConnId, (numCis * sizeof(dmConnId_t))); WsfMsgSend(dmCb.handlerId, pMsg); } @@ -867,7 +871,7 @@ void DmCisCigSetSca(uint8_t cigId, uint8_t sca) * \return None. */ /*************************************************************************************************/ -void DmCisCigSetPackingFraming(uint8_t cigId, uint8_t packing, uint32_t framing) +void DmCisCigSetPackingFraming(uint8_t cigId, uint8_t packing, uint8_t framing) { dmCisCigCb_t *pCigCb; diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_conn_cte.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_conn_cte.c index 86824ea9f5..925d87b6a9 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_conn_cte.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_conn_cte.c @@ -1,4 +1,4 @@ -/*************************************************************************************************/ +/*************************************************************************************************/ /*! * \file * @@ -6,7 +6,7 @@ * * Copyright (c) 2018-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -412,11 +412,12 @@ static void dmConnCteActRxSampleStart(dmConnCteMsg_t *pMsg) /* if currently idle */ if (pCteCb->rxSampleState == DM_CONN_CTE_STATE_IDLE) { + pCteCb->rxSampleState = DM_CONN_CTE_STATE_STARTING; + + /* set connection CTE receive parameters, and enable Connection IQ sampling */ HciLeSetConnCteRxParamsCmd(pCcb->handle, TRUE, pMsg->rxSampleStart.slotDurations, pMsg->rxSampleStart.switchPatternLen, pMsg->rxSampleStart.pAntennaIDs); - - pCteCb->rxSampleState = DM_CONN_CTE_STATE_STARTING; } else { @@ -446,9 +447,10 @@ static void dmConnCteActRxSampleStop(dmConnCteMsg_t *pMsg) /* if currently sampling */ if (pCteCb->rxSampleState == DM_CONN_CTE_STATE_SAMPLING) { - HciLeSetConnCteRxParamsCmd(pCcb->handle, FALSE, 0, 0, NULL); - pCteCb->rxSampleState = DM_CONN_CTE_STATE_STOPPING; + + /* disable Connection IQ sampling */ + HciLeSetConnCteRxParamsCmd(pCcb->handle, FALSE, 0, 0, NULL); } else { @@ -499,10 +501,11 @@ static void dmConnCteActReqStart(dmConnCteMsg_t *pMsg) /* if currently idle */ if (pCteCb->reqState == DM_CONN_CTE_STATE_IDLE) { + pCteCb->reqState = DM_CONN_CTE_STATE_STARTING; + + /* enable connection CTE request */ HciLeConnCteReqEnableCmd(pCcb->handle, TRUE, pMsg->reqStart.cteReqInt, pMsg->reqStart.reqCteLen, pMsg->reqStart.reqCteType); - - pCteCb->reqState = DM_CONN_CTE_STATE_STARTING; } else { @@ -532,9 +535,10 @@ static void dmConnCteActReqStop(dmConnCteMsg_t *pMsg) /* if currently initiating */ if (pCteCb->reqState == DM_CONN_CTE_STATE_INITIATING) { - HciLeConnCteReqEnableCmd(pCcb->handle, FALSE, 0, 0, 0); - pCteCb->reqState = DM_CONN_CTE_STATE_STOPPING; + + /* disable connection CTE request */ + HciLeConnCteReqEnableCmd(pCcb->handle, FALSE, 0, 0, 0); } else { @@ -564,9 +568,10 @@ void dmConnCteActRspStart(dmConnCteMsg_t *pMsg) /* if currently idle */ if (pCteCb->rspState == DM_CONN_CTE_STATE_IDLE) { - HciLeConnCteRspEnableCmd(pCcb->handle, TRUE); - pCteCb->rspState = DM_CONN_CTE_STATE_STARTING; + + /* enable connection CTE response */ + HciLeConnCteRspEnableCmd(pCcb->handle, TRUE); } else { @@ -596,9 +601,10 @@ void dmConnCteActRspStop(dmConnCteMsg_t *pMsg) /* if currently responding */ if (pCteCb->rspState == DM_CONN_CTE_STATE_RESPONDING) { - HciLeConnCteRspEnableCmd(pCcb->handle, FALSE); - pCteCb->rspState = DM_CONN_CTE_STATE_STOPPING; + + /* disable connection CTE response */ + HciLeConnCteRspEnableCmd(pCcb->handle, FALSE); } else { diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_iso.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_iso.c index 22edbf858f..8216fb9e5a 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_iso.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_iso.c @@ -4,7 +4,7 @@ * * \brief DM Isochronous (ISO) data path management. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,6 +30,7 @@ #include "dm_main.h" #include "dm_conn.h" #include "dm_cis.h" +#include "hci_core_iso.h" /************************************************************************************************** Macros @@ -44,8 +45,8 @@ /*! Number of columns in the state machine state tables */ #define DM_ISO_NUM_COLS 2 -/*! Number of data path directions */ -#define DM_ISO_NUM_DIR 2 +/*! Data path direction none */ +#define DM_ISO_DATA_DIR_NONE 0xFF /************************************************************************************************** Data Types @@ -122,14 +123,25 @@ typedef union /*! ISO connection control block */ typedef struct { - uint16_t handle; /*!< Connection handle of CIS or BIS. */ - uint8_t state[DM_ISO_NUM_DIR];/*!< Main state for each direction. */ - bool_t rmReqEvtSent; /*!< TRUE if remove data path request or event been sent. */ - uint8_t inUse; /*!< TRUE if entry in use. */ + uint16_t handle; /*!< Connection handle of CIS or BIS. */ + uint8_t state[DM_ISO_NUM_DIR]; /*!< Main state for each direction. */ + uint8_t dpDir; /*!< Direction being setup. */ + uint8_t directionBits; /*!< Directions being removed. */ + uint8_t inUse; /*!< TRUE if entry in use. */ +} dmIsoConnCb_t; + +/*! ISO control block */ +typedef struct +{ + dmIsoConnCb_t ccb[DM_ISO_DATA_PATH_MAX];/*!< ISO connection control block. */ + hciIsoCback_t cisCback; /*!< ISO CIS callback. */ + hciIsoCback_t bisCback; /*!< ISO BIS callback. */ + dmIsoDataPathSetupCback_t setupCback; /*!< ISO data path setup callback. */ + dmIsoDataPathRemoveCback_t removeCback; /*!< ISO data path remove callback. */ } dmIsoCb_t; /*! Action functions */ -typedef void (*dmIsoAct_t)(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldState); +typedef void (*dmIsoAct_t)(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, uint8_t oldState); /************************************************************************************************** Local Functions @@ -139,13 +151,13 @@ static void dmIsoReset(void); static void dmIsoMsgHandler(wsfMsgHdr_t *pMsg); static void dmIsoHciHandler(hciEvt_t *pEvent); -static void dmIsoSmActNone(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldState); -static void dmIsoSmActSetup(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldState); -static void dmIsoSmActSetupSuccess(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldState); -static void dmIsoSmActSetupFailed(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldState); -static void dmIsoSmActRemove(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldState); -static void dmIsoSmActRemoved(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldState); -static void dmIsoSmActRemoveFailed(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldState); +static void dmIsoSmActNone(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, uint8_t oldState); +static void dmIsoSmActSetup(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, uint8_t oldState); +static void dmIsoSmActSetupSuccess(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, uint8_t oldState); +static void dmIsoSmActSetupFailed(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, uint8_t oldState); +static void dmIsoSmActRemove(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, uint8_t oldState); +static void dmIsoSmActRemoved(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, uint8_t oldState); +static void dmIsoSmActRemoveFailed(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, uint8_t oldState); /************************************************************************************************** Local Variables @@ -217,7 +229,53 @@ static const dmFcnIf_t dmIsoFcnIf = }; /*! DM ISO control block */ -static dmIsoCb_t dmIsoCb[DM_ISO_DATA_PATH_MAX]; +static dmIsoCb_t dmIsoCb; + +/*************************************************************************************************/ +/*! + * \brief Set an ISO data path setup event. + * + * \param pIsoCcb CIG control block. + * \param pMsg WSF message. + * \param pEvt Event to be set. + * + * \return None. + */ +/*************************************************************************************************/ +static void dmIsoSetDataPathSetupEvt(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, + dmSetupIsoDataPathEvt_t *pEvt) +{ + pEvt->hdr.event = DM_ISO_DATA_PATH_SETUP_IND; + pEvt->hdr.param = pMsg->hdr.param; + pEvt->hdr.status = pMsg->hdr.status; + + pEvt->handle = pMsg->hciLeSetupIsoDataPathCmdCmpl.handle; + pEvt->status = pMsg->hciLeSetupIsoDataPathCmdCmpl.status; + pEvt->dpDir = pIsoCcb->dpDir; +} + +/*************************************************************************************************/ +/*! + * \brief Set an ISO data path remove event. + * + * \param pIsoCcb CIG control block. + * \param pMsg WSF message. + * \param pEvt Event to be set. + * + * \return None. + */ +/*************************************************************************************************/ +static void dmIsoSetDataPathRemoveEvt(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, + dmRemoveIsoDataPathEvt_t *pEvt) +{ + pEvt->hdr.event = DM_ISO_DATA_PATH_REMOVE_IND; + pEvt->hdr.param = pMsg->hdr.param; + pEvt->hdr.status = pMsg->hdr.status; + + pEvt->handle = pMsg->hciLeRemoveIsoDataPathCmdCmpl.handle; + pEvt->status = pMsg->hciLeRemoveIsoDataPathCmdCmpl.status; + pEvt->directionBits = pIsoCcb->directionBits; +} /*************************************************************************************************/ /*! @@ -228,23 +286,24 @@ static dmIsoCb_t dmIsoCb[DM_ISO_DATA_PATH_MAX]; * \return Pointer to ISO control block or NULL if failure. */ /*************************************************************************************************/ -dmIsoCb_t *dmIsoCbAlloc(uint16_t handle) +dmIsoConnCb_t *dmIsoCbAlloc(uint16_t handle) { - dmIsoCb_t *pIsoCb = dmIsoCb; + dmIsoConnCb_t *pIsoCcb = dmIsoCb.ccb; uint8_t i; - for (i = 0; i < DM_ISO_DATA_PATH_MAX; i++, pIsoCb++) + for (i = 0; i < DM_ISO_DATA_PATH_MAX; i++, pIsoCcb++) { - if (pIsoCb->inUse == FALSE) + if (pIsoCcb->inUse == FALSE) { - memset(pIsoCb, 0, sizeof(dmIsoCb_t)); + memset(pIsoCcb, 0, sizeof(dmIsoConnCb_t)); - pIsoCb->handle = handle; - pIsoCb->inUse = TRUE; + pIsoCcb->handle = handle; + pIsoCcb->inUse = TRUE; + pIsoCcb->dpDir = DM_ISO_DATA_DIR_NONE; DM_TRACE_ALLOC1("dmIsoCbAlloc %d", handle); - return pIsoCb; + return pIsoCcb; } } @@ -257,16 +316,16 @@ dmIsoCb_t *dmIsoCbAlloc(uint16_t handle) /*! * \brief Deallocate a DM ISO control block. * - * \param pIsoCb ISO control block. + * \param pIsoCcb ISO control block. * * \return None. */ /*************************************************************************************************/ -void dmIsoCbDealloc(dmIsoCb_t *pIsoCb) +void dmIsoCbDealloc(dmIsoConnCb_t *pIsoCcb) { - DM_TRACE_FREE1("dmIsoCbDealloc %d", pIsoCb->handle); + DM_TRACE_FREE1("dmIsoCbDealloc %d", pIsoCcb->handle); - pIsoCb->inUse = FALSE; + pIsoCcb->inUse = FALSE; } /*************************************************************************************************/ @@ -278,16 +337,16 @@ void dmIsoCbDealloc(dmIsoCb_t *pIsoCb) * \return Pointer to ISO control block. NULL if not found. */ /*************************************************************************************************/ -dmIsoCb_t *dmIsoCbByHandle(uint16_t handle) +dmIsoConnCb_t *dmIsoCbByHandle(uint16_t handle) { - dmIsoCb_t *pIsoCb = dmIsoCb; + dmIsoConnCb_t *pIsoCcb = dmIsoCb.ccb; uint8_t i; - for (i = DM_ISO_DATA_PATH_MAX; i > 0; i--, pIsoCb++) + for (i = DM_ISO_DATA_PATH_MAX; i > 0; i--, pIsoCcb++) { - if (pIsoCb->inUse && (pIsoCb->handle == handle)) + if (pIsoCcb->inUse && (pIsoCcb->handle == handle)) { - return pIsoCb; + return pIsoCcb; } } @@ -300,14 +359,14 @@ dmIsoCb_t *dmIsoCbByHandle(uint16_t handle) /*! * \brief Empty action. * - * \param pIsoCb CIG control block. + * \param pIsoCcb CIG control block. * \param pMsg WSF message. * \param oldState Old state. * * \return None. */ /*************************************************************************************************/ -static void dmIsoSmActNone(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldState) +static void dmIsoSmActNone(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, uint8_t oldState) { return; } @@ -316,34 +375,48 @@ static void dmIsoSmActNone(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldState /*! * \brief Setup ISO data path for the given connection handle. * - * \param pIsoCb CIG control block. + * \param pIsoCcb CIG control block. * \param pMsg WSF message. * \param oldState Old state. * * \return None. */ /*************************************************************************************************/ -static void dmIsoSmActSetup(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldState) +static void dmIsoSmActSetup(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, uint8_t oldState) { dmIsoApiSetup_t *pSetup = &pMsg->apiSetup; /* if connection handle is for CIS, BIS or BIS Sync */ - if (DmCisConnInUse(pIsoCb->handle) || DmBisInUse(pIsoCb->handle) || DmBisSyncInUse(pIsoCb->handle)) + if (DmCisConnInUse(pIsoCcb->handle) || DmBisInUse(pIsoCcb->handle) || DmBisSyncInUse(pIsoCcb->handle)) { /* setup ISO data path */ HciLeSetupIsoDataPathCmd(&pSetup->dataPathParam); + + /* if also need to setup ISO data path in the Host */ + if (dmIsoCb.setupCback != NULL) + { + (*dmIsoCb.setupCback)(&pSetup->dataPathParam); + } + + /* if no pending setup command */ + if (pIsoCcb->dpDir == DM_ISO_DATA_DIR_NONE) + { + /* save data path direction */ + pIsoCcb->dpDir = pSetup->dataPathParam.dpDir; + } + /* else direction will be set when command complete received */ } else { - DM_TRACE_WARN1("dmIsoSmActSetup: connection handle (%d) isn't for CIS or BIS", pIsoCb->handle); + DM_TRACE_WARN1("dmIsoSmActSetup: connection handle (%d) isn't for CIS or BIS", pIsoCcb->handle); pMsg->hdr.status = HCI_ERR_UNKNOWN_HANDLE; /* restore old state */ - pIsoCb->state[pSetup->dataPathParam.dpDir] = oldState; + pIsoCcb->state[pSetup->dataPathParam.dpDir] = oldState; /* notify app about failure */ - dmIsoSmActSetupFailed(pIsoCb, pMsg, oldState); + dmIsoSmActSetupFailed(pIsoCcb, pMsg, oldState); } } @@ -351,66 +424,83 @@ static void dmIsoSmActSetup(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldStat /*! * \brief Handle a ISO data path setup successful event from HCI. * - * \param pIsoCb CIG control block. + * \param pIsoCcb CIG control block. * \param pMsg WSF message. * \param oldState Old state. * * \return None. */ /*************************************************************************************************/ -static void dmIsoSmActSetupSuccess(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldState) +static void dmIsoSmActSetupSuccess(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, uint8_t oldState) { - pMsg->hdr.event = DM_ISO_DATA_PATH_SETUP_IND; - (*dmCb.cback)((dmEvt_t *) pMsg); + dmSetupIsoDataPathEvt_t evt; + + dmIsoSetDataPathSetupEvt(pIsoCcb, pMsg, &evt); + + (*dmCb.cback)((dmEvt_t *) &evt); } /*************************************************************************************************/ /*! * \brief Handle a ISO data path setup failure event from HCI. * - * \param pIsoCb CIG control block. + * \param pIsoCcb CIG control block. * \param pMsg WSF message. * \param oldState Old state. * * \return None. */ /*************************************************************************************************/ -static void dmIsoSmActSetupFailed(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldState) +static void dmIsoSmActSetupFailed(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, uint8_t oldState) { + dmSetupIsoDataPathEvt_t evt; + + dmIsoSetDataPathSetupEvt(pIsoCcb, pMsg, &evt); + /* if both data path directions in idle state */ - if ((pIsoCb->state[HCI_ISO_DATA_DIR_INPUT] == DM_ISO_SM_ST_IDLE) && - (pIsoCb->state[HCI_ISO_DATA_DIR_OUTPUT] == DM_ISO_SM_ST_IDLE)) + if ((pIsoCcb->state[HCI_ISO_DATA_DIR_INPUT] == DM_ISO_SM_ST_IDLE) && + (pIsoCcb->state[HCI_ISO_DATA_DIR_OUTPUT] == DM_ISO_SM_ST_IDLE)) { - dmIsoCbDealloc(pIsoCb); + dmIsoCbDealloc(pIsoCcb); } - pMsg->hdr.event = DM_ISO_DATA_PATH_SETUP_IND; - (*dmCb.cback)((dmEvt_t *) pMsg); + (*dmCb.cback)((dmEvt_t *) &evt); } /*************************************************************************************************/ /*! * \brief Remove ISO data path for the given connection handle. * - * \param pIsoCb CIG control block. + * \param pIsoCcb CIG control block. * \param pMsg WSF message. * \param oldState Old state. * * \return None. */ /*************************************************************************************************/ -static void dmIsoSmActRemove(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldState) +static void dmIsoSmActRemove(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, uint8_t oldState) { dmIsoApiRemove_t *pRemove = &pMsg->apiRemove; - /* if remove data path request hasn't been sent down for this handle */ - if (pIsoCb->rmReqEvtSent == FALSE) + /* if remove data path request hasn't been sent down for both directions */ + if (pIsoCcb->directionBits != (HCI_ISO_DATA_PATH_INPUT_BIT | HCI_ISO_DATA_PATH_OUTPUT_BIT)) { /* remove ISO data path */ HciLeRemoveIsoDataPathCmd(pMsg->hdr.param, pRemove->directionBits); - /* in case if both data path directions are being removed together */ - pIsoCb->rmReqEvtSent = TRUE; + /* if also need to remove ISO data path in the Host */ + if (dmIsoCb.removeCback != NULL) + { + (*dmIsoCb.removeCback)(pMsg->hdr.param, pRemove->directionBits); + } + + /* if no pending remove command */ + if (pIsoCcb->directionBits == 0) + { + /* save data path directions */ + pIsoCcb->directionBits = pRemove->directionBits; + } + /* else direction will be set when command complete received */ } } @@ -418,33 +508,32 @@ static void dmIsoSmActRemove(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldSta /*! * \brief Handle a ISO data path removed event from HCI. * - * \param pIsoCb CIG control block. + * \param pIsoCcb CIG control block. * \param pMsg WSF message. * \param oldState Old state. * * \return None. */ /*************************************************************************************************/ -static void dmIsoSmActRemoved(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldState) +static void dmIsoSmActRemoved(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, uint8_t oldState) { /* if remove data path event hasn't been sent up for this handle */ - if (pIsoCb->rmReqEvtSent == FALSE) + if (pIsoCcb->directionBits != 0) { - uint8_t event = pMsg->hdr.event; + dmRemoveIsoDataPathEvt_t evt; - pMsg->hdr.event = DM_ISO_DATA_PATH_REMOVE_IND; - (*dmCb.cback)((dmEvt_t *) pMsg); + dmIsoSetDataPathRemoveEvt(pIsoCcb, pMsg, &evt); - /* in case if both data path directions are being removed with single command */ - pMsg->hdr.event = event; - pIsoCb->rmReqEvtSent = TRUE; + (*dmCb.cback)((dmEvt_t *) &evt); + + pIsoCcb->directionBits = 0; } /* if both data path directions in idle state */ - if ((pIsoCb->state[HCI_ISO_DATA_DIR_INPUT] == DM_ISO_SM_ST_IDLE) && - (pIsoCb->state[HCI_ISO_DATA_DIR_OUTPUT] == DM_ISO_SM_ST_IDLE)) + if ((pIsoCcb->state[HCI_ISO_DATA_DIR_INPUT] == DM_ISO_SM_ST_IDLE) && + (pIsoCcb->state[HCI_ISO_DATA_DIR_OUTPUT] == DM_ISO_SM_ST_IDLE)) { - dmIsoCbDealloc(pIsoCb); + dmIsoCbDealloc(pIsoCcb); } } @@ -452,35 +541,43 @@ static void dmIsoSmActRemoved(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldSt /*! * \brief Handle a ISO data path remove failure event from HCI. * - * \param pIsoCb CIG control block. + * \param pIsoCcb CIG control block. * \param pMsg WSF message. * \param oldState Old state. * * \return None. */ /*************************************************************************************************/ -static void dmIsoSmActRemoveFailed(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t oldState) +static void dmIsoSmActRemoveFailed(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, uint8_t oldState) { - pMsg->hdr.event = DM_ISO_DATA_PATH_REMOVE_IND; - (*dmCb.cback)((dmEvt_t *) pMsg); + if (pIsoCcb->directionBits != 0) + { + dmRemoveIsoDataPathEvt_t evt; + + dmIsoSetDataPathRemoveEvt(pIsoCcb, pMsg, &evt); + + (*dmCb.cback)((dmEvt_t *) &evt); + + pIsoCcb->directionBits = 0; + } } /*************************************************************************************************/ /*! * \brief Execute the DM ISO state machine. * - * \param pIsoCb ISO control block. + * \param pIsoCcb ISO control block. * \param pMsg WSF message. * \param direction Data path direction. * * \return None. */ /*************************************************************************************************/ -void dmIsoSmExecute(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t direction) +void dmIsoSmExecute(dmIsoConnCb_t *pIsoCcb, dmIsoMsg_t *pMsg, uint8_t direction) { uint8_t action; uint8_t event; - uint8_t state = pIsoCb->state[direction]; + uint8_t state = pIsoCcb->state[direction]; DM_TRACE_INFO2("dmIsoSmExecute event=%d state=%d", pMsg->hdr.event, state); @@ -491,10 +588,10 @@ void dmIsoSmExecute(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t direction) action = dmIsoStateTbl[state][event][DM_ISO_ACTION]; /* set next state */ - pIsoCb->state[direction] = dmIsoStateTbl[state][event][DM_ISO_NEXT_STATE]; + pIsoCcb->state[direction] = dmIsoStateTbl[state][event][DM_ISO_NEXT_STATE]; /* execute action function */ - (*dmIsoAct[action])(pIsoCb, pMsg, state); + (*dmIsoAct[action])(pIsoCcb, pMsg, state); } /*************************************************************************************************/ @@ -506,14 +603,14 @@ void dmIsoSmExecute(dmIsoCb_t *pIsoCb, dmIsoMsg_t *pMsg, uint8_t direction) /*************************************************************************************************/ static void dmIsoReset(void) { - dmIsoCb_t *pIsoCb = dmIsoCb; + dmIsoConnCb_t *pIsoCcb = dmIsoCb.ccb; uint8_t i; - for (i = 0; i < DM_ISO_DATA_PATH_MAX; i++, pIsoCb++) + for (i = 0; i < DM_ISO_DATA_PATH_MAX; i++, pIsoCcb++) { - if (pIsoCb->inUse) + if (pIsoCcb->inUse) { - dmIsoCbDealloc(pIsoCb); + dmIsoCbDealloc(pIsoCcb); } } } @@ -529,35 +626,32 @@ static void dmIsoReset(void) /*************************************************************************************************/ static void dmIsoMsgHandler(wsfMsgHdr_t *pMsg) { - dmIsoCb_t *pIsoCb; + dmIsoConnCb_t *pIsoCcb; /* look up cb from handle */ - if ((pIsoCb = dmIsoCbByHandle(pMsg->param)) != NULL) + if ((pIsoCcb = dmIsoCbByHandle(pMsg->param)) != NULL) { if (pMsg->event == DM_ISO_MSG_API_SETUP) { /* execute state machine */ - dmIsoSmExecute(pIsoCb, (dmIsoMsg_t *) pMsg, ((dmIsoApiSetup_t *) pMsg)->dataPathParam.dpDir); + dmIsoSmExecute(pIsoCcb, (dmIsoMsg_t *) pMsg, ((dmIsoApiSetup_t *) pMsg)->dataPathParam.dpDir); } else /* DM_ISO_MSG_API_REMOVE */ { uint8_t directionBits = ((dmIsoApiRemove_t *) pMsg)->directionBits; - - /* in case if both data path directions are being removed with single command */ - pIsoCb->rmReqEvtSent = FALSE; /* if input direction being removed */ if (directionBits & HCI_ISO_DATA_PATH_INPUT_BIT) { /* execute state machine */ - dmIsoSmExecute(pIsoCb, (dmIsoMsg_t *) pMsg, HCI_ISO_DATA_DIR_INPUT); + dmIsoSmExecute(pIsoCcb, (dmIsoMsg_t *) pMsg, HCI_ISO_DATA_DIR_INPUT); } /* if output direction being removed */ if (directionBits & HCI_ISO_DATA_PATH_OUTPUT_BIT) { /* execute state machine */ - dmIsoSmExecute(pIsoCb, (dmIsoMsg_t *) pMsg, HCI_ISO_DATA_DIR_OUTPUT); + dmIsoSmExecute(pIsoCcb, (dmIsoMsg_t *) pMsg, HCI_ISO_DATA_DIR_OUTPUT); } } } @@ -574,16 +668,14 @@ static void dmIsoMsgHandler(wsfMsgHdr_t *pMsg) /*************************************************************************************************/ static void dmIsoDpHciHandler(hciEvt_t *pEvent) { - dmIsoCb_t *pIsoCb; + dmIsoConnCb_t *pIsoCcb; /* look up cb from handle */ - if ((pIsoCb = dmIsoCbByHandle(pEvent->hdr.param)) != NULL) + if ((pIsoCcb = dmIsoCbByHandle(pEvent->hdr.param)) != NULL) { /* translate HCI event to state machine event */ if (pEvent->hdr.event == HCI_LE_SETUP_ISO_DATA_PATH_CMD_CMPL_CBACK_EVT) { - uint8_t direction; - if (pEvent->hdr.status == HCI_SUCCESS) { pEvent->hdr.event = DM_ISO_MSG_HCI_LE_SETUP_ISO_DATA_PATH_CMD_CMPL; @@ -593,21 +685,27 @@ static void dmIsoDpHciHandler(hciEvt_t *pEvent) pEvent->hdr.event = DM_ISO_MSG_HCI_LE_SETUP_ISO_DATA_PATH_CMD_CMPL_FAIL; } - /* find out direction being set up */ - if (pIsoCb->state[HCI_ISO_DATA_DIR_INPUT] == DM_ISO_SM_ST_CONFIGING) + /* execute state machine */ + dmIsoSmExecute(pIsoCcb, (dmIsoMsg_t *) pEvent, pIsoCcb->dpDir); + + /* if there's pending setup command for other direction */ + if (pIsoCcb->state[HCI_ISO_DATA_DIR_INPUT] == DM_ISO_SM_ST_CONFIGING) { - direction = HCI_ISO_DATA_DIR_INPUT; + pIsoCcb->dpDir = HCI_ISO_DATA_DIR_INPUT; + } + else if (pIsoCcb->state[HCI_ISO_DATA_DIR_OUTPUT] == DM_ISO_SM_ST_CONFIGING) + { + pIsoCcb->dpDir = HCI_ISO_DATA_DIR_OUTPUT; } else { - direction = HCI_ISO_DATA_DIR_OUTPUT; + pIsoCcb->dpDir = DM_ISO_DATA_DIR_NONE; } - - /* execute state machine */ - dmIsoSmExecute(pIsoCb, (dmIsoMsg_t *) pEvent, direction); } else /* HCI_LE_REMOVE_ISO_DATA_PATH_CMD_CMPL_CBACK_EVT */ { + uint8_t directionBits = pIsoCcb->directionBits; + if (pEvent->hdr.status == HCI_SUCCESS) { pEvent->hdr.event = DM_ISO_MSG_HCI_LE_REMOVE_ISO_DATA_PATH_CMD_CMPL; @@ -617,21 +715,32 @@ static void dmIsoDpHciHandler(hciEvt_t *pEvent) pEvent->hdr.event = DM_ISO_MSG_HCI_LE_REMOVE_ISO_DATA_PATH_CMD_CMPL_FAIL; } - /* in case if both data path directions are being removed with single command */ - pIsoCb->rmReqEvtSent = FALSE; - /* if input direction being removed */ - if (pIsoCb->state[HCI_ISO_DATA_DIR_INPUT] == DM_ISO_SM_ST_REMOVING) + if (directionBits & HCI_ISO_DATA_PATH_INPUT_BIT) { /* execute state machine */ - dmIsoSmExecute(pIsoCb, (dmIsoMsg_t *) pEvent, HCI_ISO_DATA_DIR_INPUT); + dmIsoSmExecute(pIsoCcb, (dmIsoMsg_t *) pEvent, HCI_ISO_DATA_DIR_INPUT); } /* if output direction being removed */ - if (pIsoCb->state[HCI_ISO_DATA_DIR_OUTPUT] == DM_ISO_SM_ST_REMOVING) + if (directionBits & HCI_ISO_DATA_PATH_OUTPUT_BIT) { /* execute state machine */ - dmIsoSmExecute(pIsoCb, (dmIsoMsg_t *) pEvent, HCI_ISO_DATA_DIR_OUTPUT); + dmIsoSmExecute(pIsoCcb, (dmIsoMsg_t *) pEvent, HCI_ISO_DATA_DIR_OUTPUT); + } + + /* if there's pending remove command for other direction */ + if (pIsoCcb->state[HCI_ISO_DATA_DIR_INPUT] == DM_ISO_SM_ST_REMOVING) + { + pIsoCcb->directionBits = HCI_ISO_DATA_PATH_INPUT_BIT; + } + else if (pIsoCcb->state[HCI_ISO_DATA_DIR_OUTPUT] == DM_ISO_SM_ST_REMOVING) + { + pIsoCcb->directionBits = HCI_ISO_DATA_PATH_OUTPUT_BIT; + } + else + { + pIsoCcb->directionBits = 0; } } } @@ -684,6 +793,72 @@ static void dmIsoHciHandler(hciEvt_t *pEvent) } } +/*************************************************************************************************/ +/*! + * \brief Default HCI ISO data callback function for CIS connections. + * + * \param pPacket A buffer containing an ISO packet. + * + * \return None. + */ +/*************************************************************************************************/ +static void dmIsoCisCback(uint8_t *pPacket) +{ + hciIsoDataPkt_t isoPkt; + + hciCoreUnpackIsoDataPkt(pPacket, &isoPkt); + + if (isoPkt.ps == HCI_SUCCESS) + { + DM_TRACE_INFO2("dmIsoCisCback: CIS Packet of isoLen %u received for handle = %d", + isoPkt.isoLen, isoPkt.handle); + + /* If role is master, loopback data to slave */ + if (DmCisConnRole(isoPkt.handle) == DM_ROLE_MASTER) + { + /* Make new buffer and copy ISO packet over. */ + uint8_t *pBuf = WsfMsgAlloc(HCI_GET_SDU_HDR_LEN(FALSE) + isoPkt.sduLen); + if (pBuf) + { + memcpy(pBuf + HCI_GET_SDU_HDR_LEN(FALSE), isoPkt.pIsoSdu, isoPkt.isoLen); + + DmSendIsoData(isoPkt.handle, isoPkt.sduLen, pBuf, FALSE, 0); + } + } + } +} + +/*************************************************************************************************/ +/*! + * \brief Default HCI ISO data callback function for BIS connections. + * + * \param pPacket A buffer containing an ISO packet. + * + * \return None. + */ +/*************************************************************************************************/ +static void dmIsoBisCback(uint8_t *pPacket) +{ + hciIsoDataPkt_t isoPkt; + + hciCoreUnpackIsoDataPkt(pPacket, &isoPkt); + + if (isoPkt.ps == HCI_SUCCESS) + { + /* if insufficient security for Broadcast_Code */ + if (DmBigSyncGetSecLevel(isoPkt.handle) > DM_SEC_LEVEL_BCAST_NONE) + { + DM_TRACE_INFO2("dmIsoBisCback: BIS packet of isoLen %d dropped for handle = %d", + isoPkt.isoLen, isoPkt.handle); + return; + } + + /* Handle BIS packet here. */ + DM_TRACE_INFO2("dmIsoBisCback: BIS Packet of sduLen %d received for handle = %d", + isoPkt.sduLen, isoPkt.handle); + } +} + /*************************************************************************************************/ /*! * \brief HCI ISO data callback function. @@ -696,25 +871,28 @@ static void dmIsoHciHandler(hciEvt_t *pEvent) static void dmIsoHciIsoCback(uint8_t *pPacket) { uint16_t handle; - uint16_t hciLen; - uint8_t *p = pPacket; - /* parse HCI handle and length */ - BSTREAM_TO_UINT16(handle, p); + /* parse HCI handle */ + BYTES_TO_UINT16(handle, pPacket); handle &= HCI_HANDLE_MASK; - BSTREAM_TO_UINT16(hciLen, p); - /* if connection handle is for BIS Sync */ + /* if connection handle is for BIS sync */ if (DmBisSyncInUse(handle)) { - /* if insufficient security for Broadcast_Code */ - if (DmBigSyncGetSecLevel(handle) > DM_SEC_LEVEL_BCAST_NONE) - { - DM_TRACE_INFO2("dmIsoHciIsoCback: BIS packet of length %u dropped for handle = %u", hciLen, handle); - } + (*dmIsoCb.bisCback)(pPacket); + } + /* if connection handle is for CIS */ + else if (DmCisConnInUse(handle)) + { + (*dmIsoCb.cisCback)(pPacket); + } + else + { + /* Packet was not handled. */ + DM_TRACE_WARN1("dmIsoHciHandleIsoPkt: Packet not handled. handle = %u", handle); } - /* deallocate buffer */ + /* Packet successfully handled. Free pointer. */ WsfMsgFree(pPacket); } @@ -746,12 +924,52 @@ void DmIsoInit(void) dmFcnIfTbl[DM_ID_ISO] = (dmFcnIf_t *) &dmIsoFcnIf; + /* Initialize default ISO data callbacks */ + dmIsoCb.cisCback = dmIsoCisCback; + dmIsoCb.bisCback = dmIsoBisCback; + /* Register with HCI */ HciIsoRegister(dmIsoHciIsoCback, dmIsoHciFlowCback); WsfTaskUnlock(); } +/*************************************************************************************************/ +/*! + * \brief Register CIS, BIS and setup callbacks for the HCI ISO data path. + * + * \param cisCback CIS data callback function (may be NULL). + * \param bisCback BIS data callback function (may be NULL). + * \param setupCback ISO data path setup callback function (NULL when the codec in the LL). + * \param removeCback ISO data path remove callback function (NULL when the codec in the LL). + * + * \return None. + */ + /*************************************************************************************************/ +void DmIsoRegister(hciIsoCback_t cisCback, hciIsoCback_t bisCback, + dmIsoDataPathSetupCback_t setupCback, dmIsoDataPathRemoveCback_t removeCback) +{ + if (cisCback != NULL) + { + dmIsoCb.cisCback = cisCback; + } + + if (bisCback != NULL) + { + dmIsoCb.bisCback = bisCback; + } + + if (setupCback != NULL) + { + dmIsoCb.setupCback = setupCback; + } + + if (removeCback != NULL) + { + dmIsoCb.removeCback = removeCback; + } +} + /*************************************************************************************************/ /*! * \brief Setup the isochronous data path between the Host and the Controller for an established @@ -764,22 +982,22 @@ void DmIsoInit(void) /*************************************************************************************************/ void DmIsoDataPathSetup(HciIsoSetupDataPath_t *pDataPathParam) { - dmIsoCb_t *pIsoCb = NULL; + dmIsoConnCb_t *pIsoCcb = NULL; uint16_t handle = pDataPathParam->handle; dmIsoApiSetup_t *pMsg; - WSF_ASSERT(pDataPathParam->dpDir < DM_ISO_NUM_DIR) + WSF_ASSERT(pDataPathParam->dpDir < DM_ISO_NUM_DIR); /* make sure ISO cb not already allocated */ WsfTaskLock(); - if ((pIsoCb = dmIsoCbByHandle(handle)) == NULL) + if ((pIsoCcb = dmIsoCbByHandle(handle)) == NULL) { /* allocate Cig cb */ - pIsoCb = dmIsoCbAlloc(handle); + pIsoCcb = dmIsoCbAlloc(handle); } WsfTaskUnlock(); - if (pIsoCb != NULL) + if (pIsoCcb != NULL) { if ((pMsg = WsfMsgAlloc(sizeof(dmIsoApiSetup_t) + pDataPathParam->codecConfigLen)) != NULL) { @@ -887,3 +1105,19 @@ void DmReadLocalSupCtrDly(HciReadLocalSupControllerDly_t *pDelayParam) { HciReadLocalSupControllerDlyCmd(pDelayParam); } + +/*************************************************************************************************/ +/*! + * \brief Send ISO Data. + * + * \param handle ISO Handle to send data. + * \param len Length of data (Excluding header). + * \param pData Pointer to start of ISO buffer. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSendIsoData(uint16_t handle, uint16_t len, uint8_t *pData, bool_t useTs, uint32_t ts) +{ + hciSendIsoData(handle, len, pData, useTs, ts); +} diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_main.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_main.c index 90116478d8..91b44d4ad8 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_main.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_main.c @@ -6,7 +6,7 @@ * * Copyright (c) 2009-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -123,10 +123,10 @@ static const uint8_t dmHciToIdTbl[] = DM_ID_ISO, /* HCI_READ_LOCAL_SUP_CTR_DLY_CMD_CMPL_CBACK_EVT */ DM_ID_BIS, /* HCI_LE_CREATE_BIG_CMPL_CBACK_EVT */ DM_ID_BIS, /* HCI_LE_TERM_BIG_CMPL_CBACK_EVT */ - DM_ID_BIS_SYNC, /* HCI_LE_BIG_SYNC_EST_CBACK_EVT */ + DM_ID_BIS_SYNC, /* HCI_LE_BIG_SYNC_EST_CBACK_EVT */ DM_ID_BIS_SYNC, /* HCI_LE_BIG_SYNC_LOST_CBACK_EVT */ DM_ID_BIS_SYNC, /* HCI_LE_BIG_TERM_SYNC_CMPL_CBACK_EVT */ - DM_ID_BIS_SYNC /* HCI_LE_BIG_INFO_ADV_REPORT_CBACK_EVT */ + DM_ID_SYNC /* HCI_LE_BIG_INFO_ADV_REPORT_CBACK_EVT */ #if MBED_CONF_CORDIO_ROUTE_UNHANDLED_COMMAND_COMPLETE_EVENTS , DM_ID_DEV /* HCI_UNHANDLED_CMD_COMPL_CBACK_EVT */ #endif @@ -208,8 +208,8 @@ static const uint16_t dmEvtCbackLen[] = sizeof(HciLeCisEstEvt_t), /* DM_CIS_OPEN_IND */ sizeof(hciDisconnectCmplEvt_t), /* DM_CIS_CLOSE_IND */ sizeof(HciLeReqPeerScaCmplEvt_t_t), /* DM_REQ_PEER_SCA_IND */ - sizeof(hciLeSetupIsoDataPathCmdCmplEvt_t), /* DM_ISO_DATA_PATH_SETUP_IND */ - sizeof(hciLeRemoveIsoDataPathCmdCmplEvt_t), /* DM_ISO_DATA_PATH_REMOVE_IND */ + sizeof(dmSetupIsoDataPathEvt_t), /* DM_ISO_DATA_PATH_SETUP_IND */ + sizeof(dmRemoveIsoDataPathEvt_t), /* DM_ISO_DATA_PATH_REMOVE_IND */ sizeof(hciConfigDataPathCmdCmplEvt_t), /* DM_DATA_PATH_CONFIG_IND */ sizeof(hciReadLocalSupCodecsCmdCmplEvt_t), /* DM_READ_LOCAL_SUP_CODECS_IND */ sizeof(hciReadLocalSupCodecCapCmdCmplEvt_t), /* DM_READ_LOCAL_SUP_CODEC_CAP_IND */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_past.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_past.c index 983e293cba..dc3602fddc 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_past.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_past.c @@ -6,7 +6,7 @@ * * Copyright (c) 2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -332,7 +332,8 @@ void DmPastSetInfoTrsf(dmConnId_t connId, uint16_t serviceData, uint8_t advHandl * \param syncTimeout Maximum permitted time between successful receives. If this time is * exceeded, synchronization is lost. * \param cteType Whether to only synchronize to periodic advertising with certain - * types of Constant Tone Extension. + * types of Constant Tone Extension (0 indicates that the presence or + * absence of a Constant Tone Extension is irrelevant). * * \return None. */ @@ -365,7 +366,8 @@ void DmPastConfig(dmConnId_t connId, uint8_t mode, uint16_t skip, uint16_t syncT * \param syncTimeout Maximum permitted time between successful receives. If this time is * exceeded, synchronization is lost. * \param cteType Whether to only synchronize to periodic advertising with certain - * types of Constant Tone Extension. + * types of Constant Tone Extension (0 indicates that the presence or + * absence of a Constant Tone Extension is irrelevant). * * \return None. */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_scan.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_scan.h index 4a42f5ce54..aef831f5d5 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_scan.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_scan.h @@ -6,7 +6,7 @@ * * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -81,7 +81,7 @@ typedef struct bdAddr_t advAddr; uint16_t skip; uint16_t syncTimeout; - uint8_t unused; + uint8_t syncCteType; } dmSyncApiStart_t; /* Data structure for DM_SYNC_MSG_API_ADD_DEV_TO_PER_ADV_LIST */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sec.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sec.c index c3869e3ec6..b4278af83c 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sec.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sec.c @@ -6,7 +6,7 @@ * * Copyright (c) 2010-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -368,17 +368,17 @@ void DmSecSetLocalIrk(uint8_t *pIrk) /*! * \brief This function sets the local identity address used by the device. * - * \param pAddr Pointer to the address. - * \param type Type of the address. + * \param identityAddr Local identity address. + * \param addrType Local identity address type. * * \return None. */ /*************************************************************************************************/ -void DmSecSetLocalIdentityAddr(const uint8_t *pAddr, uint8_t type) +void DmSecSetLocalIdentityAddr(const bdAddr_t identityAddr, uint8_t addrType) { WsfTaskLock(); - dmSecCb.addrType = type; - BdaCpy(dmSecCb.bdAddr, pAddr); + dmSecCb.addrType = addrType; + BdaCpy(dmSecCb.identityAddr, identityAddr); WsfTaskUnlock(); } @@ -415,28 +415,32 @@ uint8_t *DmSecGetLocalIrk(void) /*************************************************************************************************/ uint8_t *DmSecGetLocalIdentityAddr(void) { - if (dmSecCb.addrType != DM_ADDR_NONE) { - return dmSecCb.bdAddr; - } else { - return HciGetBdAddr(); + /* if the local identity address has been set */ + if (dmSecCb.addrType != DM_ADDR_NONE) + { + return dmSecCb.identityAddr; } + + return HciGetBdAddr(); } /*************************************************************************************************/ /*! * \brief For internal use only. This function gets the local identity address type used by the - * device. + * device. * * \return The identity address type. */ /*************************************************************************************************/ uint8_t DmSecGetLocalIdentityAddrType(void) { - if (dmSecCb.addrType != DM_ADDR_NONE) { + /* if the local identity address has been set */ + if (dmSecCb.addrType != DM_ADDR_NONE) + { return dmSecCb.addrType; - } else { - return DM_ADDR_PUBLIC; } + + return DM_ADDR_PUBLIC; } /*************************************************************************************************/ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sec.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sec.h index 7f3dd58113..36cf5ce184 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sec.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sec.h @@ -6,7 +6,7 @@ * * Copyright (c) 2009-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -81,10 +81,10 @@ typedef union /* Security control block type */ typedef struct { - uint8_t *pIrk; - uint8_t *pCsrk; - bdAddr_t bdAddr; - uint8_t addrType; + uint8_t *pIrk; /* Pointer to local Identity Resolving Key (IRK) */ + uint8_t *pCsrk; /* Pointer to local Connection Signature Resolving Key (CSRK) */ + bdAddr_t identityAddr; /* Local identity address */ + uint8_t addrType; /* Local identity address type */ } dmSecCb_t; /************************************************************************************************** diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sync_ae.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sync_ae.c index 1f0fb97919..615a9bf069 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sync_ae.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sync_ae.c @@ -7,7 +7,7 @@ * * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -361,7 +361,7 @@ void dmSyncSmActStart(dmSyncCb_t *pScb, dmSyncMsg_t *pMsg) HciLePerAdvCreateSyncCmd(dmCb.syncOptions, pMsg->apiSyncStart.advSid, pMsg->apiSyncStart.advAddrType, pMsg->apiSyncStart.advAddr, pMsg->apiSyncStart.skip, pMsg->apiSyncStart.syncTimeout, - pMsg->apiSyncStart.unused); + pMsg->apiSyncStart.syncCteType); } /*************************************************************************************************/ @@ -449,6 +449,9 @@ void dmSyncSmActSyncEstFailed(dmSyncCb_t *pScb, dmSyncMsg_t *pMsg) /*************************************************************************************************/ void dmSyncSmActSyncLost(dmSyncCb_t *pScb, dmSyncMsg_t *pMsg) { + /* set sync handle */ + pMsg->perAdvSyncLost.syncHandle = pScb->handle; + /* deallocate scb */ dmSyncCbDealloc(pScb); @@ -561,7 +564,8 @@ void dmSyncReset(void) if (pScb->inUse) { /* set sync handle */ - syncLost.hdr.param = syncLost.syncHandle = pScb->handle; + syncLost.hdr.param = pScb->syncId; + syncLost.syncHandle = pScb->handle; /* handle the event */ dmSyncHciHandler((hciEvt_t *) &syncLost); @@ -585,8 +589,33 @@ void dmSyncHciHandler(hciEvt_t *pEvent) /* handle special case for periodic advertising report event */ if (pEvent->hdr.event == HCI_LE_PER_ADV_REPORT_CBACK_EVT) { - pEvent->hdr.event = DM_PER_ADV_REPORT_IND; - (*dmCb.cback)((dmEvt_t *) pEvent); + if ((pScb = dmSyncCbByHandle(pEvent->hdr.param)) != NULL) + { + /* set sync id */ + pEvent->hdr.param = pScb->syncId; + + pEvent->hdr.event = DM_PER_ADV_REPORT_IND; + (*dmCb.cback)((dmEvt_t *) pEvent); + } + + return; + } + + /* handle special case for BIGInfo advertising report event */ + if (pEvent->hdr.event == HCI_LE_BIG_INFO_ADV_REPORT_CBACK_EVT) + { + if ((pScb = dmSyncCbByHandle(pEvent->hdr.param)) != NULL) + { + /* store sync info */ + pScb->encrypt = pEvent->leBigInfoAdvRpt.encrypt; + + /* set sync id */ + pEvent->hdr.param = pScb->syncId; + + pEvent->hdr.event = DM_BIG_INFO_ADV_REPORT_IND; + (*dmCb.cback)((dmEvt_t *) pEvent); + } + return; } @@ -692,13 +721,16 @@ void dmSyncMsgHandler(wsfMsgHdr_t *pMsg) * \param pAdvAddr Advertiser address. * \param skip Number of periodic advertising packets that can be skipped after * successful receive. - * \param syncTimeout Synchronization timeout. + * \param syncTimeout Synchronization timeout, in the units of 10ms. + * \param syncCteType Whether to only synchronize to periodic advertising with certain types + * of Constant Tone Extension (0 indicates that the presence or absence of + * a Constant Tone Extension is irrelevant). * * \return Sync identifier. */ /*************************************************************************************************/ dmSyncId_t DmSyncStart(uint8_t advSid, uint8_t advAddrType, const uint8_t *pAdvAddr, uint16_t skip, - uint16_t syncTimeout) + uint16_t syncTimeout, uint8_t syncCteType) { dmSyncCb_t *pScb = NULL; dmSyncApiStart_t *pMsg; @@ -723,7 +755,7 @@ dmSyncId_t DmSyncStart(uint8_t advSid, uint8_t advAddrType, const uint8_t *pAdvA BdaCpy(pMsg->advAddr, pAdvAddr); pMsg->skip = skip; pMsg->syncTimeout = syncTimeout; - pMsg->unused = 0; + pMsg->syncCteType = syncCteType; WsfMsgSend(dmCb.handlerId, pMsg); /* return sync id */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/hci/hci_main.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/hci/hci_main.c index 10eadb379e..91c54d4601 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/hci/hci_main.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/hci/hci_main.c @@ -85,13 +85,13 @@ void HciAclRegister(hciAclCback_t aclCback, hciFlowCback_t flowCback) /*! * \brief Register callbacks for the HCI ISO data path. * - * \param aclCback ISO data callback function. + * \param isoCback ISO data callback function. * \param flowCback Flow control callback function. * * \return None. */ /*************************************************************************************************/ -void HciIsoRegister(hciAclCback_t isoCback, hciFlowCback_t flowCback) +void HciIsoRegister(hciIsoCback_t isoCback, hciFlowCback_t flowCback) { hciCb.isoCback = isoCback; hciCb.isoFlowCback = flowCback; @@ -111,6 +111,9 @@ void HciHandlerInit(wsfHandlerId_t handlerId) /* store handler ID */ hciCb.handlerId = handlerId; + /* Set ISO call back to free payloads in the case that uninitialized ISO gets an unexpected ISO packet. */ + hciCb.isoCback = (hciIsoCback_t) WsfMsgFree; + /* init rx queue */ WSF_QUEUE_INIT(&hciCb.rxQueue); diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/l2c/l2c_coc.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/l2c/l2c_coc.c index f78873f143..3a0d20cea5 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/l2c/l2c_coc.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/l2c/l2c_coc.c @@ -6,7 +6,7 @@ * * Copyright (c) 2014-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -1273,7 +1273,7 @@ static void l2cCocSendData(l2cChanCb_t *pChanCb) uint16_t len; uint8_t *pBuf; - L2C_TRACE_INFO3("l2cCocSendData pTxPkt:%x peerCredits:%d flowDisabled:%d", (uint32_t)pChanCb->pTxPkt, pChanCb->peerCredits, pChanCb->pConnCb->flowDisabled); + L2C_TRACE_INFO3("l2cCocSendData pTxPkt:%p peerCredits:%d flowDisabled:%d", pChanCb->pTxPkt, pChanCb->peerCredits, pChanCb->pConnCb->flowDisabled); /* while we have data and peer credits and flow is not disabled */ while (pChanCb->pTxPkt != NULL && pChanCb->peerCredits > 0 && !pChanCb->pConnCb->flowDisabled) @@ -2230,7 +2230,21 @@ static void l2cCocCtrlCback(wsfMsgHdr_t *pMsg) if (!pConnCb->flowDisabled) { /* check for pending data to be sent on this connection */ - //tbd + for (uint8_t i = 0; i < L2C_COC_CHAN_MAX; i++) + { + l2cChanCb_t *pChanCb = &l2cCocCb.chanCb[i]; + + if (pConnCb->flowDisabled) + { + return; + } + + if ((pChanCb->pConnCb == pConnCb) && (pChanCb->state == L2C_CHAN_STATE_CONNECTED) && + (pChanCb->pTxPkt)) + { + l2cCocSendData(pChanCb); + } + } } } @@ -2276,7 +2290,7 @@ static void l2cCocApiDataReq(l2cCocMsg_t *pMsg) { l2cChanCb_t *pChanCb = l2cChanCbByCid(pMsg->dataReq.localCid); - L2C_TRACE_INFO2("l2cCocApiDataReq sduLen:%d peerMps:%d", pMsg->dataReq.sduLen, pChanCb->peerMps); + L2C_TRACE_INFO3("l2cCocApiDataReq cid: %d sduLen:%d peerMps:%d", pMsg->dataReq.localCid, pMsg->dataReq.sduLen, pChanCb->peerMps); /* if channel connected */ if (pChanCb->state == L2C_CHAN_STATE_CONNECTED) diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_act.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_act.c index 486c55cebd..ba5c2d7c2b 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_act.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_act.c @@ -6,7 +6,7 @@ * * Copyright (c) 2010-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -569,7 +569,6 @@ bool_t smpSendKey(smpCcb_t *pCcb, uint8_t keyDist) UINT8_TO_BSTREAM(p, SMP_CMD_ID_ADDR_INFO); UINT8_TO_BSTREAM(p, DmSecGetLocalIdentityAddrType()); BDA_TO_BSTREAM(p, DmSecGetLocalIdentityAddr()); - } else if ((keyDist & SMP_KEY_DIST_SIGN) && (pCcb->lastSentKey == 0 || pCcb->lastSentKey == SMP_CMD_ID_ADDR_INFO || @@ -661,6 +660,7 @@ bool_t smpProcRcvKey(smpCcb_t *pCcb, dmSecKeyIndEvt_t *pKeyInd, uint8_t *pBuf, u { /* parse signing information packet */ Calc128Cpy(pKeyInd->keyData.csrk.key, pBuf); + pKeyInd->secLevel = (pCcb->auth & SMP_AUTH_MITM_FLAG) ? DM_SEC_LEVEL_ENC_AUTH : DM_SEC_LEVEL_ENC; pKeyInd->type = DM_KEY_CSRK; keyIndReady = TRUE; } diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_main.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_main.h index 45a0737750..00455cf400 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_main.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_main.h @@ -6,7 +6,7 @@ * * Copyright (c) 2010-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -278,6 +278,7 @@ typedef struct uint8_t Ra[SMP_RAND_LEN]; /* Initiator Ra */ uint8_t Rb[SMP_RAND_LEN]; /* Responder Nb */ uint8_t PeerCb[SMP_RAND_LEN]; /* Peer Responder Confirm */ + uint8_t LocalCb[SMP_RAND_LEN]; /* Local Confirm */ uint8_t PeerCa_Ea[SMP_RAND_LEN]; /* Peer Responder Confirm or DH Key Check */ } smpScScratch_t; diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_sc_act.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_sc_act.c index f722964bb6..9cc484c7d7 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_sc_act.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_sc_act.c @@ -6,7 +6,7 @@ * * Copyright (c) 2010-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,6 +46,9 @@ #define SMP_DHKEY_QUAL_INCLUDED FALSE #endif +/* Min number of differences required in the bits of the local and peer public keys */ +#define SMP_PUBLIC_KEY_DELTA_REQUIRED 2 + /************************************************************************************************** Global Variables **************************************************************************************************/ @@ -496,32 +499,71 @@ void smpScActAuthSelect(smpCcb_t *pCcb, smpMsg_t *pMsg) { wsfMsgHdr_t hdr; uint8_t *pPacket = pMsg->data.pPacket + L2C_PAYLOAD_START; + uint16_t deltaCnt = 0; /* Process public key from peer (store in MSB first format) */ WStrReverseCpy(pCcb->pScCcb->pPeerPublicKey->pubKeyX, &pPacket[SMP_PUB_KEY_X_POS], SMP_PUB_KEY_LEN); WStrReverseCpy(pCcb->pScCcb->pPeerPublicKey->pubKeyY, &pPacket[SMP_PUB_KEY_Y_POS], SMP_PUB_KEY_LEN); - /* Message state machine indicating authorization mode (JW, OOB, or passkey) */ + /* Verify the peer and local keys do not match and are also not the same except for one bit */ + for (uint8_t i = 0; i < SMP_PUB_KEY_LEN; i++) + { + uint8_t peerByteX = pCcb->pScCcb->pPeerPublicKey->pubKeyX[i]; + uint8_t peerByteY = pCcb->pScCcb->pPeerPublicKey->pubKeyY[i]; + uint8_t localByteX = pCcb->pScCcb->pLocalPublicKey->pubKeyX[i]; + uint8_t localByteY = pCcb->pScCcb->pLocalPublicKey->pubKeyY[i]; + + for (uint8_t j = 0; j < 8; j++) + { + if ((peerByteX & (1 << j)) != (localByteX & (1 << j))) + { + deltaCnt++; + } + + if ((peerByteY & (1 << j)) != (localByteY & (1 << j))) + { + deltaCnt++; + } + } + + if (deltaCnt >= SMP_PUBLIC_KEY_DELTA_REQUIRED) + { + break; + } + } + + /* Setup message */ hdr.param = pCcb->connId; - switch(pCcb->pScCcb->authType) + if (deltaCnt < SMP_PUBLIC_KEY_DELTA_REQUIRED) { - case SMP_AUTH_TYPE_NUM_COMP: - case SMP_AUTH_TYPE_JUST_WORKS: - hdr.event = SMP_MSG_INT_JW_NC; - break; - case SMP_AUTH_TYPE_OOB: - hdr.event = SMP_MSG_INT_OOB; - break; - case SMP_AUTH_TYPE_PASSKEY: - hdr.event = SMP_MSG_INT_PASSKEY; - break; - default: + /* Cancel pairing */ hdr.status = SMP_ERR_UNSPECIFIED; hdr.event = SMP_MSG_API_CANCEL_REQ; - break; + } + else + { + /* Select authorization mode (JW, OOB, or passkey) */ + switch(pCcb->pScCcb->authType) + { + case SMP_AUTH_TYPE_NUM_COMP: + case SMP_AUTH_TYPE_JUST_WORKS: + hdr.event = SMP_MSG_INT_JW_NC; + break; + case SMP_AUTH_TYPE_OOB: + hdr.event = SMP_MSG_INT_OOB; + break; + case SMP_AUTH_TYPE_PASSKEY: + hdr.event = SMP_MSG_INT_PASSKEY; + break; + default: + hdr.status = SMP_ERR_UNSPECIFIED; + hdr.event = SMP_MSG_API_CANCEL_REQ; + break; + } } + /* Message state machine */ smpSmExecute(pCcb, (smpMsg_t *) &hdr); } diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_sc_main.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_sc_main.c index 0051554237..8cdecbf3fe 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_sc_main.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_sc_main.c @@ -6,7 +6,7 @@ * * Copyright (c) 2010-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -608,15 +608,16 @@ void SmpScGetCancelMsgWithReattempt(dmConnId_t connId, wsfMsgHdr_t *pHdr, uint8_ * \brief Process failure and check attempt count * * \param pCcb Connection control block. + * \param status Status to include. * * \return none. */ /*************************************************************************************************/ -void smpScFailWithReattempt(smpCcb_t *pCcb) +void smpScFailWithReattempt(smpCcb_t *pCcb, uint8_t status) { wsfMsgHdr_t hdr; - SmpScGetCancelMsgWithReattempt(pCcb->connId, &hdr, SMP_ERR_CONFIRM_VALUE); + SmpScGetCancelMsgWithReattempt(pCcb->connId, &hdr, status); smpSmExecute(pCcb, (smpMsg_t *)&hdr); } diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_sc_main.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_sc_main.h index e54242a908..5acb4eed71 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_sc_main.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_sc_main.h @@ -6,7 +6,7 @@ * * Copyright (c) 2010-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -130,7 +130,7 @@ smpScPubKey_t *smpGetPeerPublicKey(dmConnId_t connId); void smpSetPeerPublicKey(dmConnId_t connId, smpScPubKey_t *pKey); void SmpScSetOobCfg(dmConnId_t connId, dmSecLescOobCfg_t *pConfig); void smpScAuthReq(smpCcb_t *pCcb, uint8_t oob, uint8_t display); -void smpScFailWithReattempt(smpCcb_t *pCcb); +void smpScFailWithReattempt(smpCcb_t *pCcb, uint8_t status); void SmpScInit(void); /* common command send functoins */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smpi_act.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smpi_act.c index 404a9e20da..2f7eb47998 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smpi_act.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smpi_act.c @@ -164,6 +164,9 @@ void smpiActProcPairRsp(smpCcb_t *pCcb, smpMsg_t *pMsg) /* proceed to process pairing */ if (smpCb.procPairing(pCcb, &oob, &display)) { + /* clear key ready */ + pCcb->keyReady = FALSE; + smpCb.procAuthReq(pCcb, oob, display); } } diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smpi_sc_act.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smpi_sc_act.c index 38ed419709..eaf7addb3e 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smpi_sc_act.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smpi_sc_act.c @@ -6,7 +6,7 @@ * * Copyright (c) 2010-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -161,7 +161,7 @@ void smpiScActJwncCalcG2(smpCcb_t *pCcb, smpMsg_t *pMsg) /* Check the result of the F4 confirm calculation */ if (memcmp(pCcb->pScCcb->pScratch->PeerCb, pCmac->pCiphertext, SMP_CONFIRM_LEN)) { - smpScFailWithReattempt(pCcb); + smpScFailWithReattempt(pCcb, SMP_ERR_CONFIRM_VALUE); } else { @@ -223,11 +223,19 @@ void smpiScActPkCalcCb(smpCcb_t *pCcb, smpMsg_t *pMsg) /* Record the Nbi */ WStrReverseCpy(pCcb->pScCcb->pScratch->Nb_Eb, pNb, SMP_RAND_LEN); - /* Cb = f4(PKbx, PKax, Nbi, Rai) where f4(U, V, x, Z) = AES-CMACx (U || V || Z) */ - SmpScCalcF4(pCcb, pMsg, - pCcb->pScCcb->pPeerPublicKey->pubKeyX, - pCcb->pScCcb->pLocalPublicKey->pubKeyX, - smpGetPkBit(pCcb), pCcb->pScCcb->pScratch->Nb_Eb); + /* Verify the random value was not reflected */ + if (!memcmp(pCcb->pScCcb->pScratch->Na_Ea, pCcb->pScCcb->pScratch->Nb_Eb, SMP_RAND_LEN)) + { + smpScFailWithReattempt(pCcb, SMP_ERR_UNSPECIFIED); + } + else + { + /* Cb = f4(PKbx, PKax, Nbi, Rai) where f4(U, V, x, Z) = AES-CMACx (U || V || Z) */ + SmpScCalcF4(pCcb, pMsg, + pCcb->pScCcb->pPeerPublicKey->pubKeyX, + pCcb->pScCcb->pLocalPublicKey->pubKeyX, + smpGetPkBit(pCcb), pCcb->pScCcb->pScratch->Nb_Eb); + } } /*************************************************************************************************/ @@ -243,6 +251,9 @@ void smpiScActPkCalcCb(smpCcb_t *pCcb, smpMsg_t *pMsg) void smpiScActPkSendCnf(smpCcb_t *pCcb, smpMsg_t *pMsg) { SMP_TRACE_128("Cai", pMsg->aes.pCiphertext); + + /* Keep a copy of the confirm value we send to the peer */ + memcpy(pCcb->pScCcb->pScratch->LocalCb, pMsg->aes.pCiphertext, SMP_RAND_LEN); /* Send the Cai to the peer */ smpScSendPairCnf(pCcb, pMsg, pMsg->aes.pCiphertext); @@ -264,12 +275,20 @@ void smpiScActPkSendRand(smpCcb_t *pCcb, smpMsg_t *pMsg) /* Record the Cbi from the responder */ WStrReverseCpy(pCcb->pScCcb->pScratch->PeerCb, pCb, SMP_CONFIRM_LEN); + + /* Verify confirm value is not reflected */ + if (!memcmp(pCcb->pScCcb->pScratch->PeerCb, pCcb->pScCcb->pScratch->LocalCb, SMP_RAND_LEN)) + { + smpScFailWithReattempt(pCcb, SMP_ERR_UNSPECIFIED); + } + else + { + /* Next command is the Pair Random */ + pCcb->nextCmdCode = SMP_CMD_PAIR_RAND; - /* Next command is the Pair Random */ - pCcb->nextCmdCode = SMP_CMD_PAIR_RAND; - - /* Send the Nai */ - smpScSendRand(pCcb, pMsg, pCcb->pScCcb->pScratch->Na_Ea); + /* Send the Nai */ + smpScSendRand(pCcb, pMsg, pCcb->pScCcb->pScratch->Na_Ea); + } } /*************************************************************************************************/ @@ -289,7 +308,7 @@ void smpiScActPkCheck(smpCcb_t *pCcb, smpMsg_t *pMsg) /* Verify the Calculated Cbi to previously received Cbi */ if (memcmp(pCcb->pScCcb->pScratch->PeerCb, pMsg->aes.pCiphertext, SMP_RAND_LEN)) { - smpScFailWithReattempt(pCcb); + smpScFailWithReattempt(pCcb, SMP_ERR_CONFIRM_VALUE); } else { @@ -377,7 +396,7 @@ void smpiScActOobSendRand(smpCcb_t *pCcb, smpMsg_t *pMsg) /* Verify the Cb matches the value passed from the responder via OOB methods */ if (memcmp(pCcb->pScCcb->pScratch->PeerCb, pMsg->aes.pCiphertext, SMP_CONFIRM_LEN)) { - smpScFailWithReattempt(pCcb); + smpScFailWithReattempt(pCcb, SMP_ERR_CONFIRM_VALUE); return; } } @@ -466,6 +485,8 @@ void smpiScActDHKeyCheckVerify(smpCcb_t *pCcb, smpMsg_t *pMsg) memcpy(buf, pCcb->pScCcb->pLtk->ltk_t, encKeyLen); memset((buf + encKeyLen), 0, (SMP_KEY_LEN - encKeyLen)); pCcb->keyReady = TRUE; + + SMP_TRACE_128("LTK:", pCcb->pScCcb->pLtk->ltk_t); /* Initiate encryption */ DmSmpEncryptReq(pCcb->connId, smpGetScSecLevel(pCcb), buf); diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smpr_act.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smpr_act.c index 086a013a44..40ec0e0ad2 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smpr_act.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smpr_act.c @@ -151,6 +151,9 @@ void smprActSendPairRsp(smpCcb_t *pCcb, smpMsg_t *pMsg) /* process pairing request and response data */ if (smpCb.procPairing(pCcb, &oob, &display)) { + /* clear key ready */ + pCcb->keyReady = FALSE; + /* set next expected packet */ if ((pCcb->pairReq[SMP_AUTHREQ_POS] & pMsg->dm.pair.auth & SMP_AUTH_SC_FLAG) == SMP_AUTH_SC_FLAG) { diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smpr_sc_act.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smpr_sc_act.c index 062799ba7c..be0abbcf14 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smpr_sc_act.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smpr_sc_act.c @@ -6,7 +6,7 @@ * * Copyright (c) 2010-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -77,8 +77,12 @@ void smprScActSendPubKey(smpCcb_t *pCcb, smpMsg_t *pMsg) /* Execute Common Auth Select actions */ smpScActAuthSelect(pCcb, pMsg); - /* Send our public key */ - smpScSendPubKey(pCcb, pMsg); + /* Verify auth select didn't result in a cancel request */ + if (pCcb->state) + { + /* Send our public key */ + smpScSendPubKey(pCcb, pMsg); + } } /*************************************************************************************************/ @@ -306,7 +310,7 @@ void smprScActPkSendRand(smpCcb_t *pCcb, smpMsg_t *pMsg) /* Verify the Calculated Cai to previously received Cai */ if (memcmp(pCcb->pScCcb->pScratch->PeerCa_Ea, pMsg->aes.pCiphertext, SMP_RAND_LEN)) { - smpScFailWithReattempt(pCcb); + smpScFailWithReattempt(pCcb, SMP_ERR_CONFIRM_VALUE); } else { @@ -417,7 +421,7 @@ void smprScActOobSendRand(smpCcb_t *pCcb, smpMsg_t *pMsg) /* Check that the Ca value passed via OOB methods match expectations */ if (memcmp(pCcb->pScCcb->pScratch->PeerCa_Ea, pMsg->aes.pCiphertext, SMP_CONFIRM_LEN)) { - smpScFailWithReattempt(pCcb); + smpScFailWithReattempt(pCcb, SMP_ERR_CONFIRM_VALUE); return; } } @@ -527,6 +531,8 @@ void smprScActDHKeyCheckSend(smpCcb_t *pCcb, smpMsg_t *pMsg) memset((pCcb->pScCcb->pLtk->ltk_t + encKeyLen), 0, (SMP_KEY_LEN - encKeyLen)); pCcb->keyReady = TRUE; + + SMP_TRACE_128("LTK:", pCcb->pScCcb->pLtk->ltk_t); /* Send the DH Key check Eb to the initiator */ smpScSendDHKeyCheck(pCcb, pMsg, pCcb->pScCcb->pScratch->Nb_Eb); diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_bb.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_bb.h index 17d341712b..8fba0cc9da 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_bb.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_bb.h @@ -6,7 +6,7 @@ * * Copyright (c) 2016-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -55,6 +55,7 @@ enum BB_STATUS_RX_TIMEOUT, /*!< Receive packet timeout. */ BB_STATUS_CRC_FAILED, /*!< Receive packet with CRC verification failed. */ BB_STATUS_FRAME_FAILED, /*!< Receive packet with frame verification failed. */ + BB_STATUS_MIC_FAILED, /*!< Receive packet with MIC verification failed. */ BB_STATUS_ACK_FAILED, /*!< ACK packet failure. */ BB_STATUS_ACK_TIMEOUT, /*!< ACK packet timeout. */ BB_STATUS_TX_CCA_FAILED, /*!< Transmit CCA failure. */ @@ -222,22 +223,6 @@ void PalBbLoadCfg(PalBbCfg_t *pCfg); /*************************************************************************************************/ uint32_t PalBbGetCurrentTime(void); -/*************************************************************************************************/ -/*! - * \brief Get the current FRC time. - * - * \param pTime Pointer to return the current time. - * - * \return TRUE if time is valid, FALSE otherwise. - * - * Get the current FRC time. - * - * \note FRC is limited to the same bit-width as the BB clock. Return value is available - * only when the BB is active. - */ -/*************************************************************************************************/ -bool_t PalBbGetTimestamp(uint32_t *pTime); - /*************************************************************************************************/ /*! * \brief Called to register a protocol's Radio and Timer IRQ callback functions. diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_bb_ble.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_bb_ble.h index 074c9492b1..d7536d5e1d 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_bb_ble.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_bb_ble.h @@ -175,6 +175,15 @@ void PalBbBleEnable(void); /*************************************************************************************************/ void PalBbBleDisable(void); +/*************************************************************************************************/ +/*! + * \brief Low power operation. + * + * \note Called by upper baseband code. + */ +/*************************************************************************************************/ +void PalBbBleLowPower(void); + /*! \} */ /* PAL_BB_BLE_INIT */ /*! \addtogroup PAL_BB_BLE_CHAN @@ -202,6 +211,24 @@ void PalBbBleDisable(void); /*************************************************************************************************/ void PalBbBleSetChannelParam(PalBbBleChan_t *pChan); +/*************************************************************************************************/ +/*! + * \brief Set the inline encryption packet count for transmit. + * + * \param pktCtr Packet counter value, a 39-bit value (upper bits are ignored). + */ +/*************************************************************************************************/ +void PalBbBleSetInlineEncryptPacketCount(uint64_t pktCtr); + +/*************************************************************************************************/ +/*! + * \brief Set the inline decryption packet count for reception. + * + * \param pktCtr Packet counter value, a 39-bit value (upper bits are ignored). + */ +/*************************************************************************************************/ +void PalBbBleSetInlineDecryptPacketCount(uint64_t pktCtr); + /*! \} */ /* PAL_BB_BLE_CHAN */ /*! \addtogroup PAL_BB_BLE_DATA @@ -334,35 +361,6 @@ void PalBbBleEnableDataWhitening(bool_t enable); /*************************************************************************************************/ void PalBbBleEnablePrbs15(bool_t enable); -/*************************************************************************************************/ -/*! - * \brief Set inline encryption/decryption direction bit. - * - * \param dir 0=slave, non-zero=master - * - */ -/*************************************************************************************************/ -void PalBbBleInlineEncryptDecryptSetDirection(uint8_t dir); - -/*************************************************************************************************/ -/*! - * \brief Set the inline encryption packet count for transmit. - * - * \param count Packet counter value, a 39-bit value - * - */ -/*************************************************************************************************/ -void PalBbBleInlineEncryptSetPacketCount(uint64_t count); - -/*************************************************************************************************/ -/*! - * \brief Low power operation. - * - * \note Called by upper baseband code. - */ -/*************************************************************************************************/ -void PalBbBleLowPower(void); - /*! \} */ /* PAL_BB_BLE_TEST */ #ifdef __cplusplus diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_bb_ble_tester.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_bb_ble_tester.h index 543e628b0b..de1f64d176 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_bb_ble_tester.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_bb_ble_tester.h @@ -107,8 +107,8 @@ void PalBbTesterSetModifyTxPktTrigger(uint16_t hdrMask, uint16_t hdrValue); * If adjustment value is out of range, maximum allowed value is used. */ /*************************************************************************************************/ - void PalBbTesterAdjTxTifsNs(int16_t adjNs); + #ifdef __cplusplus }; #endif diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_btn.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_btn.h index 4000dd77d5..72402d09bc 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_btn.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_btn.h @@ -65,7 +65,8 @@ enum PAL_BTN_AUDIO_RWD, /*!< Fast Rewind button. */ PAL_BTN_AUDIO_VOL_UP, /*!< Volume Up button. */ PAL_BTN_AUDIO_VOL_DN, /*!< Volume Down button. */ - PAL_BTN_AUDIO_MUTE /*!< Mute button. */ + PAL_BTN_AUDIO_MUTE, /*!< Mute button. */ + PAL_BTN_PAUSE /*!< Pause button. */ }; /************************************************************************************************** diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_cfg.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_cfg.h index 4aaea0e7a3..673a4d5692 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_cfg.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_cfg.h @@ -6,7 +6,7 @@ * * Copyright (c) 2018-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,15 +42,17 @@ extern "C" { typedef enum { PAL_CFG_ID_BD_ADDR, /*!< BD address. */ - PAL_CFG_ID_BLE_PHY, /*!< Ble PHY. */ + PAL_CFG_ID_BLE_PHY, /*!< BLE PHY. */ PAL_CFG_ID_LL_PARAM, /*!< LL parameters. */ PAL_CFG_ID_MAC_ADDR, /*!< MAC address. */ PAL_CFG_ID_UUID, /*!< UUID. */ + PAL_CFG_ID_BOOTSTRAP /*!< Bootstrap. */ } PalCfgId_t; /************************************************************************************************** Function Declarations **************************************************************************************************/ + void PalCfgLoadData(uint8_t cfgId, void *pBuf, uint32_t len); void PalCfgSetDeviceUuid(uint8_t *pBuf); diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_codec.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_codec.h index f387f57a10..147aff1176 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_codec.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_codec.h @@ -2,7 +2,7 @@ /*! * \file * - * \brief Hardware audio codec interface file. + * \brief Codec interface file. * * Copyright (c) 2019-2020 Packetcraft, Inc. * @@ -23,8 +23,7 @@ #ifndef PAL_CODEC_H #define PAL_CODEC_H -#include "wsf_types.h" -#include "wsf_os.h" +#include "pal_types.h" #ifdef __cplusplus extern "C" { @@ -44,64 +43,102 @@ typedef enum { PAL_CODEC_DIR_INPUT = 0, /*!< Input data path. */ PAL_CODEC_DIR_OUTPUT = 1 /*!< Output data path. */ -} PalAudioDir_t; +} PalCodecDir_t; /*! \brief Audio Channel. */ typedef enum { PAL_CODEC_CH_LEFT = 0, /*!< Left channel. */ PAL_CODEC_CH_RIGHT = 1, /*!< Right channel. */ - AUDIO_NUM_CH /*!< Right channel. */ -} PalAudioChan_t; + PAL_CODEC_NUM_CH /*!< Total number of channel. */ +} PalCodecChan_t; -/*! \brief Audio Channel mask. */ -enum +/*! \brief Codec IDs. */ +typedef enum { - PAL_CODEC_CH_LEFT_BIT = (1 << PAL_CODEC_CH_LEFT), - PAL_CODEC_CH_RIGHT_BIT = (1 << PAL_CODEC_CH_RIGHT) -}; + /* Standard codecs. */ + PAL_CODEC_ID_LC3_10000US_48KHZ_16B_L = 0x0000, + PAL_CODEC_ID_LC3_10000US_48KHZ_16B_R = 0x0001, + PAL_CODEC_ID_LC3_10000US_16KHZ_16B_L = 0x0002, + PAL_CODEC_ID_LC3_10000US_16KHZ_16B_R = 0x0003, + PAL_CODEC_ID_LC3_7500US_48KHZ_16B_L = 0x0004, + PAL_CODEC_ID_LC3_7500US_48KHZ_16B_R = 0x0005, + /* Custom codecs. */ + PAL_CODEC_ID_SBC_10000US_16KHZ_16B_JS = 0xF000, + PAL_CODEC_ID_OPUS_10000US_48KHZ_16B_JS = 0xF100, + PAL_CODEC_ID_BV32_15000US_16KHZ_16B_M = 0xF200, +} PalCodecId_t; + +/*! \brief Codec info block. */ +typedef struct +{ + uint8_t codecFmt; /*!< Coding format. */ + uint16_t codecId; /*!< Codec ID. */ +} PalCodecInfo_t; /*! \brief Standard codec info block. */ typedef struct { uint8_t codecId; /*!< Codec ID. */ -} AudioStdCodecInfo_t; + uint8_t supTrans; /*!< Supported transport mask. */ +} PalCodecStdInfo_t; /*! \brief VS codec info block. */ typedef struct { uint16_t compId; /*!< Company ID. */ uint16_t codecId; /*!< Codec ID. */ -} AudioVsCodecInfo_t; + uint8_t supTrans; /*!< Supported transport mask. */ +} PalCodecVsInfo_t; /*! \brief Buffer available call signature. */ -typedef void (*PalCodecDataReady_t)(uint16_t id); +typedef void (*PalCodecDataInCback_t)(uint16_t id, uint32_t pktCtr, uint32_t ts, uint8_t *pData, uint16_t actLen); -/*! \brief Codec. */ +/*! \brief Stream parameters. */ typedef struct { - PalAudioDir_t dir; /*!< Stream data direction. */ - uint16_t chMask; /*!< Audio channel mask. */ - uint32_t intervalUsec; /*!< SDU interval in microseconds. */ + PalCodecDir_t dir; /*!< Stream data direction. */ uint32_t pktCtr; /*!< Initial packet counter value. */ - PalCodecDataReady_t rdyCback; /*!< Data ready callback. */ -} PalCodecSreamParam_t; + uint16_t chMask; /*!< Channel mask. */ + uint16_t codecId; /*!< Codec ID. */ + PalCodecDataInCback_t inCback;/*!< Data input callback. */ +} PalCodecStreamParam_t; + +/*! \brief Codec capability. */ +typedef struct +{ + uint32_t sampFreq; /*!< Sampling frequency. */ + uint32_t frmDurUsec; /*!< Frame duration in microseconds. */ + uint16_t numChan; /*!< Channel count. */ + uint16_t minFrmLen; /*!< Minimum frame length. */ + uint16_t maxFrmLen; /*!< Maximum frame length. */ + uint32_t minDlyOutUsec; /*!< Minimum output delay in microseconds. */ + uint32_t maxDlyOutUsec; /*!< Maximum output delay in microseconds. */ + uint32_t minDlyInUsec; /*!< Minimum input delay in microseconds. */ + uint32_t maxDlyInUsec; /*!< Maximum input delay in microseconds. */ +} PalCodecCap_t; /************************************************************************************************** Function Declarations **************************************************************************************************/ /* Codec Information */ -void PalCodecReadLocalSupportedCodecs(uint8_t *pNumStd, AudioStdCodecInfo_t stdCodecs[], - uint8_t *pNumVs, AudioVsCodecInfo_t vsCodecs[]); -bool_t PalCodecReadLocalSupportedCodecCapabilities(uint8_t codingFmt, uint16_t compId, uint16_t vsCodecId, PalAudioDir_t dir); -bool_t PalCodecReadLocalSupportedControllerDelay(uint8_t codingFmt, uint16_t compId, uint16_t vsCodecId, PalAudioDir_t dir, +void PalCodecGetSupported(uint8_t codingFmt, uint8_t *pNumInfo, PalCodecInfo_t info[]); +bool_t PalCodecGetCapability(PalCodecId_t codecId, PalCodecCap_t *pCap); + +// TODO remove +void PalCodecReadLocalSupportedCodecs(uint8_t *pNumStd, PalCodecStdInfo_t stdCodecs[], + uint8_t *pNumVs, PalCodecVsInfo_t vsCodecs[]); +bool_t PalCodecReadLocalSupportedCodecCapabilities(uint8_t codingFmt, uint16_t compId, uint16_t vsCodecId, PalCodecDir_t dir, uint8_t transType, + uint8_t *pCapLen, uint8_t *pCap); +bool_t PalCodecReadLocalSupportedControllerDelay(uint8_t codingFmt, uint16_t compId, uint16_t vsCodecId, PalCodecDir_t dir, uint8_t transType, uint32_t *pMinDly, uint32_t *pMaxDly); -bool_t PalCodecConfigureDataPath(PalAudioDir_t dir, uint8_t dataPathId); +bool_t PalCodecConfigureDataPath(PalCodecDir_t dir, uint8_t vsCfgLen, const uint8_t *pVsCfg); /* Audio Amplifier */ void PalCodecAmpInit(void); -uint8_t PalCodecAmpGetVol(void); +uint8_t PalCodecAmpGetVolume(void); +void PalCodecAmpSetVolume(uint8_t vol); void PalCodecAmpVolumeUp(void); void PalCodecAmpVolumeDown(void); void PalCodecAmpMute(void); @@ -109,10 +146,10 @@ void PalCodecAmpUnmute(void); /* Data Path */ void PalCodecDataInit(void); -bool_t PalCodecDataStartStream(uint16_t id, PalCodecSreamParam_t *pParam); -void PalCodecDataStopStream(uint16_t id); -uint16_t PalCodecDataStreamIn(uint16_t id, uint8_t *pBuf, uint16_t len, uint32_t *pPktCtr); -void PalCodecDataStreamOut(uint16_t id, const uint8_t *pBuf, uint16_t len, uint32_t pktCtr); +bool_t PalCodecDataStartStream(uint16_t id, PalCodecStreamParam_t *pParam); +void PalCodecDataStopStream(uint16_t id, PalCodecDir_t dir); +void PalCodecDataStreamIn(uint16_t id, uint8_t *pBuf, uint16_t len); +void PalCodecDataStreamOut(uint16_t id, const uint8_t *pBuf, uint16_t len, uint32_t sduRef); /*! \} */ /* PAL_CODEC */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_crypto.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_crypto.h index bfecbbb946..d3e4c2c289 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_crypto.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_crypto.h @@ -116,8 +116,6 @@ void PalCryptoAesCmac(const uint8_t *pKey, uint8_t *pOut, const uint8_t *pIn, ui void PalCryptoAesEnable(PalCryptoEnc_t *pEnc, uint8_t id, uint8_t localDir); bool_t PalCryptoAesCcmEncrypt(PalCryptoEnc_t *pEnc, uint8_t *pHdr, uint8_t *pBuf, uint8_t *pMic); bool_t PalCryptoAesCcmDecrypt(PalCryptoEnc_t *pEnc, uint8_t *pBuf); -void PalCryptoSetEncryptPacketCount(PalCryptoEnc_t *pEnc, uint64_t pktCnt); -void PalCryptoSetDecryptPacketCount(PalCryptoEnc_t *pEnc, uint64_t pktCnt); /*! \} */ /* PAL_CRYPTO */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_flash.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_flash.h index 46c8e7a76e..9836bd9a42 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_flash.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_flash.h @@ -3,10 +3,10 @@ * \file * * \brief PAL flash driver. - * + * * Copyright (c) 2018-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,9 +38,6 @@ extern "C" { Data Types **************************************************************************************************/ -/*! \brief Callback. This may be returned in interrupt context. */ -typedef void (*PalFlashCback_t)(bool_t status); - /*! \brief Operational states. */ typedef enum { @@ -50,24 +47,39 @@ typedef enum PAL_FLASH_STATE_BUSY /*!< Busy state. */ } PalFlashState_t; +/*! \brief Partition. */ +typedef enum +{ + PAL_FLASH_PART_NVM = 0, /*!< Non-Volatile Memory partition. */ + PAL_FLASH_PART_FOTA_FW, /*!< Firmware image partition. */ + PAL_FLASH_PART_FOTA_AUTH, /*!< Firmware image authentication partition. */ + PAL_FLASH_PART_MAX /*!< Maximum number of partitions. */ +} PalFlashPartition_t; + +/*! \brief Operation completion callback (may be called in interrupt context).. */ +typedef void (*PalFlashCback_t)(void); + /************************************************************************************************** Function Declarations **************************************************************************************************/ /* Initialization */ -void PalFlashInit(PalFlashCback_t actCback); +void PalFlashInit(void); void PalFlashDeInit(void); /* Control and Status */ -PalFlashState_t PalNvmGetState(void); -uint32_t PalNvmGetTotalSize(void); -uint32_t PalNvmGetSectorSize(void); +PalFlashState_t PalFlashGetState(PalFlashPartition_t part); +uint32_t PalFlashGetTotalSize(PalFlashPartition_t part); +uint32_t PalFlashGetSectorSize(PalFlashPartition_t part); +bool_t PalFlashService(void); /* Data Transfer */ -void PalFlashRead(void *pBuf, uint32_t size, uint32_t srcAddr); -void PalFlashWrite(void *pBuf, uint32_t size, uint32_t dstAddr); -void PalFlashEraseSector(uint32_t size, uint32_t startAddr); -void PalFlashEraseChip(void); +void PalFlashRead(PalFlashPartition_t part, void *pBuf, uint32_t size, uint32_t offset, + PalFlashCback_t compCback); +void PalFlashWrite(PalFlashPartition_t part, void *pBuf, uint32_t size, + uint32_t offset, PalFlashCback_t compCback); +void PalFlashEraseSector(PalFlashPartition_t part, uint32_t size, uint32_t offset, + PalFlashCback_t compCback); /*! \} */ /* PAL_FLASH */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_frc.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_frc.h new file mode 100644 index 0000000000..f59cfb8dff --- /dev/null +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_frc.h @@ -0,0 +1,55 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief FRC interface file. + * + * Copyright (c) 2019-2020 Packetcraft, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ + +#ifndef PAL_FRC_H +#define PAL_FRC_H + +#include "pal_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \addtogroup PAL_FRC + * \{ */ + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/* Initialization */ +void PalFrcInit(void); + +/* Control and Status */ +uint32_t PalFrcGetCurrentTime(void); +void palFrcSetWakeup(uint32_t nextWakeMs); +uint32_t PalFrcMsToTicks(uint32_t deltaMs); +uint32_t PalFrcDeltaMs(uint32_t endTime, uint32_t startTime); +uint32_t PalFrcDeltaUs(uint32_t endTime, uint32_t startTime); + +/*! \} */ /* PAL_FRC */ + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_i2s.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_i2s.h index f1748ebe7a..6d168f215e 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_i2s.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_i2s.h @@ -92,6 +92,7 @@ void PalI2sDeConfig(void); /* Data Transfer */ void PalI2sReadData(uint8_t *pData, uint16_t len); void PalI2sWriteData(const uint8_t *pData, uint16_t len); +void PalI2sReadWriteData(uint8_t *pRdData, const uint8_t *pWrData, uint16_t len); /*! \} */ /* PAL_I2S */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_io_exp.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_io_exp.h index 012f97a42e..52a7e9aea3 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_io_exp.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_io_exp.h @@ -4,7 +4,7 @@ * * \brief I/O expander driver definition. * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,51 +32,55 @@ extern "C" { /*! \addtogroup PAL_IO_EXP * \{ */ +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief Invalid device ID. */ +#define PAL_IO_EXP_INVALID_ID 0xFF + /************************************************************************************************** Data Types **************************************************************************************************/ /*! \brief Read register completion callback. */ -typedef void (*PalIoExpRdRegCompCback_t)(bool_t status, uint8_t portValue); +typedef void (*PalIoExpReadCompCback_t)(uint32_t value); /*! \brief Write register completion callback. */ -typedef void (*PalIoExpWrRegCompCback_t)(bool_t status); +typedef void (*PalIoExpWriteCompCback_t)(void); + +/*! \brief Device configuration. */ +typedef struct +{ + PalIoExpReadCompCback_t rdCback; /*!< Read data completion callback. */ + PalIoExpWriteCompCback_t wrCback; /*!< Write data completion callback. */ + uint32_t inputMask; /*!< Bitmask for input pins (1 for input, 0 for output). */ + uint8_t addr; /*!< Device address defined by the voltage on the board. */ +} PalIoExpConfig_t; /*! \brief Operational states. */ typedef enum { PAL_IO_EXP_STATE_UNINIT = 0, /*!< Uninitialized state. */ PAL_IO_EXP_STATE_ERROR = 0, /*!< Error state. */ - PAL_IO_EXP_STATE_INIT = 1, /*!< Initialized state. */ - PAL_IO_EXP_STATE_READY = 2, /*!< Ready state. */ - PAL_IO_EXP_STATE_BUSY = 3, /*!< Busy state. */ + PAL_IO_EXP_STATE_READY = 1, /*!< Ready state. */ + PAL_IO_EXP_STATE_BUSY = 2, /*!< Busy state. */ } PalIoExpState_t; -/*! \brief Operations. */ -typedef enum -{ - PAL_IO_EXP_OP_INPUT = 0x00, /*!< Input Port. Read only. */ - PAL_IO_EXP_OP_OUTPUT = 0x01, /*!< Output Port. Read/write. */ - PAL_IO_EXP_OP_POL_INV = 0x02, /*!< Polarity Inversion. Read/write. */ - PAL_IO_EXP_OP_CONFIG = 0x03 /*!< Configuration. Read/write. */ -} PalIoOp_t; - /************************************************************************************************** Function Declarations **************************************************************************************************/ /* Initialization */ -void PalIoExpInit(void); +uint8_t PalIoExpInit(PalIoExpConfig_t *pCfg); void PalIoExpDeInit(void); -uint8_t PalIoExpRegisterDevice(uint8_t subAddr); -void PalIoExpRegisterCback(uint8_t devHandle, PalIoExpRdRegCompCback_t rdCback, PalIoExpWrRegCompCback_t wrCback); /* Control and Status */ -PalIoExpState_t PalIoExpGetState(uint8_t devHandle); +PalIoExpState_t PalIoExpGetState(uint8_t id); /* Data transfer */ -void PalIoExpRead(uint8_t devHandle, PalIoOp_t op); -void PalIoExpWrite(uint8_t devHandle, PalIoOp_t op, uint8_t value); +void PalIoExpRead(uint8_t id); +void PalIoExpWrite(uint8_t id, uint32_t value); /*! \} */ /* PAL_IO_EXP */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_ipc.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_ipc.h new file mode 100644 index 0000000000..1f71526c88 --- /dev/null +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_ipc.h @@ -0,0 +1,70 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief IPC driver definition. + * + * Copyright (c) 2019-2020 Packetcraft, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ + +#ifndef PAL_IPC_H +#define PAL_IPC_H + +#include "pal_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \addtogroup PAL_IPC + * \{ */ + +/************************************************************************************************** + Type Definitions +**************************************************************************************************/ + +/*! \brief Operational states. */ +typedef enum +{ + PAL_IPC_STATE_UNINIT = 0, /*!< Uninitialized state. */ + PAL_IPC_STATE_ERROR = 0, /*!< Error state. */ + PAL_IPC_STATE_IDLE, /*!< Initialized state. */ + PAL_IPC_STATE_BUSY /*!< Busy state. */ +} PalIpcState_t; + +typedef void (*PalIpcMsgHandler_t)(uint8_t *pBuf, uint16_t len); + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/* Initialization */ +void PalIpcInit(PalIpcMsgHandler_t recvCback); +void PalIpcDeInit(void); + +/* Control and Status */ +PalIpcState_t PalIpcGetState(void); + +/* Data Transfer */ +void PalIpcWriteData(const uint8_t *pData, uint16_t len); + +/*! \} */ /* PAL_IPC */ + +#ifdef __cplusplus +}; +#endif + +#endif /* PAL_IPC_H */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_led.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_led.h index 5f81d16efd..06b274d871 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_led.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_led.h @@ -40,8 +40,8 @@ extern "C" { enum { /* System signals. */ - PAL_LED_ID_CPU_ACTIVE = 0x30, /*!< CPU active LED ID. */ - PAL_LED_ID_ERROR = 0x31, /*!< Error LED ID. */ + PAL_LED_ID_CPU_ACTIVE = 30, /*!< CPU active LED ID. */ + PAL_LED_ID_ERROR = 31 /*!< Error LED ID. */ }; /************************************************************************************************** diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_radio.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_radio.h index bfea3badb3..90dc7072e8 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_radio.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_radio.h @@ -119,15 +119,6 @@ void PalRadioGetSupTxPower(int8_t *pMinTxPwr, int8_t *pMaxTxPwr); /*************************************************************************************************/ void PalRadioReadRfPathComp(int16_t *pTxPathComp, int16_t *pRxPathComp); -/*************************************************************************************************/ -/*! - * \brief Get receive RF path compensation. - * - * \return Transmit RF path compensation (in 1-dBm units). - */ -/*************************************************************************************************/ -int8_t PalRadioGetRxRfPathComp(void); - /*! \} */ /* PAL_RADIO */ #ifdef __cplusplus diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_radio2.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_radio2.h index f7f9cbad19..bfcaf01848 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_radio2.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_radio2.h @@ -4,7 +4,7 @@ * * \brief Radio interface file. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ #define PAL_RADIO_H #include +#include "pal_types.h" #ifdef __cplusplus extern "C" { @@ -58,7 +59,8 @@ typedef enum PAL_RADIO_STATUS_SUCCESS, /*!< Operation completed successfully. */ PAL_RADIO_STATUS_FAILED, /*!< General failure. */ PAL_RADIO_STATUS_TIMEOUT, /*!< Rx timed out. */ - PAL_RADIO_STATUS_CRC_FAILED /*!< Rx CRC match failed. */ + PAL_RADIO_STATUS_CRC_FAILED, /*!< Rx CRC match failed. */ + PAL_RADIO_STATUS_MIC_FAILED /*!< Rx MIC match failed. */ } PalRadioStatus_t; typedef enum @@ -74,7 +76,7 @@ typedef enum typedef void (*PalRadioTxComp_t)(PalRadioStatus_t status); /*! \brief Rx completion call signature. */ -typedef void (*PalRadioRxComp_t)(PalRadioStatus_t status, uint32_t tstamp, PalRadioPhy_t phy, int8_t rssi); +typedef void (*PalRadioRxComp_t)(PalRadioStatus_t status, uint32_t startOffs, PalRadioPhy_t phy, int8_t rssi); /************************************************************************************************** Functions @@ -85,6 +87,7 @@ void PalRadioInit(void); void PalRadioDeInit(void); /* Control and Status */ +PalRadioState_t PalRadioGetState(void); void PalRadioRegisterTxComplete(PalRadioTxComp_t cback); void PalRadioRegisterRxComplete(PalRadioRxComp_t cback); void PalRadioSetAccessAddress(uint32_t addr); @@ -95,14 +98,23 @@ int8_t PalRadioGetTxPower(void); void PalRadioSetPhy(PalRadioPhy_t txPhy, PalRadioPhy_t rxPhy); void PalRadioSetDataWhitening(uint8_t ena); void PalRadioSetPrbs15(uint8_t ena); -PalRadioState_t PalRadioGetState(void); + +/* Encryption */ +void PalRadioSetEncryption(uint8_t txEna, uint8_t rxEna); +void PalRadioSetSessionKey(uint8_t *pSK); +void PalRadioSetIV(uint8_t *pIV); +void PalRadioSetDirection(uint8_t dir); +void PalRadioSetEncryptionType(uint8_t type); +void PalRadioSetPacketCounter(uint64_t pktCtr); /* Data Transfer */ void PalRadioTxStart(uint32_t dueTime); -void PalRadioTxNext(uint32_t offsUsec); +void PalRadioTxTifs(uint16_t tifsUsec); +void PalRadioTxOffset(uint32_t offsUsec); void PalRadioTxData(uint8_t *pBuf, uint16_t len); -void PalRadioRxStart(uint32_t dueTime, uint32_t rxTimeoutUsec); -void PalRadioRxNext(uint32_t offsUsec, uint32_t rxTimeoutUsec); +bool_t PalRadioRxStart(uint32_t dueTime, uint32_t rxTimeoutUsec); +void PalRadioRxTifs(uint16_t tifsUsec, uint32_t rxTimeoutUsec); +bool_t PalRadioRxOffset(uint32_t offsUsec, uint32_t rxTimeoutUsec); void PalRadioRxData(uint8_t *pBuf, uint16_t len); void PalRadioStop(void); diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_rtc.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_rtc.h index 4e45c4028e..f158364076 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_rtc.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_rtc.h @@ -34,22 +34,6 @@ extern "C" { /*! \addtogroup PAL_RTC * \{ */ -/************************************************************************************************** - Macros -**************************************************************************************************/ - -/*! \brief Max value of RTC. */ -#define PAL_MAX_RTC_COUNTER_VAL (0x00FFFFFF) - -/*! \brief Clock frequency of the RTC timer used. */ -#define PAL_RTC_TICKS_PER_SEC (32768) /* RTC ticks per second (with prescaler) */ - -/*! \brief 23 RTC ticks time(700us) for xtal start up befor scheduler load. */ -#define PAL_HFCLK_OSC_SETTLE_TICKS (23) - -/*! \brief Platform RTC callback. */ -typedef void (*palRtcIrqCback_t)(void); - /************************************************************************************************** Type Definitions **************************************************************************************************/ @@ -62,6 +46,9 @@ typedef enum PAL_RTC_STATE_READY = 1 /*!< Ready state. */ } PalRtcState_t; +/*! \brief Platform RTC callback. */ +typedef void (*palRtcIrqCback_t)(void); + /************************************************************************************************** Function Declarations **************************************************************************************************/ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_sys.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_sys.h index fb7928b8be..a82f85fcea 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_sys.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_sys.h @@ -6,7 +6,7 @@ * * Copyright (c) 2016-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,16 +38,14 @@ extern "C" { Macros **************************************************************************************************/ -/* Common error handling routines; for use with PAL implementation only. */ - #ifdef DEBUG -/*! \brief Parameter check. */ +/*! \brief Error check routines; for use with PAL implementation only. */ #define PAL_SYS_ASSERT(expr) { if (!(expr)) { PalSysAssertTrap(); } } #else -/*! \brief Parameter check (disabled). */ +/*! \brief Error check routines (disabled). */ #define PAL_SYS_ASSERT(expr) #endif @@ -64,16 +62,15 @@ void PalSysAssertTrap(void); void PalSysSetTrap(bool_t enable); uint32_t PalSysGetAssertCount(void); uint32_t PalSysGetStackUsage(void); +bool_t PalSysDiagTraceWrite(const uint8_t *pBuf, uint32_t len); /* Power Management */ -void PalSysSleep(void); -bool_t PalSysIsBusy(void); -void PalSysSetBusy(void); -void PalSysSetIdle(void); +void PalSysSleep(uint32_t nextWakeMs); +void PalSysWakeFromDeepSleep(void); /* Critical Section */ -void PalEnterCs(void); -void PalExitCs(void); +void PalSysCsEnter(void); +void PalSysCsExit(void); /*! \} */ /* PAL_SYS */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_timer.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_timer.h index 282722dc0d..e4396a4c4b 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_timer.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/platform/include/pal_timer.h @@ -34,19 +34,6 @@ extern "C" { /*! \addtogroup PAL_TIMER * \{ */ -/************************************************************************************************** - Macros -**************************************************************************************************/ - -/*! \brief Operational states. */ -typedef enum -{ - PAL_TIMER_STATE_UNINIT = 0, /*!< Uninitialized state. */ - PAL_TIMER_STATE_ERROR = 0, /*!< Error state. */ - PAL_TIMER_STATE_READY, /*!< Ready state. */ - PAL_TIMER_STATE_BUSY /*!< Busy state. */ -} PalTimerState_t; - /************************************************************************************************** Data Types **************************************************************************************************/ @@ -54,6 +41,15 @@ typedef enum /*! \brief Completion callback. */ typedef void (*PalTimerCompCback_t)(void); +/*! \brief Timer states. */ +typedef enum +{ + PAL_TIMER_STATE_UNINIT = 0, + PAL_TIMER_STATE_ERROR = 0, + PAL_TIMER_STATE_READY, + PAL_TIMER_STATE_BUSY +} PalTimerState_t; + /************************************************************************************************** Function Declarations **************************************************************************************************/ @@ -64,9 +60,9 @@ void PalTimerDeInit(void); /* Control and Status */ PalTimerState_t PalTimerGetState(void); +uint32_t PalTimerGetTimeToNextExpiration(void); void PalTimerStart(uint32_t expUsec); void PalTimerStop(void); -uint32_t PalTimerGetCurrentTime(void); /*! \} */ /* PAL_TIMER */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/hci_defs.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/hci_defs.h index c6ebb3dc4f..9404ed1a93 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/hci_defs.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/hci_defs.h @@ -6,7 +6,7 @@ * * Copyright (c) 2009-2019 ARM Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,10 +47,21 @@ extern "C" { #define HCI_PB_START_C2H 0x2000 /*!< Packet boundary flag, start, controller-to-host */ #define HCI_HANDLE_MASK 0x0FFF /*!< Mask for handle bits in ACL packet */ #define HCI_HANDLE_NONE 0xFFFF /*!< Value for invalid handle */ +#define HCI_ISO_GROUP_ID_NONE 0xFF /*!< Value for invalid CIG/BIG ID */ + +/* ISO Header. */ +#define HCI_TS_FLAG_MASK (1 << 14) + /*!< Timestamp flag mask for ISO packets. */ +#define HCI_DATA_LOAD_LEN_MASK 0x3FFF /*!< HCI Data load length. */ + +/* ISO Data load. */ #define HCI_ISO_DL_MIN_LEN 4 /*!< ISO Data Load header minimum length */ #define HCI_ISO_DL_MAX_LEN 8 /*!< ISO Data Load header maximum length */ #define HCI_ISO_TS_LEN 4 /*!< ISO Data Load timestamp length */ +#define HCI_ISO_DL_SDU_LEN_MASK 0x0FFF /*!< HCI SDU Length mask. */ +#define HCI_ISO_DL_PS_MASK 0xC000 /*!< HCI Packet status mask. */ + /**@}*/ /** \name Packet types @@ -176,11 +187,12 @@ extern "C" { #define HCI_OCF_SET_CONTROLLER_TO_HOST_FC 0x31 #define HCI_OCF_HOST_BUFFER_SIZE 0x33 #define HCI_OCF_HOST_NUM_CMPL_PKTS 0x35 +#define HCI_OCF_READ_AFH_CHAN_ASSESMENT_MODE 0x48 +#define HCI_OCF_WRITE_AFH_CHAN_ASSESSMENT_MODE 0x49 /* Version 4.1 */ #define HCI_OCF_SET_EVENT_MASK_PAGE2 0x63 #define HCI_OCF_READ_AUTH_PAYLOAD_TO 0x7B #define HCI_OCF_WRITE_AUTH_PAYLOAD_TO 0x7C - /* Version 5.2 */ #define HCI_OCF_CONFIG_DATA_PATH 0x83 /**@}*/ @@ -338,6 +350,9 @@ extern "C" { #define HCI_OCF_LE_SET_PATH_LOSS_REPORTING_PARAMS 0x78 #define HCI_OCF_LE_SET_PATH_LOSS_REPORTING_ENABLE 0x79 #define HCI_OCF_LE_SET_TX_POWER_REPORT_ENABLE 0x7A +/* Version Sydney */ +#define HCI_OCF_LE_SET_DEF_SUBRATE 0x7D +#define HCI_OCF_LE_SUBRATE_REQ 0x7E /**@}*/ /** \name Opcode manipulation macros @@ -360,6 +375,8 @@ extern "C" { #define HCI_OPCODE_SET_EVENT_MASK HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_SET_EVENT_MASK) #define HCI_OPCODE_RESET HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_RESET) +#define HCI_OPCODE_READ_AFH_CHAN_ASSESMENT_MODE HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_READ_AFH_CHAN_ASSESMENT_MODE) +#define HCI_OPCODE_WRITE_AFH_CHAN_ASSESSMENT_MODE HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_WRITE_AFH_CHAN_ASSESSMENT_MODE) #define HCI_OPCODE_READ_TX_PWR_LVL HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_READ_TX_PWR_LVL) #define HCI_OPCODE_SET_EVENT_MASK_PAGE2 HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_SET_EVENT_MASK_PAGE2) #define HCI_OPCODE_READ_AUTH_PAYLOAD_TO HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_READ_AUTH_PAYLOAD_TO) @@ -503,6 +520,10 @@ extern "C" { #define HCI_OPCODE_LE_SET_PATH_LOSS_REPORTING_PARAMS HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_PATH_LOSS_REPORTING_PARAMS) #define HCI_OPCODE_LE_SET_PATH_LOSS_REPORTING_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_PATH_LOSS_REPORTING_ENABLE) #define HCI_OPCODE_LE_SET_TX_POWER_REPORT_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_TX_POWER_REPORT_ENABLE) +/* Version Sydney */ +#define HCI_OPCODE_LE_SET_DEF_SUBRATE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_DEF_SUBRATE) +#define HCI_OPCODE_LE_SUBRATE_REQ HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SUBRATE_REQ) + /**@}*/ /** \name Packetcraft Vendor Specific @@ -635,8 +656,7 @@ extern "C" { #define HCI_LEN_LE_SET_PAST_PARAM 8 #define HCI_LEN_LE_SET_DEFAULT_PAST_PARAM 6 #define HCI_LEN_LE_GENERATE_DHKEY_V2 65 - -/* Version Milan */ +/* Version 5.2 */ #define HCI_LEN_LE_SET_CIG_PARAMS(numCis) (15 + (9 * (numCis))) #define HCI_LEN_LE_CREATE_CIS(numCis) (1 + (4 * (numCis))) #define HCI_LEN_LE_REMOVE_CIG 1 @@ -654,6 +674,8 @@ extern "C" { #define HCI_LEN_LE_ISO_READ_TEST_COUNTERS 2 #define HCI_LEN_LE_ISO_TEST_END 2 #define HCI_LEN_LE_SET_HOST_FEATURE 2 +/* Version Sydney */ +#define HCI_LEN_LE_SET_DEF_SUBRATE 1 /**@}*/ /** \name Events @@ -671,6 +693,7 @@ extern "C" { #define HCI_ENC_KEY_REFRESH_CMPL_EVT 0x30 #define HCI_LE_META_EVT 0x3E #define HCI_AUTH_PAYLOAD_TIMEOUT_EVT 0x57 +#define HCI_ENC_CHANGE_V2_EVT 0x59 #define HCI_VENDOR_SPEC_EVT 0xFF /**@}*/ @@ -717,6 +740,8 @@ extern "C" { #define HCI_LE_PATH_LOSS_REPORT_EVT 0x20 #define HCI_LE_POWER_REPORT_EVT 0x21 #define HCI_LE_BIG_INFO_ADV_REPORT_EVT 0x22 +/* Version Sydney */ +#define HCI_LE_SUBRATE_CHANGE_EVT 0x23 /**@}*/ /** \name Event parameter lengths @@ -768,7 +793,9 @@ extern "C" { #define HCI_LEN_LE_POWER_REPORT 9 /*!< Power reporting event length. */ #define HCI_LEN_LE_PATH_LOSS_ZONE 5 /*!< Path loss reporting event length. */ #define HCI_LEN_LE_BIG_INFO_ADV_REPORT 20 /*!< BIG Info advertising report length. */ - +/* Version Sydney */ +#define HCI_LEN_ENC_CHANGE_V2 5 /*!< Encryption change (V2) event length. */ +#define HCI_LEN_LE_SUBRATE_CHANGE 12 /*!< Subrate change event length. */ /**@}*/ /** \name Supported commands @@ -909,18 +936,20 @@ extern "C" { #define HCI_SUP_LE_SET_HOST_FEATURE 0x02 /*!< Byte 44 */ #define HCI_SUP_LE_READ_ISO_LINK_QUALITY 0x04 /*!< Byte 44 */ #define HCI_SUP_LE_ENH_READ_TX_POWER_LEVEL 0x08 /*!< Byte 44 */ -#define HCI_SUP_LE_READ_REMOTE_TX_POWER_LEVEL 0x01 /*!< Byte 44 */ -#define HCI_SUP_LE_SET_PATH_LOSS_REPORT_PARAM 0x02 /*!< Byte 44 */ -#define HCI_SUP_LE_SET_PATH_LOSS_REPORT_ENABLE 0x04 /*!< Byte 44 */ -#define HCI_SUP_LE_SET_TX_POWER_REPORT_ENABLE 0x08 /*!< Byte 44 */ +#define HCI_SUP_LE_READ_REMOTE_TX_POWER_LEVEL 0x10 /*!< Byte 44 */ +#define HCI_SUP_LE_SET_PATH_LOSS_REPORT_PARAM 0x20 /*!< Byte 44 */ +#define HCI_SUP_LE_SET_PATH_LOSS_REPORT_ENABLE 0x40 /*!< Byte 44 */ +#define HCI_SUP_LE_SET_TX_POWER_REPORT_ENABLE 0x80 /*!< Byte 44 */ #define HCI_SUP_LE_TRANSMITTER_TEST_V4 0x01 /*!< Byte 45 */ #define HCI_SUP_READ_LOCAL_SUP_CODECS_V2 0x02 /*!< Byte 45 */ #define HCI_SUP_READ_LOCAL_SUP_CODEC_CAP 0x04 /*!< Byte 45 */ #define HCI_SUP_READ_LOCAL_SUP_CTR_DLY 0x08 /*!< Byte 45 */ #define HCI_SUP_CONFIG_DATA_PATH 0x10 /*!< Byte 45 */ +/* Version Sydney */ +#define HCI_SUP_LE_SET_DEF_SUBRATE 0x01 /*!< Byte 46 */ +#define HCI_SUP_LE_SET_SUBRATE_REQ 0x02 /*!< Byte 46 */ #define HCI_SUP_CMD_LEN 64 /*!< Byte length of support cmd field. */ - /**@}*/ /** \name Event mask @@ -941,6 +970,7 @@ extern "C" { */ /**@{*/ #define HCI_EVT_MASK_AUTH_PAYLOAD_TIMEOUT 0x80 /*!< Byte 2 */ +#define HCI_EVT_MASK_ENC_CHANGE_V2 0x02 /*!< Byte 3 */ /**@}*/ /** \name LE event mask @@ -984,10 +1014,10 @@ extern "C" { #define HCI_EVT_MASK_LE_BIG_SYNC_LOST_EVT 0x20 /*!< Byte 3 */ #define HCI_EVT_MASK_LE_PEER_SCA_CMPL_EVT 0x40 /*!< Byte 3 */ #define HCI_EVT_MASK_LE_PATH_LOSS_REPORT_EVT 0x80 /*!< Byte 3 */ - #define HCI_EVT_MASK_LE_TX_POWER_REPORT_EVT 0x01 /*!< Byte 4 (Bit 32)*/ #define HCI_EVT_MASK_LE_BIG_INFO_ADV_RPT_EVT 0x02 /*!< Byte 4 */ - +/* Version Sydney */ +#define HCI_EVT_MASK_LE_SUBRATE_CHANGE_EVT 0x04 /*!< Byte 4 */ /**@}*/ /** \name LE supported features @@ -1027,7 +1057,7 @@ extern "C" { #define HCI_LE_SUP_FEAT_PAST_RECIPIENT 0x0000000002000000 /*!< Periodic Advertising Sync Transfer Recipient supported */ #define HCI_LE_SUP_FEAT_SCA_UPDATE 0x0000000004000000 /*!< Sleep Clock Accuracy Update supported */ #define HCI_LE_SUP_FEAT_REMOTE_PUB_KEY_VALIDATION 0x0000000008000000 /*!< Remote Public Key Validation supported */ -/* Version Milan */ +/* Version 5.2 */ #define HCI_LE_SUP_FEAT_CIS_MASTER 0x0000000010000000 /*!< Connected Isochronous Master Role supported */ #define HCI_LE_SUP_FEAT_CIS_SLAVE 0x0000000020000000 /*!< Connected Isochronous Slave Role supported */ #define HCI_LE_SUP_FEAT_ISO_BROADCASTER 0x0000000040000000 /*!< Isochronous Broadcaster Role supported */ @@ -1313,8 +1343,8 @@ extern "C" { */ /**@{*/ #define HCI_SYNC_TRSF_MODE_OFF 0x00 /*!< Periodic sync transfer receive is disabled */ -#define HCI_SYNC_TRSF_MODE_REP_DISABLED 0x01, /*!< Periodic sync transfer receive is enabled, report event is disabled */ -#define HCI_SYNC_TRSF_MODE_REP_ENABLED 0x02, /*!< Periodic sync transfer receive is enabled, report event is enabled */ +#define HCI_SYNC_TRSF_MODE_REP_DISABLED 0x01 /*!< Periodic sync transfer receive is enabled, report event is disabled */ +#define HCI_SYNC_TRSF_MODE_REP_ENABLED 0x02 /*!< Periodic sync transfer receive is enabled, report event is enabled */ /**@}*/ /** \name Periodic advertising create sync options bits @@ -1409,6 +1439,26 @@ extern "C" { #define HCI_CTE_TYPE_REQ_AOD_2_US 0x02 /*!< AoD Constant Tone Extension with 2 us slots */ /**@}*/ +/** \name Sync CTE Type bits +* +*/ +/**@{*/ +#define HCI_SYNC_CTE_TYPE_DONT_SYNC_AOA_BIT (1<<0) /*!< Do not sync to packets with an AoA Constant Tone Extension */ +#define HCI_SYNC_CTE_TYPE_DONT_SYNC_AOD_1_US_BIT (1<<1) /*!< Do not sync to packets with an AoD Constant Tone Extension with 1 us slots */ +#define HCI_SYNC_CTE_TYPE_DONT_SYNC_AOD_2_US_BIT (1<<2) /*!< Do not sync to packets with an AoD Constant Tone Extension with 2 us slots */ +#define HCI_SYNC_CTE_TYPE_DONT_SYNC_TYPE_3_BIT (1<<3) /*!< Do not sync to packets with a type 3 Constant Tone Extension */ +/**@}*/ + +/** \name CTE Type bits +* +*/ +/**@{*/ +#define HCI_CTE_TYPE_DONT_SYNC_AOA_BIT (1<<0) /*!< Do not sync to packets with an AoA Constant Tone Extension */ +#define HCI_CTE_TYPE_DONT_SYNC_AOD_1_US_BIT (1<<1) /*!< Do not sync to packets with an AoD Constant Tone Extension with 1 us slots */ +#define HCI_CTE_TYPE_DONT_SYNC_AOD_2_US_BIT (1<<2) /*!< Do not sync to packets with an AoD Constant Tone Extension with 2 us slots */ +#define HCI_CTE_TYPE_DONT_SYNC_WITHOUT_CTE_BIT (1<<4) /*!< Do not sync to packets without Constant Tone Extension */ +/**@}*/ + /** \name Bluetooth core specification versions * */ @@ -1422,10 +1472,9 @@ extern "C" { /**@}*/ #ifndef HCI_VER_BT -#define HCI_VER_BT HCI_VER_BT_CORE_SPEC_5_1 +# define HCI_VER_BT HCI_VER_BT_CORE_SPEC_5_1 #endif - /** \name Parameter lengths * */ @@ -1454,6 +1503,14 @@ extern "C" { #define HCI_PER_ADV_RPT_DATA_LEN_OFFSET 6 /*!< Length field offset of periodic advertising report data */ /**@}*/ +/** \name Maximum Advertising Handle and SID +* +*/ +/**@{*/ +#define HCI_MAX_ADV_HANDLE 0xEF /*!< Maximum advertising handle */ +#define HCI_MAX_ADV_SID 0x0F /*!< Maximum advertising SID */ +/**@}*/ + /** \name Number of Antenna IDs in Switching Pattern * */ @@ -1472,18 +1529,32 @@ extern "C" { #define HCI_CONN_IQ_RPT_SAMPLE_CNT_OFFSET 12 /*!< Sample count field offset of connection IQ report */ /**@}*/ +/** \name CIG Count +* +*/ +/**@{*/ +#define HCI_MAX_CIG_COUNT 2 /*!< Maximum count for CIG */ +/**@}*/ + /** \name CIS Count * */ /**@{*/ -#define HCI_MAX_CIS_COUNT 0x10 /*!< Maximum count for CIS */ +#define HCI_MAX_CIS_COUNT 6 /*!< Maximum count for CIS */ +/**@}*/ + +/** \name BIG Count +* +*/ +/**@{*/ +#define HCI_MAX_BIG_COUNT 2 /*!< Maximum count for BIG */ /**@}*/ /** \name BIS Count * */ /**@{*/ -#define HCI_MAX_BIS_COUNT 0x10 /*!< Maximum count for BIS */ +#define HCI_MAX_BIS_COUNT 6 /*!< Maximum count for BIS */ /**@}*/ /** \name CIG IDs @@ -1596,7 +1667,7 @@ extern "C" { */ /**@{*/ #define HCI_ISO_DATA_PATH_HCI 0x00 /*!< HCI data path. */ -#define HCI_ISO_DATA_PATH_VS_I2S 0x01 /*!< Vendor Specific: I2S data path. */ +#define HCI_ISO_DATA_PATH_VS 0x01 /*!< Vendor Specific. */ #define HCI_ISO_DATA_PATH_DISABLED 0xFF /*!< Data path is disabled. */ /**@}*/ @@ -1667,10 +1738,18 @@ extern "C" { * */ /**@{*/ -#define HCI_ID_LC3 0x01 /*!< LC3 ID */ +#define HCI_ID_LC3 0x06 /*!< LC3 ID */ #define HCI_ID_VS 0xFF /*!< Vendor specific ID */ /**@}*/ +/** \name Coding Format Assigned Numbers + * + */ +/**@{*/ +#define HCI_CODEC_TRANSPORT_CIS 0x02 /*!< Codec supported over LE CIS */ +#define HCI_CODEC_TRANSPORT_BIS 0x03 /*!< Codec supported over LE BIS */ +/**@}*/ + /* \} */ /* STACK_HCI_API */ #ifdef __cplusplus diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/ll_defs.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/ll_defs.h index 03c81f1bb8..e75ade00f7 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/ll_defs.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/ll_defs.h @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -147,6 +147,8 @@ enum #define LL_MAX_ADV_HANDLE 0xEF /*!< Maximum advertising handle. */ #define LL_MAX_ADV_SID 0x0F /*!< Maximum advertising SID */ +#define LL_DID_NOT_PRESENT 0xFF /*!< Periodic advertising data DID was not present. */ + #define LL_EXT_ADV_HDR_MIN_LEN 1 /*!< Minimum extended advertising header length (ExtHdrLen and AdvMode fields). */ #define LL_EXT_ADV_HDR_MAX_LEN 64 /*!< Maximum extended advertising header length (ExtHdrLen, AdvMode fields and Extended header). */ #define LL_EXT_HDR_FLAG_LEN 1 /*!< Length of extended header flag field */ @@ -167,7 +169,7 @@ enum #define LL_EXT_ADVB_NORMAL_TIME_S8 ((LL_BLE_US_PER_BYTE_CODED_S8 * (LL_EXT_ADVB_NORMAL_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_CODED_S8) /*!< Time for a Coded S8 advertising channel PDU with normal length. */ -#define LL_AUX_PTR_MAX_USEC 2457600 /*!< Maximum AuxPtr offset value in microseconds. */ +#define LL_AUX_PTR_MAX_USEC 2457300 /*!< Maximum AuxPtr offset value in microseconds. */ #define LL_SYNC_MIN_TIMEOUT 0x000A /*!< Minimum synchronization timeout. */ #define LL_SYNC_MAX_TIMEOUT 0x4000 /*!< Maximum synchronization timeout. */ @@ -176,7 +178,7 @@ enum #define LL_PER_ADV_INT_MIN 0x0006 /*!< Minimum periodic advertising interval. */ -#define LL_SYNC_OFFS_ADJUST_USEC LL_AUX_PTR_MAX_USEC /*!< Sync offset adjust of 2.4576 seconds. */ +#define LL_SYNC_OFFS_ADJUST_USEC 2457600 /*!< Sync offset adjust of 2.4576 seconds. */ #define LL_SYNC_INFO_LEN 18 /*!< Size of SyncInfo field. */ /*! \brief Periodic sync transfer receive mode. */ @@ -185,7 +187,8 @@ enum LL_SYNC_TRSF_MODE_OFF = 0, /*!< Periodic sync transfer receive is disabled. */ LL_SYNC_TRSF_MODE_REP_DISABLED = 1, /*!< Periodic sync transfer receive is enabled, report event is disabled. */ LL_SYNC_TRSF_MODE_REP_ENABLED = 2, /*!< Periodic sync transfer receive is enabled, report event is enabled. */ - LL_SYNC_TRSF_MAX_MODE = LL_SYNC_TRSF_MODE_REP_ENABLED + LL_SYNC_TRSF_MODE_DUP_FILTERED = 3, /*!< Periodic sync transfer receive is enabled, report event is enabled, duplicates will be filtered if ADI field is present. */ + LL_SYNC_TRSF_MAX_MODE = LL_SYNC_TRSF_MODE_DUP_FILTERED }; /*** Data PDU ***/ @@ -234,7 +237,12 @@ enum LL_PDU_CIS_TERM_IND = 0x22, /*!< CIS terminate indication PDU. */ LL_PDU_PWR_CTRL_REQ = 0x23, /*!< Power Control request. */ LL_PDU_PWR_CTRL_RSP = 0x24, /*!< Power Control response. */ - LL_PDU_PWR_CHNG_IND = 0x25, /*!< Transmit power change indication PDU. */ + LL_PDU_PWR_CHANGE_IND = 0x25, /*!< Transmit power change indication PDU. */ + /* --- Core Spec Sydney --- */ + LL_PDU_SUBRATE_REQ = 0x26, /*!< Connection subrate request PDU. */ + LL_PDU_SUBRATE_IND = 0x27, /*!< Connection subrate indication PDU. */ + LL_PDU_CH_REPORTING_IND = 0x28, /*!< Channel class reporting indication PDU. */ + LL_PDU_CH_STATUS_IND = 0x29, /*!< Channel status indication PDU. */ LL_PDU_UNSPECIFIED = 0xFF /*!< Unspecified PDU. */ }; @@ -275,7 +283,7 @@ enum #define LL_CIS_SDU_CONFIG_RSP_LEN 4 /*!< CIS SDU config response PDU length. */ #define LL_PWR_CTRL_REQ_LEN 4 /*!< Power Control request PDU length. */ #define LL_PWR_CTRL_RSP_LEN 5 /*!< Power Control response PDU length. */ -#define LL_PWR_CHNG_IND_LEN 5 /*!< Power Indication PDU length. */ +#define LL_PWR_CHANGE_IND_LEN 5 /*!< Power Indication PDU length. */ #define LL_EMPTY_PDU_LEN 2 /*!< Length of an empty data PDU. */ @@ -288,6 +296,11 @@ enum #define LL_MAX_NUM_CHAN_DATA 37 /*!< Maximum number of used data channels. */ #define LL_MIN_NUM_CHAN_DATA 2 /*!< Minimum number of used data channels. */ +/* --- Core Spec Sydney --- */ +#define LL_SUBRATE_REQ_LEN 11 /*!< LL Connection subrating request PDU length. */ +#define LL_SUBRATE_IND_LEN 11 /*!< LL Connection subrating indication PDU length. */ +#define LL_CH_REPORTING_LEN 4 /*!< Channel class reporting indication PDU length. */ +#define LL_CH_STATUS_LEN 11 /*!< Channel status indication PDU length. */ /*! \brief Data PDU LLID types. */ enum @@ -336,7 +349,7 @@ enum #define LL_MAX_DATA_TIME_MIN 328 /*!< Minimum value for maximum Data PDU time */ #define LL_MAX_DATA_TIME_ABS_MAX 17040 /*!< Absolute maximum limit for maximum Data PDU time */ -#define LL_MAX_DATA_TIME_ABS_MAX_1M 2128 /*!< Absolute maximum limit for maximum Data PDU time (LE 1M PHY) */ +#define LL_MAX_DATA_TIME_ABS_MAX_1M 2120 /*!< Absolute maximum limit for maximum Data PDU time (LE 1M PHY). Core Spec Table 4.5: 2128 if CTE is supported, else 2120. */ #define LL_MAX_DATA_TIME_ABS_MIN_CODED 2704 /*!< Absolute minimum limit for maximum Data PDU time (CODED PHY) */ #define LL_T_PRT_SEC 40 /*!< LLCP procedure response timeout in seconds. */ @@ -490,7 +503,7 @@ enum #define LL_MAX_TIFS_DEVIATION 2 /*!< Maximum TIFS deviation in microseconds. */ -#define LL_WW_RX_DEVIATION_USEC 16 /*!< RX deviation in microseconds for window widening. */ +#define LL_WW_RX_DEVIATION_USEC 16 /*!< Rx deviation in microseconds for window widening. */ #define LL_30_USEC_OFFS_MAX_USEC 245730 /*!< Maximum value for 30 microseconds offset unit in microseconds. */ @@ -528,9 +541,6 @@ enum #define LL_BIG_MIN_INSTANT 6 /*!< Minimum number of BIG Events to apply a BIG Control PDU. */ -#define LL_BIG_CONTROL_ACCESS_ADDR UINT32_C(0x7A412493) - /*!< BIG Control access address. */ - /*** Modify Sleep Clock Accuracy ***/ /*! \brief Action parameter. */ @@ -587,6 +597,31 @@ enum LL_CODEC_TRANS_BIS_BIT = (1 << 3) /*!< Codec supported over LE BIS. */ }; +/*** Channel classification ***/ + +#define LL_CH_RPT_SPACING_MIN 5 /*!< Minimum value for minimum spacing and max delay parameter. */ +#define LL_CH_RPT_SPACING_DEFAULT 10 /*!< Default spacing for channel reporting indication. */ +#define LL_CH_RPT_SPACING_MAX 150 /*!< Maximum value for minimum spacing and max delay parameter. */ + +#define LL_CH_CLASS_BAD 3 /*!< Channel classification is bad. */ +#define LL_CH_CLASS_UNKNOWN 0 /*!< Channel classification is unknown. */ + +/*! \brief Minimum and maximum time between LL_CHANNEL_STATUS_IND reports in 200ms units. */ +enum +{ + LCTR_MIN_CH_STATUS_INTERVAL = 5, /*!< Channel class reporting minimum (1 second). */ + LCTR_MAX_CH_STATUS_INTERVAL = 150, /*!< Channel class reporting maximum (30 seconds). */ +}; + +/*** Enhanced connection update ***/ + +/*! \brief Minimum and maximum subrate. */ +enum +{ + LCTR_MIN_SUBRATE = 1, /*!< Minimum subrate. */ + LCTR_MAX_SUBRATE = 500 /*!< Maximum subrate. */ +}; + #ifdef __cplusplus }; #endif diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/util/bstream.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/util/bstream.h index ee2b12c660..21378057b6 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/util/bstream.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/util/bstream.h @@ -6,7 +6,7 @@ * * Copyright (c) 2009-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -82,6 +82,8 @@ extern "C" { /**@{*/ /*! \brief convert little endian uint16_t to array of bytes. */ #define UINT16_TO_BYTES(n) ((uint8_t) (n)), ((uint8_t)((n) >> 8)) +/*! \brief convert little endian uint24_t to array of bytes. */ +#define UINT24_TO_BYTES(n) ((uint8_t) (n)), ((uint8_t)((n) >> 8)), ((uint8_t)((n) >> 16)) /*! \brief convert little endian uint32_t to array of bytes. */ #define UINT32_TO_BYTES(n) ((uint8_t) (n)), ((uint8_t)((n) >> 8)), ((uint8_t)((n) >> 16)), ((uint8_t)((n) >> 24)) /**@}*/ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_buf.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_buf.h index d8f8138041..fb422b2451 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_buf.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_buf.h @@ -222,6 +222,15 @@ void WsfBufGetPoolStats(WsfBufPoolStat_t *pStat, uint8_t numPool); /*************************************************************************************************/ void WsfBufDiagRegister(WsfBufDiagCback_t callback); +/*************************************************************************************************/ +/*! + * \brief Get the number of outstanding memory pool buffers + * + * \return The number of outstanding buffers + */ +/*************************************************************************************************/ +uint32_t WsfBufNumOutstanding(void); + /*! \} */ /* WSF_BUF_API */ #ifdef __cplusplus diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_cs.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_cs.h index dff5b4ac83..3abbe74617 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_cs.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_cs.h @@ -6,7 +6,7 @@ * * Copyright (c) 2009-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,34 +42,34 @@ extern "C" { /*************************************************************************************************/ /*! - * \def WSF_CS_INIT - * - * \brief Initialize critical section. This macro may define a variable. - * - * \param cs Critical section variable to be defined. - */ + * \def WSF_CS_INIT + * + * \brief Initialize critical section. This macro may define a variable. + * + * \param cs Critical section variable to be defined. + */ /*************************************************************************************************/ #define WSF_CS_INIT(cs) /*************************************************************************************************/ /*! - * \def WSF_CS_ENTER - * - * \brief Enter a critical section. - * - * \param cs Critical section variable. - */ + * \def WSF_CS_ENTER + * + * \brief Enter a critical section. + * + * \param cs Critical section variable. + */ /*************************************************************************************************/ -#define WSF_CS_ENTER(cs) WsfCsEnter() +#define WSF_CS_ENTER(cs) WsfCsEnter() /*************************************************************************************************/ /*! - * \def WSF_CS_EXIT - * - * \brief Exit a critical section. - * - * \param cs Critical section variable. - */ + * \def WSF_CS_EXIT + * + * \brief Exit a critical section. + * + * \param cs Critical section variable. + */ /*************************************************************************************************/ #define WSF_CS_EXIT(cs) WsfCsExit() @@ -95,7 +95,7 @@ void WsfCsEnter(void); /*************************************************************************************************/ /*! - * \brief Enter a critical section. + * \brief Exit a critical section. */ /*************************************************************************************************/ void WsfCsExit(void); diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_efs.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_efs.h index 984405f43f..c5fcaf939f 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_efs.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_efs.h @@ -6,7 +6,7 @@ * * Copyright (c) 2014-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,6 +52,7 @@ extern "C" { /**@{*/ #define WSF_EFS_SUCCESS 0 /*!< \brief Success */ #define WSF_EFS_FAILURE 1 /*!< \brief Failure */ +#define WSF_EFS_CBACK_REQUIRED 2 /*!< \brief File sytem callback required */ #define WSF_EFS_GET_FAILED 0xFFFF /*!< \brief Get operation failure */ #define WSF_EFS_PUT_FAILED 0xFFFF /*!< \brief PUT operation failure */ /**@}*/ @@ -105,6 +106,9 @@ extern "C" { /**@{*/ #define WSF_EFS_WDXS_PUT_COMPLETE_CMD 0x00 /*!< \brief Put Complete */ #define WSF_EFS_VALIDATE_CMD 0x01 /*!< \brief Validate Req for the file */ +#define WSF_EFS_RESTORE_ATTRS_CMD 0x02 /*!< \brief Restore file attributes */ +#define WSF_EFS_GET_FS_CBACK_MODE_CMD 0x03 /*!< \brief Filesystem callback check */ +#define WSF_EFS_CFG_FOTA_CMD 0x04 /*!< \brief Configure FOTA and reboot */ /**@}*/ /*! \brief Media Specific Command Identifiers reserved for applications begin at 0x80 */ @@ -114,6 +118,13 @@ extern "C" { Data Types **************************************************************************************************/ +/* EFS address data type */ +#if (defined CPU_64BIT) && (CPU_64BIT == 1) +typedef uint64_t efsAddr_t; +#else +typedef uint32_t efsAddr_t; +#endif + /*! \brief File handle data type */ typedef uint16_t wsfEfsHandle_t; @@ -130,7 +141,7 @@ typedef struct typedef struct { uint32_t maxSize; /*!< \brief File maximum size. */ - uint32_t address; /*!< \brief File storage address. */ + efsAddr_t address; /*!< \brief File storage address. */ uint8_t media; /*!< \brief File media. */ uint32_t size; /*!< \brief File size. */ wsfEsfAttributes_t attributes; /*!< \brief File attributes. */ @@ -163,7 +174,7 @@ typedef uint8_t wsfMediaInitFunc_t(void); * \return Status of the operation. */ /*************************************************************************************************/ -typedef uint8_t wsfMediaEraseFunc_t(uint8_t *pAddress, uint32_t size); +typedef uint8_t wsfMediaEraseFunc_t(efsAddr_t pAddress, uint32_t size); /*************************************************************************************************/ /*! @@ -176,7 +187,7 @@ typedef uint8_t wsfMediaEraseFunc_t(uint8_t *pAddress, uint32_t size); * \return Status of the operation. */ /*************************************************************************************************/ -typedef uint8_t wsfMediaReadFunc_t(uint8_t *pBuf, uint8_t *pAddress, uint32_t size); +typedef uint8_t wsfMediaReadFunc_t(uint8_t *pBuf, efsAddr_t pAddress, uint32_t size); /*************************************************************************************************/ /*! @@ -189,7 +200,7 @@ typedef uint8_t wsfMediaReadFunc_t(uint8_t *pBuf, uint8_t *pAddress, uint32_t si * \return Status of the operation. */ /*************************************************************************************************/ -typedef uint8_t wsfMediaWriteFunc_t(const uint8_t *pBuf, uint8_t *pAddress, uint32_t size); +typedef uint8_t wsfMediaWriteFunc_t(const uint8_t *pBuf, efsAddr_t pAddress, uint32_t size); /*************************************************************************************************/ /*! @@ -206,9 +217,9 @@ typedef uint8_t wsfMediaHandleCmdFunc_t(uint8_t cmd, uint32_t param); /*! \brief Media Control data type */ typedef struct { - uint32_t startAddress; /*!< \brief Start address. */ - uint32_t endAddress; /*!< \brief End address. */ - uint32_t pageSize; /*!< \brief Page size. */ + efsAddr_t startAddress; /*!< \brief Start address. */ + efsAddr_t endAddress; /*!< \brief End address. */ + efsAddr_t pageSize; /*!< \brief Page size. */ wsfMediaInitFunc_t *init; /*!< \brief Media intialization callback. */ wsfMediaEraseFunc_t *erase; /*!< \brief Media erase callback. */ wsfMediaReadFunc_t *read; /*!< \brief Media read callback. */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_msg.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_msg.h index 9fc66d6572..6e7aabe01f 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_msg.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_msg.h @@ -6,7 +6,7 @@ * * Copyright (c) 2009-2018 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,6 +34,13 @@ extern "C" { /*! \addtogroup WSF_MSG_API * \{ */ + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +extern const uint8_t WSF_MSG_HDR_SIZE; + /************************************************************************************************** Function Declarations **************************************************************************************************/ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_os.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_os.h index 2f526954f7..41fb93870d 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_os.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_os.h @@ -89,7 +89,7 @@ typedef wsfHandlerId_t wsfTaskId_t; typedef uint8_t wsfTaskEvent_t; /*! \brief Idle check function. */ -typedef bool_t (*WsfOsIdleCheckFunc_t)(void); +typedef bool_t (*WsfOsIdleHandler_t)(void); /************************************************************************************************** External Variables @@ -187,7 +187,17 @@ wsfHandlerId_t WsfOsSetNextHandler(wsfEventHandler_t handler); /*************************************************************************************************/ /*! - * \brief Check if WSF is ready to sleep. +* \brief Initialize OS control structure. +* +* \return None. +*/ +/*************************************************************************************************/ +void WsfOsInit(void); + +/*************************************************************************************************/ +/*! + * \brief Check if WSF is ready to sleep. This function should be called when interrupts + * are disabled. * * \return Return TRUE if there are no pending WSF task events set, FALSE otherwise. */ @@ -201,31 +211,6 @@ bool_t wsfOsReadyToSleep(void); /*************************************************************************************************/ void wsfOsDispatcher(void); -/*************************************************************************************************/ -/*! -* \brief Initialize OS control structure. -* -* \return None. -*/ -/*************************************************************************************************/ -void WsfOsInit(void); - -/*************************************************************************************************/ -/*! - * \brief OS starts main loop - */ -/*************************************************************************************************/ -void WsfOsEnterMainLoop(void); - -/*************************************************************************************************/ -/*! - * \brief Register service check functions. - * - * \param func Service function. - */ -/*************************************************************************************************/ -void WsfOsRegisterSleepCheckFunc(WsfOsIdleCheckFunc_t func); - /*! \} */ /* WSF_OS_API */ #ifdef __cplusplus diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_timer.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_timer.h index c07c1ec5d1..58d2ee29b7 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_timer.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_timer.h @@ -115,7 +115,7 @@ void WsfTimerUpdate(wsfTimerTicks_t ticks); /*************************************************************************************************/ /*! * \brief Return the number of ticks until the next timer expiration. Note that this - * function can return zero even if a timer is running, indicating the timer + * function can return zero even if a timer is running, indicating a timer * has expired but has not yet been serviced. * * \param pTimerRunning Returns TRUE if a timer is running, FALSE if no timers running. @@ -137,21 +137,6 @@ wsfTimerTicks_t WsfTimerNextExpiration(bool_t *pTimerRunning); /*************************************************************************************************/ wsfTimer_t *WsfTimerServiceExpired(wsfTaskId_t taskId); -/*************************************************************************************************/ -/*! - * \brief Check if there is an active timer and if there is enough time to - * go to sleep. - */ -/*************************************************************************************************/ -void WsfTimerSleep(void); - -/*************************************************************************************************/ -/*! - * \brief Update WSF timer based on elapsed RTC ticks. - */ -/*************************************************************************************************/ -void WsfTimerSleepUpdate(void); - /*! \} */ /* WSF_TIMER_API */ #ifdef __cplusplus diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_trace.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_trace.h index 106b97b4f4..c066494117 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_trace.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_trace.h @@ -56,11 +56,6 @@ extern "C" { #define LL_TRACE_ENABLED FALSE #endif -#ifndef AUD_TRACE_ENABLED -/*! \brief Trace enabled for audio subsystem */ -#define AUD_TRACE_ENABLED FALSE -#endif - /************************************************************************************************** Data Types **************************************************************************************************/ @@ -143,7 +138,7 @@ bool_t WsfTokenService(void); #ifdef TOKEN_GENERATION #define WSF_TOKEN(subsys, stat, msg) \ - __WSF_TOKEN_DEFINE_( \ + __WSF_TOKEN_DEFINE__( \ /* token: */ MODULE_ID, __LINE__, \ /* origin: */ __FILE__, subsys, \ /* message: */ stat, msg) @@ -293,21 +288,6 @@ bool_t WsfTokenService(void); /*! \brief 3 argument HCI error trace. */ #define HCI_TRACE_ERR3(msg, var1, var2, var3) WSF_TRACE3("HCI", "ERR", msg, var1, var2, var3) -#if !MBED_CONF_CORDIO_TRACE_HCI_PACKETS -/*! \brief HCI PDUMP on command. */ -#define HCI_PDUMP_CMD(len, pBuf) -/*! \brief HCI PDUMP on event. */ -#define HCI_PDUMP_EVT(len, pBuf) -/*! \brief HCI PDUMP on transmitted ACL message. */ -#define HCI_PDUMP_TX_ACL(len, pBuf) -/*! \brief HCI PDUMP on Received ACL message. */ -#define HCI_PDUMP_RX_ACL(len, pBuf) -/*! \brief HCI PDUMP on transmitted ISO message. */ -#define HCI_PDUMP_TX_ISO(len, pBuf) -/*! \brief HCI PDUMP on Received ISO message. */ -#define HCI_PDUMP_RX_ISO(len, pBuf) -#endif // !MBED_CONF_CORDIO_TRACE_HCI_PACKETS - /*! \brief 0 argument DM info trace. */ #define DM_TRACE_INFO0(msg) WSF_TRACE0("DM", "INFO", msg) /*! \brief 1 argument DM info trace. */ @@ -495,8 +475,8 @@ bool_t WsfTokenService(void); /*! \brief 3 argument App error trace. */ #define APP_TRACE_ERR3(msg, var1, var2, var3) WSF_TRACE3("APP", "ERR", msg, var1, var2, var3) -/*! \brief 0 argument LL info trace. */ #if (LL_TRACE_ENABLED == TRUE) +/*! \brief 0 argument LL info trace. */ #define LL_TRACE_INFO0(msg) WSF_TRACE0("LL", "INFO", msg) /*! \brief 1 argument LL info trace. */ #define LL_TRACE_INFO1(msg, var1) WSF_TRACE1("LL", "INFO", msg, var1) @@ -520,31 +500,6 @@ bool_t WsfTokenService(void); #define LL_TRACE_ERR2(msg, var1, var2) WSF_TRACE2("LL", "ERR", msg, var1, var2) /*! \brief 3 argument LL error trace. */ #define LL_TRACE_ERR3(msg, var1, var2, var3) WSF_TRACE3("LL", "ERR", msg, var1, var2, var3) - -/*! \brief 0 argument BBP warning trace. */ -#define BBP_TRACE_INFO0(msg) WSF_TRACE0("BBP", "INFO", msg) -/*! \brief 1 argument BBP warning trace. */ -#define BBP_TRACE_INFO1(msg, var1) WSF_TRACE1("BBP", "INFO", msg, var1) -/*! \brief 2 argument BBP warning trace. */ -#define BBP_TRACE_INFO2(msg, var1, var2) WSF_TRACE2("BBP", "INFO", msg, var1, var2) -/*! \brief 3 argument BBP info trace. */ -#define BBP_TRACE_INFO3(msg, var1, var2, var3) WSF_TRACE3("BBP", "INFO", msg, var1, var2, var3) -/*! \brief 0 argument BBP warning trace. */ -#define BBP_TRACE_WARN0(msg) WSF_TRACE0("BBP", "WARN", msg) -/*! \brief 1 argument BBP warning trace. */ -#define BBP_TRACE_WARN1(msg, var1) WSF_TRACE1("BBP", "WARN", msg, var1) -/*! \brief 2 argument BBP warning trace. */ -#define BBP_TRACE_WARN2(msg, var1, var2) WSF_TRACE2("BBP", "WARN", msg, var1, var2) -/*! \brief 3 argument BBP warning trace. */ -#define BBP_TRACE_WARN3(msg, var1, var2, var3) WSF_TRACE3("BBP", "WARN", msg, var1, var2, var3) -/*! \brief 0 argument BBP error trace. */ -#define BBP_TRACE_ERR0(msg) WSF_TRACE0("BBP", "ERR", msg) -/*! \brief 1 argument BBP error trace. */ -#define BBP_TRACE_ERR1(msg, var1) WSF_TRACE1("BBP", "ERR", msg, var1) -/*! \brief 2 argument BBP error trace. */ -#define BBP_TRACE_ERR2(msg, var1, var2) WSF_TRACE2("BBP", "ERR", msg, var1, var2) -/*! \brief 3 argument BBP error trace. */ -#define BBP_TRACE_ERR3(msg, var1, var2, var3) WSF_TRACE3("BBP", "ERR", msg, var1, var2, var3) #else /* LL_TRACE_ENABLED */ #define LL_TRACE_INFO0(msg) /*! \brief 1 argument LL info trace. */ @@ -569,82 +524,57 @@ bool_t WsfTokenService(void); #define LL_TRACE_ERR2(msg, var1, var2) /*! \brief 3 argument LL error trace. */ #define LL_TRACE_ERR3(msg, var1, var2, var3) - -/*! \brief 0 argument BBP warning trace. */ -#define BBP_TRACE_INFO0(msg) -/*! \brief 1 argument BBP warning trace. */ -#define BBP_TRACE_INFO1(msg, var1) -/*! \brief 2 argument BBP warning trace. */ -#define BBP_TRACE_INFO2(msg, var1, var2) -/*! \brief 3 argument BBP info trace. */ -#define BBP_TRACE_INFO3(msg, var1, var2, var3) -/*! \brief 0 argument BBP warning trace. */ -#define BBP_TRACE_WARN0(msg) -/*! \brief 1 argument BBP warning trace. */ -#define BBP_TRACE_WARN1(msg, var1) -/*! \brief 2 argument BBP warning trace. */ -#define BBP_TRACE_WARN2(msg, var1, var2) -/*! \brief 3 argument BBP warning trace. */ -#define BBP_TRACE_WARN3(msg, var1, var2, var3) -/*! \brief 0 argument BBP error trace. */ -#define BBP_TRACE_ERR0(msg) -/*! \brief 1 argument BBP error trace. */ -#define BBP_TRACE_ERR1(msg, var1) -/*! \brief 2 argument BBP error trace. */ -#define BBP_TRACE_ERR2(msg, var1, var2) -/*! \brief 3 argument BBP error trace. */ -#define BBP_TRACE_ERR3(msg, var1, var2, var3) #endif /* LL_TRACE_ENABLED */ #if (AUD_TRACE_ENABLED == TRUE) -/*! \brief 0 argument AUD info trace. */ +/*! \brief 0 argument audio info trace. */ #define AUD_TRACE_INFO0(msg) WSF_TRACE0("AUD", "INFO", msg) -/*! \brief 1 argument AUD info trace. */ +/*! \brief 1 argument audio info trace. */ #define AUD_TRACE_INFO1(msg, var1) WSF_TRACE1("AUD", "INFO", msg, var1) -/*! \brief 2 argument AUD info trace. */ +/*! \brief 2 argument audio info trace. */ #define AUD_TRACE_INFO2(msg, var1, var2) WSF_TRACE2("AUD", "INFO", msg, var1, var2) -/*! \brief 3 argument AUD info trace. */ +/*! \brief 3 argument audio info trace. */ #define AUD_TRACE_INFO3(msg, var1, var2, var3) WSF_TRACE3("AUD", "INFO", msg, var1, var2, var3) -/*! \brief 0 argument AUD warning trace. */ +/*! \brief 0 argument audio warning trace. */ #define AUD_TRACE_WARN0(msg) WSF_TRACE0("AUD", "WARN", msg) -/*! \brief 1 argument AUD warning trace. */ +/*! \brief 1 argument audio warning trace. */ #define AUD_TRACE_WARN1(msg, var1) WSF_TRACE1("AUD", "WARN", msg, var1) -/*! \brief 2 argument AUD warning trace. */ +/*! \brief 2 argument audio warning trace. */ #define AUD_TRACE_WARN2(msg, var1, var2) WSF_TRACE2("AUD", "WARN", msg, var1, var2) -/*! \brief 3 argument AUD warning trace. */ +/*! \brief 3 argument audio warning trace. */ #define AUD_TRACE_WARN3(msg, var1, var2, var3) WSF_TRACE3("AUD", "WARN", msg, var1, var2, var3) -/*! \brief 0 argument AUD error trace. */ +/*! \brief 0 argument audio error trace. */ #define AUD_TRACE_ERR0(msg) WSF_TRACE0("AUD", "ERR", msg) -/*! \brief 1 argument AUD error trace. */ +/*! \brief 1 argument audio error trace. */ #define AUD_TRACE_ERR1(msg, var1) WSF_TRACE1("AUD", "ERR", msg, var1) -/*! \brief 2 argument AUD error trace. */ +/*! \brief 2 argument audio error trace. */ #define AUD_TRACE_ERR2(msg, var1, var2) WSF_TRACE2("AUD", "ERR", msg, var1, var2) -/*! \brief 3 argument AUD error trace. */ +/*! \brief 3 argument audio error trace. */ #define AUD_TRACE_ERR3(msg, var1, var2, var3) WSF_TRACE3("AUD", "ERR", msg, var1, var2, var3) -#else /* AUD_TRACE_ENABLED */ -/*! \brief 0 argument AUD info trace. */ +#else +/*! \brief 0 argument audio info trace. */ #define AUD_TRACE_INFO0(msg) -/*! \brief 1 argument AUD info trace. */ +/*! \brief 1 argument audio info trace. */ #define AUD_TRACE_INFO1(msg, var1) -/*! \brief 2 argument AUD info trace. */ +/*! \brief 2 argument audio info trace. */ #define AUD_TRACE_INFO2(msg, var1, var2) -/*! \brief 3 argument AUD info trace. */ +/*! \brief 3 argument audio info trace. */ #define AUD_TRACE_INFO3(msg, var1, var2, var3) -/*! \brief 0 argument AUD warning trace. */ +/*! \brief 0 argument audio warning trace. */ #define AUD_TRACE_WARN0(msg) -/*! \brief 1 argument AUD warning trace. */ +/*! \brief 1 argument audio warning trace. */ #define AUD_TRACE_WARN1(msg, var1) -/*! \brief 2 argument AUD warning trace. */ +/*! \brief 2 argument audio warning trace. */ #define AUD_TRACE_WARN2(msg, var1, var2) -/*! \brief 3 argument AUD warning trace. */ +/*! \brief 3 argument audio warning trace. */ #define AUD_TRACE_WARN3(msg, var1, var2, var3) -/*! \brief 0 argument AUD error trace. */ +/*! \brief 0 argument audio error trace. */ #define AUD_TRACE_ERR0(msg) -/*! \brief 1 argument AUD error trace. */ +/*! \brief 1 argument audio error trace. */ #define AUD_TRACE_ERR1(msg, var1) -/*! \brief 2 argument AUD error trace. */ +/*! \brief 2 argument audio error trace. */ #define AUD_TRACE_ERR2(msg, var1, var2) -/*! \brief 3 argument AUD error trace. */ +/*! \brief 3 argument audio error trace. */ #define AUD_TRACE_ERR3(msg, var1, var2, var3) #endif /* AUD_TRACE_ENABLED */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_types.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_types.h index e7815d5b9d..42a6185738 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_types.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/include/wsf_types.h @@ -55,6 +55,18 @@ extern "C" { #define TRUE (!FALSE) #endif +#ifndef UINT64_C +#define UINT64_C(x) x##ULL +#endif + +#ifndef UINT32_C +#define UINT32_C(x) x##UL +#endif + +#ifndef UINT8_C +#define UINT8_C(x) (x) +#endif + /*! \} */ /* Integer Data Types */ #ifdef __cplusplus diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_assert.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_assert.c index d19b942f81..f643547957 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_assert.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_assert.c @@ -1,11 +1,9 @@ /*************************************************************************************************/ /*! - * \file wsf_assert.c + * \file * * \brief Assert implementation. * - * Copyright (c) 2009-2018 Arm Ltd. All Rights Reserved. - * * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -47,16 +45,12 @@ void WsfAssert(const char *pFile, uint16_t line) #endif { /* Possibly unused parameters */ + (void)line; #if WSF_TOKEN_ENABLED == TRUE (void)modId; -#else - (void)pFile; -#endif - (void)line; - -#if WSF_TOKEN_ENABLED == TRUE WSF_TRACE_ERR2("Assertion detected on %s:%u", modId, line); #else + (void)pFile; WSF_TRACE_ERR2("Assertion detected on %s:%u", pFile, line); #endif diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_buf.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_buf.c index be2ab9cfc0..6a5e85c5dc 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_buf.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_buf.c @@ -91,6 +91,9 @@ uint8_t wsfPoolOverFlowCount[WSF_BUF_STATS_MAX_POOL]; static WsfBufDiagCback_t wsfBufDiagCback = NULL; #endif +/* The number of outstanding memory pool buffers */ +static uint32_t wsfOutstandingBufCount = 0; + /*************************************************************************************************/ /*! * \brief Calculate size required by the buffer pool. @@ -293,6 +296,9 @@ void *WsfBufAlloc(uint16_t len) /* Next free buffer is stored inside current free buffer. */ pPool->pFree = pBuf->pNext; + /* Increment the number of allocated buffers */ + wsfOutstandingBufCount++; + #if WSF_BUF_FREE_CHECK_ASSERT == TRUE pBuf->free = 0; #endif @@ -406,6 +412,9 @@ void WsfBufFree(void *pBuf) p->pNext = pPool->pFree; pPool->pFree = p; + /* Decrement the number of allocated buffers */ + wsfOutstandingBufCount--; + /* Exit critical section. */ WSF_CS_EXIT(cs); @@ -523,3 +532,15 @@ void WsfBufDiagRegister(WsfBufDiagCback_t callback) (void)callback; #endif } + +/*************************************************************************************************/ +/*! + * \brief Get the number of outstanding memory pool buffers + * + * \return The number of outstanding buffers + */ +/*************************************************************************************************/ +uint32_t WsfBufNumOutstanding(void) +{ + return wsfOutstandingBufCount; +} diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_bufio.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_bufio.c index 3ed4341722..db8677f5d3 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_bufio.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_bufio.c @@ -88,13 +88,13 @@ static void wsfBufIoUartTxStart(uint16_t len) /* Check if TX length exceeds 1 octet size from UART driver. */ if (len <= 0xFF) { - PalUartWriteData(PAL_UART_ID_TERMINAL, WsfBufIoCb.tx.pBuf + WsfBufIoCb.tx.out, (uint16_t)len); WsfBufIoCb.tx.crt = len; + PalUartWriteData(PAL_UART_ID_TERMINAL, WsfBufIoCb.tx.pBuf + WsfBufIoCb.tx.out, (uint16_t)len); } else { + WsfBufIoCb.tx.crt = 0xFF; PalUartWriteData(PAL_UART_ID_TERMINAL, WsfBufIoCb.tx.pBuf + WsfBufIoCb.tx.out, 0xFF); - WsfBufIoCb.tx.crt = 0xFF; } } diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_detoken.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_detoken.c index f29d5cbe07..870a9fb3cf 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_detoken.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_detoken.c @@ -4,8 +4,6 @@ * * \brief Token trace decode. * - * Copyright (c) 2018 Arm Ltd. All Rights Reserved. - * * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -54,7 +52,7 @@ * \brief Initialize detoken trace. */ /*************************************************************************************************/ -void WsfDetokenInit() +void WsfDetokenInit(void) { /* Take no action - place holder should future platform require initialization */ } @@ -83,6 +81,8 @@ void WsfDetokenEnable(bool_t enable) * \brief Find token by id via binary search * * \param token Token identifier. + * + * \return Returns a pointer to token. */ /*************************************************************************************************/ static const tokenElem_t *wsfDetokenFindToken(uint32_t token) @@ -123,6 +123,8 @@ static const tokenElem_t *wsfDetokenFindToken(uint32_t token) * \brief Find token string by id via binary search * * \param token Token identifier. + * + * \return Returns a token string. */ /*************************************************************************************************/ static const char *wsfDetokenFindTokenString(uint32_t token) diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_efs.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_efs.c index 94f64ac6aa..792fe0c8d8 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_efs.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_efs.c @@ -1,12 +1,10 @@ /*************************************************************************************************/ /*! - * \file wsf_efs.c + * \file * * \brief Embedded File System service. * - * Copyright (c) 2014-2018 Arm Ltd. All Rights Reserved. - * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -88,7 +86,7 @@ wsfEfsControl_t *WsfEfsGetFileByHandle(wsfEfsHandle_t handle) * \return TRUE if overlap, else FALSE. */ /*************************************************************************************************/ -static bool_t wsfEfsFileOverlap(wsfEfsHandle_t handle, uint8_t media, uint32_t address, uint32_t size) +static bool_t wsfEfsFileOverlap(wsfEfsHandle_t handle, uint8_t media, efsAddr_t address, uint32_t size) { if (wsfEfsMediaValid(media)) { @@ -98,17 +96,21 @@ static bool_t wsfEfsFileOverlap(wsfEfsHandle_t handle, uint8_t media, uint32_t a (wsfEfsFileTbl[handle].media == media)) { /* Calculate the top and bottom addresses of the files */ - uint32_t top1 = wsfEfsFileTbl[handle].address; - uint32_t bottom1 = wsfEfsFileTbl[handle].address + wsfEfsFileTbl[handle].maxSize - 1; - uint32_t top2 = address; - uint32_t bottom2 = address + size - 1; + efsAddr_t top1 = wsfEfsFileTbl[handle].address; + efsAddr_t bottom1 = wsfEfsFileTbl[handle].address + wsfEfsFileTbl[handle].maxSize - 1; + efsAddr_t top2 = address; + efsAddr_t bottom2 = address + size - 1; /* Check for overlap */ if ((top2 >= top1) && (top2 <= bottom1)) + { return TRUE; + } if ((bottom2 >= top1) && (bottom2 <= bottom1)) + { return TRUE; + } } } @@ -126,12 +128,12 @@ static bool_t wsfEfsFileOverlap(wsfEfsHandle_t handle, uint8_t media, uint32_t a * \return The next available offset. */ /*************************************************************************************************/ -static uint32_t wsfEfsFindAvailableOffset(uint8_t media, uint32_t size) +static efsAddr_t wsfEfsFindAvailableOffset(uint8_t media, uint32_t size) { if (wsfEfsMediaValid(media)) { int8_t i; - uint32_t address = wsfEfsMediaTbl[media]->startAddress; + efsAddr_t address = wsfEfsMediaTbl[media]->startAddress; for (i=0; i wsfEfsMediaTbl[media]->endAddress) + { return WSF_EFS_INVALID_OFFSET; + } } } @@ -157,8 +161,6 @@ static uint32_t wsfEfsFindAvailableOffset(uint8_t media, uint32_t size) /*************************************************************************************************/ /*! * \brief Initialize the embedded file system. - * - * \return none. */ /*************************************************************************************************/ void WsfEfsInit(void) @@ -190,7 +192,7 @@ void WsfEfsInit(void) wsfEfsHandle_t WsfEfsAddFile(uint32_t maxSize, uint8_t media, wsfEsfAttributes_t *pAttr, uint32_t offset) { wsfEfsHandle_t handle; - uint32_t address = offset; + efsAddr_t address = offset; wsfEfsControl_t *pFile = NULL; if (wsfEfsMediaValid(media)) @@ -212,7 +214,9 @@ wsfEfsHandle_t WsfEfsAddFile(uint32_t maxSize, uint8_t media, wsfEsfAttributes_t address = wsfEfsFindAvailableOffset(media, maxSize); if (address == WSF_EFS_INVALID_OFFSET) + { return WSF_EFS_INVALID_HANDLE; + } } else { @@ -233,7 +237,9 @@ wsfEfsHandle_t WsfEfsAddFile(uint32_t maxSize, uint8_t media, wsfEsfAttributes_t for (i=0; ierase) { - uint32_t address = pFile->address; + efsAddr_t address = pFile->address; uint32_t size = pFile->maxSize; - status = wsfEfsMediaTbl[media]->erase((uint8_t *) address, size); + status = wsfEfsMediaTbl[media]->erase(address, size); pFile->size = 0; } } @@ -389,14 +395,14 @@ uint16_t WsfEfsGet(wsfEfsHandle_t handle, uint32_t offset, uint8_t *pBuffer, uin } else if (offset < pFile->size) { - uint32_t address = pFile->address + offset; + efsAddr_t address = pFile->address + offset; if (offset + len > pFile->size) { len = (uint16_t) (pFile->size - offset); } - wsfEfsMediaTbl[media]->read(pBuffer, (uint8_t *) address, len); + wsfEfsMediaTbl[media]->read(pBuffer, address, len); return len; } @@ -438,14 +444,14 @@ uint16_t WsfEfsPut(wsfEfsHandle_t handle, uint32_t offset, const uint8_t *pBuffe } else if (offset < pFile->maxSize) { - uint32_t address = pFile->address + offset; + efsAddr_t address = pFile->address + offset; if (offset + len > pFile->maxSize) { len = (uint16_t) (pFile->maxSize - offset); } - wsfEfsMediaTbl[media]->write(pBuffer, (uint8_t *) address, len); + wsfEfsMediaTbl[media]->write(pBuffer, address, len); /* If writing to the end of the file, update the file size */ if (offset + len > pFile->size) diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_heap.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_heap.c index a16fe67f28..e78d280a7f 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_heap.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_heap.c @@ -1,11 +1,9 @@ /*************************************************************************************************/ /*! - * \file wsf_heap.c + * \file * * \brief Heap service. * - * Copyright (c) 2009-2018 Arm Ltd. All Rights Reserved. - * * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -87,5 +85,5 @@ uint32_t WsfHeapCountAvailable(void) /*************************************************************************************************/ uint32_t WsfHeapCountUsed(void) { - return 0; + return 0; } diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_msg.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_msg.c index 4f5f4144fa..d6d02a9d4d 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_msg.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_msg.c @@ -1,12 +1,10 @@ /*************************************************************************************************/ /*! - * \file wsf_msg.c + * \file * * \brief Message passing service. * - * Copyright (c) 2009-2018 Arm Ltd. All Rights Reserved. - * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,13 +32,16 @@ Data Types **************************************************************************************************/ -/* Internal message buf structure */ +/*! \brief Internal message buf structure */ typedef struct wsfMsg_tag { struct wsfMsg_tag *pNext; wsfHandlerId_t handlerId; } wsfMsg_t; +/*! \brief Size of wsfMsg header. */ +const uint8_t WSF_MSG_HDR_SIZE = sizeof(wsfMsg_t); + /*************************************************************************************************/ /*! * \brief Allocate a data message buffer to be sent with WsfMsgSend(). diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_queue.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_queue.c index bf8ecebc4c..cbc5499450 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_queue.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_queue.c @@ -1,11 +1,9 @@ /*************************************************************************************************/ /*! - * \file wsf_queue.c + * \file * * \brief General purpose queue service. * - * Copyright (c) 2009-2018 Arm Ltd. All Rights Reserved. - * * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -167,7 +165,6 @@ void WsfQueuePush(wsfQueue_t *pQueue, void *pElem) * \param pElem Pointer to element to be inserted. * \param pPrev Pointer to previous element in the queue before element to be inserted. * Note: set pPrev to NULL if pElem is first element in queue. - * \return None. */ /*************************************************************************************************/ void WsfQueueInsert(wsfQueue_t *pQueue, void *pElem, void *pPrev) @@ -212,7 +209,6 @@ void WsfQueueInsert(wsfQueue_t *pQueue, void *pElem, void *pPrev) * \param pElem Pointer to element to be removed. * \param pPrev Pointer to previous element in the queue before element to be removed. * Note: set pPrev to NULL if pElem is first element in queue. - * \return None. */ /*************************************************************************************************/ void WsfQueueRemove(wsfQueue_t *pQueue, void *pElem, void *pPrev) diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_timer.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_timer.c index 956ee07d36..b7b78d2036 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_timer.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_timer.c @@ -1,11 +1,9 @@ /*************************************************************************************************/ /*! - * \file wsf_timer.c + * \file * * \brief Timer service. * - * Copyright (c) 2009-2019 Arm Ltd. All Rights Reserved. - * * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,69 +23,18 @@ #include "wsf_types.h" #include "wsf_queue.h" #include "wsf_timer.h" - #include "wsf_assert.h" -#include "wsf_cs.h" #include "wsf_trace.h" -#include "pal_rtc.h" -#include "pal_led.h" -#include "pal_sys.h" /************************************************************************************************** Macros **************************************************************************************************/ -#if (WSF_MS_PER_TICK == 10) -/* convert seconds to timer ticks */ -#define WSF_TIMER_SEC_TO_TICKS(sec) (100 * (sec) + 1) +/*! \brief Convert seconds to timer ticks, round up to ensure sufficient time expires. */ +#define WSF_TIMER_SEC_TO_TICKS(sec) ((sec * 1000 + (WSF_MS_PER_TICK - 1)) / WSF_MS_PER_TICK) -/* convert milliseconds to timer ticks */ -/* Extra tick should be added to guarantee waiting time is longer than the specified ms. */ -#define WSF_TIMER_MS_TO_TICKS(ms) (((uint32_t)(((uint64_t)(ms) * (uint64_t)(419431)) >> 22)) + 1) - -/*! \brief WSF timer ticks per second. */ -#define WSF_TIMER_TICKS_PER_SEC (1000 / WSF_MS_PER_TICK) - -#elif (WSF_MS_PER_TICK == 1) -/* convert seconds to timer ticks */ -#define WSF_TIMER_SEC_TO_TICKS(sec) (1000 * (sec) + 1) - -/*! \brief Convert milliseconds to timer ticks. */ -/*! \brief Extra tick should be added to guarantee waiting time is longer than the specified ms. */ -#define WSF_TIMER_MS_TO_TICKS(ms) ((uint64_t)(ms) + 1) - -#define WSF_TIMER_TICKS_PER_SEC (1000) - -#else -#error "WSF_TIMER_MS_TO_TICKS() and WSF_TIMER_SEC_TO_TICKS not defined for WSF_MS_PER_TICK" -#endif - -/*! \brief Number of RTC ticks per WSF timer tick. */ -#define WSF_TIMER_RTC_TICKS_PER_WSF_TICK ((PAL_RTC_TICKS_PER_SEC + WSF_TIMER_TICKS_PER_SEC - 1) / (WSF_TIMER_TICKS_PER_SEC)) - -/*! \brief Calculate number of elapsed WSF timer ticks. */ -#define WSF_RTC_TICKS_TO_WSF(x) ((x) / WSF_TIMER_RTC_TICKS_PER_WSF_TICK) - -/*! \brief Mask of seconds part in RTC ticks. */ -#define WSF_TIMER_RTC_TICKS_SEC_MASK (0x00FF8000) - -/*! \brief Addition of RTC ticks. */ -#define WSF_TIMER_RTC_ADD_TICKS(x, y) (((x) + (y)) & PAL_MAX_RTC_COUNTER_VAL) - -/*! \brief Subtraction of RTC ticks. */ -#define WSF_TIMER_RTC_SUB_TICKS(x, y) ((PAL_MAX_RTC_COUNTER_VAL + 1 + (x) - (y)) & PAL_MAX_RTC_COUNTER_VAL) - -/*! \brief Minimum RTC ticks required to go into sleep. */ -#define WSF_TIMER_MIN_RTC_TICKS_FOR_SLEEP (2) - -/*! - * \brief Computing the difference between two RTC counter values. - * - * Calculate elapsed ticks since last WSF timer update, with remainder; - * since the RTC timer is 24 bit set the 24th bit to handle any underflow. - */ -#define WSF_TIMER_RTC_ELAPSED_TICKS(x) ((PAL_MAX_RTC_COUNTER_VAL + 1 + (x) - wsfTimerRtcLastTicks \ - + wsfTimerRtcRemainder) & PAL_MAX_RTC_COUNTER_VAL) +/*! \brief Convert milliseconds to timer ticks, round up to ensure sufficient time expires. */ +#define WSF_TIMER_MS_TO_TICKS(ms) ((ms + (WSF_MS_PER_TICK - 1)) / WSF_MS_PER_TICK) /************************************************************************************************** Global Variables @@ -95,12 +42,6 @@ wsfQueue_t wsfTimerTimerQueue; /*!< Timer queue */ -/*! \brief Last RTC value read. */ -static uint32_t wsfTimerRtcLastTicks = 0; - -/*! \brief Remainder value. */ -static uint32_t wsfTimerRtcRemainder = 0; - /*************************************************************************************************/ /*! * \brief Remove a timer from queue. Note this function does not lock task scheduling. @@ -180,56 +121,6 @@ static void wsfTimerInsert(wsfTimer_t *pTimer, wsfTimerTicks_t ticks) WsfTaskUnlock(); } -/*************************************************************************************************/ -/*! - * \brief Convert WSF ticks into RTC ticks. - * - * \return Number of RTC ticks - */ -/*************************************************************************************************/ -static uint32_t wsfTimerTicksToRtc(wsfTimerTicks_t wsfTicks) -{ - uint32_t numSec = wsfTicks / WSF_TIMER_TICKS_PER_SEC; - uint32_t remainder = wsfTicks - numSec * WSF_TIMER_TICKS_PER_SEC; - - return ((numSec * PAL_RTC_TICKS_PER_SEC) + (remainder * WSF_TIMER_RTC_TICKS_PER_WSF_TICK)); -} - -/*************************************************************************************************/ -/*! - * \brief Return the number of ticks until the next timer expiration. Note that this - * function can return zero even if a timer is running, indicating a timer - * has expired but has not yet been serviced. - * - * \param pTimerRunning Returns TRUE if a timer is running, FALSE if no timers running. - * - * \return The number of ticks until the next timer expiration. - */ -/*************************************************************************************************/ -wsfTimerTicks_t WsfTimerNextExpiration(bool_t *pTimerRunning) -{ - wsfTimerTicks_t ticks; - - /* task schedule lock */ - WsfTaskLock(); - - if (wsfTimerTimerQueue.pHead == NULL) - { - *pTimerRunning = FALSE; - ticks = 0; - } - else - { - *pTimerRunning = TRUE; - ticks = ((wsfTimer_t *) wsfTimerTimerQueue.pHead)->ticks; - } - - /* task schedule unlock */ - WsfTaskUnlock(); - - return ticks; -} - /*************************************************************************************************/ /*! * \brief Initialize the timer service. This function should only be called once @@ -239,9 +130,6 @@ wsfTimerTicks_t WsfTimerNextExpiration(bool_t *pTimerRunning) void WsfTimerInit(void) { WSF_QUEUE_INIT(&wsfTimerTimerQueue); - - wsfTimerRtcLastTicks = 0; - wsfTimerRtcRemainder = 0; } /*************************************************************************************************/ @@ -254,10 +142,12 @@ void WsfTimerInit(void) /*************************************************************************************************/ void WsfTimerStartSec(wsfTimer_t *pTimer, wsfTimerTicks_t sec) { - WSF_TRACE_INFO2("WsfTimerStartSec pTimer:0x%x ticks:%u", (uint32_t)pTimer, WSF_TIMER_SEC_TO_TICKS(sec)); + uint32_t time = WSF_TIMER_SEC_TO_TICKS(sec); + + WSF_TRACE_INFO2("WsfTimerStartSec pTimer:0x%x ticks:%u", (uint32_t)pTimer, time); /* insert timer into queue */ - wsfTimerInsert(pTimer, WSF_TIMER_SEC_TO_TICKS(sec)); + wsfTimerInsert(pTimer, time); } /*************************************************************************************************/ @@ -270,10 +160,12 @@ void WsfTimerStartSec(wsfTimer_t *pTimer, wsfTimerTicks_t sec) /*************************************************************************************************/ void WsfTimerStartMs(wsfTimer_t *pTimer, wsfTimerTicks_t ms) { - WSF_TRACE_INFO2("WsfTimerStartMs pTimer:0x%x ticks:%u", (uint32_t)pTimer, WSF_TIMER_MS_TO_TICKS(ms)); + uint32_t ticks = WSF_TIMER_MS_TO_TICKS(ms); + + WSF_TRACE_INFO2("WsfTimerStartMs pTimer:0x%x ticks:%u", (uint32_t)pTimer, ticks); /* insert timer into queue */ - wsfTimerInsert(pTimer, WSF_TIMER_MS_TO_TICKS(ms)); + wsfTimerInsert(pTimer, ticks); } /*************************************************************************************************/ @@ -335,6 +227,35 @@ void WsfTimerUpdate(wsfTimerTicks_t ticks) WsfTaskUnlock(); } +/*************************************************************************************************/ +/*! + * \brief Return the number of ticks until the next timer expiration. Note that this + * function can return zero even if a timer is running, indicating a timer + * has expired but has not yet been serviced. + * + * \param pTimerRunning Returns TRUE if a timer is running, FALSE if no timers running. + * + * \return The number of ticks until the next timer expiration. + */ +/*************************************************************************************************/ +wsfTimerTicks_t WsfTimerNextExpiration(bool_t *pTimerRunning) +{ + wsfTimerTicks_t ticks; + + if (wsfTimerTimerQueue.pHead == NULL) + { + *pTimerRunning = FALSE; + ticks = 0; + } + else + { + *pTimerRunning = TRUE; + ticks = ((wsfTimer_t *) wsfTimerTimerQueue.pHead)->ticks; + } + + return ticks; +} + /*************************************************************************************************/ /*! * \brief Service expired timers for the given task. @@ -378,127 +299,3 @@ wsfTimer_t *WsfTimerServiceExpired(wsfTaskId_t taskId) return NULL; } - -/*************************************************************************************************/ -/*! - * \brief Function for checking if there is an active timer and if there is enough time to - * go to sleep and going to sleep. - */ -/*************************************************************************************************/ -void WsfTimerSleep(void) -{ - wsfTimerTicks_t nextExpiration; - - /* If PAL system is busy, no need to sleep. */ - if (PalSysIsBusy()) - { - return; - } - - bool_t running; - nextExpiration = WsfTimerNextExpiration(&running); - - if (running) - { - uint32_t awake = wsfTimerTicksToRtc(nextExpiration); - uint32_t rtcCurrentTicks = PalRtcCounterGet(); - uint32_t elapsed = WSF_TIMER_RTC_ELAPSED_TICKS(rtcCurrentTicks); - - /* if we have time to sleep before timer expiration */ - if ((awake - elapsed) > WSF_TIMER_MIN_RTC_TICKS_FOR_SLEEP) - { - uint32_t compareVal = (rtcCurrentTicks + awake - elapsed) & PAL_MAX_RTC_COUNTER_VAL; - - /* set RTC timer compare */ - PalRtcCompareSet(0, compareVal); - - /* enable RTC interrupt */ - PalRtcEnableCompareIrq(0); - - /* one final check for OS activity then enter sleep */ - PalEnterCs(); - if (wsfOsReadyToSleep()) - { - PalLedOff(PAL_LED_ID_CPU_ACTIVE); - PalSysSleep(); - PalLedOn(PAL_LED_ID_CPU_ACTIVE); - } - PalExitCs(); - } - else - { - /* Not enough time to go to sleep. Let the system run till the pending timer expires. */ - LL_TRACE_WARN0("WsfTimerSleep, not enough time to sleep"); - } - } - else - { - /* disable RTC interrupt */ - PalRtcDisableCompareIrq(0); - - /* one final check for OS activity then enter sleep */ - PalEnterCs(); - if (wsfOsReadyToSleep()) - { - PalLedOff(PAL_LED_ID_CPU_ACTIVE); - PalSysSleep(); - PalLedOn(PAL_LED_ID_CPU_ACTIVE); - } - PalExitCs(); - } -} - -/*************************************************************************************************/ -/*! - * \brief Function for updating WSF timer based on elapsed RTC ticks. - */ -/*************************************************************************************************/ -void WsfTimerSleepUpdate(void) -{ - uint32_t elapsed; - wsfTimerTicks_t wsfElapsed = 0; - uint32_t secBoundary, prevBoundary; - - /* Get current RTC tick count. */ - uint32_t rtcCurrentTicks = PalRtcCounterGet(); - - if (rtcCurrentTicks != wsfTimerRtcLastTicks) - { - /* Check if RTC ticks go beyond seconds boundary. */ - if ((rtcCurrentTicks & WSF_TIMER_RTC_TICKS_SEC_MASK) != (wsfTimerRtcLastTicks & WSF_TIMER_RTC_TICKS_SEC_MASK)) - { - /* Calculate current and previous second boundary */ - secBoundary = WSF_TIMER_RTC_ADD_TICKS((wsfTimerRtcLastTicks & WSF_TIMER_RTC_TICKS_SEC_MASK), PAL_RTC_TICKS_PER_SEC); - prevBoundary = WSF_TIMER_RTC_SUB_TICKS(secBoundary, PAL_RTC_TICKS_PER_SEC); - - /* Check how many wsf ticks were already counted in this second. */ - /* Claim all uncounted wsf ticks within the second. */ - wsfElapsed += (WSF_TIMER_TICKS_PER_SEC - WSF_RTC_TICKS_TO_WSF(WSF_TIMER_RTC_SUB_TICKS(wsfTimerRtcLastTicks, prevBoundary))); - - while (WSF_TIMER_RTC_SUB_TICKS(rtcCurrentTicks, secBoundary) >= PAL_RTC_TICKS_PER_SEC) - { - wsfElapsed += WSF_TIMER_TICKS_PER_SEC; - secBoundary = WSF_TIMER_RTC_ADD_TICKS(secBoundary, PAL_RTC_TICKS_PER_SEC); - } - - wsfTimerRtcRemainder = 0; - wsfTimerRtcLastTicks = secBoundary; - } - - /* Elapsed must be less than PAL_RTC_TICKS_PER_SEC at this point. */ - elapsed = WSF_TIMER_RTC_ELAPSED_TICKS(rtcCurrentTicks); - - /* Rough conversion from RTC ticks to WFS ticks. It will be synchronized at the end of each second boundary. */ - wsfElapsed += (wsfTimerTicks_t) WSF_RTC_TICKS_TO_WSF(elapsed); - - if (wsfElapsed) - { - /* update last ticks and remainder */ - wsfTimerRtcLastTicks = rtcCurrentTicks; - wsfTimerRtcRemainder = elapsed - (WSF_RTC_TICKS_TO_WSF(elapsed) * WSF_TIMER_RTC_TICKS_PER_WSF_TICK); - - /* update wsf timers */ - WsfTimerUpdate(wsfElapsed); - } - } -} diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_trace.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_trace.c index 41c8ba0714..c59c7ef739 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_trace.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/wsf/sources/port/baremetal/wsf_trace.c @@ -221,7 +221,9 @@ void WsfTrace(const char *pStr, ...) /* Format message. */ len = PrintVsn(buf, WSF_PRINTF_MAX_LEN - WSF_TRACE_SUFFIX_LEN, pStr, args); +#if !defined(WSF_TRACE_LF_DISABLE) || (WSF_TRACE_LF_DISABLE == FALSE) buf[len++] = '\r'; +#endif buf[len++] = '\n'; /* Deliver message. */ diff --git a/connectivity/FEATURE_BLE/libraries/cordio_updates/.gitignore b/connectivity/FEATURE_BLE/libraries/cordio_updates/.gitignore new file mode 100644 index 0000000000..8d98f9debd --- /dev/null +++ b/connectivity/FEATURE_BLE/libraries/cordio_updates/.gitignore @@ -0,0 +1 @@ +.* diff --git a/connectivity/FEATURE_BLE/libraries/cordio_updates/ReadMe.md b/connectivity/FEATURE_BLE/libraries/cordio_updates/ReadMe.md new file mode 100644 index 0000000000..3d5e7d8fde --- /dev/null +++ b/connectivity/FEATURE_BLE/libraries/cordio_updates/ReadMe.md @@ -0,0 +1,49 @@ +# Cordio Updates + +## How to Update Cordio + +Run the `update-cordio` script. It will clone the current and + +A suite of scripts to assist updating Cordio. The suite can be run from within the source tree or moved to another location if MBED_PATH is set as an environment file or in a file called `.cordio-update` colocated with the script. + +### Invocation + +``` +Usage: update-cordio [options] [functions] + +Options: + -h,--help Show this help and quit + +Functions: + --ghclone Clone the GitHub repo (old Cordio) + --bbclone Clone to BitBucket repos (new Cordio) + --clean Clean up cloned repos + --restructure Restructure the new Cordio to match how the old Cordio was brought into mbed OS + --make-diffs Create diffs between the old Cordio and mbed OS + --summary Create a summary of the cloned repos + --replace Replace the Cordio in MBED_ROOT with the new Cordio + +NB: By default, all of the above functions are implicitly enabled and will run in order. Explicitly enabling a function +implicitly disables the others unless they are explicitly enabled as well. The order of execution can not be affected by +command-line arguments. + +Configuration file: +If present, configuration will be read from a file called $CONFIG_FILE in the same location as the script. The following +variables can be set there: + + MBED_ROOT Path to a local copy of the mbed OS Git repo, main branch. The default is to look for a .git + directory that is higher than the current directory. + WORKDIR Directory to store work in. Defaults to a random temporary directory which is deleted if the + script exits for any reason (user-supplied directories are not deleted). + GITHUB_USERNAME Username to use when pulling Git repo. Defaults to current user's name. + GITHUB_PASSWORD Password to use when pulling Git repo. Required if --ghclone is enabled. + BITBUCKET_USERNAME Username to use when pulling BitBucket repos. Defaults to current user's name. + BITBUCKET_PASSWORD Password to use when pulling BitBucket repos. Required if --bbclone is enabled. + +Environment: +If no configuration file is present the above variables will be read from the environment. Additionally, the following +can be set: + + EDITOR Set to an executable program. Defaults to $DEFAULT_EDITOR. + dos2unix Should be executable via PATH. +``` \ No newline at end of file diff --git a/connectivity/FEATURE_BLE/libraries/cordio_updates/restructure.py b/connectivity/FEATURE_BLE/libraries/cordio_updates/restructure.py new file mode 100755 index 0000000000..2d2ae889dd --- /dev/null +++ b/connectivity/FEATURE_BLE/libraries/cordio_updates/restructure.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2021 Arm Limited +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from pathlib import Path +import os +import sys + +def best_match(p, paths): + idx = 0 + while True: + idx += 1 + if idx >= len(p.parts): + return None + try: + paths = list(filter( + lambda q: q.parts[-idx] == p.parts[-idx] if idx < len(q.parts) else False, + paths + )) + except IndexError: + return None + if len(paths) == 1: + return paths[0] + +def restructure(mbed, old_cordio, new_cordio): + mbed_files = list(Path(mbed).glob('**/*.c')) + list(Path(mbed).glob('**/*.h')) + old_files = list(Path(old_cordio).glob('**/*.c')) + list(Path(old_cordio).glob('**/*.h')) + new_files = list(Path(new_cordio).glob('**/*.c')) + list(Path(new_cordio).glob('**/*.h')) + + dir_move = dict() + unmoved = [] + + # Pass 1: In NEW CORDIO, move files that were moved between OLD CORDIO and MBED, and delete files that were in OLD + # CORDIO but weren't included in MBED. + total = len(new_files) + count = 0 + for newf in new_files: + oldf = best_match(newf, old_files) + mbedf = best_match(newf, mbed_files) + if not oldf: + # File was added to Cordio + unmoved.append(newf) + elif not mbedf: + # File was removed by ARM + print('rm -f \"{}\"'.format(newf.relative_to(new_cordio))) + else: + # File was moved by ARM + newf_rel = newf.relative_to(new_cordio) + mbedf_rel = mbedf.relative_to(mbed) + target = '/'.join(mbedf_rel.parts[:-1]) + dir_move[newf_rel.parts[:-1]] = target + print(f'mkdir -p \"{target}\"') + print(f'mv -f \"{newf_rel}\" \"{mbedf_rel}\"') + count += 1 + print('\rPass 1: {}/{} files ({}%)'.format(count, total, 100*count//total), file=sys.stderr, end='') + print('', file=sys.stderr) + + # Pass 2: In NEW CORDIO, move files that were added to NEW CORDIO to where their siblings were moved where possible. + total = len(unmoved) + count = 0 + unmovable = 0 + for newf in unmoved: + newf_rel = newf.relative_to(new_cordio) + target_dir = dir_move.get(newf_rel.parts[:-1]) + if target_dir: + print(f'mv -f \"{newf_rel}\" \"{target_dir}\"') + else: + unmovable += 1 + count += 1 + print('\rPass 2: {}/{} files ({}%)'.format(count, total, 100*count//total), file=sys.stderr, end='') + print(f'\nDone', file=sys.stderr) + +if __name__ == '__main__': + if len(sys.argv) != 4 or not all([os.path.isdir(p) for p in sys.argv[1:]]): + print(f'Usage: {sys.argv[0]} ') + restructure( + os.path.realpath(sys.argv[1]), + os.path.realpath(sys.argv[2]), + os.path.realpath(sys.argv[3]) + ) diff --git a/connectivity/FEATURE_BLE/libraries/cordio_updates/summary.py b/connectivity/FEATURE_BLE/libraries/cordio_updates/summary.py new file mode 100755 index 0000000000..1797a3f087 --- /dev/null +++ b/connectivity/FEATURE_BLE/libraries/cordio_updates/summary.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2021 Arm Limited +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import math +import sys + +if __name__ == '__main__': + if len(sys.argv) < 2: + print(f'Usage: {sys.argv[0]} separator $*" >&2 +} + +function die { + redify "> $*" + exit 1 +} + +function die_if_unset { + [[ -z ${!1} ]] && die "$1 is not set" +} + +function cleanup { + [[ "$WORKDIR" =~ \/tmp\/.+ ]] && [[ -d "$WORKDIR" ]] && rm -rf "$WORKDIR" +} +trap cleanup EXIT + +function prompt { + say $* + blueify -n "Type \"yes\" when you are ready to continue: " >&2 + local answer + while true; do + read answer + if [[ "$answer" = "yes" ]]; then + break + else + redify -n "Please type \"yes\": " >&2 + fi + done +} + +function show_usage { + cat <&2 ; exit 1 ;; + esac + + shift + done + + if [[ $[CLONE_OLD + $CLONE_NEW + $CLEAN + $RESTRUCTURE + $DIFFS + $SUMMARY + $REPLACE] -eq 0 ]]; then + CLONE_OLD=1 + CLONE_NEW=1 + CLEAN=1 + RESTRUCTURE=1 + DIFFS=1 + SUMMARY=1 + REPLACE=1 + fi + + if [[ $CLONE_OLD -ne 0 ]]; then + die_if_unset GITHUB_PASSWORD + if [[ -z "$GITHUB_USERNAME" ]]; then + say "Warning: GITHUB_USERNAME is not set, $USER will be used" + GITHUB_USERNAME=$USER + fi + fi + + if [[ $CLONE_NEW -ne 0 ]]; then + die_if_unset BITBUCKET_PASSWORD + if [[ -z "$BITBUCKET_USERNAME" ]]; then + say "Warning: BITBUCKET_USERNAME is not set, $USER will be used" + BITBUCKET_USERNAME=$USER + fi + fi +} + +function mbedcp { + cp -arf "$MBED_ROOT/$1" "$1" +} + +function dir_setup { + say "Ensuring directory structure..." + mkdir -p "$MBED_ROOT" + mkdir -p "$WORKDIR/$OLD_DIR" + mkdir -p "$WORKDIR/$NEW_DIR" + cd "$WORKDIR" + + MBED_ROOT=$(realpath "$MBED_ROOT") + WORKDIR=$(realpath "$WORKDIR") + OLD_DIR=$(realpath "$WORKDIR/$OLD_DIR") + NEW_DIR=$(realpath "$WORKDIR/$NEW_DIR") +} + +# Clone a GH or BB repo with credentials +# $@ = args for git clone +function clone_with_creds { + if [[ ! -z $(echo "$1" | grep github) ]]; then + git clone "$1" "$2" </dev/null | wc -l) -ne 0 ]]; then + say "$3 contains files, so repo won't be cloned" + return + fi + + clone_checkout_mv "$1" "$3" "$4" + [[ "$1" != "$2" ]] && clone_checkout_mv "$2" "$3" "$5" + + # Delete unneeded dirs + rm -rf $3/{ble-apps,ble-mesh-apps,ble-mesh-model,ble-mesh-profile,ble-profiles} +} + +function clone_old { + clone_repo_pair "$OLD_CONTROLLER_REPO" "$OLD_HOST_REPO" "$OLD_DIR" "$OLD_CONTROLLER_SHA" "$OLD_HOST_SHA" +} + +function clone_new { + clone_repo_pair "$NEW_CONTROLLER_REPO" "$NEW_HOST_REPO" "$NEW_DIR" "$NEW_CONTROLLER_SHA" "$NEW_HOST_SHA" +} + +function initial_cleanup { + find -type f \( ! -iname '.*' -a ! -iname '*.c' -a ! -iname '*.h' \) -exec rm -rf {} \; 2>/dev/null + find -type d \( -iname 'build' -o -iname 'doc' -o -iname 'documentation' \) -exec rm -rf {} \; 2>/dev/null + find -type d -empty -delete 2>/dev/null + [[ -x $(which dos2unix) ]] && find -type f \( -iname '*.c' -o -iname '*.h' \) -exec dos2unix {} \; 2>/dev/null >&2 +} + +function findrel { + find $* -exec realpath --relative-to="$1" {} \; +} + +function restructure { + prompt "I am going to look at where files from the OLD CORDIO ended up when it was last integrated into MBED OS. \ +I will then generate a script to apply those changes to the NEW CORDIO (you will be asked to check and edit the script \ +before it runs). >1000 files will be moved or deleted, but files in the NEW CORDIO that didn't exist in the OLD CORDIO \ +or were moved by PC will stay where they are, so you may need to move them manually." + tmpfile=$(mktemp) + echo "#!/bin/bash" >"$tmpfile" + echo "# $tmpfile - Double check the changes. If happy with them, remove the 'exit 0' line below." >>"$tmpfile" + echo "exit 0" >>"$tmpfile" + "$HERE/restructure.py" "$MBED_ROOT" "$OLD_DIR" "$NEW_DIR" | sort -u >>"$tmpfile" + "$EDITOR" "$tmpfile" + chmod +x "$tmpfile" + cd "$NEW_DIR" + "$tmpfile" + rm "$tmpfile" + find -type d -empty -delete + count=$(find \( -iname '*.c' -o -iname '*.h' \) | grep -vE 'connectivity' | wc -l) + if [[ $count -gt 0 ]]; then + prompt "There are $count files that couldn't be moved - they were probably added or moved by PacketCraft. \ +You should now manually rearrange them." + fi + cd .. +} + +function make_diffs { + local old2mbed="$DIFF_DIR/old2mbed" + local old2new="$DIFF_DIR/old2new" + mkdir -p "$old2mbed" "$old2new" + + local old + find "$OLD_DIR" \( -iname '*.c' -o -iname '*.h' \) | while read old; do + local mbed=$(find "$MBED_ROOT" -name "$(basename "$old")" | head -n 1) + local new=$(find "$NEW_DIR" -name "$(basename "$old")" | head -n 1) + + [[ "$mbed" = "" ]] && continue # File not included in mbed + [[ "$new" = "" ]] && continue # File deleted from Cordio + + local out="$old2mbed/$(realpath --relative-to="$MBED_ROOT" "$mbed").diff" + mkdir -p "$(dirname "$out")" + + if git diff "$old" "$mbed" >"$out" || git diff "$new" "$mbed" >/dev/null; then + rm -f "$out" + else + echo "diff \"old/$old\" \"mbed/$mbed\"" >&2 + fi + + out="$old2new/$(realpath --relative-to="$MBED_ROOT" "$mbed").diff" + mkdir -p "$(dirname "$out")" + + if git diff "$old" "$new" >"$out" || git diff "$new" "$mbed" >/dev/null; then + rm -f "$out" + else + echo "diff \"old$old\" \"new$new\"" >&2 + fi + done + + # Delete empty files & dirs + find "$DIFF_DIR" -empty -delete + count=$(find "$DIFF_DIR" -iname '*.diff' | wc -l) + prompt "I have created $(find "$DIFF_DIR" -name '*.diff' | wc -l) diffs between files in OLD CORDIO and MBED OS. \ +You now need to apply the diffs manually to the NEW CORDIO to reapply fixes." +} + +export TAG_SEPARATOR="==========" +function findtags { + find "$1" \( -iname '*.c' -o -iname '*.h' \) | ctags --filter=yes | awk '{print $1,$2}' + echo "$TAG_SEPARATOR" +} + +function summary { + tags=$(mktemp) + + findtags "$OLD_DIR" >>"$tags" + findtags "$NEW_DIR" >>"$tags" + "$HERE/summary.py" "$TAG_SEPARATOR" <"$tags" + + rm -f "$tags" +} + +function replace { + prompt "I am now going to copy the new Cordio files over the old ones (use ^C if you don't want this). \ +I will then ask you to create a Git commit (if you abort the commit the changes will remain unstaged)." + + # Delete existing source files + find "$MBED_ROOT/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources" \( -iname '*.c' -o -iname '*.h' \) -delete + find "$MBED_ROOT/connectivity/FEATURE_BLE/libraries/cordio_stack" \( -iname '*.c' -o -iname '*.h' \) -delete + find "$MBED_ROOT/connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack" \( -iname '*.c' -o -iname '*.h' \) -delete + find "$MBED_ROOT/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/" \( -iname 'hci_*.c' -o -iname 'wsf_*.c' \) -delete + + # Delete any dirs that became empty. + find "$MBED_ROOT/connectivity" -type d -empty -delete + + # Copy the new files over. + cp -arf "$NEW_DIR/connectivity/*" "$MBED_ROOT/connectivity/" + git add . + git commit + git reset +} + +################################################################################ +# Script +################################################################################ +check_env $* +dir_setup +[[ $CLONE_OLD -ne 0 ]] && clone_old +[[ $CLONE_NEW -ne 0 ]] && clone_new +[[ $CLEAN -ne 0 ]] && initial_cleanup +[[ $RESTRUCTURE -ne 0 ]] && restructure +[[ $DIFFS -ne 0 ]] && make_diffs +[[ $SUMMARY -ne 0 ]] && summary +[[ $REPLACE -ne 0 ]] && replace diff --git a/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp index 4a93bc41ee..30a85d902c 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp @@ -754,6 +754,9 @@ void BLEInstanceBase::callDispatcher() timestamp_t nextTimestamp = (timestamp_t) (WsfTimerNextExpiration(&pTimerRunning) * WSF_MS_PER_TICK); if (pTimerRunning) { nextTimeout.attach(timeoutCallback, milliseconds(nextTimestamp)); + #if PAL_ALLOW_DEEP_SLEEP + _hci_driver->on_deep_sleep(nextTimestamp); + #endif } else { critical_section.disable(); _hci_driver->on_host_stack_inactivity(); diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp index 0ecee16e93..a7f292643b 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp @@ -1673,7 +1673,8 @@ ble_error_t PalGap::periodic_advertising_create_sync( peer_address_type.value(), peer_address.data(), allowed_skip, - sync_timeout + sync_timeout, + 0 ); if (sync_id == DM_SYNC_ID_NONE) { diff --git a/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/hci_tr.c b/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/hci_tr.c index 9245499fa1..a3c871d4ad 100644 --- a/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/hci_tr.c +++ b/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/hci_tr.c @@ -2,11 +2,9 @@ /*! * \file hci_tr.c * - * \brief HCI transport module. + * \brief HCI transport implementation for Nordic. * - * Copyright (c) 2011-2018 Arm Ltd. All Rights Reserved. - * - * Copyright (c) 2019 Packetcraft, Inc. + * Copyright (c) 2019-2020 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,18 +20,23 @@ */ /*************************************************************************************************/ -#include #include "wsf_types.h" #include "wsf_msg.h" +#include "wsf_trace.h" #include "wsf_assert.h" #include "util/bstream.h" #include "hci_api.h" #include "hci_core.h" -#include "hci_tr.h" +#include "hci_defs.h" #include "hci_drv.h" +#include +#include + +/************************************************************************************************** + Macros +**************************************************************************************************/ /* PORTING: EXACTLE removed as replaced by zero copy hci driver in mbedos */ - uint16_t hci_mbed_os_drv_write(uint8_t type, uint16_t len, uint8_t *pData); /************************************************************************************************** @@ -48,6 +51,10 @@ typedef enum HCI_RX_STATE_COMPLETE } hciRxState_t; +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + /*************************************************************************************************/ /*! * \fn hciTrSendAclData @@ -65,47 +72,48 @@ void hciTrSendAclData(void *pContext, uint8_t *pData) /* PORTING: sending and fragmenting done by mbed-os */ uint16_t len; - /* get 16-bit length */ + /* transmit ACL header and data */ BYTES_TO_UINT16(len, (pData + 2)) len += HCI_ACL_HDR_LEN; - /* transmit ACL header and data */ if (hci_mbed_os_drv_write(HCI_ACL_TYPE, len, pData) == len) { #if CORDIO_ZERO_COPY_HCI /* pData is not freed as the hci_mbed_os_drv_write took ownership of the WSF buffer */ #else /* free buffer */ - hciCoreTxAclComplete((hciCoreConn_t *)pContext, pData); + hciCoreTxAclComplete(pContext, pData); #endif // CORDIO_ZERO_COPY_HCI } } /*************************************************************************************************/ /*! + * \fn hciTrSendCmd + * * \brief Send a complete HCI command to the transport. * - * \param pCmdData WSF msg buffer containing an HCI command. + * \param pData WSF msg buffer containing an HCI command. * * \return None. */ /*************************************************************************************************/ -void hciTrSendCmd(uint8_t *pCmdData) +void hciTrSendCmd(uint8_t *pData) { /* PORTING: sending done by mbed-os */ uint16_t len; /* get length */ - len = pCmdData[2] + HCI_CMD_HDR_LEN; + len = pData[2] + HCI_CMD_HDR_LEN; /* transmit ACL header and data */ - if (hci_mbed_os_drv_write(HCI_CMD_TYPE, len, pCmdData) == len) + if (hci_mbed_os_drv_write(HCI_CMD_TYPE, len, pData) == len) { #if CORDIO_ZERO_COPY_HCI /* pData is not freed as the hci_mbed_os_drv_write took ownership of the WSF buffer */ #else - /* free buffer */ - WsfMsgFree(pCmdData); + /* free command buffer */ + WsfMsgFree(pData); #endif // CORDIO_ZERO_COPY_HCI } } @@ -265,3 +273,40 @@ void hciTrSerialRxIncoming(uint8_t *pBuf, uint8_t len) } } } + +/*************************************************************************************************/ +/*! + * \fn hciTrInit + * + * \brief Initialize HCI transport resources. + * + * \param port COM port. + * \param baudRate Baud rate. + * \param flowControl TRUE if flow control is enabled + * + * \return TRUE if initialization succeeds, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t hciTrInit( uint8_t port, uint32_t baudRate, bool_t flowControl ) +{ + /* Parameters are not used */ + (void) port; + (void) baudRate; + (void) flowControl; + + return (FALSE); +} + +/*************************************************************************************************/ +/*! + * \fn hcrTrShutdown + * + * \brief Close HCI transport resources. + * + * \return None. + */ +/*************************************************************************************************/ +void hciTrShutdown(void) +{ + +} diff --git a/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/hci_vs.c b/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/hci_vs.c index 42b3961798..e5ff01ce3d 100644 --- a/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/hci_vs.c +++ b/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/hci_vs.c @@ -2,7 +2,7 @@ /*! * \file hci_vs.c * - * \brief HCI vendor specific functions for generic controllers. + * \brief HCI vendor specific functions for single-chip. * * Copyright (c) 2011-2018 Arm Ltd. All Rights Reserved. * @@ -32,8 +32,6 @@ #include "hci_mbed_os_adaptation.h" -/* PORTING: reset handling code has been removed since it's handled by the mbed-os driver */ - /*************************************************************************************************/ /*! * \fn hciCoreResetStart @@ -49,17 +47,6 @@ void hciCoreResetStart(void) hci_mbed_os_start_reset_sequence(); } -/*************************************************************************************************/ -/*! - * \fn hciCoreResetSequence - * - * \brief Implement the HCI reset sequence. - * - * \param pMsg HCI event message from previous command in the sequence. - * - * \return None. - */ -/*************************************************************************************************/ void hciCoreResetSequence(uint8_t *pMsg) { /* PORTING: reset sequence handled by mbed-os */ @@ -69,7 +56,7 @@ void hciCoreResetSequence(uint8_t *pMsg) void hci_mbed_os_signal_reset_sequence_done(void) { /* last command in sequence; set resetting state and call callback */ - wsfMsgHdr_t hdr; + wsfMsgHdr_t hdr; hciCb.resetting = FALSE; hdr.param = 0; hdr.event = HCI_RESET_SEQ_CMPL_CBACK_EVT; @@ -140,5 +127,6 @@ uint8_t hciCoreHwErrorRcvd(uint8_t *p) /*************************************************************************************************/ void HciVsInit(uint8_t param) { + /* XXX */ hciCoreCb.extResetSeq = NULL; } diff --git a/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/mbed_wsf_trace.h b/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/mbed_wsf_trace.h index bbfda75c7a..77458ee60c 100644 --- a/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/mbed_wsf_trace.h +++ b/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/mbed_wsf_trace.h @@ -21,17 +21,31 @@ #if MBED_CONF_MBED_TRACE_ENABLE void wsf_mbed_trace_init(); -#if MBED_CONF_CORDIO_TRACE_HCI_PACKETS +# if MBED_CONF_CORDIO_TRACE_HCI_PACKETS void wsf_mbed_trace_hci(const uint8_t *pBuf, uint32_t len, const uint8_t *prefix); -#define HCI_PDUMP_CMD(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "CMD") -#define HCI_PDUMP_EVT(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "EVT") -#define HCI_PDUMP_TX_ACL(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "ACL_TX") -#define HCI_PDUMP_RX_ACL(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "ACL_RX") -#define HCI_PDUMP_TX_ISO(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "ISO_TX") -#define HCI_PDUMP_RX_ISO(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "ISO_RX") -#endif // MBED_CONF_CORDIO_TRACE_HCI_PACKETS +# define HCI_PDUMP_CMD(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "CMD") +# define HCI_PDUMP_EVT(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "EVT") +# define HCI_PDUMP_TX_ACL(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "ACL_TX") +# define HCI_PDUMP_RX_ACL(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "ACL_RX") +# define HCI_PDUMP_TX_ISO(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "ISO_TX") +# define HCI_PDUMP_RX_ISO(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "ISO_RX") +# else +# define HCI_PDUMP_CMD(len, pBuf) +# define HCI_PDUMP_EVT(len, pBuf) +# define HCI_PDUMP_TX_ACL(len, pBuf) +# define HCI_PDUMP_RX_ACL(len, pBuf) +# define HCI_PDUMP_TX_ISO(len, pBuf) +# define HCI_PDUMP_RX_ISO(len, pBuf) +# endif // MBED_CONF_CORDIO_TRACE_HCI_PACKETS +#else +# define HCI_PDUMP_CMD(len, pBuf) +# define HCI_PDUMP_EVT(len, pBuf) +# define HCI_PDUMP_TX_ACL(len, pBuf) +# define HCI_PDUMP_RX_ACL(len, pBuf) +# define HCI_PDUMP_TX_ISO(len, pBuf) +# define HCI_PDUMP_RX_ISO(len, pBuf) #endif // MBED_CONF_MBED_TRACE_ENABLE #endif // MBED_WSF_TRACE_H_ diff --git a/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/pal_mbed_os_adaptation.cpp b/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/pal_mbed_os_adaptation.cpp index 3cc95861ab..7365113c4c 100644 --- a/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/pal_mbed_os_adaptation.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/pal_mbed_os_adaptation.cpp @@ -141,27 +141,28 @@ MBED_WEAK void PalExitCs(void) } /* ISO channels */ - -MBED_WEAK void PalCodecReadLocalSupportedCodecs(uint8_t *pNumStd, AudioStdCodecInfo_t stdCodecs[], - uint8_t *pNumVs, AudioVsCodecInfo_t vsCodecs[]) +MBED_WEAK void PalCodecReadLocalSupportedCodecs(uint8_t *pNumStd, PalCodecStdInfo_t stdCodecs[], + uint8_t *pNumVs, PalCodecVsInfo_t vsCodecs[]) { MBED_ERROR(function_not_implemented, "Provide implementation of PalCodecReadLocalSupportedCodecs"); } MBED_WEAK bool_t PalCodecReadLocalSupportedCodecCapabilities( - uint8_t codingFmt, uint16_t compId, uint16_t vsCodecId, PalAudioDir_t dir) + uint8_t codingFmt, uint16_t compId, uint16_t vsCodecId, PalCodecDir_t dir, uint8_t transType, + uint8_t *pCapLen, uint8_t *pCap) { MBED_ERROR(function_not_implemented, "Provide implementation of PalCodecReadLocalSupportedCodecCapabilities"); return 0; } MBED_WEAK bool_t PalCodecReadLocalSupportedControllerDelay( - uint8_t codingFmt, uint16_t compId, uint16_t vsCodecId, PalAudioDir_t dir, uint32_t *pMinDly, uint32_t *pMaxDly) + uint8_t codingFmt, uint16_t compId, uint16_t vsCodecId, PalCodecDir_t dir, uint8_t transType, + uint32_t *pMinDly, uint32_t *pMaxDly) { MBED_ERROR(function_not_implemented, "Provide implementation of PalCodecReadLocalSupportedControllerDelay"); return 0; } -MBED_WEAK bool_t PalCodecConfigureDataPath(PalAudioDir_t dir, uint8_t dataPathId) +MBED_WEAK bool_t PalCodecConfigureDataPath(PalCodecDir_t dir, uint8_t vsCfgLen, const uint8_t *pVsCfg) { MBED_ERROR(function_not_implemented, "Provide implementation of PalCodecConfigureDataPath"); return 0; @@ -172,24 +173,23 @@ MBED_WEAK void PalCodecDataInit(void) MBED_ERROR(function_not_implemented, "Provide implementation of PalCodecDataInit"); } -MBED_WEAK bool_t PalCodecDataStartStream(uint16_t id, PalCodecSreamParam_t *pParam) +MBED_WEAK bool_t PalCodecDataStartStream(uint16_t id, PalCodecStreamParam_t *pParam) { MBED_ERROR(function_not_implemented, "Provide implementation of PalCodecDataStartStream"); return 0; } -MBED_WEAK void PalCodecDataStopStream(uint16_t id) +MBED_WEAK void PalCodecDataStopStream(uint16_t id, PalCodecDir_t dir) { MBED_ERROR(function_not_implemented, "Provide implementation of PalCodecDataStopStream"); } -MBED_WEAK uint16_t PalCodecDataStreamIn(uint16_t id, uint8_t *pBuf, uint16_t len, uint32_t *pPktCtr) +MBED_WEAK void PalCodecDataStreamIn(uint16_t id, uint8_t *pBuf, uint16_t len) { MBED_ERROR(function_not_implemented, "Provide implementation of PalCodecDataStreamIn"); - return 0; } -MBED_WEAK void PalCodecDataStreamOut(uint16_t id, const uint8_t *pBuf, uint16_t len, uint32_t pktCtr) +MBED_WEAK void PalCodecDataStreamOut(uint16_t id, const uint8_t *pBuf, uint16_t len, uint32_t sduRef) { MBED_ERROR(function_not_implemented, "Provide implementation of PalCodecDataStreamOut"); } diff --git a/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/wsf_os.c b/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/wsf_os.c index cfbe758f7f..57f10f0275 100644 --- a/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/wsf_os.c +++ b/connectivity/FEATURE_BLE/source/cordio/stack_adaptation/wsf_os.c @@ -87,7 +87,7 @@ typedef struct /*! \brief OS structure */ typedef struct { - wsfOsTask_t task; + wsfOsTask_t task; /* PORTING: sleep checking funcs removed as not needed as handled by mbedos */ } wsfOs_t; @@ -148,7 +148,6 @@ void WsfSetEvent(wsfHandlerId_t handlerId, wsfEventMask_t event) wsfOs.task.taskEventMask |= WSF_HANDLER_EVENT; WSF_CS_EXIT(cs); - /* set event in OS */ wsf_mbed_ble_signal_event(); } @@ -170,8 +169,7 @@ void WsfTaskSetReady(wsfHandlerId_t handlerId, wsfTaskEvent_t event) WSF_CS_ENTER(cs); wsfOs.task.taskEventMask |= event; WSF_CS_EXIT(cs); - - /* set event in OS */ + wsf_mbed_ble_signal_event(); } @@ -225,7 +223,6 @@ bool_t wsfOsReadyToSleep(void) { return (wsfOs.task.taskEventMask == 0); } - /*************************************************************************************************/ /*! * \brief Initialize OS control structure. diff --git a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/CMakeLists.txt b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/CMakeLists.txt index ea255676a1..e94fd377e6 100644 --- a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/CMakeLists.txt +++ b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/CMakeLists.txt @@ -17,6 +17,7 @@ target_sources(mbed-ble-cordio stack/sources/pal_bb_ble_rf.c stack/sources/pal_cfg.c stack/sources/pal_crypto.c + stack/sources/pal_frc.c stack/sources/pal_timer.c ) diff --git a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/NRFCordioHCIDriver.cpp b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/NRFCordioHCIDriver.cpp index 7e7a0a0bb9..a42f43bc68 100644 --- a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/NRFCordioHCIDriver.cpp +++ b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/NRFCordioHCIDriver.cpp @@ -31,6 +31,7 @@ #include "custom_chci_tr.h" #include "pal_bb.h" #include "pal_cfg.h" +#include "pal_frc.h" #include "lhci_api.h" #include "wsf_assert.h" #include "wsf_buf.h" @@ -53,6 +54,8 @@ #define DBG_WARN(...) #endif +#include "mbed_nrf5x_adaptation.h" + using namespace ble; /*! \brief Typical implementation revision number (LlRtCfg_t::implRev). */ @@ -117,7 +120,6 @@ const LlRtCfg_t NRFCordioHCIDriver::_ll_cfg = { /*uint16_t*/ .auxDelayUsec = 0, /** Delay of auxiliary packet in microseconds from the time specified by auxPtr. */ /*uint16_t*/ .auxPtrOffsetUsec = 0, - /* Scanner */ /** Maximum scan request received events. */ /*uint8_t*/ .maxScanReqRcvdEvt = MBED_CONF_CORDIO_LL_MAX_SCAN_REQUEST_EVENTS, @@ -137,7 +139,6 @@ const LlRtCfg_t NRFCordioHCIDriver::_ll_cfg = { /*int8_t*/ .defTxPwrLvl = 0, /** Allowable CE jitter on a slave (account for master's sleep clock resolution). */ /*uint8_t*/ .ceJitterUsec = 0, - /* ISO */ /** Default number of ISO transmit buffers. */ /*uint8_t*/ .numIsoTxBuf = 0, @@ -147,7 +148,6 @@ const LlRtCfg_t NRFCordioHCIDriver::_ll_cfg = { /*uint16_t*/ .maxIsoSduLen = 0, /** Maximum ISO PDU buffer size. */ /*uint16_t*/ .maxIsoPduLen = 0, - /* CIS */ /** Maximum number of CIG. */ /*uint8_t*/ .maxCig = 0, @@ -155,17 +155,14 @@ const LlRtCfg_t NRFCordioHCIDriver::_ll_cfg = { /*uint8_t*/ .maxCis = 0, /** Subevent spacing above T_MSS. */ /*uint16_t*/ .cisSubEvtSpaceDelay = 0, - /* BIS */ /** Maximum number of BIG. */ /* uint8_t */ .maxBig = 0, /** Maximum number of BIS. */ /* uint8_t */ .maxBis = 0, - /* DTM */ /** DTM Rx synchronization window in milliseconds. */ /*uint16_t*/ .dtmRxSyncMs = 10000, - /* PHY */ /** 2M PHY supported. */ /*bool_t*/ .phy2mSup = MBED_CONF_CORDIO_LL_PHY_2M_SUPPORT, @@ -175,10 +172,15 @@ const LlRtCfg_t NRFCordioHCIDriver::_ll_cfg = { /*bool_t*/ .stableModIdxTxSup = TRUE, /** Rx stable modulation index supported. */ /*bool_t*/ .stableModIdxRxSup = TRUE, +/** High RSSI threshold for power monitoring. */ +/*int8_t*/ .pcHighThreshold = -50, +/** Low RSSI threshold for power monitoring. */ +/*int8_t*/ .pcLowThreshold = -70, +/** Interval spacing of channel classification reporting. */ +/*uint8_t*/ .chClassIntSpacing = 50 }; -extern "C" void TIMER0_IRQHandler(void); -extern "C" void TIMER2_IRQHandler(void); +extern "C" void PAL_BB_IRQ_HANDLER(void); NRFCordioHCIDriver::NRFCordioHCIDriver(CordioHCITransportDriver& transport_driver) : CordioHCIDriver(transport_driver), _is_init(false), _stack_buffer(NULL) { @@ -188,20 +190,20 @@ NRFCordioHCIDriver::NRFCordioHCIDriver(CordioHCITransportDriver& transport_drive NRFCordioHCIDriver::~NRFCordioHCIDriver() { - // Deativate all interrupts + // Deactivate all interrupts NVIC_DisableIRQ(RADIO_IRQn); - NVIC_DisableIRQ(TIMER0_IRQn); + NVIC_DisableIRQ(PAL_BB_IRQn); // Switch off Radio peripheral // TODO interop with 802.15.4 NRF_RADIO->POWER = 0; // Stop timer - NRF_TIMER0->TASKS_STOP = 1; - NRF_TIMER0->TASKS_CLEAR = 1; + PAL_BB_TIMER->TASKS_STOP = 1; + PAL_BB_TIMER->TASKS_CLEAR = 1; NVIC_ClearPendingIRQ(RADIO_IRQn); - NVIC_ClearPendingIRQ(TIMER0_IRQn); + NVIC_ClearPendingIRQ(PAL_BB_IRQn); MBED_ASSERT(_stack_buffer != NULL); free(_stack_buffer); @@ -262,21 +264,24 @@ void NRFCordioHCIDriver::do_initialize() { } NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; + // Start RTC. + PAL_BB_RTC->TASKS_STOP = 1; + PAL_BB_RTC->TASKS_CLEAR = 1; + PAL_BB_RTC->PRESCALER = 0; /* clear prescaler */ + PAL_BB_RTC->TASKS_START = 1; - // Start RTC0 - NRF_RTC0->TASKS_STOP = 1; - NRF_RTC0->TASKS_CLEAR = 1; - NRF_RTC0->PRESCALER = 0; /* clear prescaler */ - NRF_RTC0->TASKS_START = 1; +#if PAL_ALLOW_DEEP_SLEEP + // Start FRC. + PalFrcInit(); +#endif // Cycle radio peripheral power to guarantee known radio state NRF_RADIO->POWER = 0; NRF_RADIO->POWER = 1; // mbed-os target uses IRQ Handler names with _v added at the end - // (TIMER0_IRQHandler_v and TIMER2_IRQHandler_v) so we need to register these manually - NVIC_SetVector(TIMER0_IRQn, (uint32_t)TIMER0_IRQHandler); - NVIC_SetVector(TIMER2_IRQn, (uint32_t)TIMER2_IRQHandler); + // (PAL_BB_IRQ_HANDLER_v) so we need to register this manually + NVIC_SetVector(PAL_BB_IRQn, (uint32_t)PAL_BB_IRQ_HANDLER); // Extremely ugly for(uint32_t irqn = 0; irqn < 32; irqn++) @@ -343,6 +348,15 @@ bool NRFCordioHCIDriver::get_random_static_address(ble::address_t& address) return true; } +void NRFCordioHCIDriver::on_deep_sleep(timestamp_t wakeTimeMs) +{ +#if PAL_ALLOW_DEEP_SLEEP + if (wakeTimeMs > PAL_WAKE_LATENCY_MS) { + palFrcSetWakeup(wakeTimeMs - PAL_WAKE_LATENCY_MS); + } +#endif +} + ble::CordioHCIDriver& ble_cordio_get_hci_driver() { static NRFCordioHCITransportDriver transport_driver; diff --git a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/NRFCordioHCIDriver.h b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/NRFCordioHCIDriver.h index a9d97efdf2..1305106e3a 100644 --- a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/NRFCordioHCIDriver.h +++ b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/NRFCordioHCIDriver.h @@ -19,7 +19,7 @@ #define NRF_CORDIO_HCI_DRIVER_H_ #include "ble/driver/CordioHCIDriver.h" - +#include "hal/ticker_api.h" namespace ble { /** @@ -62,6 +62,10 @@ public: */ virtual bool get_random_static_address(ble::address_t& address); + /** + * @copydoc copydoc CordioHciDriver::on_deep_sleep + */ + virtual void on_deep_sleep(timestamp_t wakeTimeMs); private: /** * Initialize the chip. diff --git a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/mbed_lib.json b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/mbed_lib.json index 05e5a45eee..64b982031c 100644 --- a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/mbed_lib.json +++ b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/mbed_lib.json @@ -8,7 +8,7 @@ }, "hci-driver-buffer-size": { "help": "Defines the memory to be allocated by the NRFCordiHciDriver.", - "value": 12500 + "value": 16368 }, "wsf-pool-buffer-size": { "help": "Defines the memory allocated for the wsf memory pool.", @@ -17,7 +17,7 @@ }, "target_overrides": { "MCU_NRF52840": { - "hci-driver-buffer-size": 16056 + "hci-driver-buffer-size": 16368 } }, "macros": [ @@ -28,6 +28,9 @@ "INIT_ENCRYPTED", "LHCI_ENABLE_VS=0", "BB_CLK_RATE_HZ=1000000", - "LL_MAX_PER_SCAN=3" + "LL_MAX_PER_SCAN=3", + "NRFX_RTC_ENABLED=1", + "NRFX_RTC2_ENABLED=1", + "NRFX_CLOCK_ENABLED=1" ] } diff --git a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/include/mbed_nrf5x_adaptation.h b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/include/mbed_nrf5x_adaptation.h new file mode 100644 index 0000000000..6f6105419d --- /dev/null +++ b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/include/mbed_nrf5x_adaptation.h @@ -0,0 +1,34 @@ +/* mbed Microcontroller Library + * Copyright (c) 2021 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_NRF5X_ADAPTATION_H +#define MBED_NRF5X_ADAPTATION_H + +#include "nrf.h" + +/* RTC1 and TIMER3 used by Cordio baseband scheduler. */ +#define PAL_BB_RTC NRF_RTC1 +#define PAL_BB_TIMER NRF_TIMER3 +#define PAL_BB_IRQn TIMER3_IRQn +#define PAL_BB_IRQ_HANDLER TIMER3_IRQHandler +#define PAL_BB_IRQ_EXPIRY_CHANNEL 5 +#define PAL_BB_TIMER_EXPIRY_INTENSET_MASK TIMER_INTENSET_COMPARE5_Msk +#define PAL_BB_TIMER_EXPIRY_INTENCLR_MASK TIMER_INTENCLR_COMPARE5_Msk + +#define PAL_ALLOW_DEEP_SLEEP 1 +#define PAL_WAKE_LATENCY_MS 5 + +#endif // ! MBED_NRF5X_ADAPTATION_H diff --git a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb.c b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb.c index 18286bb065..96c50ff4f4 100644 --- a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb.c +++ b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb.c @@ -26,10 +26,15 @@ #include "pal_types.h" #include "pal_bb.h" #include "pal_bb.h" +#include "pal_led.h" + #include "nrf.h" #include "nrf_timer.h" + #include +#include "mbed_nrf5x_adaptation.h" + /************************************************************************************************** Local Variables **************************************************************************************************/ @@ -111,7 +116,7 @@ void PalBbDisable(void) void PalBbLoadCfg(PalBbCfg_t *pCfg) { pCfg->clkPpm = 20; - pCfg->rfSetupDelayUsec = BB_RF_SETUP_DELAY_US; + pCfg->rfSetupDelayUsec = BB_RF_SETUP_DELAY_US; pCfg->maxScanPeriodMsec = BB_MAX_SCAN_PERIOD_MS; pCfg->schSetupDelayUsec = BB_SCH_SETUP_DELAY_US; #if (BB_CLK_RATE_HZ == 32768) @@ -141,58 +146,20 @@ uint32_t PalBbGetCurrentTime(void) if (USE_RTC_BB_CLK) { /* return the RTC counter value */ - return BB_TICKS_TO_US(NRF_RTC1->COUNTER); + return BB_TICKS_TO_US(PAL_BB_RTC->COUNTER); } else { /* Capture current TIMER0 count to capture register 3 */ - nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE3); + nrf_timer_task_trigger(PAL_BB_TIMER, NRF_TIMER_TASK_CAPTURE3); /* Read and return the captured count value from capture register 3 */ - return BB_TICKS_TO_US(nrf_timer_cc_read(NRF_TIMER0, NRF_TIMER_CC_CHANNEL3)); + return BB_TICKS_TO_US(nrf_timer_cc_read(PAL_BB_TIMER, NRF_TIMER_CC_CHANNEL3)); } } return 0; } -/*************************************************************************************************/ -/*! - * \brief Get the current FRC time tick. - * - * \param pTime Pointer to return the current time. - * - * \return Status error code. - * - * Get the current FRC time. - * - * \note FRC is limited to the same bit-width as the BB clock. Return value is available - * only when the BB is active. - */ -/*************************************************************************************************/ -bool_t PalBbGetTimestamp(uint32_t *pTime) -{ - if (palBbEnableCnt == 0) - { - return FALSE; - } - - if (USE_RTC_BB_CLK && pTime) - { - /* return the RTC counter value */ - *pTime = NRF_RTC1->COUNTER; - } - else if (pTime) - { - /* Capture current TIMER0 count to capture register 3 */ - nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE3); - - /* Read and return the captured count value from capture register 3 */ - *pTime = nrf_timer_cc_read(NRF_TIMER0, NRF_TIMER_CC_CHANNEL3); - } - - return TRUE; -} - /*************************************************************************************************/ /*! * \brief Called to register a protocol's Radio and Timer IRQ callback functions. @@ -238,7 +205,7 @@ void RADIO_IRQHandler(void) * \brief Combined BLE and 154 timer interrupt handler. */ /*************************************************************************************************/ -void TIMER0_IRQHandler(void) +void PAL_BB_IRQ_HANDLER(void) { if (palBbTimerIrqCbackTbl[palBbProtId]) { diff --git a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb_ble.c b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb_ble.c index 35452d15f6..24b390679b 100644 --- a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb_ble.c +++ b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb_ble.c @@ -27,14 +27,15 @@ * NOTES: * * While BB is enabled certain resources are consumed and are off limits during that time. - * Timer0 should not be touched while BB is enabled. It's available apart from that. + * TIMER0 should not be touched while BB is enabled. It's available apart from that. * PPI Channels 14 & 15 are used while BB is enabled. They are available apart from that. * - * Timer0's compare/capture registers are assigned specific uses: + * TIMER0's compare/capture registers are assigned specific uses: * CC[0] - triggers radio TXEN or RXEN task, PPI triggered * CC[1] - RX timeout * CC[2] - captures *every* radio PAYLOAD event time, PPI triggered * CC[3] - manual capture of current time + * CC[4] - captures *every* radio ADDRESS event time, PPI triggered * * PPI Channel 14: * Used to trigger TXEN or RXEN task on timer event COMPARE[0]. @@ -42,30 +43,37 @@ * PPI Channel 15: * Used to trigger timer capture to CC[2] on every radio PAYLOAD event. * + * PPI Channel 16: + * Used to trigger timer capture to CC[4] on every radio ADDRESS event. + * * If BB_CLK_RATE_HZ == 32768 (low power mode): * * Additional two channels of NRF RTC1 are controlled here. - * CC[1] - Compare value for NRF timer0 start task. + * CC[1] - Compare value for NRF TIMER0 start task. * CC[2] - Compare value for NRF HFCLK start task. */ #include "pal_types.h" #include "pal_bb.h" #include "pal_rtc.h" -#include "pal_bb.h" #include "pal_led.h" #include "pal_bb_ble.h" #include "pal_radio.h" +#include "pal_timer.h" #include "ll_defs.h" + #include "nrf.h" #include "nrf_gpio.h" #include "nrf_gpiote.h" + #include #if (LL_ENABLE_TESTER) #include "ll_tester_api.h" #endif +#include "mbed_nrf5x_adaptation.h" + /************************************************************************************************** Macros **************************************************************************************************/ @@ -109,8 +117,9 @@ #define ENC_LPLUS4_LEN 1 /* length of the "L+4" field */ #define ENC_RFU_LEN 1 /* length of the "RFU" field */ #define ENC_MIC_LEN 4 /* length of the MIC field */ -#define ENC_TX_BUF_LEN ( ENC_H_FIELD_LEN + ENC_LPLUS4_LEN + ENC_RFU_LEN + ENC_MAXPACKETSIZE ) -#define ENC_OUTPUT_BUF_LEN ( ENC_TX_BUF_LEN + ENC_MIC_LEN ) +#define ENC_PLAIN_BUF_LEN ( ENC_H_FIELD_LEN + ENC_LPLUS4_LEN + ENC_RFU_LEN + ENC_MAXPACKETSIZE ) +#define ENC_ENCRYPTED_BUF_LEN ( ENC_PLAIN_BUF_LEN + ENC_MIC_LEN ) +#define ENC_RFU_OFFSET 2 /* offset of the "RFU" field */ /* +/- range for TIFS adjustment */ #define TIFS_ADJ_RANGE_USECS 8 /* the +/- maximums for TIFS adjustment */ @@ -155,10 +164,6 @@ #define BB_ENABLE_INLINE_DEC_RX FALSE #endif -#ifndef DIAG_PINS_ENA -#define DIAG_PINS_ENA 1 -#endif - /* LED definitions */ #ifndef BB_LED_ENA #define BB_LED_ENA 0 @@ -168,7 +173,7 @@ #define BB_LED_1M_ON() PalLedOn(0) #define BB_LED_2M_ON() PalLedOn(1) #define BB_LED_CODED_ON() PalLedOn(0); PalLedOn(1) -#define BB_LED_OFF() PalLedOff(0); PalLedOff(1) +#define BB_LED_OFF() PalLedOff(0); PalLedOff(1); #else #define BB_LED_1M_ON() #define BB_LED_2M_ON() @@ -227,6 +232,8 @@ static uint8_t *palBbGetTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt); static void BbBleDrvTimerIRQHandler(void); static void BbBleDrvRadioIRQHandler(void); +extern int8_t palRadioGetTxRfPathComp(void); + /************************************************************************************************** Local Variables **************************************************************************************************/ @@ -250,23 +257,28 @@ uint8_t bbRxPhyOptions; uint8_t tifsTxPhyOptions; uint16_t bbTxLen; bool_t bbEncryptTxFlag; +bool_t bbDecryptRxFlag; bool_t bbEncryptTxSuppressMic; -uint8_t bbEncryptTxBuf[ENC_TX_BUF_LEN+2]; /* add two for overrun protection */ -uint8_t bbEncryptScratchBuf[ENC_SCRATCH_BUF_LEN+2]; /* add two for overrun protection */ -uint8_t bbEncryptOutBuf[ENC_OUTPUT_BUF_LEN+2]; /* add two for overrun protection */ +uint8_t bbEncryptType; +uint8_t bbEncryptDirection; +uint64_t bbEncryptPacketCounter; +uint64_t bbDecryptPacketCounter; +uint8_t bbEncryptPlainBuf[ENC_PLAIN_BUF_LEN+2]; /* add two for overrun protection */ +uint8_t bbEncryptScratchBuf[ENC_SCRATCH_BUF_LEN+2]; /* add two for overrun protection */ +uint8_t bbEncryptEncryptedBuf[ENC_ENCRYPTED_BUF_LEN+2]; /* add two for overrun protection */ uint8_t bbEncryptCcmData[ENC_CCM_DATA_STRUCT_LEN]; uint8_t bbTrlSave[BB_TRL_MAX_LEN]; uint8_t *bbTrlSavedPtr = NULL; uint8_t bbTrlSavedLen; PalBbBleOpParam_t bbOpParam; -#ifndef BB_ASSERT_ENABLED -#define BB_ASSERT_ENABLED FALSE -#endif -#if BB_ASSERT_ENABLED == TRUE +#if BB_ENABLE_ASSERT == TRUE bool_t keySetFlag = 0; bool_t ivSetFlag = 0; -bool_t packetCountSetFlag = 0; +bool_t encryptTypeSetFlag = 0; +bool_t directionSetFlag = 0; +bool_t txPacketCountSetFlag = 0; +bool_t rxPacketCountSetFlag = 0; #endif #if (LL_ENABLE_TESTER == TRUE) @@ -297,7 +309,7 @@ bool_t invalidateAccAddrOnceTx = FALSE; /* enable BB assertions */ #ifdef BB_ENABLE_ASSERT -#define BB_ASSERT(x) { if (!(X)) { return; } } +#define BB_ASSERT(x) { if (!(x)) { return; } } #else #define BB_ASSERT(x) #endif @@ -385,7 +397,7 @@ uint16_t diagCancels = 0; /*************************************************************************************************/ /*! - * \brief Config GPIO as input or output. + * \brief Configure GPIO as input or output. * * \param pin Pin number. */ @@ -500,17 +512,17 @@ static inline void palBbSetRadioMode(uint8_t phy, uint8_t option) #if (USE_RTC_BB_CLK) /*************************************************************************************************/ /*! - * \brief Set the time for the timer0 to start. + * \brief Set the time for the PAL_BB_TIMER to start. * - * \param startTime timer0 start time. + * \param startTime PAL_BB_TIMER start time. * */ /*************************************************************************************************/ static void palBbStartTimer(uint32_t startTime) { - bbEventStartTime = NRF_RTC1->CC[1] = startTime; - NRF_RTC1->EVENTS_COMPARE[1] = 0; - WAIT_FOR_WR_BUF_EMPTY(NRF_RTC1->EVENTS_COMPARE[1]); + bbEventStartTime = PAL_BB_RTC->CC[1] = startTime; + PAL_BB_RTC->EVENTS_COMPARE[1] = 0; + WAIT_FOR_WR_BUF_EMPTY(PAL_BB_RTC->EVENTS_COMPARE[1]); } #endif @@ -525,18 +537,17 @@ void PalBbBleLowPower(void) { /* Stop high frequency timer between BLE events if low lower mode. */ #if (USE_RTC_BB_CLK) - NRF_TIMER0->TASKS_STOP = 1; - NRF_TIMER0->TASKS_CLEAR = 1; + PAL_BB_TIMER->TASKS_STOP = 1; + PAL_BB_TIMER->TASKS_CLEAR = 1; #endif } -#if (BB_ENABLE_INLINE_ENC_TX || BB_ENABLE_INLINE_DEC_RX) +#if (BB_ENABLE_INLINE_ENC_TX) /*************************************************************************************************/ /*! * \brief Enable or disable inline encryption on transmit. * * \param enable Boolean flag to enable or disable TX encryption - * */ /*************************************************************************************************/ static void palBbBleInlineEncryptTxEnable(bool_t enable) @@ -546,13 +557,31 @@ static void palBbBleInlineEncryptTxEnable(bool_t enable) /* copy encryption enable to global variable */ bbEncryptTxFlag = enable; } +#endif +#if (BB_ENABLE_INLINE_DEC_RX) +/*************************************************************************************************/ +/*! + * \brief Enable or disable inline decryption on reception. + * + * \param enable Boolean flag to enable or disable RX decryption + */ +/*************************************************************************************************/ +static void palBbBleInlineDecryptRxEnable(bool_t enable) +{ + BB_ASSERT(driverState == IDLE_STATE); /* driver must be idle */ + + /* copy decryption enable to global variable */ + bbDecryptRxFlag = enable; +} +#endif + +#if (BB_ENABLE_INLINE_ENC_TX || BB_ENABLE_INLINE_DEC_RX) /*************************************************************************************************/ /*! * \brief Set inline encryption/decryption MIC suppression. * * \param enable Boolean flag to indicate if MIC is suppressed - * */ /*************************************************************************************************/ static void palBbBleInlineEncryptDecryptSuppressMic(bool_t enable) @@ -568,14 +597,13 @@ static void palBbBleInlineEncryptDecryptSuppressMic(bool_t enable) * \brief Set inline encryption/decryption key. * * \param key Pointer to 16-byte key value - * */ /*************************************************************************************************/ static void palBbBleInlineEncryptDecryptSetKey(uint8_t *pKey) { BB_ASSERT(driverState == IDLE_STATE); /* driver must be idle */ - #if BB_ASSERT_ENABLED == TRUE + #if BB_ENABLE_ASSERT == TRUE keySetFlag = 1; #endif @@ -591,14 +619,13 @@ static void palBbBleInlineEncryptDecryptSetKey(uint8_t *pKey) * \brief Set inline encryption/decryption IV (initialization vector). * * \param key Pointer to 8-byte value for IV - * */ /*************************************************************************************************/ static void palBbBleDrvInlineEncryptDecryptSetIv(uint8_t *pIV) { BB_ASSERT(driverState == IDLE_STATE); /* driver must be idle */ - #if BB_ASSERT_ENABLED == TRUE + #if BB_ENABLE_ASSERT == TRUE ivSetFlag = 1; #endif @@ -606,49 +633,74 @@ static void palBbBleDrvInlineEncryptDecryptSetIv(uint8_t *pIV) memcpy(&bbEncryptCcmData[25], pIV, 8); } +/*************************************************************************************************/ +/*! + * \brief Set inline encryption/decryption type. + * + * \param encType 0=PAL_BB_TYPE_ACL, CIS, BIS + */ +/*************************************************************************************************/ +static void palBbBleInlineEncryptSetType(uint8_t encType) +{ + #if BB_ENABLE_ASSERT == TRUE + encryptTypeSetFlag = 1; + #endif + + bbEncryptType = encType; +} + /*************************************************************************************************/ /*! * \brief Set inline encryption/decryption direction bit. * * \param dir 0=slave, non-zero=master - * */ /*************************************************************************************************/ -void PalBbBleInlineEncryptDecryptSetDirection(uint8_t dir) +void palBbBleInlineEncryptDecryptSetDirection(uint8_t dir) { - if (dir) - { - /* master */ - bbEncryptCcmData[24] = 1; - } - else - { - bbEncryptCcmData[24] = 0; - } + #if BB_ENABLE_ASSERT == TRUE + directionSetFlag = 1; + #endif + + bbEncryptDirection = dir; } /*************************************************************************************************/ /*! * \brief Set the inline encryption packet count for transmit. * - * \param count Packet counter value, a 39-bit value - * + * \param pktCtr Packet counter value, a 39-bit value (upper bits are ignored). */ /*************************************************************************************************/ -void PalBbBleInlineEncryptSetPacketCount(uint64_t count) +void PalBbBleSetInlineEncryptPacketCount(uint64_t pktCtr) { BB_ASSERT(driverState == IDLE_STATE); /* driver must be idle */ - #if BB_ASSERT_ENABLED == TRUE - packetCountSetFlag = 1; + #if BB_ENABLE_ASSERT == TRUE + txPacketCountSetFlag = 1; #endif /* populate packet counter */ - bbEncryptCcmData[16] = (count >> 0) & 0xFF; - bbEncryptCcmData[17] = (count >> 8) & 0xFF; - bbEncryptCcmData[18] = (count >> 16) & 0xFF; - bbEncryptCcmData[19] = (count >> 24) & 0xFF; - bbEncryptCcmData[20] = (count >> 32) & 0x7F; /* only 7-bits of MSB are used (packet count is 39 bits) */ + bbEncryptPacketCounter = pktCtr; +} + +/*************************************************************************************************/ +/*! + * \brief Set the inline decryption packet count for receive. + * + * \param pktCtr Packet counter value, a 39-bit value (upper bits are ignored). + */ +/*************************************************************************************************/ +void PalBbBleSetInlineDecryptPacketCount(uint64_t pktCtr) +{ + BB_ASSERT(driverState == IDLE_STATE); /* driver must be idle */ + + #if BB_ENABLE_ASSERT == TRUE + rxPacketCountSetFlag = 1; + #endif + + /* populate packet counter */ + bbDecryptPacketCounter = pktCtr; } #endif @@ -708,21 +760,22 @@ void PalBbBleInit(void) /* set default of no encryption */ bbEncryptTxFlag = 0; + bbDecryptRxFlag = 0; #if (USE_RTC_BB_CLK) - NRF_RTC1->EVTENCLR = RTC_EVTENCLR_COMPARE1_Msk; - NRF_RTC1->EVTENCLR = RTC_EVTENCLR_COMPARE2_Msk; + PAL_BB_RTC->EVTENCLR = RTC_EVTENCLR_COMPARE1_Msk; + PAL_BB_RTC->EVTENCLR = RTC_EVTENCLR_COMPARE2_Msk; #endif /* update driver state */ driverState = SLEEP_STATE; ///////////////////////////////////////////////////////////////////////////////// - #if BB_ASSERT_ENABLED + #if BB_ENABLE_ASSERT /* initialize buffers with 0xAA's, last two bytes used by assert to detect buffer overrun */ - memset(bbEncryptTxBuf, 0xAA, sizeof(bbEncryptTxBuf)); - memset(bbEncryptOutBuf, 0xAA, sizeof(bbEncryptOutBuf)); - memset(bbEncryptScratchBuf, 0xAA, sizeof(bbEncryptScratchBuf)); + memset(bbEncryptPlainBuf, 0xAA, sizeof(bbEncryptPlainBuf)); + memset(bbEncryptEncryptedBuf, 0xAA, sizeof(bbEncryptEncryptedBuf)); + memset(bbEncryptScratchBuf, 0xAA, sizeof(bbEncryptScratchBuf)); #endif ///////////////////////////////////////////////////////////////////////////////// @@ -745,10 +798,10 @@ void PalBbBleInit(void) void PalBbBleEnable(void) { /* Give the BB the highest priority. */ - NVIC_SetPriority(RADIO_IRQn, 0); - NVIC_SetPriority(TIMER0_IRQn, 0); + NVIC_SetPriority(RADIO_IRQn, 1); + NVIC_SetPriority(PAL_BB_IRQn, 1); - BB_ASSERT(NVIC_GetPriority(RADIO_IRQn) == NVIC_GetPriority(TIMER0_IRQn)); /* BB driver related interrupts must have same priority */ + BB_ASSERT(NVIC_GetPriority(RADIO_IRQn) == NVIC_GetPriority(PAL_BB_IRQn)); /* BB driver related interrupts must have same priority */ BB_ASSERT(driverState == SLEEP_STATE); /* the BB driver should never be re-enabled */ BB_ASSERT(NRF_CLOCK->HFCLKSTAT & CLOCK_HFCLKSTAT_STATE_Msk); /* HF clock must be running */ #if (USE_RTC_BB_CLK) @@ -762,48 +815,48 @@ void PalBbBleEnable(void) #endif /* stop timer if it was somehow running (timer must be stopped for configuration) */ - NRF_TIMER0->TASKS_STOP = 1; + PAL_BB_TIMER->TASKS_STOP = 1; /* clear timer to zero count */ - NRF_TIMER0->TASKS_CLEAR = 1; + PAL_BB_TIMER->TASKS_CLEAR = 1; /* configure timer */ - NRF_TIMER0->MODE = TIMER_MODE_MODE_Timer; - NRF_TIMER0->BITMODE = TIMER_BITMODE_BITMODE_32Bit; - NRF_TIMER0->PRESCALER = TIMER_PRESCALER; /* f = 16MHz / (2 ^ TIMER_PRESCALER), for TIMER_PRESCALER of 4, clock has 1us resolution + PAL_BB_TIMER->MODE = TIMER_MODE_MODE_Timer; + PAL_BB_TIMER->BITMODE = TIMER_BITMODE_BITMODE_32Bit; + PAL_BB_TIMER->PRESCALER = TIMER_PRESCALER; /* f = 16MHz / (2 ^ TIMER_PRESCALER), for TIMER_PRESCALER of 4, clock has 1us resolution TIMER_PRESCALER of 3, clock is 0.5us resolution TIMER_PRESCALER of 2, clock is 0.25us resolution TIMER_PRESCALER of 1, clock is 0.125us resolution */ /* - * Configure the PPI Channel 13 - "Chan 13: RTC.COMPARE[0] -> TIMER[0].START" + * Configure the PPI Channel 13 - "Chan 13: RTC.COMPARE[0] -> TIMER[3].START" * - * This channel is used to trigger starting TIMER[0] for radio operations. + * This channel is used to trigger starting TIMER[3] for radio operations. */ #if (USE_RTC_BB_CLK) - /* timer0 starts when RTC0.COMPARE[1] event is triggered */ - NRF_PPI->CH[13].EEP = (uint32_t) &NRF_RTC1->EVENTS_COMPARE[1]; - NRF_PPI->CH[13].TEP = (uint32_t) &NRF_TIMER0->TASKS_START; + /* TIMER0 starts when RTC0.COMPARE[1] event is triggered */ + NRF_PPI->CH[13].EEP = (uint32_t) &PAL_BB_RTC->EVENTS_COMPARE[1]; + NRF_PPI->CH[13].TEP = (uint32_t) &PAL_BB_TIMER->TASKS_START; NRF_PPI->CHENSET = PPI_CHENSET_CH13_Msk; /* enable channel */ /* HFCLK starts when RTC0.COMPARE[2] event is triggered */ - NRF_PPI->CH[10].EEP = (uint32_t) &NRF_RTC1->EVENTS_COMPARE[2]; + NRF_PPI->CH[10].EEP = (uint32_t) &PAL_BB_RTC->EVENTS_COMPARE[2]; NRF_PPI->CH[10].TEP = (uint32_t) &NRF_CLOCK->TASKS_HFCLKSTART; NRF_PPI->CHENSET = PPI_CHENSET_CH10_Msk; /* enable channel */ #else - /* timer0 is a free running clock */ - NRF_TIMER0->TASKS_START = 1; + /* TIMER0 is a free running clock */ + PAL_BB_TIMER->TASKS_START = 1; #endif /* - * Configure the PPI Channel 14 - "Chan 14: TIMER[0].COMPARE[0] -> TXEN/RXEN" + * Configure the PPI Channel 14 - "Chan 14: TIMER[3].COMPARE[0] -> TXEN/RXEN" * * This channel is used to trigger radio task TXEN, or RXEN, on timer event COMPARE[0]. * It is only enabled when needed. The PPI task parameter is meant to be configured just * before the channel is enabled. This task will be either TXEN or RXEN depending on radio * operation. The event is static and never changes. It is configured below. */ - NRF_PPI->CH[14].EEP = (uint32_t) &NRF_TIMER0->EVENTS_COMPARE[0]; /* configure event */ + NRF_PPI->CH[14].EEP = (uint32_t) &PAL_BB_TIMER->EVENTS_COMPARE[0]; /* configure event */ /* * Configure and enable PPI Channel 15 - "Chan 15: PAYLOAD -> CAPTURE[2]" @@ -815,9 +868,22 @@ void PalBbBleEnable(void) * It will stay active until the BB driver is disabled. */ NRF_PPI->CH[15].EEP = (uint32_t) &NRF_RADIO->EVENTS_PAYLOAD; /* configure event */ - NRF_PPI->CH[15].TEP = (uint32_t) &NRF_TIMER0->TASKS_CAPTURE[2]; /* configure task */ + NRF_PPI->CH[15].TEP = (uint32_t) &PAL_BB_TIMER->TASKS_CAPTURE[2]; /* configure task */ NRF_PPI->CHENSET = PPI_CHENSET_CH15_Msk; /* enable channel */ + /* + * Configure and enable PPI Channel 16 - "Chan 16: ADDRESS -> CAPTURE[4]" + * + * This channel is used to capture the timer value on every radio ADDRESS event. + * It is configured to trigger timer task CAPTURE[4] which copies the timer to CC[4]. + * + * Once this channel is set up and enabled, it requires no further action. + * It will stay active until the BB driver is disabled. + */ + NRF_PPI->CH[16].EEP = (uint32_t) &NRF_RADIO->EVENTS_ADDRESS; /* configure event */ + NRF_PPI->CH[16].TEP = (uint32_t) &PAL_BB_TIMER->TASKS_CAPTURE[4]; /* configure task */ + NRF_PPI->CHENSET = PPI_CHENSET_CH16_Msk; /* enable channel */ + /* * NOTE: Per Nordic support team response, PPI channels do not require a reset. * The PPI configured event will trigger the configured task every time it happens, @@ -825,10 +891,10 @@ void PalBbBleEnable(void) * reference manual.) */ - /* clear out and enable TIMER0 interrupts at system level */ - NRF_TIMER0->INTENCLR = 0xFFFFFFFF; - NVIC_ClearPendingIRQ(TIMER0_IRQn); - NVIC_EnableIRQ(TIMER0_IRQn); + /* clear out and enable BB scheduler interrupts at system level */ + PAL_BB_TIMER->INTENCLR = 0xFFFFFFFF; + NVIC_ClearPendingIRQ(PAL_BB_IRQn); + NVIC_EnableIRQ(PAL_BB_IRQn); /* clear out and enable RADIO interrupts at system level */ NRF_RADIO->INTENCLR = 0xFFFFFFFF; @@ -846,8 +912,8 @@ void PalBbBleEnable(void) */ #if (USE_RTC_BB_CLK) - NRF_RTC1->EVTENSET = RTC_EVTENSET_COMPARE1_Msk; - NRF_RTC1->EVTENSET = RTC_EVTENSET_COMPARE2_Msk; + PAL_BB_RTC->EVTENSET = RTC_EVTENSET_COMPARE1_Msk; + PAL_BB_RTC->EVTENSET = RTC_EVTENSET_COMPARE2_Msk; #endif /* enable the radio "TIFS Expired" interrupt (triggers on radio PAYLOAD event) */ @@ -891,16 +957,17 @@ void PalBbBleDisable(void) /* disable PPI channels */ NRF_PPI->CHENCLR = PPI_CHENCLR_CH14_Msk; /* Chan 14: COMPARE[0] -> TXEN/RXEN */ NRF_PPI->CHENCLR = PPI_CHENCLR_CH15_Msk; /* Chan 15: PAYLOAD -> CAPTURE[2] */ + NRF_PPI->CHENCLR = PPI_CHENCLR_CH16_Msk; /* Chan 16: ADDRESS -> CAPTURE[4] */ #if (USE_RTC_BB_CLK) - NRF_RTC1->EVTENCLR = RTC_EVTENCLR_COMPARE1_Msk; - NRF_RTC1->EVTENCLR = RTC_EVTENCLR_COMPARE2_Msk; + PAL_BB_RTC->EVTENCLR = RTC_EVTENCLR_COMPARE1_Msk; + PAL_BB_RTC->EVTENCLR = RTC_EVTENCLR_COMPARE2_Msk; #endif /* disable and clean up TIMER0 interrupts */ - NVIC_DisableIRQ(TIMER0_IRQn); - NRF_TIMER0->INTENCLR = 0xFFFFFFFF; - NVIC_ClearPendingIRQ(TIMER0_IRQn); + NVIC_DisableIRQ(PAL_BB_IRQn); + PAL_BB_TIMER->INTENCLR = 0xFFFFFFFF; + NVIC_ClearPendingIRQ(PAL_BB_IRQn); /* disable and clean up RADIO interrupts */ NVIC_DisableIRQ(RADIO_IRQn); @@ -1075,17 +1142,25 @@ static void palBbBleSetChannelParam(PalBbBleChan_t *pChan) /* set the power parameter to the value that was actually set in hardware */ pChan->txPower = txPower; -#if (BB_ENABLE_INLINE_ENC_TX || BB_ENABLE_INLINE_DEC_RX) +#if BB_ENABLE_INLINE_ENC_TX /* enable inline encryption */ palBbBleInlineEncryptTxEnable(pChan->enc.enaEncrypt); +#endif +#if BB_ENABLE_INLINE_DEC_RX + /* enable inline decryption */ + palBbBleInlineDecryptRxEnable(pChan->enc.enaDecrypt); +#endif + +#if (BB_ENABLE_INLINE_ENC_TX || BB_ENABLE_INLINE_DEC_RX) /* set encryption parameters */ if (pChan->enc.enaEncrypt || pChan->enc.enaDecrypt) { palBbBleInlineEncryptDecryptSuppressMic(FALSE); /* TODO add MIC suppression */ palBbBleInlineEncryptDecryptSetKey(pChan->enc.sk); palBbBleDrvInlineEncryptDecryptSetIv(pChan->enc.iv); - PalBbBleInlineEncryptDecryptSetDirection(pChan->enc.dir); + palBbBleInlineEncryptSetType(pChan->enc.type); + palBbBleInlineEncryptDecryptSetDirection(pChan->enc.dir); } #endif } @@ -1281,8 +1356,7 @@ void PalBbBleTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) uint16_t hdr; BYTES_TO_UINT16(hdr, pBuf); - if (bbModifyTxHdrMask && - ((hdr & bbModifyTxHdrMask) == bbModifyTxHdrValue)) + if ((hdr & bbModifyTxHdrMask) == bbModifyTxHdrValue) { if (bbTxAccAddrInvalidChanMask & (UINT64_C(1) << bbChanIndex)) { @@ -1337,8 +1411,7 @@ void PalBbBleTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) /* set Tx CRC init */ NRF_RADIO->CRCINIT = bbTxCrcInit; - if (bbModifyTxHdrMask && - ((hdr & bbModifyTxHdrMask) == bbModifyTxHdrValue)) + if ((hdr & bbModifyTxHdrMask) == bbModifyTxHdrValue) { if (bbTxCrcInitInvalidChanMask & (UINT64_C(1) << bbChanIndex)) { @@ -1384,15 +1457,15 @@ void PalBbBleTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) bbDueOffsetUsec = 1; /* CC[0] can't trigger on 0 */ } - NRF_TIMER0->CC[0] = bbDueOffsetUsec; - NRF_TIMER0->EVENTS_COMPARE[0] = 0; - WAIT_FOR_WR_BUF_EMPTY(NRF_TIMER0->EVENTS_COMPARE[0]); + PAL_BB_TIMER->CC[0] = bbDueOffsetUsec; + PAL_BB_TIMER->EVENTS_COMPARE[0] = 0; + WAIT_FOR_WR_BUF_EMPTY(PAL_BB_TIMER->EVENTS_COMPARE[0]); palBbStartTimer(txStart); #else BB_ASSERT(bbDueOffsetUsec == 0); /* Always 0 with HFCLK. */ - NRF_TIMER0->CC[0] = txStart; - NRF_TIMER0->EVENTS_COMPARE[0] = 0; - WAIT_FOR_WR_BUF_EMPTY(NRF_TIMER0->EVENTS_COMPARE[0]); + PAL_BB_TIMER->CC[0] = txStart; + PAL_BB_TIMER->EVENTS_COMPARE[0] = 0; + WAIT_FOR_WR_BUF_EMPTY(PAL_BB_TIMER->EVENTS_COMPARE[0]); #endif /* configure radio hardware registers for transmit */ @@ -1402,8 +1475,7 @@ void PalBbBleTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk; - uint32_t currentBbTick; - (void)PalBbGetTimestamp(¤tBbTick); + uint32_t currentBbTick = PalBbGetCurrentTime(); /* see if the due time is in the past (or a very long way, away) */ #if (USE_RTC_BB_CLK) @@ -1429,7 +1501,7 @@ void PalBbBleTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) NRF_PPI->CHENSET = PPI_CHENSET_CH14_Msk; /* enable channel */ /* see if the compare point was already reached */ - if (NRF_TIMER0->EVENTS_COMPARE[0]) + if (PAL_BB_TIMER->EVENTS_COMPARE[0]) { /* it's 99.99999% certain did not make it, but... maybe, just maybe... */ if (NRF_RADIO->STATE == RADIO_STATE_STATE_Disabled) @@ -1674,6 +1746,9 @@ static void palBbTxHwRadioConfig(uint8_t * pTxBuf) uint32_t plen = 0; #endif + /* set the mode */ + palBbSetRadioMode(bbTxPhy, bbTxPhyOptions); + if (!bbEncryptTxFlag) { /*------------------------------------------------------------------------------ @@ -1706,9 +1781,6 @@ static void palBbTxHwRadioConfig(uint8_t * pTxBuf) /* set packet pointer to supplied buffer */ NRF_RADIO->PACKETPTR = (uint32_t)pTxBuf; - - /* set the mode */ - palBbSetRadioMode(bbTxPhy, bbTxPhyOptions); } else { @@ -1730,7 +1802,8 @@ static void palBbTxHwRadioConfig(uint8_t * pTxBuf) BB_ASSERT( keySetFlag ); /* encryption key has not been set */ BB_ASSERT( ivSetFlag ); /* iv was not set */ - BB_ASSERT( packetCountSetFlag ); /* packet count was not set */ + BB_ASSERT( txPacketCountSetFlag ); /* packet count was not set */ + BB_ASSERT( directionSetFlag ); /* direction was not set */ /* configure PCNF0 */ NRF_RADIO->PCNF0 = (((uint32_t)( 1 /* S0 field in bytes */ )) << RADIO_PCNF0_S0LEN_Pos) | @@ -1740,7 +1813,7 @@ static void palBbTxHwRadioConfig(uint8_t * pTxBuf) (((uint32_t)((bbTxPhy == BB_PHY_BLE_CODED) ? 3 : 0 /* TERM field in bits*/ )) << RADIO_PCNF0_TERMLEN_Pos) | (((uint32_t)((bbTxPhy == BB_PHY_BLE_CODED) ? 2 : 0 /* CI field in bits */ )) << RADIO_PCNF0_CILEN_Pos) | (((uint32_t)( 0 /* CRCINC field */ )) << RADIO_PCNF0_CRCINC_Pos) | - (((uint32_t)( 1 /* S1INCL filed */ )) << RADIO_PCNF0_S1INCL_Pos) | + (((uint32_t)( 1 /* S1INCL field */ )) << RADIO_PCNF0_S1INCL_Pos) | #endif ((uint32_t)( plen /* preamble field in bits */ )); @@ -1752,21 +1825,31 @@ static void palBbTxHwRadioConfig(uint8_t * pTxBuf) (((uint32_t)( bbRadioPcnf1WhiteEn )) << RADIO_PCNF1_WHITEEN_Pos ); /* set packet pointer to the soon-to-be encrypted buffer */ - NRF_RADIO->PACKETPTR = (uint32_t)&bbEncryptOutBuf[0]; + NRF_RADIO->PACKETPTR = (uint32_t)&bbEncryptEncryptedBuf[0]; + + /* set encryption direction */ + bbEncryptCcmData[24] = bbEncryptDirection; + + /* set encrypt packet counter */ + bbEncryptCcmData[16] = (bbEncryptPacketCounter >> 0) & 0xFF; + bbEncryptCcmData[17] = (bbEncryptPacketCounter >> 8) & 0xFF; + bbEncryptCcmData[18] = (bbEncryptPacketCounter >> 16) & 0xFF; + bbEncryptCcmData[19] = (bbEncryptPacketCounter >> 24) & 0xFF; + bbEncryptCcmData[20] = (bbEncryptPacketCounter >> 32) & 0x7F; /* only 7-bits of MSB are used (packet count is 39 bits) */ /* get length from packet to transmit */ bbTxLen = pTxBuf[1]; - BB_ASSERT(bbTxLen <= ENC_MAX_PAYLOAD_LEN); /* payload exceeds Nordic's maximum possible for encryption */ + BB_ASSERT(bbTxLen <= ENC_MAXPACKETSIZE); /* payload exceeds Nordic's maximum possible for encryption */ /* construct header in Nordic format */ - bbEncryptTxBuf[0] = pTxBuf[0]; /* field "H" */ - bbEncryptTxBuf[1] = bbTxLen; /* field "L" */ - bbEncryptTxBuf[2] = 0; /* field "RFU" */ + bbEncryptPlainBuf[0] = pTxBuf[0]; /* field "H" */ + bbEncryptPlainBuf[1] = bbTxLen; /* field "L" */ + bbEncryptPlainBuf[2] = 0; /* field "RFU" */ /* copy the payload into Nordic format transmit buffer */ - memcpy(&bbEncryptTxBuf[3], &pTxBuf[2], bbTxLen); - BB_ASSERT(bbEncryptTxBuf[sizeof(bbEncryptTxBuf)-1] == 0xAA); /* buffer overrun from memcpy */ - BB_ASSERT(bbEncryptTxBuf[sizeof(bbEncryptTxBuf)-2] == 0xAA); /* buffer overrun from memcpy */ + memcpy(&bbEncryptPlainBuf[3], &pTxBuf[2], bbTxLen); + BB_ASSERT(bbEncryptPlainBuf[sizeof(bbEncryptPlainBuf)-1] == 0xAA); /* buffer overrun from memcpy */ + BB_ASSERT(bbEncryptPlainBuf[sizeof(bbEncryptPlainBuf)-2] == 0xAA); /* buffer overrun from memcpy */ NRF_CCM->ENABLE = (CCM_ENABLE_ENABLE_Disabled << CCM_ENABLE_ENABLE_Pos); NRF_CCM->ENABLE = (CCM_ENABLE_ENABLE_Enabled << CCM_ENABLE_ENABLE_Pos); @@ -1774,8 +1857,8 @@ static void palBbTxHwRadioConfig(uint8_t * pTxBuf) NRF_CCM->CNFPTR = (uint32_t)bbEncryptCcmData; NRF_CCM->SCRATCHPTR = (uint32_t)bbEncryptScratchBuf; - NRF_CCM->INPTR = (uint32_t)bbEncryptTxBuf; - NRF_CCM->OUTPTR = (uint32_t)bbEncryptOutBuf; + NRF_CCM->INPTR = (uint32_t)bbEncryptPlainBuf; + NRF_CCM->OUTPTR = (uint32_t)bbEncryptEncryptedBuf; uint32_t ccmModeDatarate; switch (bbTxPhy) @@ -1807,7 +1890,7 @@ static void palBbTxHwRadioConfig(uint8_t * pTxBuf) if (bbEncryptTxSuppressMic) { /* set the length field in output buffer to 0xFF, used to detect when it has been populated via DMA */ - bbEncryptOutBuf[1] = 0xFF; + bbEncryptEncryptedBuf[1] = 0xFF; /* clear the ENDKSGEN event, aka "key-stream generation complete" event */ WAIT_FOR_WR_BUF_EMPTY(NRF_CCM->EVENTS_ENDKSGEN); @@ -1829,7 +1912,7 @@ static void palBbTxHwRadioConfig(uint8_t * pTxBuf) #endif /* set shortcut to start encryption immediately after key generation */ - NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; // TODO - probably just need to set once at initialization ***** + NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; /* start encryption */ NRF_CCM->TASKS_KSGEN = 1; @@ -1869,10 +1952,10 @@ void CCM_AAR_IRQHandler(void) */ /* wait for the length field to be populated by the Nordic hardware */ - while (bbEncryptOutBuf[1] == 0xFF) + while (bbEncryptEncryptedBuf[1] == 0xFF) { /////////////////////////////////////////////////////////////////////////////// - #ifdef BB_ASSERT_ENABLED + #ifdef BB_ENABLE_ASSERT uint8_t busycount = 0; BB_ASSERT(busycount < 10); /* got stuck */ busycount++; @@ -1881,8 +1964,8 @@ void CCM_AAR_IRQHandler(void) } /* overwrite with the length field with the original length, that does not include the MIC */ - BB_ASSERT(bbTxLen == (bbEncryptOutBuf[1] - 4)); /* the populated length should be exactly +4 */ - bbEncryptOutBuf[1] = bbTxLen; + BB_ASSERT(bbTxLen == (bbEncryptEncryptedBuf[1] - 4)); /* the populated length should be exactly +4 */ + bbEncryptEncryptedBuf[1] = bbTxLen; } #if (LL_ENABLE_TESTER) @@ -1893,12 +1976,12 @@ void CCM_AAR_IRQHandler(void) /* disable this interrupt */ NRF_CCM->INTENCLR = CCM_INTENCLR_ENDCRYPT_Msk; - bbEncryptOutBuf[0] ^= llTesterCb.pktLlId & 0x03; + bbEncryptEncryptedBuf[0] ^= llTesterCb.pktLlId & 0x03; - bbEncryptOutBuf[bbTxLen] ^= (llTesterCb.pktMic >> 0) & 0xFF; - bbEncryptOutBuf[bbTxLen+1] ^= (llTesterCb.pktMic >> 8) & 0xFF; - bbEncryptOutBuf[bbTxLen+2] ^= (llTesterCb.pktMic >> 16) & 0xFF; - bbEncryptOutBuf[bbTxLen+3] ^= (llTesterCb.pktMic >> 24) & 0xFF; + bbEncryptEncryptedBuf[bbTxLen] ^= (llTesterCb.pktMic >> 0) & 0xFF; + bbEncryptEncryptedBuf[bbTxLen+1] ^= (llTesterCb.pktMic >> 8) & 0xFF; + bbEncryptEncryptedBuf[bbTxLen+2] ^= (llTesterCb.pktMic >> 16) & 0xFF; + bbEncryptEncryptedBuf[bbTxLen+3] ^= (llTesterCb.pktMic >> 24) & 0xFF; } #endif } @@ -2010,15 +2093,15 @@ void PalBbBleRxData(uint8_t *pBuf, uint16_t len) bbDueOffsetUsec = 1; /* CC[0] can't trigger on 0 */ } - NRF_TIMER0->CC[0] = bbDueOffsetUsec; - NRF_TIMER0->EVENTS_COMPARE[0] = 0; - WAIT_FOR_WR_BUF_EMPTY(NRF_TIMER0->EVENTS_COMPARE[0]); + PAL_BB_TIMER->CC[0] = bbDueOffsetUsec; + PAL_BB_TIMER->EVENTS_COMPARE[0] = 0; + WAIT_FOR_WR_BUF_EMPTY(PAL_BB_TIMER->EVENTS_COMPARE[0]); palBbStartTimer(rxStart - 1); /* Subtract 1 for receive uncertainty due to rounding. */ #else BB_ASSERT(bbDueOffsetUsec == 0); /* Always 0 with HFCLK. */ - NRF_TIMER0->CC[0] = rxStart; - NRF_TIMER0->EVENTS_COMPARE[0] = 0; - WAIT_FOR_WR_BUF_EMPTY(NRF_TIMER0->EVENTS_COMPARE[0]); + PAL_BB_TIMER->CC[0] = rxStart; + PAL_BB_TIMER->EVENTS_COMPARE[0] = 0; + WAIT_FOR_WR_BUF_EMPTY(PAL_BB_TIMER->EVENTS_COMPARE[0]); #endif #if (USE_RTC_BB_CLK) @@ -2056,7 +2139,7 @@ void PalBbBleRxData(uint8_t *pBuf, uint16_t len) correction = 0; } /* set timer compare CC[1] for RX timeout (allow time to recognize address, and account for propagation delay) */ - NRF_TIMER0->CC[1] = NRF_TIMER0->CC[0] + PAL_BB_TIMER->CC[1] = PAL_BB_TIMER->CC[0] + TICKS_PER_USEC * (bbRxTimeoutUsec + preambleTime + accessAddrTime @@ -2065,8 +2148,8 @@ void PalBbBleRxData(uint8_t *pBuf, uint16_t len) + correction); /* clear RX timeout compare event, but do not enable interrupt, that happens in radio isr */ - NRF_TIMER0->EVENTS_COMPARE[1] = 0; - WAIT_FOR_WR_BUF_EMPTY(NRF_TIMER0->EVENTS_COMPARE[1]); + PAL_BB_TIMER->EVENTS_COMPARE[1] = 0; + WAIT_FOR_WR_BUF_EMPTY(PAL_BB_TIMER->EVENTS_COMPARE[1]); /* configure radio hardware registers for receive */ palBbRxHwRadioConfig(pBuf, len); @@ -2077,8 +2160,7 @@ void PalBbBleRxData(uint8_t *pBuf, uint16_t len) RADIO_SHORTS_ADDRESS_RSSISTART_Msk | RADIO_SHORTS_DISABLED_RSSISTOP_Msk; - uint32_t currentBbTick; - (void)PalBbGetTimestamp(¤tBbTick); + uint32_t currentBbTick = PalBbGetCurrentTime(); /* see if the due time is in the past (or a very long way, away) */ #if (USE_RTC_BB_CLK) @@ -2103,7 +2185,7 @@ void PalBbBleRxData(uint8_t *pBuf, uint16_t len) NRF_PPI->CHENSET = PPI_CHENSET_CH14_Msk; /* enable channel */ /* see if the compare point was already reached */ - if (NRF_TIMER0->EVENTS_COMPARE[0]) + if (PAL_BB_TIMER->EVENTS_COMPARE[0]) { /* it's 99.99999% certain did not make it, but... maybe, just maybe... */ if (NRF_RADIO->STATE == RADIO_STATE_STATE_Disabled) @@ -2303,8 +2385,15 @@ static void palBbRxHwRadioConfig(uint8_t * pRxBuf, uint16_t len) #else uint32_t plen = 0; #endif - /* configure PCNF0 */ - NRF_RADIO->PCNF0 = (((uint32_t)( 1 /* S0 field in bytes */ )) << RADIO_PCNF0_S0LEN_Pos) | + + /* set the mode */ + palBbSetRadioMode(bbRxPhy, bbTxPhyOptions); + + if (!bbDecryptRxFlag) + { + /* No decryption */ + /* configure PCNF0 */ + NRF_RADIO->PCNF0 = (((uint32_t)( 1 /* S0 field in bytes */ )) << RADIO_PCNF0_S0LEN_Pos) | (((uint32_t)( 8 /* length field in bits */ )) << RADIO_PCNF0_LFLEN_Pos) | (((uint32_t)( 0 /* S1 field in bits */ )) << RADIO_PCNF0_S1LEN_Pos) | #if defined(NRF52840_XXAA) @@ -2315,18 +2404,109 @@ static void palBbRxHwRadioConfig(uint8_t * pRxBuf, uint16_t len) #endif ((uint32_t)( plen /* preamble field in bits */ )); - /* configure PCNF1 */ - NRF_RADIO->PCNF1 = (((uint32_t)( len - PDU_HEADER_LEN /* max len */ )) << RADIO_PCNF1_MAXLEN_Pos ) | + /* configure PCNF1 */ + NRF_RADIO->PCNF1 = (((uint32_t)( len - PDU_HEADER_LEN /* max len */ )) << RADIO_PCNF1_MAXLEN_Pos ) | (((uint32_t)( 0 /* static len */ )) << RADIO_PCNF1_STATLEN_Pos ) | (((uint32_t)( NORDIC_BASE_ADDR_LEN )) << RADIO_PCNF1_BALEN_Pos ) | (((uint32_t)( RADIO_PCNF1_ENDIAN_Little )) << RADIO_PCNF1_ENDIAN_Pos ) | (((uint32_t)( bbRadioPcnf1WhiteEn )) << RADIO_PCNF1_WHITEEN_Pos ); - /* set up memory location where received packet gets stored */ - NRF_RADIO->PACKETPTR = (uint32_t)pRxBuf; + /* set up memory location where received packet gets stored */ + NRF_RADIO->PACKETPTR = (uint32_t)pRxBuf; - /* set the mode */ - palBbSetRadioMode(bbRxPhy, bbTxPhyOptions); + } + else + { + /* Decryption */ + BB_ASSERT( keySetFlag ); /* encryption key has not been set */ + BB_ASSERT( ivSetFlag ); /* iv was not set */ + BB_ASSERT( rxPacketCountSetFlag ); /* packet count was not set */ + BB_ASSERT( directionSetFlag ); /* direction was not set */ + BB_ASSERT( encryptTypeSetFlag ); /* decrypt type was not set */ + + /* configure PCNF0 */ + NRF_RADIO->PCNF0 = (((uint32_t)( 1 /* S0 field in bytes */ )) << RADIO_PCNF0_S0LEN_Pos) | + (((uint32_t)( 8 /* length field in bits */ )) << RADIO_PCNF0_LFLEN_Pos) | + (((uint32_t)( 0 /* S1 field in bits */ )) << RADIO_PCNF0_S1LEN_Pos) | +#if defined(NRF52840_XXAA) + (((uint32_t)((bbRxPhy == BB_PHY_BLE_CODED) ? 3 : 0 /* TERM field in bits*/ )) << RADIO_PCNF0_TERMLEN_Pos) | + (((uint32_t)((bbRxPhy == BB_PHY_BLE_CODED) ? 2 : 0 /* CI field in bits */ )) << RADIO_PCNF0_CILEN_Pos) | + (((uint32_t)( 0 /* CRCINC field */ )) << RADIO_PCNF0_CRCINC_Pos) | + (((uint32_t)( 1 /* S1INCL field */ )) << RADIO_PCNF0_S1INCL_Pos) | +#endif + ((uint32_t)( plen /* preamble field in bits */ )); + + /* configure PCNF1 */ + NRF_RADIO->PCNF1 = (((uint32_t)( len - PDU_HEADER_LEN /* maximum packet length */ )) << RADIO_PCNF1_MAXLEN_Pos ) | + (((uint32_t)( 0 /* static packet length */ )) << RADIO_PCNF1_STATLEN_Pos ) | + (((uint32_t)( NORDIC_BASE_ADDR_LEN )) << RADIO_PCNF1_BALEN_Pos ) | + (((uint32_t)( RADIO_PCNF1_ENDIAN_Little )) << RADIO_PCNF1_ENDIAN_Pos ) | + (((uint32_t)( bbRadioPcnf1WhiteEn )) << RADIO_PCNF1_WHITEEN_Pos ); + + /* set packet pointer to the encrypted buffer */ + NRF_RADIO->PACKETPTR = (uint32_t)&bbEncryptEncryptedBuf[0]; + + /* update decryption direction for ACL/CIS */ + if ((bbEncryptType == PAL_BB_TYPE_ACL) || (bbEncryptType == PAL_BB_TYPE_CIS)) + { + bbEncryptCcmData[24] = !bbEncryptDirection; + } + else + { + bbEncryptCcmData[24] = bbEncryptDirection; + } + + /* set decrypt packet counter */ + bbEncryptCcmData[16] = (bbDecryptPacketCounter >> 0) & 0xFF; + bbEncryptCcmData[17] = (bbDecryptPacketCounter >> 8) & 0xFF; + bbEncryptCcmData[18] = (bbDecryptPacketCounter >> 16) & 0xFF; + bbEncryptCcmData[19] = (bbDecryptPacketCounter >> 24) & 0xFF; + bbEncryptCcmData[20] = (bbDecryptPacketCounter >> 32) & 0x7F; /* only 7-bits of MSB are used (packet count is 39 bits) */ + + NRF_CCM->ENABLE = (CCM_ENABLE_ENABLE_Disabled << CCM_ENABLE_ENABLE_Pos); + NRF_CCM->ENABLE = (CCM_ENABLE_ENABLE_Enabled << CCM_ENABLE_ENABLE_Pos); + + NRF_CCM->CNFPTR = (uint32_t)bbEncryptCcmData; + NRF_CCM->SCRATCHPTR = (uint32_t)bbEncryptScratchBuf; + + NRF_CCM->INPTR = (uint32_t)bbEncryptEncryptedBuf; + NRF_CCM->OUTPTR = (uint32_t)pRxBuf; + + uint32_t ccmModeDatarate; + switch (bbRxPhy) + { + default: + case BB_PHY_BLE_1M: + ccmModeDatarate = CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos; + break; + case BB_PHY_BLE_2M: + ccmModeDatarate = CCM_MODE_DATARATE_2Mbit << CCM_MODE_DATARATE_Pos; + break; +#if defined(NRF52840_XXAA) + case BB_PHY_BLE_CODED: + ccmModeDatarate = ((bbRxPhyOptions == BB_PHY_OPTIONS_BLE_S2) ? CCM_MODE_DATARATE_500Kbps : CCM_MODE_DATARATE_125Kbps) + << CCM_MODE_DATARATE_Pos; + break; +#endif + } + + NRF_CCM->MODE = (CCM_MODE_MODE_Decryption << CCM_MODE_MODE_Pos) | + (ccmModeDatarate) | + (CCM_MODE_LENGTH_Extended << CCM_MODE_LENGTH_Pos); + + NRF_CCM->EVENTS_ENDCRYPT = 0; + NRF_CCM->EVENTS_ENDKSGEN = 0; + NRF_CCM->EVENTS_ERROR = 0; + + /* disable shortcut between ENDKSGEN and CRYPT for on-the-fly decryption */ + NRF_CCM->SHORTS = 0; + + /* enable PPI between RADIO->EVENTS_ADDRESS and CCM->TASKS_CRYPT*/ + NRF_PPI->CHENSET = PPI_CHENSET_CH25_Msk; + + /* start key stream generation */ + NRF_CCM->TASKS_KSGEN = 1; + } /* remember where the receive buffer is located, used later when processing the completed receive */ bbpRxBuf = pRxBuf; @@ -2345,28 +2525,46 @@ static void palBbRxHwRadioConfig(uint8_t * pRxBuf, uint16_t len) /*************************************************************************************************/ void BbBleDrvTimerIRQHandler(void) { - BB_ASSERT(NRF_TIMER0->INTENSET == TIMER_INTENSET_COMPARE1_Msk); /* only RX timeout should be enabled */ - /* -----------------------------------------------------------------------------* * COMPARE1 - "RX Timeout" * -----------------------------------------------------------------------------*/ - BB_ASSERT(NRF_TIMER0->EVENTS_COMPARE[1]); - BB_ASSERT(driverState == RX_STATE); /* an RX timeout should only occur for an RX */ - BB_ASSERT(NRF_RADIO->STATE == RADIO_STATE_STATE_Rx); /* should only be timeout if receiver is actually on */ - /* disable this interrupt */ - NRF_TIMER0->INTENCLR = TIMER_INTENCLR_COMPARE1_Msk; - - /* Once the ADDRESS event has happened, the receive will not be timed out. This event happens - * just after the incoming preamble/address has been recognized. - */ - if (NRF_RADIO->EVENTS_ADDRESS == 0) + if (PAL_BB_TIMER->INTENSET & TIMER_INTENSET_COMPARE1_Msk) { - /* stop the radio */ - palBbRadioHardStop(); + BB_ASSERT(PAL_BB_TIMER->EVENTS_COMPARE[1]); + BB_ASSERT(driverState == RX_STATE); /* an RX timeout should only occur for an RX */ + BB_ASSERT(NRF_RADIO->STATE == RADIO_STATE_STATE_Rx); /* should only be timeout if receiver is actually on */ - /* send notification of timeout */ - bbRxCallback(BB_STATUS_RX_TIMEOUT, 0, 0, 0, 0); + /* disable this interrupt */ + PAL_BB_TIMER->INTENCLR = TIMER_INTENCLR_COMPARE1_Msk; + + /* Once the ADDRESS event has happened, the receive will not be timed out. This event happens + * just after the incoming preamble/address has been recognized. + */ + if (NRF_RADIO->EVENTS_ADDRESS == 0) + { + /* stop the radio */ + palBbRadioHardStop(); + + /* send notification of timeout */ + bbRxCallback(BB_STATUS_RX_TIMEOUT, 0, 0, 0, 0); + } + } + + /* -----------------------------------------------------------------------------* + * COMPARE5 - "Scheduler" + * -----------------------------------------------------------------------------*/ + + if (PAL_BB_TIMER->INTENSET & PAL_BB_TIMER_EXPIRY_INTENSET_MASK) + { + PalTimerStop(); + + /* TODO move to private PAL header. */ + extern void (*palTimerExpCback)(void); + if (palTimerExpCback) + { + palTimerExpCback(); + } } } @@ -2432,13 +2630,13 @@ void BbBleDrvRadioIRQHandler(void) WAIT_FOR_WR_BUF_EMPTY(NRF_RADIO->EVENTS_ADDRESS); /* enable the RX interrupt */ - NRF_TIMER0->INTENSET = TIMER_INTENSET_COMPARE1_Msk; + PAL_BB_TIMER->INTENSET = TIMER_INTENSET_COMPARE1_Msk; /* if the compare event is set, the RX timeout already occurred */ - if (NRF_TIMER0->EVENTS_COMPARE[1]) + if (PAL_BB_TIMER->EVENTS_COMPARE[1]) { /* force a compare event, which will trigger the interrupt (it was disabled when the actual event happened) */ - NRF_TIMER0->EVENTS_COMPARE[1] = 1; + PAL_BB_TIMER->EVENTS_COMPARE[1] = 1; } } @@ -2456,8 +2654,8 @@ void BbBleDrvRadioIRQHandler(void) WAIT_FOR_WR_BUF_EMPTY(NRF_RADIO->EVENTS_PAYLOAD); /* disable the "RX Timeout" interrupt (timer COMPARE1 event) */ - NRF_TIMER0->INTENCLR = TIMER_INTENCLR_COMPARE1_Msk; - NVIC_ClearPendingIRQ(TIMER0_IRQn); /* necessary, if interrupt already "fired" this is the only way to clear it */ + PAL_BB_TIMER->INTENCLR = TIMER_INTENCLR_COMPARE1_Msk; + NVIC_ClearPendingIRQ(PAL_BB_IRQn); /* necessary, if interrupt already "fired" this is the only way to clear it */ /* * Setup for potential TIFS operation. @@ -2541,13 +2739,13 @@ void BbBleDrvRadioIRQHandler(void) * The transmit propagation delay from event to antenna is added to get the actual "antenna time" when the * last transmitted bit finishes at the antenna. */ - antennaTimeTxPktEnd = NRF_TIMER0->CC[2] /* start with timer value when payload just finished */ + antennaTimeTxPktEnd = PAL_BB_TIMER->CC[2] /* start with timer value when payload just finished */ + TICKS_PER_USEC * crcTime /* add CRC time to arrive at end of packet */ + TICKS_PER_USEC * term2Time /* add TERM2 time to arrive at end of packet */ + TICKS_PER_USEC * NRF5x_PROP_DELAY_TX_USECS; /* add propagation delay to get "antenna time" */ /* set timer trigger for upcoming TIFS receive operation */ - NRF_TIMER0->CC[0] = antennaTimeTxPktEnd /* start with "antenna time" at end of packet just transmitted */ + PAL_BB_TIMER->CC[0] = antennaTimeTxPktEnd /* start with "antenna time" at end of packet just transmitted */ + TICKS_PER_USEC * LL_BLE_TIFS_US /* add the TIFS period */ - TICKS_PER_USEC * NRF5x_tRXEN_BLE_USECS /* subtract time it takes to ramp-up for receive */ - TICKS_PER_USEC * MAX_TIFS_DEVIATION_USECS; /* subtract allowed deviation */ @@ -2557,7 +2755,7 @@ void BbBleDrvRadioIRQHandler(void) NRF_PPI->CHENSET = PPI_CHENSET_CH14_Msk; /* enable channel */ /* calculate and set RX timeout */ - NRF_TIMER0->CC[1] = antennaTimeTxPktEnd /* start with "antenna time" at end of packet just transmitted */ + PAL_BB_TIMER->CC[1] = antennaTimeTxPktEnd /* start with "antenna time" at end of packet just transmitted */ + TICKS_PER_USEC * LL_BLE_TIFS_US /* add the TIFS period */ + TICKS_PER_USEC * preambleTime /* allow time preamble to be received */ + TICKS_PER_USEC * accessAddrTime /* allow time access address to be received */ @@ -2575,8 +2773,8 @@ void BbBleDrvRadioIRQHandler(void) */ /* clear RX timeout compare event, but do not enable interrupt, that happens in radio isr */ - NRF_TIMER0->EVENTS_COMPARE[1] = 0; - WAIT_FOR_WR_BUF_EMPTY(NRF_TIMER0->EVENTS_COMPARE[1]); + PAL_BB_TIMER->EVENTS_COMPARE[1] = 0; + WAIT_FOR_WR_BUF_EMPTY(PAL_BB_TIMER->EVENTS_COMPARE[1]); /* a TX is completing, the radio will soon be ramping up for possible TIFS RX */ tifsState = TIFS_RX_RAMPUP; @@ -2651,13 +2849,13 @@ void BbBleDrvRadioIRQHandler(void) } /* calculate "antenna time" when the packet ended (see comments in above transmit code for more explanation) */ - antennaTimeRxPktEnd = NRF_TIMER0->CC[2] /* start with timer value when payload just finished */ + antennaTimeRxPktEnd = PAL_BB_TIMER->CC[2] /* start with timer value when payload just finished */ + TICKS_PER_USEC * crcTime /* add CRC time to arrive at end of packet */ + TICKS_PER_USEC * term2Time /* add TERM2 time to arrive at end of packet */ - TICKS_PER_USEC * NRF5x_PROP_DELAY_RX_USECS; /* subtract propagation delay to get "antenna time" */ /* set timer trigger for upcoming TIFS transmit operation */ - NRF_TIMER0->CC[0] = antennaTimeRxPktEnd /* start with antenna time */ + PAL_BB_TIMER->CC[0] = antennaTimeRxPktEnd /* start with antenna time */ + TICKS_PER_USEC * LL_BLE_TIFS_US /* add the TIFS period */ - TICKS_PER_USEC * NRF5x_tTXEN_BLE_USECS /* subtract ramp-up time */ - TICKS_PER_USEC * NRF5x_PROP_DELAY_TX_USECS /* subtract internal propagation delay */ @@ -2709,14 +2907,14 @@ void BbBleDrvRadioIRQHandler(void) correction = 4; } - NRF_TIMER0->CC[0] = BB_US_TO_BB_TICKS(bbOpParam.ifsTime - (NRF5x_tRXEN_BLE_USECS + NRF5x_PROP_DELAY_RX_USECS)); + PAL_BB_TIMER->CC[0] = BB_US_TO_BB_TICKS(bbOpParam.ifsTime - (NRF5x_tRXEN_BLE_USECS + NRF5x_PROP_DELAY_RX_USECS)); /* configure and enable PPI trigger for RXEN, happens on next timer COMPARE[0] just configured above */ NRF_PPI->CH[14].TEP = (uint32_t) &NRF_RADIO->TASKS_RXEN; /* configure task */ NRF_PPI->CHENSET = PPI_CHENSET_CH14_Msk; /* enable channel */ /* set timer compare CC[1] for RX timeout (allow time to recognize address, and account for propagation delay) */ - NRF_TIMER0->CC[1] = NRF_TIMER0->CC[0] + PAL_BB_TIMER->CC[1] = PAL_BB_TIMER->CC[0] + TICKS_PER_USEC * (30 /* TODO Resolve total deviation allowed */ + preambleTime + accessAddrTime @@ -2736,8 +2934,8 @@ void BbBleDrvRadioIRQHandler(void) */ /* clear RX timeout compare event, but do not enable interrupt, that happens in radio isr */ - NRF_TIMER0->EVENTS_COMPARE[1] = 0; - WAIT_FOR_WR_BUF_EMPTY(NRF_TIMER0->EVENTS_COMPARE[1]); + PAL_BB_TIMER->EVENTS_COMPARE[1] = 0; + WAIT_FOR_WR_BUF_EMPTY(PAL_BB_TIMER->EVENTS_COMPARE[1]); /* update channel parameters */ if (bbOpParam.pIfsChan) @@ -2756,7 +2954,7 @@ void BbBleDrvRadioIRQHandler(void) (driverState == TX_STATE)) { /* calculate start time */ - NRF_TIMER0->CC[0] = BB_US_TO_BB_TICKS(bbOpParam.ifsTime - (NRF5x_tTXEN_BLE_USECS + NRF5x_PROP_DELAY_TX_USECS)); + PAL_BB_TIMER->CC[0] = BB_US_TO_BB_TICKS(bbOpParam.ifsTime - (NRF5x_tTXEN_BLE_USECS + NRF5x_PROP_DELAY_TX_USECS)); /* configure and enable PPI trigger for TXEN, happens on next timer COMPARE[0] */ NRF_PPI->CH[14].TEP = (uint32_t) &NRF_RADIO->TASKS_TXEN; /* configure task */ @@ -2785,10 +2983,10 @@ void BbBleDrvRadioIRQHandler(void) */ /* capture current time */ - NRF_TIMER0->TASKS_CAPTURE[3] = 1; + PAL_BB_TIMER->TASKS_CAPTURE[3] = 1; /* see if current time is already past the TX/RX trigger point */ - if ((NRF_TIMER0->CC[0] - NRF_TIMER0->CC[3]) & 0x80000000) + if ((PAL_BB_TIMER->CC[0] - PAL_BB_TIMER->CC[3]) & 0x80000000) { /* disable the PPI channel... which was just enabled */ NRF_PPI->CHENCLR = PPI_CHENCLR_CH14_Msk; /* COMPARE[0] -> TXEN/RXEN */ @@ -2825,6 +3023,17 @@ void BbBleDrvRadioIRQHandler(void) driverState = IDLE_STATE; BB_LED_OFF(); + /* Workaround for TX idle failure in Coded PHY */ + /* TODO: add max attempts */ + while (NRF_RADIO->STATE != RADIO_STATE_STATE_Disabled) + { + /* Workaround for TX idle failure in Coded PHY */ + NRF_RADIO->TASKS_RXEN = 1; + + /* disable the radio, start early at the top here */ + NRF_RADIO->TASKS_DISABLE = 1; + } + /* run callback function */ palBbRestoreTrl(); bbTxCallback(BB_STATUS_SUCCESS); @@ -2838,32 +3047,40 @@ void BbBleDrvRadioIRQHandler(void) uint32_t timestamp; uint32_t timestampUsesc; int8_t rssi; - uint8_t pduLen; #if defined(NRF52840_XXAA) - uint8_t byteRate; int32_t correction; #endif /* get the PDU payload length from received packet, used later to compute start timestamp */ - pduLen = bbpRxBuf[1]; + uint8_t pduLen = bbpRxBuf[BB_DATA_PDU_LEN_OFFSET]; + + if (bbDecryptRxFlag) + { + /* disable PPI between RADIO->EVENTS_ADDRESS and CCM->TASKS_CRYPT */ + NRF_PPI->CHENCLR = PPI_CHENSET_CH25_Msk; + + if (pduLen) + { + /* shift Rx data to remove NRF CCM RFU byte */ + memcpy(&bbpRxBuf[ENC_RFU_OFFSET], &bbpRxBuf[ENC_RFU_OFFSET+ENC_RFU_LEN], pduLen); + } + } /* * Calculate the 'start' timestamp. It is "antenna time" of the first packet bit. * - * The timestamp is derived from the a previous timer capture (held in CC[2]) that occurred at PAYLOAD event. - * It calculated by subtracting back from payload complete to the packet start. + * The timestamp is derived from the a previous timer capture (held in CC[4]) that occurred at ADDRESS event. + * It calculated by subtracting back from preamble and AA to the packet start. * * The PDU payload length was retrieved from the incoming buffer of the last receive packet. */ - timestamp = NRF_TIMER0->CC[2] - (TICKS_PER_USEC * NRF5x_PROP_DELAY_RX_USECS); + timestamp = PAL_BB_TIMER->CC[4] - (TICKS_PER_USEC * NRF5x_PROP_DELAY_RX_USECS); switch(bbRxPhy) { case BB_PHY_BLE_1M: timestamp -= (TICKS_PER_USEC * LL_BLE_US_PER_BYTE_1M * ( LL_PREAMBLE_LEN_1M + /* preamble */ - LL_AA_LEN + /* address */ - PDU_HEADER_LEN + /* PDU header */ - pduLen )); /* PDU payload */ + LL_AA_LEN)); /* address */ #if defined(NRF52840_XXAA) timestamp -= (2 * TICKS_PER_USEC); /* Adjustment based on the sniffer trace observation. */ @@ -2871,9 +3088,7 @@ void BbBleDrvRadioIRQHandler(void) break; case BB_PHY_BLE_2M: timestamp -= (TICKS_PER_USEC * LL_BLE_US_PER_BYTE_2M * ( LL_PREAMBLE_LEN_2M + /* preamble */ - LL_AA_LEN + /* address */ - PDU_HEADER_LEN + /* PDU header */ - pduLen )); /* PDU payload */ + LL_AA_LEN)); /* address */ #if defined(NRF52840_XXAA) timestamp += (3 * TICKS_PER_USEC); /* Adjustment based on the sniffer trace observation. */ @@ -2881,14 +3096,9 @@ void BbBleDrvRadioIRQHandler(void) break; #if defined(NRF52840_XXAA) case BB_PHY_BLE_CODED: - byteRate = (bbRxPhyOptions == BB_PHY_OPTIONS_BLE_S2) ? LL_BLE_US_PER_BYTE_CODED_S2 : LL_BLE_US_PER_BYTE_CODED_S8; - correction = (bbRxPhyOptions == BB_PHY_OPTIONS_BLE_S2) ? 20 : 160; + correction = (bbRxPhyOptions == BB_PHY_OPTIONS_BLE_S2) ? 5 : 40; timestamp -= (TICKS_PER_USEC * LL_BLE_US_PER_BIT_CODED_S8 * ( LL_PREAMBLE_LEN_CODED_BITS + /* preamble */ - LL_AA_LEN * 8 + /* address */ - LL_CI_LEN_BITS + /* CI */ - LL_TERM1_LEN_BITS) + /* TERM1 */ - TICKS_PER_USEC * byteRate * ( PDU_HEADER_LEN + /* PDU header */ - pduLen )); /* PDU payload */ + LL_AA_LEN * 8 )); /* address */ timestamp -= TICKS_PER_USEC * correction; /* Empirical value */ /* Adjustment based on the sniffer trace observation. */ @@ -2897,12 +3107,9 @@ void BbBleDrvRadioIRQHandler(void) #endif default: timestamp -= (TICKS_PER_USEC * LL_BLE_US_PER_BYTE_1M * ( LL_PREAMBLE_LEN_1M + /* preamble */ - LL_AA_LEN + /* address */ - PDU_HEADER_LEN + /* PDU header */ - pduLen )); /* PDU payload */ + LL_AA_LEN)); /* address */ } - #if (USE_RTC_BB_CLK) /* RTC event start time plus timestamp from HFCLK timer. */ timestampUsesc = BB_TICKS_TO_US(bbEventStartTime) + bbDueOffsetUsec + TICKS_TO_USEC(timestamp); @@ -2916,7 +3123,7 @@ void BbBleDrvRadioIRQHandler(void) #endif /* compute RSSI value at antenna end */ - rssi = (int8_t)(-(NRF_RADIO->RSSISAMPLE & 0x7F)) - PalRadioGetRxRfPathComp(); + rssi = (int8_t)(-(NRF_RADIO->RSSISAMPLE & 0x7F)) - palRadioGetTxRfPathComp(); /* update driver state, *before* callback */ driverState = IDLE_STATE; BB_LED_OFF(); @@ -2936,6 +3143,12 @@ void BbBleDrvRadioIRQHandler(void) /* CRC error - run the callback function */ bbRxCallback(BB_STATUS_CRC_FAILED, rssi, NRF_RADIO->RXCRC, timestampUsesc, bbRxPhyOptions); } + else if ((bbDecryptRxFlag) && (pduLen) && + ((NRF_CCM->MICSTATUS & CCM_MICSTATUS_MICSTATUS_Msk) == CCM_MICSTATUS_MICSTATUS_CheckFailed)) + { + /* MIC error - run the callback function */ + bbRxCallback(BB_STATUS_MIC_FAILED, rssi, NRF_RADIO->RXCRC, timestampUsesc, bbRxPhyOptions); + } else { /* Success! - run the callback function */ @@ -2997,8 +3210,8 @@ void PalBbBleCancelData(void) BB_ASSERT(driverState != SLEEP_STATE); /* driver cannot be asleep */ /* cancel RX timeout if active */ - NRF_TIMER0->INTENCLR = TIMER_INTENCLR_COMPARE1_Msk; /* disable interrupt */ - NVIC_ClearPendingIRQ(TIMER0_IRQn); /* just in case we are running in interrupt context above TIMER0 */ + PAL_BB_TIMER->INTENCLR = TIMER_INTENCLR_COMPARE1_Msk; /* disable interrupt */ + NVIC_ClearPendingIRQ(PAL_BB_IRQn); /* just in case we are running in interrupt context above TIMER0 */ /* stop radio */ palBbRadioHardStop(); @@ -3076,7 +3289,7 @@ static void palBbRadioHardStop(void) /* wait for radio to complete shutdown */ /////////////////////////////////////////////////////////////////////////////// - #if BB_ASSERT_ENABLED == TRUE + #if BB_ENABLE_ASSERT == TRUE uint8_t busycount = 0; BB_ASSERT(busycount < 10); /* radio got stuck */ busycount++; @@ -3088,6 +3301,12 @@ static void palBbRadioHardStop(void) *(volatile uint32_t *)0x4000173C &= ~0x80000000; #endif + if (bbDecryptRxFlag) + { + /* disable PPI between RADIO->EVENTS_ADDRESS and CCM->TASKS_CRYPT */ + NRF_PPI->CHENCLR = PPI_CHENSET_CH25_Msk; + } + /* clear all events */ NRF_RADIO->EVENTS_READY = 0; WAIT_FOR_WR_BUF_EMPTY(NRF_RADIO->EVENTS_READY); diff --git a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb_ble_rf.c b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb_ble_rf.c index 4669be5e46..946df7a0f1 100644 --- a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb_ble_rf.c +++ b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb_ble_rf.c @@ -72,12 +72,12 @@ int16_t bbBleRxPathComp = -1280; /*************************************************************************************************/ /*! - * \brief Get receive RF path compensation. + * \brief Get transmit RF path compensation. * * \return Transmit RF path compensation (in 1-dBm units). */ /*************************************************************************************************/ -int8_t PalRadioGetRxRfPathComp(void) +int8_t palRadioGetTxRfPathComp(void) { uint16_t pathCompUnsigned = (uint16_t)(bbBleTxPathComp - BB_BLE_MIN_PATH_COMP); @@ -195,7 +195,7 @@ int8_t PalRadioGetActualTxPower(int8_t txPwr, bool_t compFlag) if (compFlag) { - txPwr += PalRadioGetRxRfPathComp(); + txPwr += palRadioGetTxRfPathComp(); } return txPwr; diff --git a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_cfg.c b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_cfg.c index ecbb81dbd9..0f73518d7a 100644 --- a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_cfg.c +++ b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_cfg.c @@ -6,7 +6,7 @@ * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * - * Copyright (c) 2019-2020 Packetcraft, Inc. + * Copyright (c) 2019-2021 Packetcraft, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,13 +23,24 @@ /*************************************************************************************************/ #include "pal_cfg.h" +#include "pal_io_exp.h" +#include "pal_sys.h" + #include "nrf.h" +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief convert uint32_t to little endian byte stream, incrementing four bytes. */ +#define PAL_UINT32_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8); \ + *(p)++ = (uint8_t)((n) >> 16); *(p)++ = (uint8_t)((n) >> 24);} + /************************************************************************************************** Type Definitions **************************************************************************************************/ -/*! \brief LL configuration. */ +/*! \brief LL configuration (format must match LlRtCfg_t). */ typedef struct { /* Advertiser */ @@ -54,26 +65,28 @@ typedef struct uint8_t numIsoRxBuf; /*!< Default number of ISO receive buffers. */ uint16_t maxIsoSduLen; /*!< Maximum ISO buffer size between host and controller. */ uint16_t maxIsoPduLen; /*!< Maximum ISO PDU size between controllers. */ - /* CIS */ uint8_t maxCig; /*!< Maximum number of CIG. */ uint8_t maxCis; /*!< Maximum number of CIS, it is shared by the CIGs. */ uint16_t cisSubEvtSpaceDelay; /*!< Subevent spacing above T_MSS. */ - /* BIS*/ uint8_t maxBig; /*!< Maximum number of BIG. */ uint8_t maxBis; /*!< Maximum number of BIS. */ /* DTM */ uint16_t dtmRxSyncMs; /*!< DTM Rx synchronization window in milliseconds. */ + /* Power control */ + int8_t pcHighThreshold; /*!< High RSSI threshold for power monitoring. */ + int8_t pcLowThreshold; /*!< Low RSSI threshold for power monitoring. */ } PalCfgLl_t; /************************************************************************************************** - Macros + Local Variables **************************************************************************************************/ -/*! \brief convert uint32_t to little endian byte stream, incrementing four bytes. */ -#define PAL_UINT32_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8); \ - *(p)++ = (uint8_t)((n) >> 16); *(p)++ = (uint8_t)((n) >> 24);} +#if (AUDIO_CAPE) +/*! \brief Bootstrap configuration. */ +static uint32_t palCfgBootStrapCfg; +#endif /************************************************************************************************** Functions @@ -110,7 +123,7 @@ void palCfgGetBlePhyFeatures(uint8_t *pPhy2mSup, uint8_t *pPhyCodedSup, * \param pConfig Return configuration values. */ /*************************************************************************************************/ -void palCfgLoadLlParams(uint8_t *pConfig) +static void palCfgLoadLlParams(uint8_t *pConfig) { PalCfgLl_t *pCfg = (PalCfgLl_t *)pConfig; @@ -120,25 +133,22 @@ void palCfgLoadLlParams(uint8_t *pConfig) const uint16_t aclDataLen = 256; const uint16_t maxConn = 1; const uint16_t maxGroup = 1; - const uint16_t maxStream = 2; #elif !defined(NRF52840_XXAA) const uint16_t maxAdvSets = 1; const uint16_t advDataLen = 512; const uint16_t aclDataLen = 512; const uint16_t maxConn = 1; const uint16_t maxGroup = 1; - const uint16_t maxStream = 2; #else /* Default */ - const uint16_t maxAdvSets = 6; - const uint16_t advDataLen = 1650; + const uint16_t maxAdvSets = 4; + const uint16_t advDataLen = 512; const uint16_t aclDataLen = 512; - const uint16_t maxConn = 4; + const uint16_t maxConn = 2; const uint16_t maxGroup = 2; - const uint16_t maxStream = 6; #endif pCfg->maxAdvSets = maxAdvSets; - pCfg->maxAdvReports = 8; + pCfg->maxAdvReports = 4; pCfg->maxExtAdvDataLen = advDataLen; /* pCfg->defExtAdvDataFragLen */ /* Use default. */ pCfg->auxDelayUsec = 0; @@ -146,17 +156,19 @@ void palCfgLoadLlParams(uint8_t *pConfig) pCfg->maxExtScanDataLen = advDataLen; pCfg->maxConn = maxConn; pCfg->maxAclLen = aclDataLen; - pCfg->numTxBufs = 16; - pCfg->numRxBufs = 8; - pCfg->numIsoTxBuf = 16; - pCfg->numIsoRxBuf = 8; + pCfg->numTxBufs = 4; + pCfg->numRxBufs = 4; + pCfg->numIsoTxBuf = 6; + pCfg->numIsoRxBuf = 4; pCfg->maxIsoSduLen = aclDataLen; pCfg->maxIsoPduLen = 251; pCfg->maxCig = maxGroup; - pCfg->maxCis = maxStream; + pCfg->maxCis = 2; pCfg->cisSubEvtSpaceDelay = 0; pCfg->maxBig = maxGroup; - pCfg->maxBis = maxStream; + pCfg->maxBis = 4; + /* pCfg->pcHighThreshold */ /* Use default. */ + /* pCfg->pcLowThreshold */ /* Use default. */ } /*************************************************************************************************/ @@ -166,7 +178,7 @@ void palCfgLoadLlParams(uint8_t *pConfig) * \param pDevAddr device address. */ /*************************************************************************************************/ -void palCfgLoadBdAddress(uint8_t *pDevAddr) +static void palCfgLoadBdAddress(uint8_t *pDevAddr) { unsigned int devAddrLen = 6; @@ -191,7 +203,7 @@ void palCfgLoadBdAddress(uint8_t *pDevAddr) * \param pDevAddr device address. */ /*************************************************************************************************/ -void palCfgLoadExtMac154Address(uint8_t *pDevAddr) +static void palCfgLoadExtMac154Address(uint8_t *pDevAddr) { unsigned int devAddrLen = 8; @@ -227,7 +239,7 @@ void PalCfgSetDeviceUuid(uint8_t *pBuf) * \param pDevUuid Return device UUID. */ /*************************************************************************************************/ -void palCfgLoadDeviceUuid(uint8_t *pDevUuid) +static void palCfgLoadDeviceUuid(uint8_t *pDevUuid) { uint8_t *pPtr = pDevUuid; @@ -245,6 +257,46 @@ void palCfgLoadDeviceUuid(uint8_t *pDevUuid) pDevUuid[8] = ((pDevUuid[8] & 0x3F) | 0x80); } +#if (AUDIO_CAPE) +/*************************************************************************************************/ +/*! + * \brief I/O expander read callback. + */ +/*************************************************************************************************/ +static void palCfgDipSwitchReadCback(uint32_t value) +{ + palCfgBootStrapCfg = value; +} + +/*************************************************************************************************/ +/*! + * \brief Load bootstrap settings. + */ +/*************************************************************************************************/ +void palCfgLoadBootStrap(uint32_t *pCfg) +{ + const uint8_t DIP_SW_IO_EXP_ADDR = 6; + const uint32_t DIP_SW_INPUT_MASK = 0x000000FF; + + PalIoExpConfig_t palIoExpCfg = + { + .addr = DIP_SW_IO_EXP_ADDR, + .inputMask = DIP_SW_INPUT_MASK, + .rdCback = palCfgDipSwitchReadCback + }; + + uint8_t palIoExpId = PalIoExpInit(&palIoExpCfg); + PAL_SYS_ASSERT(palIoExpId != PAL_IO_EXP_INVALID_ID); + + PalIoExpRead(palIoExpId); + while (PalIoExpGetState(palIoExpId) == PAL_IO_EXP_STATE_BUSY); + + PalIoExpDeInit(); + + *pCfg = palCfgBootStrapCfg; +} +#endif + /*************************************************************************************************/ /*! * \brief Load device UUID. @@ -280,6 +332,12 @@ void PalCfgLoadData(uint8_t cfgId, void *pBuf, uint32_t len) palCfgLoadDeviceUuid(pBuf); break; +#if (AUDIO_CAPE) + case PAL_CFG_ID_BOOTSTRAP: + palCfgLoadBootStrap((uint32_t *)pBuf); + break; +#endif + default: break; } diff --git a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_crypto.c b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_crypto.c index dd012a505a..259c8c3ef7 100644 --- a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_crypto.c +++ b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_crypto.c @@ -24,6 +24,7 @@ #include "pal_crypto.h" #include "pal_bb_ble.h" +#include "pal_sys.h" #include /* Nordic specific definitions. */ @@ -640,9 +641,10 @@ void PalCryptoAesEnable(PalCryptoEnc_t *pEnc, uint8_t id, uint8_t localDir) { unsigned int mode; + PAL_SYS_ASSERT(id > PAL_CRYPTO_MAX_ID); if (id > PAL_CRYPTO_MAX_ID) { - /* TODO handle error condition */ + /* Ensure out of bounds memory access does not occur. */ return; } @@ -946,33 +948,3 @@ void PalCryptoDeInit(void) } #endif - -/*************************************************************************************************/ -/*! - * \brief Set the encrypt nonce packet counter field. - * - * \param pEnc Encryption parameters. - * \param pktCnt Counter value. - */ -/*************************************************************************************************/ -#if (BB_ENABLE_INLINE_ENC_TX) -void PalCryptoSetEncryptPacketCount(PalCryptoEnc_t *pEnc, uint64_t pktCnt) -{ - PalBbBleInlineEncryptSetPacketCount(pktCnt); -} -#endif - -/*************************************************************************************************/ -/*! - * \brief Set the decrypt nonce packet counter field. - * - * \param pEnc Encryption parameters. - * \param pktCnt Counter value. - */ -/*************************************************************************************************/ -#if (BB_ENABLE_INLINE_DEC_RX) -void PalCryptoSetDecryptPacketCount(PalCryptoEnc_t *pEnc, uint64_t pktCnt) -{ - /* TODO */ -} -#endif diff --git a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_frc.c b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_frc.c new file mode 100644 index 0000000000..3aa356e9ec --- /dev/null +++ b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_frc.c @@ -0,0 +1,207 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief FRC implementation. + * + * Low power Free Running Clock. A monotonically increasing 32-bit free running counter which + * can count even when the system is in low power states. + * + * Copyright (c) 2019-2020 Packetcraft, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ + +#include "pal_frc.h" +#include "pal_led.h" +#include "pal_sys.h" + +#include "nrfx_rtc.h" +#include "nrfx_clock.h" + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/* \brief Ticks per seconds. */ +#define PAL_FRC_TICKS_PER_SEC NRFX_RTC_DEFAULT_CONFIG_FREQUENCY + +/* \brief Maximum FRC time. */ +#define PAL_FRC_MAX_TIME 0x00FFFFFF + +/* \brief RTC channel used for wakeup. */ +#define PAL_FRC_WAKEUP_CHAN NRFX_RTC_INT_COMPARE0 + +/* \brief Maximum allowed timer value in milliseconds (511,999 ms). */ +#define PAL_FRC_MAX_WAKEUP_MS (PAL_FRC_MAX_TIME / PAL_FRC_TICKS_PER_SEC * 1000) + +/* \brief Maximum allowed timer value in microseconds (511,999,969 us). */ +#define PAL_FRC_MAX_WAKEUP_US (PAL_FRC_MAX_TIME / PAL_FRC_TICKS_PER_SEC * 1000000) + +/************************************************************************************************** + Local Variables +**************************************************************************************************/ + +/*! \brief RTC control block. */ +#if NRFX_RTC1_ENABLED +static const nrfx_rtc_t palFrcRtcInst = NRFX_RTC_INSTANCE(1); +#elif NRFX_RTC2_ENABLED +static const nrfx_rtc_t palFrcRtcInst = NRFX_RTC_INSTANCE(2); +#endif + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Set wakeup timer. + */ +/*************************************************************************************************/ +void palFrcSetWakeup(uint32_t nextWakeMs) +{ + PAL_SYS_ASSERT(nextWakeMs < PAL_FRC_MAX_WAKEUP_MS); + + uint32_t nextWake = NRFX_RTC_US_TO_TICKS(nextWakeMs * UINT64_C(1000), UINT64_C(PAL_FRC_TICKS_PER_SEC)); + uint32_t wakeTime = nrfx_rtc_counter_get(&palFrcRtcInst) + nextWake; + + nrfx_rtc_cc_set(&palFrcRtcInst, PAL_FRC_WAKEUP_CHAN, wakeTime, true); +} + +/*************************************************************************************************/ +/*! + * \brief Clear wakeup timer. + */ +/*************************************************************************************************/ +void palFrcClearWakeup(void) +{ + nrfx_rtc_cc_disable(&palFrcRtcInst, PAL_FRC_WAKEUP_CHAN); +} + +/*************************************************************************************************/ +/*! + * \brief Clock event handler. + */ +/*************************************************************************************************/ +static void palFrcWakeupClockEvent(nrfx_clock_evt_type_t event) +{ + /* No action require; ISR used to wakeup CPU. */ +} + +/*************************************************************************************************/ +/*! + * \brief RTC event handler. + */ +/*************************************************************************************************/ +static void palFrcWakeupRtcEvent(nrfx_rtc_int_type_t int_type) +{ + switch (int_type) + { + case PAL_FRC_WAKEUP_CHAN: + /* No action require; ISR used to wakeup CPU. */ + break; + default: + break; + } +} + +/************************************************************************************************** + Public Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief FRC initialization. + */ +/*************************************************************************************************/ + +void PalFrcInit(void) +{ + nrfx_err_t err; + (void)err; + + err = nrfx_clock_init(palFrcWakeupClockEvent); + PAL_SYS_ASSERT(err == NRFX_SUCCESS); + nrfx_clock_enable(); + nrfx_clock_lfclk_start(); + while (!nrfx_clock_lfclk_is_running()) { }; + + nrfx_rtc_config_t cfg = NRFX_RTC_DEFAULT_CONFIG; + err = nrfx_rtc_init(&palFrcRtcInst, &cfg, palFrcWakeupRtcEvent); + PAL_SYS_ASSERT(err == NRFX_SUCCESS); + nrfx_rtc_enable(&palFrcRtcInst); + nrfx_rtc_counter_clear(&palFrcRtcInst); + nrfx_rtc_tick_enable(&palFrcRtcInst, false); +} + +/*************************************************************************************************/ +/*! + * \brief Get current time. + * + * \return FRC time. + * + * \note Caution must be taken when performing calculations with FRC time. FRC value bit width + * and resolution may vary. + */ +/*************************************************************************************************/ +uint32_t PalFrcGetCurrentTime(void) +{ + return nrfx_rtc_counter_get(&palFrcRtcInst); +} + +/*************************************************************************************************/ +/*! + * \brief Convert time in milliseconds to FRC ticks. + * + * \param deltaMs Time in milliseconds. + * + * \return Conversation of \a deltaMs to FRC ticks. + */ +/*************************************************************************************************/ +uint32_t PalFrcMsToTicks(uint32_t timeMs) +{ + return timeMs * PAL_FRC_TICKS_PER_SEC / 1000; +} + +/*************************************************************************************************/ +/*! + * \brief Compute delta time in milliseconds. + * + * \param endTime FRC end time. + * \param startTime FRC start time. + * + * \return Delta time in milliseconds. + */ +/*************************************************************************************************/ +uint32_t PalFrcDeltaMs(uint32_t endTime, uint32_t startTime) +{ + uint32_t deltaTime = (endTime - startTime) & PAL_FRC_MAX_TIME; + return deltaTime * UINT64_C(1000) / PAL_FRC_TICKS_PER_SEC; +} + +/*************************************************************************************************/ +/*! + * \brief Compute delta time in microseconds. + * + * \param endTime FRC end time. + * \param startTime FRC start time. + * + * \return Delta time in microseconds. + */ +/*************************************************************************************************/ +uint32_t PalFrcDeltaUs(uint32_t endTime, uint32_t startTime) +{ + uint32_t deltaTime = (endTime - startTime) & PAL_FRC_MAX_TIME; + return deltaTime * UINT64_C(1000000) / PAL_FRC_TICKS_PER_SEC; +} diff --git a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_timer.c b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_timer.c index cf4ceeaf21..dede67c0a8 100644 --- a/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_timer.c +++ b/connectivity/drivers/ble/FEATURE_BLE/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_timer.c @@ -26,7 +26,7 @@ * Notes: * * This is timer driver used for scheduler and other low power related tasks. - * It has dependency on pal_rtc.c, and some scheduler and BB API due to the complexity explained below. + * It has dependency on PAL API, and some scheduler and BB API due to the complexity explained below. * This is not ideal and should be fixed later. * * If SCH_TIMER_REQUIRED == FALSE: @@ -36,7 +36,7 @@ * RTC1 timer(channel 3) is in use for scheduler. * * If SCH_TIMER_REQUIRED == TRUE and BB_CLK_RATE_HZ == 1MHz or 8MHz: - * Timer1 is in used for scheduler. + * Timer2 is in used for scheduler. * * RTC1 timer(Channel 0) is required for wsf software timer no matter what options are chosen. * @@ -62,6 +62,8 @@ #include "nrf.h" #include "nrf_gpio.h" +#include "mbed_nrf5x_adaptation.h" + /************************************************************************************************** Macros **************************************************************************************************/ @@ -75,6 +77,9 @@ #define PAL_TIMER_TICKS_TO_US(ticks) (ticks) #endif +/*! \brief 23 RTC ticks time(700us) for xtal start up befor scheduler load. */ +#define PAL_HFCLK_OSC_SETTLE_TICKS (23) + #ifdef DEBUG /*! \brief Parameter and state check. */ @@ -101,6 +106,8 @@ #define RTC_CHANNEL_START_HFCLK 2 #define RTC_CHANNEL_START_BB 3 +/* for nRF52, stall until write buffer empties */ +#define WAIT_FOR_WR_BUF_EMPTY(r) ((void)r) /************************************************************************************************** Global Variables @@ -111,9 +118,10 @@ static struct { PalTimerState_t state; /*!< State. */ uint32_t compareVal; /*!< Absolute compare value for timer expiry interrupt. */ - PalTimerCompCback_t expCback; /*!< Timer expiry call back function. */ } palTimerCb; +PalTimerCompCback_t palTimerExpCback; /*!< Timer expiry call back function. */ + /* Nordic specific internal functions. */ extern void PalRtcIrqRegister(uint8_t channelId, palRtcIrqCback_t cback); extern void PalRtcClearCompareEvents(uint8_t channelId); @@ -134,9 +142,9 @@ static void palTimerRtcIrqHandler(void) palTimerCb.state = PAL_TIMER_STATE_READY; - if (palTimerCb.expCback) + if (palTimerExpCback) { - palTimerCb.expCback(); + palTimerExpCback(); } #ifdef DEBUG @@ -163,9 +171,9 @@ static uint32_t palTimerGetCurrentTime(void) return PalRtcCounterGet(); #else /* Capture current TIMER2 count to capture register 1 */ - NRF_TIMER2->TASKS_CAPTURE[TIMER_CHANNEL_READ_TICK] = 1; + PAL_BB_TIMER->TASKS_CAPTURE[TIMER_CHANNEL_READ_TICK] = 1; /* Read and return the captured count value from capture register 1 */ - return NRF_TIMER2->CC[TIMER_CHANNEL_READ_TICK]; + return PAL_BB_TIMER->CC[TIMER_CHANNEL_READ_TICK]; #endif } return 0; @@ -192,33 +200,33 @@ void PalTimerInit(PalTimerCompCback_t expCback) PalRtcIrqRegister(RTC_CHANNEL_START_BB, palTimerRtcIrqHandler); #else /* Give scheduler timer the highest priority. */ - NVIC_SetPriority(TIMER2_IRQn, 0); /* highest priority */ - NVIC_DisableIRQ(TIMER2_IRQn); + NVIC_SetPriority(PAL_BB_IRQn, 0); /* highest priority */ + NVIC_DisableIRQ(PAL_BB_IRQn); /* stop timer if it was somehow running (timer must be stopped for configuration) */ - NRF_TIMER2->TASKS_STOP = 1; + PAL_BB_TIMER->TASKS_STOP = 1; /* clear timer to zero count */ - NRF_TIMER2->TASKS_CLEAR = 1; + PAL_BB_TIMER->TASKS_CLEAR = 1; /* configure timer */ - NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer; - NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_32Bit; - NRF_TIMER2->PRESCALER = PAL_TIMER_1MHZ_PRESCALER; /* f = 16MHz / (2 ^ TIMER_PRESCALER) */ + PAL_BB_TIMER->MODE = TIMER_MODE_MODE_Timer; + PAL_BB_TIMER->BITMODE = TIMER_BITMODE_BITMODE_32Bit; + PAL_BB_TIMER->PRESCALER = PAL_TIMER_1MHZ_PRESCALER; /* f = 16MHz / (2 ^ TIMER_PRESCALER) */ /* timer1 is a free running clock. */ - NRF_TIMER2->TASKS_START = 1; + PAL_BB_TIMER->TASKS_START = 1; /* Clear out and enable timer1 interrupt at system level. */ - NRF_TIMER2->INTENCLR = 0xFFFFFFFF; - NRF_TIMER2->EVENTS_COMPARE[TIMER_CHANNEL_START_BB] = 0; - NVIC_ClearPendingIRQ(TIMER2_IRQn); - NVIC_EnableIRQ(TIMER2_IRQn); + PAL_BB_TIMER->INTENCLR = 0xFFFFFFFF; + PAL_BB_TIMER->EVENTS_COMPARE[TIMER_CHANNEL_START_BB] = 0; + NVIC_ClearPendingIRQ(PAL_BB_IRQn); + NVIC_EnableIRQ(PAL_BB_IRQn); #endif #endif palTimerCb.compareVal = 0; - palTimerCb.expCback = expCback; + palTimerExpCback = expCback; palTimerCb.state = PAL_TIMER_STATE_READY; } @@ -231,11 +239,11 @@ void PalTimerDeInit(void) { #if SCH_TIMER_REQUIRED == TRUE #if BB_CLK_RATE_HZ != 32768 - NVIC_DisableIRQ(TIMER2_IRQn); + NVIC_DisableIRQ(PAL_BB_IRQn); /* stop timer */ - NRF_TIMER2->TASKS_STOP = 1; - NRF_TIMER2->TASKS_SHUTDOWN = 1; + PAL_BB_TIMER->TASKS_STOP = 1; + PAL_BB_TIMER->TASKS_SHUTDOWN = 1; #endif #endif @@ -254,11 +262,41 @@ PalTimerState_t PalTimerGetState(void) return palTimerCb.state; } +/*************************************************************************************************/ +/*! + * \brief Get time to the next timer expiration. + * + * \return Time to next expiration in microseconds; 0 if no timer is set.. + */ +/*************************************************************************************************/ +uint32_t PalTimerGetTimeToNextExpiration(void) +{ + if (palTimerCb.state == PAL_TIMER_STATE_BUSY) + { + uint32_t currentTime = PalBbGetCurrentTime(); + if (currentTime < palTimerCb.compareVal) + { + /* Return the number of usecs to the next timer expiration. */ + return palTimerCb.compareVal - PalBbGetCurrentTime(); + } + else + { + /* Next timer expiration is in the past. */ + return 1; + } + } + else + { + /* No timer is active. */ + return 0; + } +} + /*************************************************************************************************/ /*! * \brief Start the scheduler timer. * - * \param expTimeUsec Set timer expiry in microseconds. + * \param expTimeUsec Absolute expiration time. */ /*************************************************************************************************/ void PalTimerStart(uint32_t expTimeUsec) @@ -267,42 +305,41 @@ void PalTimerStart(uint32_t expTimeUsec) PAL_TIMER_CHECK(expTimeUsec != 0); #if SCH_TIMER_REQUIRED == TRUE + uint32_t startTimeTick = palTimerGetCurrentTime() + PAL_TIMER_US_TO_TICKS(expTimeUsec); + #if BB_CLK_RATE_HZ == 32768 - uint32_t startTimeTick = palTimerGetCurrentTime() + PAL_TIMER_US_TO_TICKS(expTimeUsec); + /* Set compare value to start BB. */ + PalRtcCompareSet(RTC_CHANNEL_START_BB, startTimeTick); - /* Set compare value to start BB. */ - PalRtcCompareSet(RTC_CHANNEL_START_BB, startTimeTick); - /* Enable RTC interrupt source to start BB. */ - PalRtcEnableCompareIrq(RTC_CHANNEL_START_BB); + /* Enable RTC interrupt source to start BB. */ + PalRtcEnableCompareIrq(RTC_CHANNEL_START_BB); - /* Set compare value to start HFCLK. */ + /* Set compare value to start HFCLK. */ + uint32_t startHFCLKTick = (startTimeTick - PAL_HFCLK_OSC_SETTLE_TICKS) & PAL_MAX_RTC_COUNTER_VAL; - uint32_t startHFCLKTick = (startTimeTick - PAL_HFCLK_OSC_SETTLE_TICKS) & PAL_MAX_RTC_COUNTER_VAL; - - PalRtcClearCompareEvents(RTC_CHANNEL_START_HFCLK); - PalRtcCompareSet(RTC_CHANNEL_START_HFCLK, startHFCLKTick); - #else - uint32_t startTimeTick = palTimerGetCurrentTime() + PAL_TIMER_US_TO_TICKS(expTimeUsec); - - /* Clear pending events. */ - NRF_TIMER2->EVENTS_COMPARE[TIMER_CHANNEL_START_BB] = 0; + PalRtcClearCompareEvents(RTC_CHANNEL_START_HFCLK); + PalRtcCompareSet(RTC_CHANNEL_START_HFCLK, startHFCLKTick); + #else + /* Clear pending events. */ + PAL_BB_TIMER->EVENTS_COMPARE[PAL_BB_IRQ_EXPIRY_CHANNEL] = 0; + WAIT_FOR_WR_BUF_EMPTY(PAL_BB_TIMER->EVENTS_COMPARE[PAL_BB_IRQ_EXPIRY_CHANNEL]); /* Set compare value. */ - NRF_TIMER2->CC[TIMER_CHANNEL_START_BB] = startTimeTick; + PAL_BB_TIMER->CC[PAL_BB_IRQ_EXPIRY_CHANNEL] = startTimeTick; - /* Enable timer1 interrupt source for CC[0]. */ - NRF_TIMER2->INTENSET = TIMER_INTENSET_COMPARE0_Msk; - #endif + /* Enable timer1 interrupt source for CC[PAL_BB_IRQ_EXPIRY_CHANNEL]. */ + PAL_BB_TIMER->INTENSET = PAL_BB_TIMER_EXPIRY_INTENSET_MASK; + #endif // BB_CLK_RATE_HZ - palTimerCb.compareVal = startTimeTick; - palTimerCb.state = PAL_TIMER_STATE_BUSY; + palTimerCb.compareVal = startTimeTick; + palTimerCb.state = PAL_TIMER_STATE_BUSY; #else (void)expTimeUsec; - if (BbGetCurrentBod() == NULL) + if (BbGetCurrentBod() == NULL && palTimerExpCback) { - SchLoadHandler(); + palTimerExpCback(); } - #endif + #endif // SCH_TIMER_REQUIRED } /*************************************************************************************************/ @@ -318,45 +355,13 @@ void PalTimerStop() PalRtcDisableCompareIrq(RTC_CHANNEL_START_BB); #else /* Disable this interrupt */ - NRF_TIMER2->INTENCLR = TIMER_INTENCLR_COMPARE0_Msk; + PAL_BB_TIMER->INTENCLR = PAL_BB_TIMER_EXPIRY_INTENCLR_MASK; #endif palTimerCb.state = PAL_TIMER_STATE_READY; #else BbCancelBod(); #endif -} - -/*************************************************************************************************/ -/*! - * \brief TIMER2 interrupt handler dedicated to scheduler timer. - */ -/*************************************************************************************************/ -void TIMER2_IRQHandler(void) -{ - #ifdef DEBUG - nrf_gpio_pin_set(PAL_TIMER_DEBUG_0_PIN); - #endif - - PAL_TIMER_CHECK(palTimerCb.state == PAL_TIMER_STATE_BUSY); - /* Check hardware status */ - PAL_TIMER_CHECK(NRF_TIMER2->EVENTS_COMPARE[TIMER_CHANNEL_START_BB]); - PAL_TIMER_CHECK(NRF_TIMER2->CC[TIMER_CHANNEL_START_BB] == palTimerCb.compareVal); - PAL_TIMER_CHECK(NRF_TIMER2->INTENSET == TIMER_INTENSET_COMPARE0_Msk); - - /* Callback function could restart timer1. However, we blindly stop timer1 first. */ - NRF_TIMER2->INTENCLR = TIMER_INTENCLR_COMPARE0_Msk; - /* Clear event again just in case. */ - NRF_TIMER2->EVENTS_COMPARE[TIMER_CHANNEL_START_BB] = 0; palTimerCb.state = PAL_TIMER_STATE_READY; - - if (palTimerCb.expCback) - { - palTimerCb.expCback(); - } - - #ifdef DEBUG - nrf_gpio_pin_clear(PAL_TIMER_DEBUG_0_PIN); - #endif } diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.c index 8d3ad4ba56..632bdf4b40 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.c +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.c @@ -109,11 +109,11 @@ __STATIC_INLINE void errata_20(void) { } } - NRF_RTC1->TASKS_STOP = 0; + COMMON_RTC_INSTANCE->TASKS_STOP = 0; #endif } -void RTC1_IRQHandler(void); +void COMMON_RTC_IRQ_HANDLER(void); void common_rtc_init(void) { @@ -129,7 +129,7 @@ void common_rtc_init(void) nrf_rtc_task_trigger(COMMON_RTC_INSTANCE, NRF_RTC_TASK_STOP); - NVIC_SetVector(RTC1_IRQn, (uint32_t)RTC1_IRQHandler); + NVIC_SetVector(COMMON_RTC_IRQn, (uint32_t)COMMON_RTC_IRQ_HANDLER); /* RTC is driven by the low frequency (32.768 kHz) clock, a proper request * must be made to have it running. @@ -228,15 +228,6 @@ void common_rtc_set_interrupt(uint32_t ticks_count, uint32_t cc_channel, #include "mbed_toolchain.h" - -#define MAX_RTC_COUNTER_VAL ((1uL << RTC_COUNTER_BITS) - 1) - -#ifndef RTC1_CONFIG_FREQUENCY - #define RTC1_CONFIG_FREQUENCY 32678 // [Hz] -#endif - - - void COMMON_RTC_IRQ_HANDLER(void) { if(!nrf_rtc_event_pending(COMMON_RTC_INSTANCE, OS_TICK_EVENT)) { diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.h index 45537c44ea..98b49df37a 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.h +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.h @@ -23,11 +23,12 @@ #define RTC_COUNTER_BITS 24u #define RTC_FREQ 32768u -// Instance 0 is reserved for SoftDevice. -// Instance 1 is used as a common one for lp_ticker and (in case +// Instances 1 and 2 are reserved for Cordio +// Instance 0 is used as a common one for lp_ticker and (in case // of NRF51) as an alternative tick source for RTOS. -#define COMMON_RTC_INSTANCE NRF_RTC1 -#define COMMON_RTC_IRQ_HANDLER RTC1_IRQHandler +#define COMMON_RTC_INSTANCE NRF_RTC0 +#define COMMON_RTC_IRQn RTC0_IRQn +#define COMMON_RTC_IRQ_HANDLER RTC0_IRQHandler #define OS_TICK_CC_CHANNEL 0 #define LP_TICKER_CC_CHANNEL 1