From be80c46e9acd17de5f5adae1155921eb094b6ce8 Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Wed, 10 Jun 2020 09:26:28 +0100 Subject: [PATCH] update cordio LL files to 20.05r --- .../stack/controller/include/ble/bb_ble_api.h | 95 +- .../controller/include/ble/bb_ble_api_op.h | 136 +- .../include/ble/bb_ble_api_pdufilt.h | 41 +- .../include/ble/bb_ble_api_periodiclist.h | 39 +- .../include/ble/bb_ble_api_reslist.h | 43 +- .../include/ble/bb_ble_api_whitelist.h | 43 +- .../include/ble/bb_ble_sniffer_api.h | 163 ++ .../stack/controller/include/ble/lhci_api.h | 47 +- .../stack/controller/include/ble/ll_api.h | 1048 +++++++--- .../stack/controller/include/ble/ll_defs.h | 492 ----- .../controller/include/ble/ll_init_api.h | 40 +- .../stack/controller/include/ble/ll_math.h | 51 +- .../controller/include/ble/sch_api_ble.h | 50 +- .../stack/controller/include/common/bb_api.h | 121 +- .../stack/controller/include/common/cfg_mac.h | 44 +- .../controller/include/common/cfg_mac_ble.h | 57 +- .../controller/include/common/chci_api.h | 58 +- .../stack/controller/include/common/chci_tr.h | 52 +- .../stack/controller/include/common/sch_api.h | 39 +- .../sources/ble/bb/bb_ble_adv_master.c | 189 +- .../sources/ble/bb/bb_ble_adv_master_ae.c | 210 +- .../sources/ble/bb/bb_ble_adv_slave.c | 152 +- .../sources/ble/bb/bb_ble_adv_slave_ae.c | 165 +- .../sources/ble/bb/bb_ble_bis_master.c | 201 ++ .../sources/ble/bb/bb_ble_bis_slave.c | 151 ++ .../controller/sources/ble/bb/bb_ble_cis.c | 104 + .../sources/ble/bb/bb_ble_cis_master.c | 344 +++ .../sources/ble/bb/bb_ble_cis_slave.c | 384 ++++ .../controller/sources/ble/bb/bb_ble_conn.c | 57 +- .../sources/ble/bb/bb_ble_conn_master.c | 109 +- .../sources/ble/bb/bb_ble_conn_slave.c | 110 +- .../ble/bb/{bb_ble_test.c => bb_ble_dtm.c} | 76 +- .../controller/sources/ble/bb/bb_ble_int.h | 95 +- .../controller/sources/ble/bb/bb_ble_main.c | 68 +- .../sources/ble/bb/bb_ble_pdufilt.c | 87 +- .../sources/ble/bb/bb_ble_periodiclist.c | 41 +- .../sources/ble/bb/bb_ble_reslist.c | 51 +- .../sources/ble/bb/bb_ble_sniffer.c | 397 ++++ .../sources/ble/bb/bb_ble_whitelist.c | 43 +- .../controller/sources/ble/include/lctr_api.h | 81 +- .../sources/ble/include/lctr_api_adv_acad.h | 85 + .../sources/ble/include/lctr_api_adv_master.h | 37 +- .../ble/include/lctr_api_adv_master_ae.h | 38 +- .../sources/ble/include/lctr_api_adv_slave.h | 37 +- .../ble/include/lctr_api_adv_slave_ae.h | 51 +- .../sources/ble/include/lctr_api_bis_master.h | 102 + .../sources/ble/include/lctr_api_bis_slave.h | 82 + .../sources/ble/include/lctr_api_cis.h | 98 + .../sources/ble/include/lctr_api_cis_master.h | 52 + .../sources/ble/include/lctr_api_cis_slave.h | 50 + .../sources/ble/include/lctr_api_conn.h | 59 +- .../sources/ble/include/lctr_api_conn_cs2.h | 37 +- .../ble/include/lctr_api_init_master.h | 37 +- .../ble/include/lctr_api_init_master_ae.h | 42 +- .../sources/ble/include/lctr_api_iso.h | 60 + .../sources/ble/include/lctr_api_pc.h | 47 + .../sources/ble/include/lctr_api_phy.h | 37 +- .../sources/ble/include/lctr_api_priv.h | 37 +- .../sources/ble/include/lctr_api_sc.h | 37 +- .../controller/sources/ble/include/lmgr_api.h | 49 +- .../sources/ble/include/lmgr_api_adv_master.h | 41 +- .../ble/include/lmgr_api_adv_master_ae.h | 37 +- .../sources/ble/include/lmgr_api_adv_slave.h | 43 +- .../ble/include/lmgr_api_adv_slave_ae.h | 37 +- .../sources/ble/include/lmgr_api_cis_master.h | 72 + .../sources/ble/include/lmgr_api_cis_slave.h | 64 + .../sources/ble/include/lmgr_api_conn.h | 37 +- .../sources/ble/include/lmgr_api_iso.h | 80 + .../sources/ble/include/lmgr_api_priv.h | 37 +- .../sources/ble/include/lmgr_api_sc.h | 37 +- .../stack/controller/sources/ble/init/init.c | 90 +- .../controller/sources/ble/init/init_ctr.c | 58 +- .../sources/ble/lctr/lctr_act_adv_master.c | 57 +- .../sources/ble/lctr/lctr_act_adv_master_ae.c | 184 +- .../sources/ble/lctr/lctr_act_adv_slave.c | 77 +- .../sources/ble/lctr/lctr_act_adv_slave_ae.c | 161 +- .../sources/ble/lctr/lctr_act_bis_master.c | 271 +++ .../sources/ble/lctr/lctr_act_bis_slave.c | 211 ++ .../sources/ble/lctr/lctr_act_cis.c | 538 +++++ .../sources/ble/lctr/lctr_act_cis_master.c | 481 +++++ .../sources/ble/lctr/lctr_act_cis_slave.c | 508 +++++ .../sources/ble/lctr/lctr_act_conn.c | 197 +- .../sources/ble/lctr/lctr_act_conn_master.c | 43 +- .../ble/lctr/lctr_act_conn_master_ae.c | 44 +- .../sources/ble/lctr/lctr_act_conn_past.c | 87 +- .../sources/ble/lctr/lctr_act_enc.c | 89 +- .../sources/ble/lctr/lctr_act_enc_master.c | 43 +- .../sources/ble/lctr/lctr_act_init_master.c | 66 +- .../ble/lctr/lctr_act_init_master_ae.c | 52 +- .../controller/sources/ble/lctr/lctr_act_pc.c | 650 ++++++ .../sources/ble/lctr/lctr_act_phy.c | 53 +- .../controller/sources/ble/lctr/lctr_int.h | 145 +- .../sources/ble/lctr/lctr_int_adv_ae.h | 74 +- .../sources/ble/lctr/lctr_int_adv_master.h | 52 +- .../sources/ble/lctr/lctr_int_adv_master_ae.h | 102 +- .../sources/ble/lctr/lctr_int_adv_slave.h | 39 +- .../sources/ble/lctr/lctr_int_adv_slave_ae.h | 108 +- .../sources/ble/lctr/lctr_int_bis.h | 292 +++ .../sources/ble/lctr/lctr_int_bis_master.h | 99 + .../sources/ble/lctr/lctr_int_bis_slave.h | 95 + .../sources/ble/lctr/lctr_int_cis.h | 535 +++++ .../sources/ble/lctr/lctr_int_cis_master.h | 115 + .../sources/ble/lctr/lctr_int_cis_slave.h | 107 + .../sources/ble/lctr/lctr_int_conn.h | 229 +- .../sources/ble/lctr/lctr_int_conn_master.h | 38 +- .../sources/ble/lctr/lctr_int_conn_slave.h | 37 +- .../sources/ble/lctr/lctr_int_enc_master.h | 37 +- .../sources/ble/lctr/lctr_int_enc_slave.h | 37 +- .../sources/ble/lctr/lctr_int_init_master.h | 37 +- .../ble/lctr/lctr_int_init_master_ae.h | 38 +- .../sources/ble/lctr/lctr_int_iso.h | 263 +++ .../sources/ble/lctr/lctr_int_master_phy.h | 37 +- .../controller/sources/ble/lctr/lctr_int_pc.h | 76 + .../sources/ble/lctr/lctr_int_priv.h | 37 +- .../sources/ble/lctr/lctr_int_slave_phy.h | 37 +- .../sources/ble/lctr/lctr_isr_adv_master.c | 67 +- .../sources/ble/lctr/lctr_isr_adv_master_ae.c | 462 +++-- .../sources/ble/lctr/lctr_isr_adv_slave.c | 81 +- .../sources/ble/lctr/lctr_isr_adv_slave_ae.c | 182 +- .../sources/ble/lctr/lctr_isr_bis_master.c | 937 +++++++++ .../sources/ble/lctr/lctr_isr_bis_slave.c | 771 +++++++ .../sources/ble/lctr/lctr_isr_cis.c | 358 ++++ .../sources/ble/lctr/lctr_isr_cis_master.c | 1205 +++++++++++ .../sources/ble/lctr/lctr_isr_cis_slave.c | 1295 ++++++++++++ .../sources/ble/lctr/lctr_isr_conn.c | 55 +- .../sources/ble/lctr/lctr_isr_conn_master.c | 129 +- .../sources/ble/lctr/lctr_isr_conn_slave.c | 144 +- .../sources/ble/lctr/lctr_isr_init_master.c | 125 +- .../ble/lctr/lctr_isr_init_master_ae.c | 322 ++- .../controller/sources/ble/lctr/lctr_main.c | 201 +- .../sources/ble/lctr/lctr_main_adv_master.c | 73 +- .../ble/lctr/lctr_main_adv_master_ae.c | 335 +-- .../sources/ble/lctr/lctr_main_adv_slave.c | 132 +- .../sources/ble/lctr/lctr_main_adv_slave_ae.c | 274 ++- .../sources/ble/lctr/lctr_main_bis.c | 1426 +++++++++++++ .../sources/ble/lctr/lctr_main_bis_master.c | 517 +++++ .../sources/ble/lctr/lctr_main_bis_slave.c | 966 +++++++++ .../sources/ble/lctr/lctr_main_cis.c | 1843 +++++++++++++++++ .../sources/ble/lctr/lctr_main_cis_master.c | 1127 ++++++++++ .../sources/ble/lctr/lctr_main_cis_slave.c | 416 ++++ .../sources/ble/lctr/lctr_main_conn.c | 444 +++- .../sources/ble/lctr/lctr_main_conn_cs2.c | 39 +- .../sources/ble/lctr/lctr_main_conn_data.c | 105 +- .../sources/ble/lctr/lctr_main_conn_master.c | 192 +- .../sources/ble/lctr/lctr_main_conn_slave.c | 128 +- .../sources/ble/lctr/lctr_main_enc_master.c | 43 +- .../sources/ble/lctr/lctr_main_enc_slave.c | 45 +- .../sources/ble/lctr/lctr_main_init_master.c | 74 +- .../ble/lctr/lctr_main_init_master_ae.c | 79 +- .../sources/ble/lctr/lctr_main_iso.c | 1196 +++++++++++ .../sources/ble/lctr/lctr_main_iso_data.c | 1181 +++++++++++ .../sources/ble/lctr/lctr_main_master_phy.c | 39 +- .../sources/ble/lctr/lctr_main_past.c | 39 +- .../sources/ble/lctr/lctr_main_pc.c | 320 +++ .../sources/ble/lctr/lctr_main_priv.c | 47 +- .../sources/ble/lctr/lctr_main_sc.c | 63 +- .../sources/ble/lctr/lctr_main_slave_phy.c | 39 +- .../sources/ble/lctr/lctr_pdu_adv.h | 37 +- .../sources/ble/lctr/lctr_pdu_adv_ae.h | 45 +- .../sources/ble/lctr/lctr_pdu_adv_master_ae.c | 143 +- .../sources/ble/lctr/lctr_pdu_adv_slave.c | 38 +- .../sources/ble/lctr/lctr_pdu_adv_slave_ae.c | 217 +- .../sources/ble/lctr/lctr_pdu_bis.c | 171 ++ .../sources/ble/lctr/lctr_pdu_conn.c | 141 +- .../sources/ble/lctr/lctr_pdu_conn.h | 72 +- .../sources/ble/lctr/lctr_pdu_enc.c | 37 +- .../sources/ble/lctr/lctr_pdu_iso.c | 242 +++ .../sources/ble/lctr/lctr_pdu_iso.h | 149 ++ .../sources/ble/lctr/lctr_sm_adv_master.c | 39 +- .../sources/ble/lctr/lctr_sm_adv_master_ae.c | 49 +- .../sources/ble/lctr/lctr_sm_adv_slave.c | 39 +- .../sources/ble/lctr/lctr_sm_adv_slave_ae.c | 69 +- .../sources/ble/lctr/lctr_sm_bis_master.c | 168 ++ .../sources/ble/lctr/lctr_sm_bis_slave.c | 129 ++ .../controller/sources/ble/lctr/lctr_sm_cis.c | 169 ++ .../sources/ble/lctr/lctr_sm_conn_master.c | 43 +- .../sources/ble/lctr/lctr_sm_conn_slave.c | 49 +- .../sources/ble/lctr/lctr_sm_init_master.c | 39 +- .../sources/ble/lctr/lctr_sm_init_master_ae.c | 39 +- .../sources/ble/lctr/lctr_sm_llcp_cis.c | 328 +++ .../ble/lctr/lctr_sm_llcp_cis_master.c | 297 +++ .../sources/ble/lctr/lctr_sm_llcp_cis_slave.c | 382 ++++ .../sources/ble/lctr/lctr_sm_llcp_conn.c | 45 +- .../ble/lctr/lctr_sm_llcp_conn_master.c | 67 +- .../ble/lctr/lctr_sm_llcp_conn_slave.c | 75 +- .../ble/lctr/lctr_sm_llcp_enc_master.c | 61 +- .../sources/ble/lctr/lctr_sm_llcp_enc_slave.c | 57 +- .../ble/lctr/lctr_sm_llcp_master_phy.c | 57 +- .../sources/ble/lctr/lctr_sm_llcp_pc.c | 546 +++++ .../sources/ble/lctr/lctr_sm_llcp_slave_phy.c | 81 +- .../controller/sources/ble/lhci/lhci_cmd.c | 50 +- .../sources/ble/lhci/lhci_cmd_adv_master.c | 39 +- .../sources/ble/lhci/lhci_cmd_adv_master_ae.c | 53 +- .../sources/ble/lhci/lhci_cmd_adv_priv.c | 39 +- .../sources/ble/lhci/lhci_cmd_adv_slave.c | 39 +- .../sources/ble/lhci/lhci_cmd_adv_slave_ae.c | 41 +- .../sources/ble/lhci/lhci_cmd_bis_master.c | 90 + .../sources/ble/lhci/lhci_cmd_bis_slave.c | 121 ++ .../sources/ble/lhci/lhci_cmd_cis_master.c | 308 +++ .../sources/ble/lhci/lhci_cmd_cis_slave.c | 138 ++ .../sources/ble/lhci/lhci_cmd_conn.c | 46 +- .../sources/ble/lhci/lhci_cmd_conn_master.c | 39 +- .../ble/lhci/lhci_cmd_conn_master_ae.c | 39 +- .../sources/ble/lhci/lhci_cmd_conn_priv.c | 39 +- .../sources/ble/lhci/lhci_cmd_enc_master.c | 37 +- .../sources/ble/lhci/lhci_cmd_enc_slave.c | 39 +- .../sources/ble/lhci/lhci_cmd_iso.c | 587 ++++++ .../sources/ble/lhci/lhci_cmd_past.c | 37 +- .../controller/sources/ble/lhci/lhci_cmd_pc.c | 215 ++ .../sources/ble/lhci/lhci_cmd_phy.c | 39 +- .../controller/sources/ble/lhci/lhci_cmd_sc.c | 37 +- .../controller/sources/ble/lhci/lhci_cmd_vs.c | 87 +- .../sources/ble/lhci/lhci_cmd_vs_adv_master.c | 37 +- .../ble/lhci/lhci_cmd_vs_adv_master_ae.c | 37 +- .../sources/ble/lhci/lhci_cmd_vs_adv_slave.c | 37 +- .../ble/lhci/lhci_cmd_vs_adv_slave_ae.c | 37 +- .../sources/ble/lhci/lhci_cmd_vs_conn.c | 53 +- .../ble/lhci/lhci_cmd_vs_conn_master.c | 37 +- .../sources/ble/lhci/lhci_cmd_vs_enc_slave.c | 37 +- .../sources/ble/lhci/lhci_cmd_vs_ext.c | 41 - .../sources/ble/lhci/lhci_cmd_vs_iso.c | 164 ++ .../sources/ble/lhci/lhci_cmd_vs_sc.c | 37 +- .../controller/sources/ble/lhci/lhci_evt.c | 41 +- .../sources/ble/lhci/lhci_evt_adv_master.c | 37 +- .../sources/ble/lhci/lhci_evt_adv_master_ae.c | 55 +- .../sources/ble/lhci/lhci_evt_adv_slave.c | 37 +- .../sources/ble/lhci/lhci_evt_adv_slave_ae.c | 41 +- .../sources/ble/lhci/lhci_evt_bis_master.c | 183 ++ .../sources/ble/lhci/lhci_evt_bis_slave.c | 129 ++ .../sources/ble/lhci/lhci_evt_cis_master.c | 115 + .../sources/ble/lhci/lhci_evt_cis_slave.c | 101 + .../sources/ble/lhci/lhci_evt_conn.c | 118 +- .../sources/ble/lhci/lhci_evt_conn_cs2.c | 37 +- .../sources/ble/lhci/lhci_evt_conn_master.c | 37 +- .../sources/ble/lhci/lhci_evt_conn_priv.c | 37 +- .../sources/ble/lhci/lhci_evt_enc_master.c | 37 +- .../sources/ble/lhci/lhci_evt_enc_slave.c | 37 +- .../sources/ble/lhci/lhci_evt_iso.c | 203 ++ .../controller/sources/ble/lhci/lhci_evt_pc.c | 124 ++ .../sources/ble/lhci/lhci_evt_phy.c | 37 +- .../controller/sources/ble/lhci/lhci_evt_sc.c | 37 +- .../controller/sources/ble/lhci/lhci_evt_vs.c | 193 +- .../controller/sources/ble/lhci/lhci_init.c | 41 +- .../sources/ble/lhci/lhci_init_adv_master.c | 39 +- .../ble/lhci/lhci_init_adv_master_ae.c | 39 +- .../sources/ble/lhci/lhci_init_adv_priv.c | 39 +- .../sources/ble/lhci/lhci_init_adv_slave.c | 39 +- .../sources/ble/lhci/lhci_init_adv_slave_ae.c | 39 +- .../sources/ble/lhci/lhci_init_bis_master.c | 40 + .../sources/ble/lhci/lhci_init_bis_slave.c | 40 + .../sources/ble/lhci/lhci_init_cis_master.c | 40 + .../sources/ble/lhci/lhci_init_cis_slave.c | 40 + .../sources/ble/lhci/lhci_init_conn.c | 39 +- .../sources/ble/lhci/lhci_init_conn_cs2.c | 39 +- .../sources/ble/lhci/lhci_init_conn_master.c | 39 +- .../ble/lhci/lhci_init_conn_master_ae.c | 39 +- .../sources/ble/lhci/lhci_init_conn_priv.c | 39 +- .../sources/ble/lhci/lhci_init_enc_master.c | 39 +- .../sources/ble/lhci/lhci_init_enc_slave.c | 39 +- .../sources/ble/lhci/lhci_init_iso.c | 69 + .../sources/ble/lhci/lhci_init_past.c | 39 +- .../sources/ble/lhci/lhci_init_pc.c | 38 + .../sources/ble/lhci/lhci_init_phy.c | 39 +- .../sources/ble/lhci/lhci_init_sc.c | 39 +- .../controller/sources/ble/lhci/lhci_int.h | 124 +- .../controller/sources/ble/lhci/lhci_main.c | 184 +- .../sources/ble/lhci/lhci_main_iso.c | 62 + .../stack/controller/sources/ble/ll/ll_init.c | 79 +- .../sources/ble/ll/ll_init_adv_master.c | 39 +- .../sources/ble/ll/ll_init_adv_master_ae.c | 39 +- .../sources/ble/ll/ll_init_adv_slave.c | 39 +- .../sources/ble/ll/ll_init_adv_slave_ae.c | 39 +- .../sources/ble/ll/ll_init_bis_master.c | 42 + .../sources/ble/ll/ll_init_bis_slave.c | 71 + .../sources/ble/ll/ll_init_cis_master.c | 45 + .../sources/ble/ll/ll_init_cis_slave.c | 73 + .../sources/ble/ll/ll_init_conn_cs2.c | 39 +- .../sources/ble/ll/ll_init_conn_master.c | 39 +- .../sources/ble/ll/ll_init_conn_slave.c | 41 +- .../sources/ble/ll/ll_init_enc_master.c | 39 +- .../sources/ble/ll/ll_init_enc_slave.c | 39 +- .../sources/ble/ll/ll_init_init_master.c | 39 +- .../sources/ble/ll/ll_init_init_master_ae.c | 39 +- .../controller/sources/ble/ll/ll_init_iso.c | 70 + .../sources/ble/ll/ll_init_master_phy.c | 39 +- .../controller/sources/ble/ll/ll_init_past.c | 39 +- .../controller/sources/ble/ll/ll_init_pc.c | 39 + .../controller/sources/ble/ll/ll_init_priv.c | 39 +- .../controller/sources/ble/ll/ll_init_sc.c | 39 +- .../sources/ble/ll/ll_init_slave_phy.c | 39 +- .../stack/controller/sources/ble/ll/ll_main.c | 157 +- .../sources/ble/ll/ll_main_adv_master.c | 39 +- .../sources/ble/ll/ll_main_adv_master_ae.c | 90 +- .../sources/ble/ll/ll_main_adv_slave.c | 45 +- .../sources/ble/ll/ll_main_adv_slave_ae.c | 62 +- .../sources/ble/ll/ll_main_bis_master.c | 128 ++ .../sources/ble/ll/ll_main_bis_slave.c | 355 ++++ .../sources/ble/ll/ll_main_cis_master.c | 500 +++++ .../sources/ble/ll/ll_main_cis_slave.c | 75 + .../controller/sources/ble/ll/ll_main_conn.c | 224 +- .../sources/ble/ll/ll_main_conn_master.c | 39 +- .../sources/ble/ll/ll_main_conn_master_ae.c | 82 +- .../sources/ble/ll/ll_main_conn_slave.c | 37 +- .../controller/sources/ble/ll/ll_main_diag.c | 41 +- .../controller/sources/ble/ll/ll_main_dtm.c | 65 +- .../sources/ble/ll/ll_main_enc_master.c | 37 +- .../sources/ble/ll/ll_main_enc_slave.c | 43 +- .../controller/sources/ble/ll/ll_main_iso.c | 278 +++ .../controller/sources/ble/ll/ll_main_past.c | 37 +- .../controller/sources/ble/ll/ll_main_pc.c | 101 + .../controller/sources/ble/ll/ll_main_phy.c | 40 +- .../controller/sources/ble/ll/ll_main_priv.c | 78 +- .../controller/sources/ble/ll/ll_main_sc.c | 37 +- .../stack/controller/sources/ble/ll/ll_math.c | 101 +- .../controller/sources/ble/lmgr/lmgr_events.c | 43 +- .../controller/sources/ble/lmgr/lmgr_main.c | 72 +- .../ble/lmgr/lmgr_main_adv_master_ae.c | 47 +- .../sources/ble/lmgr/lmgr_main_adv_slave_ae.c | 43 +- .../sources/ble/lmgr/lmgr_main_cis_master.c | 60 + .../sources/ble/lmgr/lmgr_main_conn.c | 39 +- .../sources/ble/lmgr/lmgr_main_iso.c | 52 + .../sources/ble/lmgr/lmgr_main_master.c | 39 +- .../sources/ble/lmgr/lmgr_main_priv.c | 39 +- .../sources/ble/lmgr/lmgr_main_sc.c | 39 +- .../sources/ble/lmgr/lmgr_main_slave.c | 48 +- .../controller/sources/ble/sch/sch_ble.c | 156 +- .../controller/sources/ble/sch/sch_int_rm.h | 53 +- .../controller/sources/ble/sch/sch_int_tm.h | 88 + .../stack/controller/sources/ble/sch/sch_rm.c | 383 ++-- .../stack/controller/sources/ble/sch/sch_tm.c | 352 ++++ .../controller/sources/common/bb/bb_int.h | 38 +- .../controller/sources/common/bb/bb_main.c | 189 +- .../controller/sources/common/chci/chci_tr.c | 207 +- .../controller/sources/common/sch/sch_int.h | 84 +- .../controller/sources/common/sch/sch_list.c | 321 ++- .../controller/sources/common/sch/sch_main.c | 296 +-- .../components/boards/arduino_primo.h | 2 +- .../nordic-bsp/components/boards/boards.c | 3 +- .../nordic-bsp/components/boards/boards.h | 4 +- .../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 | 155 ++ .../nordic-bsp/components/boards/pca20006.h | 2 +- .../nordic-bsp/components/boards/pca20020.h | 2 +- .../nordic-bsp/components/boards/wt51822.h | 2 +- .../stack/thirdparty/uecc/uECC.c | 2 +- .../stack/thirdparty/uecc/uECC_ll.c | 2 +- .../stack/thirdparty/uecc/uECC_ll.h | 6 +- 356 files changed, 38704 insertions(+), 9090 deletions(-) create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_sniffer_api.h delete mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/ll_defs.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_bis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_bis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis_slave.c rename features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/{bb_ble_test.c => bb_ble_dtm.c} (80%) create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_sniffer.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_acad.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_bis_master.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_bis_slave.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_cis.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_cis_master.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_cis_slave.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_iso.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_pc.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_cis_master.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_cis_slave.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_iso.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_bis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_bis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_pc.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis_master.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis_slave.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis_master.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis_slave.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_iso.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_pc.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_bis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_bis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_iso.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_iso_data.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_pc.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_bis.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_iso.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_iso.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_bis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_bis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_cis.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_cis.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_cis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_cis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_pc.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_bis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_bis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_cis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_cis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_iso.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_pc.c delete mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_ext.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_iso.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_bis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_bis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_cis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_cis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_iso.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_pc.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_bis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_bis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_cis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_cis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_iso.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_pc.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_main_iso.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_bis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_bis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_cis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_cis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_iso.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_pc.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_bis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_bis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_cis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_cis_slave.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_iso.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_pc.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_cis_master.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_iso.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_int_tm.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_tm.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10100.h diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api.h index 81b273d9c8..a9011674c9 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief BLE baseband interface file. + * \file + * + * \brief BLE baseband interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -167,8 +168,6 @@ typedef struct /*! * \brief Initialize the BLE BB. * - * \return None. - * * Initialize baseband resources. */ /*************************************************************************************************/ @@ -178,8 +177,6 @@ void BbBleInit(void); /*! * \brief Initialize for scanning master operations. * - * \return None. - * * Update the operation table with scanning master operations routines. */ /*************************************************************************************************/ @@ -189,8 +186,6 @@ void BbBleScanMasterInit(void); /*! * \brief Initialize for auxiliary scanning master operations. * - * \return None. - * * Update the operation table with auxiliary scanning master operations routines. */ /*************************************************************************************************/ @@ -200,8 +195,6 @@ void BbBleAuxScanMasterInit(void); /*! * \brief Initialize for periodic scanning master operations. * - * \return None. - * * Update the operation table with periodic scanning master operations routines. */ /*************************************************************************************************/ @@ -211,8 +204,6 @@ void BbBlePerScanMasterInit(void); /*! * \brief Initialize for connectable master operations. * - * \return None. - * * Update the operation table with connectable master operations routines. */ /*************************************************************************************************/ @@ -222,8 +213,6 @@ void BbBleConnMasterInit(void); /*! * \brief Initialize for advertising slave operations. * - * \return None. - * * Update the operation table with advertising slave operations routines. */ /*************************************************************************************************/ @@ -233,8 +222,6 @@ void BbBleAdvSlaveInit(void); /*! * \brief Initialize for auxiliary advertising slave operations. * - * \return None. - * * Update the operation table with auxiliary advertising slave operations routines. */ /*************************************************************************************************/ @@ -244,8 +231,6 @@ void BbBleAuxAdvSlaveInit(void); /*! * \brief Initialize for connectable slave operations. * - * \return None. - * * Update the operation table with connectable slave operations routines. */ /*************************************************************************************************/ @@ -255,8 +240,6 @@ void BbBleConnSlaveInit(void); /*! * \brief Initialize for test operations. * - * \return None. - * * Update the operation table with test operations routines. */ /*************************************************************************************************/ @@ -318,8 +301,6 @@ uint16_t BbBleInitPeriodicList(uint8_t numEntries, uint8_t *pFreeMem, uint32_t f * \brief Get advertising packet statistics. * * \param pStats Advertising statistics. - * - * \return None. */ /*************************************************************************************************/ void BbBleGetAdvStats(BbBleAdvPktStats_t *pStats); @@ -329,8 +310,6 @@ void BbBleGetAdvStats(BbBleAdvPktStats_t *pStats); * \brief Get scan packet statistics. * * \param pStats Scan statistics. - * - * \return None. */ /*************************************************************************************************/ void BbBleGetScanStats(BbBleScanPktStats_t *pStats); @@ -340,8 +319,6 @@ void BbBleGetScanStats(BbBleScanPktStats_t *pStats); * \brief Get auxiliary advertising packet statistics. * * \param pStats Auxiliary advertising statistics. - * - * \return None. */ /*************************************************************************************************/ void BbBleGetAuxAdvStats(BbBleAuxAdvPktStats_t *pStats); @@ -351,8 +328,6 @@ void BbBleGetAuxAdvStats(BbBleAuxAdvPktStats_t *pStats); * \brief Get auxiliary scan packet statistics. * * \param pStats Auxiliary scan statistics. - * - * \return None. */ /*************************************************************************************************/ void BbBleGetAuxScanStats(BbBleAuxScanPktStats_t *pStats); @@ -362,8 +337,6 @@ void BbBleGetAuxScanStats(BbBleAuxScanPktStats_t *pStats); * \brief Get periodic scan packet statistics. * * \param pStats Periodic scan statistics. - * - * \return None. */ /*************************************************************************************************/ void BbBleGetPerScanStats(BbBlePerScanPktStats_t *pStats); @@ -373,8 +346,6 @@ void BbBleGetPerScanStats(BbBlePerScanPktStats_t *pStats); * \brief Get connection packet statistics. * * \param pStats Connection data statistics. - * - * \return None. */ /*************************************************************************************************/ void BbBleGetConnStats(BbBleDataPktStats_t *pStats); @@ -384,8 +355,6 @@ void BbBleGetConnStats(BbBleDataPktStats_t *pStats); * \brief Get test mode packet statistics. * * \param pStats Test data statistics. - * - * \return None. */ /*************************************************************************************************/ void BbBleGetTestStats(BbBleDataPktStats_t *pStats); @@ -395,8 +364,6 @@ void BbBleGetTestStats(BbBleDataPktStats_t *pStats); * \brief Get PDU filter statistics. * * \param pStats PDU filter statistics. - * - * \return None. */ /*************************************************************************************************/ void BbBleGetPduFiltStats(BbBlePduFiltStats_t *pStats); @@ -405,8 +372,6 @@ void BbBleGetPduFiltStats(BbBlePduFiltStats_t *pStats); /*! * \brief Initialize for connected isochronous stream master operations. * - * \return None. - * * Update the operation table with CIS master operations routines. */ /*************************************************************************************************/ @@ -416,20 +381,34 @@ void BbBleCisMasterInit(void); /*! * \brief Initialize for connected isochronous stream slave operations. * - * \return None. - * * Update the operation table with CIS slave operations routines. */ /*************************************************************************************************/ void BbBleCisSlaveInit(void); +/*************************************************************************************************/ +/*! + * \brief Initialize for Broadcast isochronous stream master operations. + * + * Update the operation table with CIS master operations routines. + */ +/*************************************************************************************************/ +void BbBleBisMasterInit(void); + +/*************************************************************************************************/ +/*! + * \brief Initialize for Broadcast isochronous stream slave operations. + * + * Update the operation table with CIS slave operations routines. + */ +/*************************************************************************************************/ +void BbBleBisSlaveInit(void); + /*************************************************************************************************/ /*! * \brief Get CIS packet statistics. * * \param pStats CIS data statistics. - * - * \return None. */ /*************************************************************************************************/ void BbBleGetCisStats(BbBleDataPktStats_t *pStats); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_op.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_op.h index 874a1eb05f..1f0c57907f 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_op.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_op.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief BLE baseband interface file. + * \file + * + * \brief BLE baseband interface file. + * + * Copyright (c) 2016-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -41,7 +42,7 @@ extern "C" { **************************************************************************************************/ /*! \brief Convert BLE protocol ticks to BB ticks. */ -#define BB_BLE_TO_BB_TICKS(n) BB_US_TO_BB_TICKS((n) * LL_BLE_US_PER_TICK) +#define BB_BLE_TO_US(n) ((n) * LL_BLE_US_PER_TICK) /*! \brief Increment statistics counter. */ #define BB_INC_STAT(s) s++ @@ -51,7 +52,7 @@ extern "C" { **************************************************************************************************/ /*! \brief Operation types. */ -enum +typedef enum { BB_BLE_OP_TEST_TX, /*!< Continuous Tx test mode. */ BB_BLE_OP_TEST_RX, /*!< Continuous Rx test mode. */ @@ -65,14 +66,16 @@ enum BB_BLE_OP_MST_PER_SCAN_EVENT, /*!< Master periodic scanning event. */ BB_BLE_OP_MST_CIS_EVENT, /*!< Master CIS event. */ BB_BLE_OP_SLV_CIS_EVENT, /*!< Slave CIS event. */ + BB_BLE_OP_MST_BIS_EVENT, /*!< Master BIS event. */ + BB_BLE_OP_SLV_BIS_EVENT, /*!< Slave BIS event. */ BB_BLE_OP_NUM /*!< Total number of operations. */ -}; +} BbBleOp_t; /*! \brief Maximum request PDU length (MAX(LL_SCAN_REQ_PDU_LEN, LL_CONN_IND_PDU_LEN)). */ #define BB_REQ_PDU_MAX_LEN (LL_ADV_HDR_LEN + LL_CONN_IND_PDU_LEN) -/*! \brief Guard time at the end of a scan window to the next BOD. Backoff one advertise data exchange. */ -#define BB_SCAN_GUARD_US (LL_ADV_PKT_MAX_USEC + LL_BLE_TIFS_US + \ +/*! \brief Minimum scan time to cover one advertise data exchange. */ +#define BB_MIN_SCAN_US (LL_ADV_PKT_MAX_USEC + LL_BLE_TIFS_US + \ LL_SCAN_REQ_MAX_USEC + LL_BLE_TIFS_US + \ LL_SCAN_RSP_MAX_USEC + \ BbGetSchSetupDelayUs()) @@ -157,7 +160,7 @@ typedef struct int8_t advRssi; /*!< RSSI of advertisement. */ uint8_t advRxPhyOptions; /*!< Rx PHY options. */ uint32_t advCrc; /*!< CRC of advertisement. */ - uint32_t advStartTs; /*!< Start of advertising packet timestamp. */ + uint32_t advStartTsUsec; /*!< Start of advertising packet timestamp in microseconds. */ uint32_t elapsedUsec; /*!< Elapsed time of a single scan window in microseconds. */ /* Filter results. */ @@ -187,7 +190,7 @@ typedef struct uint8_t advChMap; /*!< Advertising channel map. */ /* Return parameters. */ - uint32_t reqStartTs; /*!< Start of request packet timestamp. */ + uint32_t reqStartTsUsec; /*!< Start of request packet timestamp in microseconds. */ /* Filter results. */ bbBlePduFiltResults_t filtResults; /*!< Results from PDU filtering. */ @@ -212,7 +215,7 @@ typedef struct int8_t auxAdvRssi; /*!< RSSI of advertisement. */ uint8_t auxRxPhyOptions; /*!< Rx PHY options. */ uint32_t auxAdvCrc; /*!< CRC of advertisement. */ - uint32_t auxStartTs; /*!< Start of auxiliary advertising packet timestamp. */ + uint32_t auxStartTsUsec; /*!< Start of auxiliary advertising packet timestamp in microseconds. */ /* Filter results. */ bbBlePduFiltResults_t filtResults; /*!< Results from PDU filtering. */ @@ -230,9 +233,8 @@ typedef struct int8_t perAdvRssi; /*!< RSSI of advertisement. */ uint8_t perRxPhyOptions; /*!< Rx PHY options. */ uint32_t perAdvCrc; /*!< CRC of advertisement. */ - uint32_t perStartTs; /*!< Start of periodic advertising packet timestamp. */ + uint32_t perStartTsUsec; /*!< Start of periodic advertising packet timestamp in microseconds. */ bool_t perIsFirstTs; /*!< True if it is the first timestamp for a serial of periodic packets. */ - } BbBleMstPerScanEvent_t; /*! \brief Slave auxiliary advertising event operation data (\ref BB_BLE_OP_SLV_AUX_ADV_EVENT). */ @@ -252,7 +254,7 @@ typedef struct /* Return parameters. */ uint8_t auxRxPhyOptions; /*!< Rx PHY options. */ - uint32_t auxReqStartTs; /*!< Start of request packet timestamp. */ + uint32_t auxReqStartTsUsec; /*!< Start of request packet timestamp in microseconds. */ /* Filter results. */ bbBlePduFiltResults_t filtResults; /*!< Results from PDU filtering. */ @@ -281,7 +283,7 @@ typedef struct BbBleRxDataComp_t rxDataCback; /*!< Receive completion callback. */ /* Return parameters. */ - uint32_t startTs; /*!< Start timestamp of the first received packet. */ + uint32_t startTsUsec; /*!< Start timestamp of the first received packet in microseconds. */ int8_t rssi; /*!< RSSI of the last received packet. */ uint8_t rxPhyOptions; /*!< Rx PHY options. */ } BbBleSlvConnEvent_t; @@ -313,12 +315,35 @@ typedef struct BbBleRxDataComp_t rxDataCback; /*!< Receive completion callback. */ /* Return parameters. */ - uint32_t startTs; /*!< Start timestamp of the first received packet. */ + bool_t isFirstTs; /*!< True for the first timestamp. */ + uint32_t startTsUsec; /*!< Start timestamp of the first received packet in microseconds. */ + uint32_t rxTsUsec; /*!< Timestamp of the received packet. in microseconds */ int8_t rssi; /*!< RSSI of the last received packet. */ uint8_t rxPhyOptions; /*!< Rx PHY options. */ uint32_t rxSyncDelayUsec; /*!< Receive timeout in microseconds. */ } BbBleSlvCisEvent_t; +/*! \brief BIS master event operation data (\ref BB_BLE_OP_MST_BIS_EVENT). */ +typedef struct +{ + uint32_t rxSyncDelayUsec; /*!< Receive timeout in microseconds. */ + BbBleExec_t execCback; /*!< Execute callback. */ + BbBleRxDataComp_t rxDataCback; /*!< Recieve completion callback. */ + + /* Return parameters. */ + uint32_t startTsUsec; /*!< First Rx timestamp. */ +} BbBleMstBisEvent_t; + +/*! \brief BIS slave event operation data (\ref BB_BLE_OP_SLV_BIS_EVENT). */ +typedef struct +{ + BbBleExec_t execCback; /*!< Execute callback. */ + BbBleTxDataComp_t txDataCback; /*!< Transmit completion callback. */ + + /* Return parameters. */ + /* None */ +} BbBleSlvBisEvent_t; + /*! \brief Continuous transmit operation data (\ref BB_BLE_OP_TEST_TX). */ typedef struct { @@ -357,6 +382,8 @@ typedef struct BbBleData_tag BbBleMstPerScanEvent_t mstPerScan; /*!< Master periodic scanning event data. */ BbBleMstCisEvent_t mstCis; /*!< Master CIS event data. */ BbBleSlvCisEvent_t slvCis; /*!< Slave CIS event data. */ + BbBleMstBisEvent_t mstBis; /*!< Master BIS event data. */ + BbBleSlvBisEvent_t slvBis; /*!< Slave BIS event data. */ BbBleTestTx_t testTx; /*!< Transmit test data. */ BbBleTestRx_t testRx; /*!< Receive test data. */ } op; /*!< Operation specific data. */ @@ -373,8 +400,6 @@ typedef struct BbBleData_tag * \param descs Array of transmit buffer descriptor. * \param cnt Number of descriptors. * - * \return None. - * * \note This function is expected to be called during the call context of * \ref BbBleSlvConnEvent_t::rxDataCback callback routine. */ @@ -388,8 +413,6 @@ void BbBleTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt); * \param pBuf Receive data buffer. * \param len Maximum length of data buffer. * - * \return None. - * * \note This function is expected to be called during the call context of * \ref BbBleSlvConnEvent_t::rxDataCback callback routine. * @@ -406,8 +429,6 @@ void BbBleRxData(uint8_t *pBuf, uint16_t len); * \param descs Array of transmit buffer descriptor. * \param cnt Number of descriptors. * - * \return None. - * * \note This function is expected to be called during the call context of * \ref BbBleMstCisEvent_t::rxDataCback or \ref BbBleSlvCisEvent_t::rxDataCback * callback routine. @@ -422,8 +443,6 @@ void BbBleCisTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt); * \param pBuf Receive data buffer. * \param len Maximum length of data buffer. * - * \return None. - * * \note This function is expected to be called during the call context of * \ref BbBleSlvCisEvent_t::rxDataCback callback routine. * @@ -432,6 +451,45 @@ void BbBleCisTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt); */ /*************************************************************************************************/ void BbBleCisRxData(uint8_t *pBuf, uint16_t len); + +/*************************************************************************************************/ +/*! + * \brief Transmit BIS Data PDU at next transmit slot. + * + * \param descs Array of transmit buffer descriptor. + * \param cnt Number of descriptors. + * \param nextPduTime Next PDU time. + * \param pNextChan Next PDU channel. + */ +/*************************************************************************************************/ +void BbBleBisTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt, uint32_t nextPduTime, PalBbBleChan_t *pNextChan); + +/*************************************************************************************************/ +/*! + * \brief Set receive BIS Data PDU buffer for next receive slot. + * + * \param pBuf Receive data buffer. + * \param len Maximum length of data buffer. + * \param nextPduTime Next PDU time. + * \param pNextChan Next PDU channel. + * \param reAcq Rx train re-acquisition required. + */ +/*************************************************************************************************/ +void BbBleBisRxData(uint8_t *pBuf, uint16_t len, uint32_t nextPduTime, PalBbBleChan_t *pNextChan, bool_t reAcq); + +/*************************************************************************************************/ +/*! + * \brief Receive data re-acquisition. + * + * \param syncTime Due time for the next Rx operation. + * \param pChan Channel parameters. + * + * Update due time for next Rx operation. Called after a missed Rx operation for re-acquisition + * of the receive train. + */ +/*************************************************************************************************/ +void BbBleBisRxDataReAcq(uint32_t syncTime, PalBbBleChan_t *pChan); + /*! \} */ /* BB_API_BLE */ #ifdef __cplusplus diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_pdufilt.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_pdufilt.h index 6654bc2e46..7b1cdd93b9 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_pdufilt.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_pdufilt.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief BLE baseband PDU filtering interface file. + * \file + * + * \brief BLE baseband PDU filtering interface file. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -143,8 +144,6 @@ bool_t BbBleExtPduFiltCheck(const bbBlePduExtFiltParams_t *pExtFiltParams, * \param pFiltResults Filter results. * \param pPeerIdAddr Storage for peer ID address. * \param pPeerIdAddrType Storage for peer ID address type; - * - * \return None. */ /*************************************************************************************************/ static inline void BbBlePduFiltResultsGetPeerIdAddr(const bbBlePduFiltResults_t *pFiltResults, uint64_t *pPeerIdAddr, uint8_t *pPeerIdAddrType) @@ -166,8 +165,6 @@ static inline void BbBlePduFiltResultsGetPeerIdAddr(const bbBlePduFiltResults_t * * \param pFiltResults Filter results. * \param pPeerRpa Storage for peer RPA or 0. - * - * \return None. */ /*************************************************************************************************/ static inline void BbBlePduFiltResultsGetPeerRpa(const bbBlePduFiltResults_t *pFiltResults, uint64_t *pPeerRpa) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_periodiclist.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_periodiclist.h index 2b4283873b..dcc7096eff 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_periodiclist.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_periodiclist.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief BLE baseband periodiclist interface file. + * \file + * + * \brief BLE baseband periodiclist interface file. + * + * Copyright (c) 2016-2017 ARM Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -65,8 +66,6 @@ uint8_t BbBlePeriodicListGetSize(void); /*! * \brief Clear all periodic list entries. * - * \return None. - * * Clear all periodic list entries stored in the BB. * * \note No resource synchronization is required to modify the periodic list resource as diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_reslist.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_reslist.h index 6ddf9e66dd..7b0ae093f5 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_reslist.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_reslist.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief BLE baseband resolving list interface file. + * \file + * + * \brief BLE baseband resolving list interface file. + * + * Copyright (c) 2016-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -69,8 +70,6 @@ typedef void (*bbBleResListAddrResNeeded_t)(uint64_t rpa, bool_t peer, uint8_t p * \brief Set address resolution needed callback. * * \param cback Callback. - * - * \return None. */ /*************************************************************************************************/ void BbBleResListSetAddrResNeededCback(bbBleResListAddrResNeeded_t cback); @@ -90,8 +89,6 @@ uint8_t BbBleResListGetSize(void); /*! * \brief Clear resolving list. * - * \return None. - * * Clear all resolving list entries stored in the BB. */ /*************************************************************************************************/ @@ -331,8 +328,6 @@ uint8_t BbBleResListLocalStatus(bool_t peerAddrRand, uint64_t peerIdentityAddr); /*! * \brief Handle timeout of local resolvable addresses. * - * \return None. - * * A new local resolvable address will be generated for each entry in the resolving list. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_whitelist.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_whitelist.h index 70aed1437f..420e8d5d81 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_whitelist.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_api_whitelist.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief BLE baseband whitelist interface file. + * \file + * + * \brief BLE baseband whitelist interface file. + * + * Copyright (c) 2016-2017 ARM Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -64,8 +65,6 @@ uint8_t BbBleWhiteListGetSize(void); /*! * \brief Clear all white list entries. * - * \return None. - * * Clear all white list entries stored in the BB. * * \note No resource synchronization is required to modify the white list resource as @@ -111,8 +110,6 @@ bool_t BbBleWhiteListRemove(bool_t randAddr, uint64_t addr); /*************************************************************************************************/ /*! * \brief Add anonymous device to the white list. - * - * \return None. */ /*************************************************************************************************/ void BbBleWhiteListAddAnonymous(void); @@ -120,8 +117,6 @@ void BbBleWhiteListAddAnonymous(void); /*************************************************************************************************/ /*! * \brief Remove anonymous device from the white list. - * - * \return None. */ /*************************************************************************************************/ void BbBleWhiteListRemoveAnonymous(void); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_sniffer_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_sniffer_api.h new file mode 100644 index 0000000000..007cfe8842 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/bb_ble_sniffer_api.h @@ -0,0 +1,163 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Packet sniffer interface file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 BB_BLE_SNIFFER_API_H +#define BB_BLE_SNIFFER_API_H + +#include "wsf_types.h" +#include "bb_api.h" +#include "pal_bb_ble.h" +#include "ll_defs.h" +#include "bb_ble_api.h" + +#ifndef BB_SNIFFER_ENABLED +/*! \brief Sniffer enabled for controller */ +#define BB_SNIFFER_ENABLED FALSE +#endif + +#ifdef __cplusplus +extern "C" { +#endif +/************************************************************************************************** + Constants +**************************************************************************************************/ + +/*! \brief Maximum number of buffer. */ +#define BB_SNIFFER_MAX_NUM_BUF 20 + +/*! \brief Max packet size for a sniffer packet. */ +#define BB_SNIFFER_MAX_PKT_SIZE 28 + +/*! \brief Output methods of sniffer. */ +enum +{ + BB_SNIFFER_OUTPUT_HCI_TOKEN, /*!< Output over HCI through tokens. */ + BB_SNIFFER_OUTPUT_TOTAL_METHODS, /*!< Total output methods. */ + + BB_SNIFFER_OUTPUT_NULL_METHOD /*!< Null output method. */ +}; + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief Sniffer Packet types (Used to parse packet for sniffer). */ +enum +{ + BB_SNIFF_PKT_TYPE_TX, /*!< Transmit packets. */ + BB_SNIFF_PKT_TYPE_RX /*!< Receive packets. */ +}; + +/*! \brief Sniffer packet metadata. */ +typedef struct +{ + uint8_t type; /*!< TX/RX. */ + uint8_t status; /*!< TX/RX status. */ + uint8_t state; /*!< State of the operation. */ + uint32_t timeStamp; /*!< Timestamp. */ + uint8_t rssi; /*!< Signal power (TxPower, or RSSI). */ + PalBbBleChan_t chan; /*!< channelization params. */ +} BbBleSnifferMeta_t; + +/*! \brief Sniffer data packet. */ +typedef struct +{ + BbBleSnifferMeta_t meta; /*!< Metadata header. */ + uint8_t hdr[LL_DATA_HDR_MAX_LEN]; /*!< Header raw data. */ +} BbBleDataSniffPkt_t; + +/*! \brief Sniffer advertisement packet. */ +typedef struct +{ + BbBleSnifferMeta_t meta; /*!< Metadata header. */ + uint8_t hdr[LL_ADV_HDR_LEN]; /*!< Header raw data. */ +} BbBleAdvSniffPkt_t; + +/*! \brief Sniffer generic packet. */ +typedef struct +{ + union + { + BbBleSnifferMeta_t meta; /*!< Metadata. */ + BbBleDataSniffPkt_t dataPkt; /*!< Data packet. */ + BbBleAdvSniffPkt_t advPkt; /*!< Advertising packet. */ + } pktType; /*!< Packet type. */ +} BbBleSnifferPkt_t; + +/*! \brief Sniffer output call signature. */ +typedef void (*bbSnifferFn_t)(BbBleSnifferPkt_t *pPkt); + +/*! \brief Sniffer get packet call signature. */ +typedef BbBleSnifferPkt_t* (*bbSnifferGetPktFn_t)(void); + +/*! \brief HCI output context. */ +typedef struct +{ + uint16_t bufIdx; /*!< Current packet buffer index. */ + BbBleSnifferPkt_t pktBuf[BB_SNIFFER_MAX_NUM_BUF]; /*!< Sotrage for packet buffer. */ +} BbBleSnifferHciCtx_t; + +/*! \brief Sniffer context. */ +typedef struct +{ + /* Control variables. */ + bool_t enabled; /*!< Enable status of sniffer. */ + bbSnifferGetPktFn_t snifferGetPktFn; /*!< Sniffer get packet function callback. */ + bbSnifferFn_t snifferOutCb; /*!< Sniffer output callback. */ + uint32_t packetCtr; /*!< Number of packets processed. */ + + /* Temporary storage. */ + uint8_t txBuf[LL_DATA_HDR_MAX_LEN]; /*!< Temporary storage for conn tx buf. */ + uint8_t chanIdx; /*!< Temporary storage for adv channel index. */ + + /* Output contexts. */ + union + { + BbBleSnifferHciCtx_t hci; /*!< HCI Output context. */ + } outputCtx; /*!< Output context union. */ +} bbSnifferCtx_t; + +/************************************************************************************************** + Globals +**************************************************************************************************/ + +extern bbSnifferCtx_t bbSnifferCtx; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +uint8_t BbBleInitSniffer(uint8_t outMethod, bool_t enable); +void bbBleSnifferMstScanPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t *pPktData); +void bbBleSnifferMstAuxScanPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t *pPktData); +void bbBleSnifferSlvAdvPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t * pPktData); +void bbBleSnifferSlvAuxAdvPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t * pPktData); +void bbBleSnifferMstPerScanPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t *pPktData); +void bbBleSnifferConnPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t * pPktData); + +#ifdef __cplusplus +}; +#endif + +#endif /* BB_BLE_TESTER_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/lhci_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/lhci_api.h index 26b00eb431..72eb718416 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/lhci_api.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/lhci_api.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer HCI subsystem API. + * \file + * + * \brief Link layer HCI subsystem API. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -46,6 +47,9 @@ typedef struct /*! \brief Command handler call signature. */ typedef bool_t (*lhciCmdHandler_t)(LhciHdr_t *pHdr, uint8_t *pBuf); +/*! \brief Event complete handler call signature. */ +typedef void (*lhciCompHandler_t)(void); + /************************************************************************************************** Function Declarations **************************************************************************************************/ @@ -68,16 +72,19 @@ void LhciPastInit(void); void LhciChannelSelection2Init(void); void LhciCisMasterInit(void); void LhciCisSlaveInit(void); +void LhciBisSlaveInit(void); +void LhciBisMasterInit(void); void LhciIsoInit(void); +void LhciPowerControlInit(void); void LhciVsExtInit(lhciCmdHandler_t decodeCmd); void LhciHandlerInit(wsfHandlerId_t handlerId); void LhciHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); void LhciIsoHandlerInit(wsfHandlerId_t handlerId); void LhciIsoHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); -void LhciSetDefaultHciSupCmd(uint8_t *pBuf); #if (LL_ENABLE_TESTER) void LhciTesterInit(void); #endif +void LhciInitFinalize(void); /* Command processing */ uint8_t LhciPackCmdStatusEvt(uint8_t *pBuf, uint8_t status, uint16_t opCode); @@ -87,8 +94,10 @@ uint8_t LhciPackVsEvt(uint8_t *pBuf, uint16_t vsEvtCode); void LhciSendEvent(uint8_t *pBuf); bool_t LhciIsEventPending(void); uint8_t LhciPackEvtHdr(uint8_t *pBuf, uint8_t evtCode, uint8_t paramLen); +bool_t LhciSnifferHandler(void); /* Event processing */ +void LhciRegisterSendTrCompleteHandler(lhciCompHandler_t compCback); bool_t LhciVsEncodeTraceMsgEvtPkt(const uint8_t *pBuf, uint32_t len); #ifdef __cplusplus diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/ll_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/ll_api.h index e0c255a0c8..c677bd4e00 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/ll_api.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/ll_api.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer interface file. + * \file + * + * \brief Link layer interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -35,14 +36,14 @@ extern "C" { #endif /*! \brief Version number. */ -#define LL_VER_NUM 0x1302 /* Default value. Auto-generated by builder. */ +#define LL_VER_NUM 1366 /************************************************************************************************** Data Types **************************************************************************************************/ /*! \brief The following status values are used in the LL API. */ -enum +typedef enum { LL_SUCCESS = 0x00, LL_ERROR_CODE_UNKNOWN_HCI_CMD = 0x01, @@ -114,7 +115,7 @@ enum LL_ERROR_CODE_LIMIT_REACHED = 0x43, LL_ERROR_CODE_OP_CANCELLED_BY_HOST = 0x44, LL_ERROR_CODE_PKT_TOO_LONG = 0x45 -}; +} LlStatus_t; /*! \addtogroup LL_API_INIT * \{ */ @@ -147,13 +148,15 @@ typedef struct /* ISO */ uint8_t numIsoTxBuf; /*!< Default number of ISO transmit buffers. */ uint8_t numIsoRxBuf; /*!< Default number of ISO receive buffers. */ - uint16_t maxIsoBufLen; /*!< Maximum ISO buffer size between host and controller. */ - uint16_t maxIsoPduLen; /*!< Maximum ISO PDU buffer size. */ - + uint16_t maxIsoSduLen; /*!< Maximum ISO SDU size between host and controller. */ + uint16_t maxIsoPduLen; /*!< Maximum ISO Data PDU buffer size. */ /* CIS */ uint8_t maxCig; /*!< Maximum number of CIG. */ - uint8_t maxCis; /*!< Maximum number of CIS. */ - uint16_t subEvtSpaceDelay; /*!< Subevent spacing above T_MSS. */ + uint8_t maxCis; /*!< Maximum number of CIS, it is shared by the CIGs. */ + uint16_t cisSubEvtSpaceDelay; /*!< Subevent spacing above T_MSS in microsecond. */ + /* 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. */ /* PHY */ @@ -246,20 +249,26 @@ typedef struct #define LL_FEAT_PAST_RECIPIENT (UINT64_C(1) << 25) /*!< Periodic Advertising Sync Transfer – Recipient supported. */ #define LL_FEAT_SCA_UPDATE (UINT64_C(1) << 26) /*!< Sleep Clock Accuracy Updates supported. */ #define LL_FEAT_REMOTE_PUB_KEY_VALIDATION (UINT64_C(1) << 27) /*!< Remote Public Key Validation supported. */ -/* --- Core Spec Milan --- */ +/* --- Core Spec 5.2 --- */ #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_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. */ -#define LL_FEAT_ALL_MASK (UINT64_C(0xFF01FFFF))/*!< All feature mask, need to be updated when new features are added. */ +#define LL_HOST_CONTROLLED_FEAT LL_FEAT_ISO_HOST_SUPPORT /*!< Feature bits controlled by the host. */ + +#define LL_FEAT_ALL_MASK (UINT64_C(0x0000000FFF01FFFF)) /*!< All feature mask, need to be updated when new features are added. */ /*! \brief This parameter identifies the device role. */ -enum +typedef enum { LL_ROLE_MASTER = 0, /*!< Role is master. */ LL_ROLE_SLAVE = 1 /*!< Role is slave. */ -}; +} LlRole_t; /*! \brief Operational mode flags. */ enum @@ -280,6 +289,7 @@ 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. */ /* 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. */ @@ -359,7 +369,7 @@ typedef struct uint8_t priAdvChanMap; /*!< Primary Advertising Channel Map. */ uint8_t ownAddrType; /*!< Own Address Type. */ uint8_t peerAddrType; /*!< Peer Address Type. */ - uint8_t *pPeerAddr; /*!< Peer Address. */ + const uint8_t *pPeerAddr; /*!< Peer Address. */ uint8_t advFiltPolicy; /*!< Advertising Filter Policy. */ int8_t advTxPwr; /*!< Advertising Tx Power. */ uint8_t priAdvPhy; /*!< Primary Advertising PHY. */ @@ -523,7 +533,7 @@ enum LL_PHYS_LE_CODED_BIT = (1 << 2), /*!< LE Coded PHY. */ }; -/*! \brief All PHYs preference. */ +/*! \brief All PHYs preference. */ enum { LL_ALL_PHY_ALL_PREFERENCES = 0, /*!< All PHY preferences. */ @@ -540,14 +550,41 @@ enum }; /*! \brief PHY types. */ +typedef enum +{ + LL_PHY_NONE = 0, /*!< PHY not selected. */ + LL_PHY_LE_1M = 1, /*!< LE 1M PHY. */ + LL_PHY_LE_2M = 2, /*!< LE 2M PHY. */ + LL_PHY_LE_CODED = 3, /*!< LE Coded PHY. */ +} LlPhy_t; + +/*! \brief Power Control managed PHYs. */ enum { - LL_PHY_NONE = 0, /*!< PHY not selected. */ - LL_PHY_LE_1M = 1, /*!< LE 1M PHY. */ - LL_PHY_LE_2M = 2, /*!< LE 2M PHY. */ - LL_PHY_LE_CODED = 3 /*!< LE Coded PHY. */ + LL_PC_PHY_1M = 1, + LL_PC_PHY_2M = 2, + LL_PC_PHY_CODED_S8 = 3, + LL_PC_PHY_CODED_S2 = 4, + + LL_PC_PHY_TOTAL = LL_PC_PHY_CODED_S2, + LL_PC_PHY_INVALID = 0xFF }; +/*! \brief Power control PHY bits. */ +enum +{ + LL_PC_1M_BIT = (1 << 0), /*!< LE 1M PHY bit. */ + LL_PC_2M_BIT = (1 << 1), /*!< LE 2M PHY bit. */ + LL_PC_CODED_S8_BIT = (1 << 2), /*!< LE Coded S8 PHY bit. */ + LL_PC_CODED_S2_BIT = (1 << 3), /*!< LE Coded S2 PHY bit. */ + LL_PC_MAX_BIT = LL_PC_CODED_S2_BIT, + + LL_PC_ALL_BITS = LL_PC_1M_BIT | LL_PC_2M_BIT | LL_PC_CODED_S8_BIT | LL_PC_CODED_S8_BIT +}; + +/*! \brief PCL path loss monitoring unused high threshold value. */ +#define LL_PC_PATH_LOSS_UNUSED_HIGH_THRESHOLD 0xFF + /*! \brief Privacy modes. */ enum { @@ -610,95 +647,170 @@ enum /*! \} */ /* LL_API_CONN */ - /*! \addtogroup LL_API_ISO * \{ */ /*! \brief Packing scheme. */ -enum +typedef enum { - LL_PACKING_SEQUENTIAL = 0, /*!< Sequential. */ - LL_PACKING_INTERLEAVED = 1 /*!< Interleaved. */ -}; - -/*! \brief Framing. */ -enum -{ - LL_FRAMING_UNFRAMED = 0, /*!< Unframed. */ - LL_FRAMING_FRAMED = 1, /*!< Framed. */ -}; + LL_PACKING_SEQUENTIAL = 0, /*!< Sequential. */ + LL_PACKING_INTERLEAVED = 1 /*!< Interleaved. */ +} LlPacking_t; /*! \brief CIS parameters. */ typedef struct { - uint8_t cisId; /*!< Used to identify a connected isochronous stream. */ - uint16_t sduSizeMToS; /*!< Maximum size of a data SDU from the master to the slave. */ - uint16_t sduSizeSToM; /*!< Maximum size of a data SDU from the slave to the master. */ - uint8_t phyMToS; /*!< PHY to be used for transmission from master to slave. */ - uint8_t phySToM; /*!< PHY to be used for transmission from master to slave. */ - uint16_t transLatMToS; /*!< Maximum time in microseconds between the transmissions of a Data PDU from the Link Layer of the master to the reception of the same Data PDU in the Link Layer of the slave. */ - uint16_t transLatSToM; /*!< Maximum time in microseconds between the transmissions of a Data PDU from the Link Layer of the slave to the reception of the same Data PDU in the Link Layer of the master. */ - uint8_t rteMToS; /*!< Maximum number of times every PDU should be retransmitted from the master to slave. */ - uint8_t rteSToM; /*!< Maximum number of times every PDU should be retransmitted from the slave to master. */ + uint8_t cisId; /*!< Used to identify a connected isochronous stream. */ + uint16_t sduSizeMToS; /*!< Maximum size of a data SDU from the master to the slave. */ + uint16_t sduSizeSToM; /*!< Maximum size of a data SDU from the slave to the master. */ + uint8_t phyMToS; /*!< PHY to be used for transmission from master to slave. */ + uint8_t phySToM; /*!< PHY to be used for transmission from master to slave. */ + uint8_t rteMToS; /*!< Maximum number of times every PDU should be retransmitted from the master to slave. */ + uint8_t rteSToM; /*!< Maximum number of times every PDU should be retransmitted from the slave to master. */ } LlCisCisParams_t; /*! \brief CIG parameters. */ typedef struct { - uint8_t cigId; /*!< Used to identify the connected isochronous group. */ - uint32_t sduIntervalMToS; /*!< The time interval between the start of consecutive SDUs from the master Host */ - uint32_t sduIntervalSToM; /*!< The time interval between the start of consecutive SDUs from the slave Host */ - uint8_t sca; /*!< Sleep clock accuracy. */ - uint8_t packing; /*!< Packing scheme. */ - uint8_t framing; /*!< Indicates the format of CIS Data PDUs. */ - uint8_t numCis; /*!< Number of CIS to set. */ - LlCisCisParams_t *pCisParam; /*!< CIS parameters. */ + uint8_t cigId; /*!< Used to identify the connected isochronous group. */ + uint32_t sduIntervalMToS; /*!< The time interval between the start of consecutive SDUs from the master Host. */ + uint32_t sduIntervalSToM; /*!< The time interval between the start of consecutive SDUs from the slave Host. */ + uint8_t sca; /*!< Sleep clock accuracy. */ + uint8_t packing; /*!< Packing scheme. */ + LlFraming_t framing:8; /*!< Indicates the format of CIS Data PDUs. */ + uint16_t transLatMToS; /*!< Maximum time in microseconds between the transmissions of a Data PDU from the Link Layer of the master to the reception of the same Data PDU in the Link Layer of the slave. */ + uint16_t transLatSToM; /*!< Maximum time in microseconds between the transmissions of a Data PDU from the Link Layer of the slave to the reception of the same Data PDU in the Link Layer of the master. */ + uint8_t numCis; /*!< Number of CIS to set. */ + LlCisCisParams_t *pCisParam; /*!< CIS parameters. */ } LlCisCigParams_t; /*! \brief CIG test CIS parameters. */ typedef struct { - uint8_t cisId; /*!< CIS identifier. */ - uint8_t nse; /*!< Maximum number of subevent in each interval on CIS. */ - uint8_t plSizeMToS; /*!< Maximum size of payload from master to slave. */ - uint8_t plSizeSToM; /*!< Maximum size of payload from slave to master. */ - uint8_t phyMToS; /*!< Master to slave PHY. */ - uint8_t phySToM; /*!< Slave to master PHY. */ - uint8_t ftMToS; /*!< Master to slave flush time. */ - uint8_t ftSToM; /*!< Slave to master flush time. */ - uint8_t bnMToS; /*!< Master to slave burst number. */ - uint8_t bnSToM; /*!< Slave to master burst number. */ + uint8_t cisId; /*!< CIS identifier. */ + uint8_t nse; /*!< Maximum number of subevent in each interval on CIS. */ + uint16_t sduSizeMToS; /*!< Maximum size of a data SDU from the master to the slave. */ + uint16_t sduSizeSToM; /*!< Maximum size of a data SDU from the slave to the master. */ + uint16_t pduSizeMToS; /*!< Maximum size of payload from master to slave. */ + uint16_t pduSizeSToM; /*!< Maximum size of payload from slave to master. */ + uint8_t phyMToS; /*!< Master to slave PHY. */ + uint8_t phySToM; /*!< Slave to master PHY. */ + uint8_t bnMToS; /*!< Master to slave burst number. */ + uint8_t bnSToM; /*!< Slave to master burst number. */ } LlCisCigCisParamsTest_t; /*! \brief CIG test CIG parameters. */ typedef struct { - uint8_t cigId; /*!< CIG identifier. */ - uint16_t isoInterval; /*!< The time duration of the isochronous PDU interval. */ - uint8_t numCis; /*!< Number of CIS. */ - uint8_t sca; /*!< Sleep clock accuracy. */ - uint8_t packing; /*!< Packing scheme. */ - LlCisCigCisParamsTest_t *pCisParam; /*!< CIS parameters. */ + uint8_t cigId; /*!< CIG identifier. */ + uint32_t sduIntervalMToS; /*!< The time interval between the start of consecutive SDUs from the master Host. */ + uint32_t sduIntervalSToM; /*!< The time interval between the start of consecutive SDUs from the slave Host. */ + uint8_t ftMToS; /*!< The flush timeout in multiples of ISO_Interval for each payload sent from the master to slave. */ + uint8_t ftSToM; /*!< The flush timeout in multiples of ISO_Interval for each payload sent from the slave to master. */ + uint16_t isoInterval; /*!< The time duration of the isochronous PDU interval. */ + uint8_t sca; /*!< Sleep clock accuracy. */ + uint8_t packing; /*!< Packing scheme. */ + LlFraming_t framing:8; /*!< Indicates the format of CIS Data PDUs. */ + uint8_t numCis; /*!< Number of CIS. */ + LlCisCigCisParamsTest_t *pCisParam; /*!< CIS parameters. */ } LlCisCigParamsTest_t; -/*! \brief CIS create CIS parameters. */ +/*! \brief Create CIS parameters. */ typedef struct { - uint16_t *pCisHandle; /*!< Pointer to the connected isochronous stream handle array. */ + uint16_t *pCisHandle; /*!< Pointer to the connected isochronous handle array. */ uint16_t *pAclHandle; /*!< Pointer to the asynchronous connection link handle array. */ } LlCisCreateCisParams_t; -/*! \brief CIS create CIS parameters. */ +/*! \brief ISO data path direction. */ +typedef enum +{ + LL_ISO_DATA_DIR_INPUT = 0x00, /*!< Input data path. */ + LL_ISO_DATA_DIR_OUTPUT = 0x01 /*!< Output data path. */ +} LlIsoDataPathDir_t; + +/*! \brief ISO data path. */ +typedef enum +{ + LL_ISO_DATA_PATH_HCI = 0x00, + LL_ISO_DATA_PATH_VS = 0x01, /*!< Vendor Specific. */ + + LL_ISO_DATA_PATH_TOTAL, /*!< Total number of data path methods. */ + + LL_ISO_DATA_PATH_DISABLED = 0xFF, /*!< Data path is disabled. */ +} LlIsoDataPath_t; + +/*! \brief ISO data path direction bit. */ +enum +{ + LL_ISO_DATA_PATH_INPUT_BIT = (1 << 0), /*!< Data path input bit. */ + LL_ISO_DATA_PATH_OUTPUT_BIT = (1 << 1) /*!< Data path output bit. */ +}; + +/*! \brief LE setup ISO Data Path command. */ typedef struct { - uint16_t isoHandle; /*!< Handle of CIS or BIS. */ - uint32_t inputBw; /*!< Input bandwidth. */ - uint32_t outputBw; /*!< Output bandwidth. */ - uint8_t inputDataPath; /*!< Input data path. */ - uint8_t outputDataPath; /*!< Output data path. */ - uint8_t inputMaxPayloadSize; /*!< Input maximum payload size. */ - uint8_t outputMaxPayloadSize; /*!< Output maximum payload size. */ -} LlIsoSetupDataPathParams_t; + uint16_t handle; /*!< Handle of CIS or BIS. */ + LlIsoDataPathDir_t dpDir:8; /*!< Data path direction. */ + uint8_t dpId; /*!< Data path ID. */ + uint8_t codecFormat; /*!< Codec Format. */ + uint16_t codecCompId; /*!< Codec Company ID. */ + uint16_t codecId; /*!< Codec ID. */ + uint32_t ctrDly; /*!< Codec ID. */ + uint8_t codecConfigLen; /*!< Codec configuration length. */ + uint8_t *pCodecConfig; /*!< Codec configuration. */ +} LlIsoSetupDataPath_t; + +/*! \brief BIG Create BIG message. */ +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. */ + uint16_t maxSdu; /*!< Maximum size of an SDU. */ + uint16_t mtlMs; /*!< Maximum time in milliseconds. */ + uint8_t rtn; /*!< Retransmitted number. */ + uint8_t phys; /*!< Transmitter PHYs of packets. */ + 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. */ +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. */ + 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. */ + uint16_t maxPdu; /*!< Maximum size of payload. */ + uint8_t phys; /*!< Transmitter PHYs of packets. */ + uint8_t packing; /*!< Sequential or Interleaved packing. */ + LlFraming_t framing:8; /*!< Unframed or Framed. */ + uint8_t bn; /*!< Number of new payloads in each interval for each BIS. */ + 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. */ +typedef struct +{ + uint8_t bigHandle; /*!< Used to identify the BIG. */ + uint16_t syncHandle; /*!< Periodic advertising train handle. */ + uint8_t encrypt; /*!< Unencrypted or Encrypted. */ + uint8_t bcstCode[LL_BC_LEN];/*!< Session key code for encrypt and decrypt BIS payloads. */ + uint8_t mse; /*!< Maximum number of subevents. */ + uint16_t bigSyncTimeout; /*!< Synchronization timeout for the BIS, in the units of 10ms. */ + uint8_t numBis; /*!< Total number of BISes in the BIG. */ + uint8_t bis[LL_MAX_BIS]; /*!< List of indices of BISes. */ +} LlBigCreateSync_t; /*! \} */ /* LL_API_ISO */ @@ -763,6 +875,35 @@ typedef struct uint16_t numRxTimeout; /*!< Receive timeout count. */ } LlTestReport_t; +/*! \brief ISO test packet payload type. */ +typedef enum +{ + LL_ISO_PLD_TYPE_ZERO_LEN = 0x00, /*!< Zero length payload. */ + LL_ISO_PLD_TYPE_VAR_LEN = 0x01, /*!< Variable length payload. */ + LL_ISO_PLD_TYPE_MAX_LEN = 0x02 /*!< Maximum length payload. */ +} LlIsoPldType_t; + +/*! \brief ISO test counter data. */ +typedef struct +{ + uint32_t numSuccess; /*!< Received good packet count. */ + uint32_t numMissed; /*!< Received missed packet count. */ + uint32_t numFailed; /*!< Received failed packet count. */ +} LlIsoTestCtrs_t; + +/*! \brief ISO link quality statistics. */ +typedef struct +{ + uint32_t txUnAckPkt; /*!< Unacked packets. */ + uint32_t txFlushedPkt; /*!< Flushed packets. */ + uint32_t txLastSubEventPkt; /*!< The CIS slave transmit CIS Data PDU on it's last subevent. */ + uint32_t retransmitPkt; /*!< Retransmitted packets. */ + uint32_t crcErrPkt; /*!< CRC error packets. */ + uint32_t rxUnreceivedPkt; /*!< Packets unreceived by flush point. */ + uint32_t duplicatePkt; /*!< Retransmitted CIS data PDUs. */ +} LlIsoLinkQual_t; + + /*! \} */ /* LL_API_TEST */ /*! \addtogroup LL_API_EVENT @@ -813,10 +954,19 @@ enum LL_CONN_IQ_REPORT_IND, /*!< LE connection IQ report received. */ LL_CTE_REQ_FAILED_IND, /*!< LE CTE request failed received. */ LL_PER_SYNC_TRSF_RCVD_IND, /*!< LE periodic advertising sync transfer received. */ - /* --- Core Spec Milan --- */ + /* --- Core Spec 5.2 --- */ LL_CIS_EST_IND, /*!< CIS established event. */ LL_CIS_REQ_IND, /*!< CIS request event. */ + LL_CREATE_BIG_CNF, /*!< Create BIG complete. */ + LL_TERM_BIG_IND, /*!< Terminate BIG complete. */ + LL_BIG_TERM_SYNC_CNF, /*!< BIG Terminate Sync complete. */ + LL_BIG_SYNC_EST_IND, /*!< BIG sync established event. */ + LL_BIG_SYNC_LOST_IND, /*!< BIG sync lost event. */ LL_REQ_PEER_SCA_IND, /*!< Request peer SCA complete. */ + 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. */ }; /*! \brief Advertising report indication */ @@ -1031,29 +1181,6 @@ typedef struct uint8_t handle; /*!< Advertising handle. */ } LlPerAdvEnableCnf_t; -/********************** CIS ******************************/ -/*! \brief CIS established event */ -typedef struct -{ - wsfMsgHdr_t hdr; /*!< Event header. */ - uint8_t status; /*!< Status. */ - uint16_t cisHandle; /*!< CIS handle. */ - uint32_t cigSyncDelayUsec; /*!< CIG synchronization delay in usec. */ - uint32_t cisSyncDelayUsec; /*!< CIS synchronization delay in usec. */ - uint8_t phyMToS; /*!< Master to slave PHY. */ - uint8_t phySToM; /*!< Slave to master PHY. */ -} LlCisEstInd_t; - -/*! \brief CIS request event */ -typedef struct -{ - wsfMsgHdr_t hdr; /*!< Event header. */ - uint16_t aclHandle; /*!< ACL handle. */ - uint16_t cisHandle; /*!< ACL handle. */ - uint8_t cigId; /*!< CIG identifier. */ - uint8_t cisId; /*!< CIS identifier. */ -} LlCisReqInd_t; - /*! \brief Extended advertising report event types. */ enum { @@ -1181,6 +1308,98 @@ typedef struct uint8_t advClkAccuracy; /*!< Advertiser clock accuracy. */ } LlPerSyncTrsfRcvdInd_t; +/*! \brief CIS established event */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t status; /*!< Status. */ + uint16_t cisHandle; /*!< CIS handle. */ + uint32_t cigSyncDelayUsec; /*!< CIG synchronization delay in usec. */ + uint32_t cisSyncDelayUsec; /*!< CIS synchronization delay in usec. */ + uint32_t transLatUsecMToS; /*!< The maximum time, in microseconds, for transmission of SDUs of all CISes from master to slave. */ + uint32_t transLatUsecSToM; /*!< The maximum time, in microseconds, for transmission of SDUs of all CISes from slave to master. */ + uint8_t phyMToS; /*!< Master to slave PHY. */ + uint8_t phySToM; /*!< Slave to master PHY. */ + uint8_t nse; /*!< Number of subevents. */ + uint8_t bnMToS; /*!< Burst number master to slave. */ + uint8_t bnSToM; /*!< Burst number slave to master. */ + uint8_t ftMToS; /*!< Flush timeout master to slave. */ + uint8_t ftSToM; /*!< Flush timeout slave to master. */ + uint16_t maxPduMToS; /*!< Max pdu master to slave. */ + uint16_t maxPduSToM; /*!< Max pdu slave to master. */ + uint16_t isoInterval; /*!< Time between two consecutive ISO anchor points. */ +} LlCisEstInd_t; + +/*! \brief CIS request event */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint16_t aclHandle; /*!< ACL handle. */ + uint16_t cisHandle; /*!< ACL handle. */ + uint8_t cigId; /*!< CIG identifier. */ + uint8_t cisId; /*!< CIS identifier. */ +} LlCisReqInd_t; + +/*! \brief Create BIG complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t status; /*!< Status. */ + uint8_t bigHandle; /*!< BIG handle. */ + uint32_t syncDelayUsec; /*!< Synchronization delay in microseconds. */ + uint32_t transLatUsec; /*!< Transport latency, in microseconds. */ + uint8_t phy; /*!< Transmit PHY. */ + uint8_t nse; /*!< Number of Sub-Events in each BIS event in the BIG. */ + uint8_t bn; /*!< Number of new payloads in each BIS event. */ + uint8_t pto; /*!< Offset used for pre-transmissions. */ + uint8_t irc; /*!< Number of times a payload is transmitted in a BIS event. */ + uint16_t maxPdu; /*!< Maximum size of the payload. */ + uint16_t isoInterval; /*!< Time between two consecutive ISO anchor points. */ + uint8_t numBis; /*!< Number of BIS. */ + uint16_t bisHandle[LL_MAX_BIS]; /*!< Connection handles of the BIS's. */ +} LlCreateBigCnf_t; + +/*! \brief Terminate BIG complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t bigHandle; /*!< BIG handle. */ + uint8_t reason; /*!< Terminate reason. */ +} LlTerminateBigInd_t; + +/*! \brief BIG Terminate complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t status; /*!< Status. */ + uint8_t bigHandle; /*!< BIG handle. */ +} LlBigTermSyncCnf_t; + +/*! \brief Create BIG complete (Sync Established) event */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t status; /*!< Status. */ + uint8_t bigHandle; /*!< BIG handle. */ + uint32_t transLatUsec; /*!< The maximum time, in microseconds, for transmission of SDUs of all BISes. */ + uint8_t nse; /*!< Number of Sub-Events in each BIS event in the BIG. */ + uint8_t bn; /*!< Number of new payloads in each BIS event. */ + uint8_t pto; /*!< Offset used for pre-transmissions. */ + uint8_t irc; /*!< Number of times a payload is transmitted in a BIS event. */ + uint16_t maxPdu; /*!< Maximum size of the payload. */ + uint16_t isoInterval; /*!< Time between two consecutive ISO anchor points. */ + uint8_t numBis; /*!< Number of BIS. */ + uint16_t bisHandle[LL_MAX_BIS]; /*!< Connection handles of the BIS's. */ +} LlBigSyncEstInd_t; + +/*! \brief BIG sync lost event */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t bigHandle; /*!< BIG handle. */ + uint8_t reason; /*!< Sync lost reason. */ +} LlBigSyncLostInd_t; + /*! \brief LE request peer SCA complete */ typedef struct { @@ -1190,6 +1409,55 @@ typedef struct uint8_t peerSca; /*!< Peer SCA. */ } LlPeerScaCnf_t; +/*! \brief LE power reporting indication. */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t status; /*!< Status. */ + uint16_t connHandle; /*!< Connection handle. */ + uint8_t reason; /*!< Report reason. */ + uint8_t phy; /*!< PHY. */ + int8_t txPower; /*!< txPower. */ + uint8_t txPowerLimits; /*!< Transmit power level limit flags. */ + int8_t delta; /*!< Change from previous txPower. */ +} LlPowerReportInd_t; + +/*! \brief VS ISO Event complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t handle; /*!< ISO handle. */ + uint32_t evtCtr; /*!< Event counter. */ +} LlIsoEventCmplInd_t; + +/*! \brief BIG Info Advertising Report event */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint16_t syncHandle; /*!< Sync handle identifying the periodic advertising train. */ + uint8_t numBis; /*!< Number of BIS. */ + uint8_t nse; /*!< Number of Sub-Events in each BIS event in the BIG. */ + uint16_t isoInterv; /*!< ISO interval. */ + uint8_t bn; /*!< Number of new payloads in each BIS event. */ + uint8_t pto; /*!< Offset used for pre-transmissions. */ + uint8_t irc; /*!< Number of times a payload is transmitted in a BIS event. */ + uint16_t maxPdu; /*!< Maximum size of the PDU. */ + uint32_t sduInterv; /*!< SDU interval. */ + uint16_t maxSdu; /*!< Maximum size of the SDU. */ + LlPhy_t phy; /*!< Transmit PHY. */ + LlFraming_t framing; /*!< Framing mode. */ + bool_t encrypt; /*!< Encryption enabled. */ +} LlBigInfoAdvRptInd_t; + +/*! \brief LE Path loss reporting event. */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint16_t connHandle; /*!< Connection handle. */ + uint8_t curPathLoss; /*!< Current path loss. */ + uint8_t zoneEntered; /*!< Zone entered. */ +} LlPathLossThresholdEvt_t; + /*! \brief Union of all event types */ typedef union { @@ -1229,10 +1497,19 @@ typedef union LlPerAdvSyncLostInd_t perAdvSyncLostInd; /*!< LE periodic advertising sync lost. */ /* --- Core Spec 5.1 --- */ LlPerSyncTrsfRcvdInd_t perASyncTrsfRcvdInd; /*!< LE periodic advertising sync transfer received. */ - /* --- Core Spec Milan --- */ - LlCisEstInd_t cisEst; /*!< LE CIS established. */ - LlCisReqInd_t cisReq; /*!< LE CIS request. */ + /* --- Core Spec 5.2 --- */ + LlCisEstInd_t cisEstInd; /*!< LE CIS established. */ + LlCisReqInd_t cisReqInd; /*!< LE CIS request. */ + LlCreateBigCnf_t createBigCnf; /*!< LE create BIG complete. */ + LlTerminateBigInd_t termBigInd; /*!< LE terminate BIG complete. */ + LlBigTermSyncCnf_t bigTermSyncCnf; /*!< LE BIG terminate sync. */ + LlBigSyncEstInd_t bigSyncEstInd; /*!< LE BIG sync established. */ + 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. */ + LlBigInfoAdvRptInd_t bigInfoInd; /*!< LE Big Info indication. */ + LlPathLossThresholdEvt_t pathLossEvt; /*!< LE Path loss threshold reporting event. */ } LlEvt_t; /*! \brief Event callback */ @@ -1242,7 +1519,7 @@ typedef bool_t (*llEvtCback_t)(LlEvt_t *pEvent); typedef void (*llAclCback_t)(uint16_t handle, uint8_t numBufs); /*! \brief ISO callback */ -typedef void (*llIsoCback_t)(uint16_t handle, uint8_t numBufs); +typedef void (*llIsoCback_t)(uint8_t numHandles, uint16_t *pHandle, uint16_t *pNumPkts); /*! \} */ /* LL_API_EVENT */ @@ -1259,8 +1536,6 @@ typedef void (*llIsoCback_t)(uint16_t handle, uint8_t numBufs); * * \param pCfg Pointer to runtime configuration parameters. * - * \return None. - * * This function returns default value for the LL subsystem's runtime configurations. */ /*************************************************************************************************/ @@ -1272,8 +1547,6 @@ void LlGetDefaultRunTimeCfg(LlRtCfg_t *pCfg); * * \param pCfg Pointer to runtime configuration parameters (data must be static). * - * \return None. - * * This function initializes the LL subsystem's runtime configuration. * * \note This routine must be called only once before any other initialization routines. @@ -1336,8 +1609,6 @@ uint16_t LlInitExtScanMem(uint8_t *pFreeMem, uint32_t freeMemSize); /*! * \brief Initialize LL subsystem for operation as an advertising slave. * - * \return None. - * * This function initializes the LL subsystem for use as an advertising slave. */ /*************************************************************************************************/ @@ -1347,8 +1618,6 @@ void LlAdvSlaveInit(void); /*! * \brief Initialize LL subsystem for operation for extended advertising slave. * - * \return None. - * * This function initializes the LL subsystem for use as an extended advertising slave. */ /*************************************************************************************************/ @@ -1358,8 +1627,6 @@ void LlExtAdvSlaveInit(void); /*! * \brief Initialize LL subsystem for operation as a connectable slave. * - * \return None. - * * This function initializes the LL subsystem for use as an advertising and connectable slave. */ /*************************************************************************************************/ @@ -1369,8 +1636,6 @@ void LlConnSlaveInit(void); /*! * \brief Initialize LL subsystem for operation as a encryptable connectable slave. * - * \return None. - * * This function initializes the LL subsystem for use as an advertising and encryptable * connectable slave. */ @@ -1381,8 +1646,6 @@ void LlEncConnSlaveInit(void); /*! * \brief Initialize LL subsystem for operation as a scanning master. * - * \return None. - * * This function initializes the LL subsystem for use as a scanning master. */ /*************************************************************************************************/ @@ -1392,8 +1655,6 @@ void LlScanMasterInit(void); /*! * \brief Initialize LL subsystem for operation for extended scanning master. * - * \return None. - * * This function initializes the LL subsystem for use as an extended scanning master. */ /*************************************************************************************************/ @@ -1403,8 +1664,6 @@ void LlExtScanMasterInit(void); /*! * \brief Initialize LL subsystem for operation as an initiating master. * - * \return None. - * * This function initializes the LL subsystem for use as an initiating master. */ /*************************************************************************************************/ @@ -1414,8 +1673,6 @@ void LlInitMasterInit(void); /*! * \brief Initialize LL subsystem for operation as an extended initiating master. * - * \return None. - * * This function initializes the LL subsystem for use as an initiating master. */ /*************************************************************************************************/ @@ -1425,8 +1682,6 @@ void LlExtInitMasterInit(void); /*! * \brief Initialize LL subsystem for operation as a connectable master. * - * \return None. - * * This function initializes the LL subsystem for use as a scanning and initiating master. */ /*************************************************************************************************/ @@ -1436,8 +1691,6 @@ void LlConnMasterInit(void); /*! * \brief Initialize LL subsystem for operation as a encryptable connectable slave. * - * \return None. - * * This function initializes the LL subsystem for use as an advertising and encryptable * connectable slave. */ @@ -1448,8 +1701,6 @@ void LlEncConnMasterInit(void); /*! * \brief Initialize LL subsystem for operation with privacy. * - * \return None. - * * This function initializes the LL subsystem for use with privacy. */ /*************************************************************************************************/ @@ -1459,8 +1710,6 @@ void LlPrivInit(void); /*! * \brief Initialize LL subsystem for secure connections. * - * \return None. - * * This function initializes the LL subsystem for secure connections. */ /*************************************************************************************************/ @@ -1470,8 +1719,6 @@ void LlScInit(void); /*! * \brief Initialize LL subsystem for PHY features (slave). * - * \return None. - * * This function initializes the LL subsystem for slave PHY features. */ /*************************************************************************************************/ @@ -1481,8 +1728,6 @@ void LlPhySlaveInit(void); /*! * \brief Initialize LL subsystem for PHY features (master). * - * \return None. - * * This function initializes the LL subsystem for master PHY features. */ /*************************************************************************************************/ @@ -1492,8 +1737,6 @@ void LlPhyMasterInit(void); /*! * \brief Initialize LL subsystem for secure connections. * - * \return None. - * * This function initializes the LL subsystem for secure connections. */ /*************************************************************************************************/ @@ -1503,8 +1746,6 @@ void LlChannelSelection2Init(void); /*! * \brief Initialize LL subsystem for test modes. * - * \return None. - * * This function initializes the LL subsystem for test modes. */ /*************************************************************************************************/ @@ -1516,22 +1757,27 @@ void LlTestInit(void); * * \param handlerId WSF handler ID. * - * \return None. - * * This function initializes the LL subsystem. It is called once upon system initialization. * It must be called before any other function in the LL API is called. */ /*************************************************************************************************/ void LlHandlerInit(wsfHandlerId_t handlerId); +/*************************************************************************************************/ +/*! + * \brief Initialize LL subsystem for operation for power control. + * + * This function initializes the LL subsystem for power control. + */ +/*************************************************************************************************/ +void LlPowerControlInit(void); + /*************************************************************************************************/ /*! * \brief LL message dispatch handler. * * \param event WSF event. * \param pMsg WSF message. - * - * \return None. */ /*************************************************************************************************/ void LlHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); @@ -1540,8 +1786,6 @@ void LlHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); /*! * \brief Reset LL subsystem. * - * \return None. - * * Reset the LL subsystem. All active connections are closed and all radio procedures such as * scanning or advertising are terminated. */ @@ -1554,8 +1798,6 @@ void LlReset(void); * * \param evtCback Client callback function. * - * \return None. - * * This function is called by a client to register for LL events. */ /*************************************************************************************************/ @@ -1568,8 +1810,6 @@ void LlEvtRegister(llEvtCback_t evtCback); * \param sendCompCback Client ACL send complete callback function. * \param recvPendCback Client ACL receive pending callback function. * - * \return None. - * * This function is called by a client to register for ACL data. */ /*************************************************************************************************/ @@ -1579,15 +1819,13 @@ void LlAclRegister(llAclCback_t sendCompCback, llAclCback_t recvPendCback); /*! * \brief Register ISO handler. * - * \param sendCompCback Client ISO send complete callback function. - * \param recvPendCback Client ISO receive pending callback function. - * - * \return None. + * \param sendIsoCompCback Client ISO send complete callback function. + * \param recvIsoPendCback Client ISO receive pending callback function. * * This function is called by a client to register for ISO data. */ /*************************************************************************************************/ -void LlIsoRegister(llIsoCback_t sendCompCback, llIsoCback_t recvPendCback); +void LlIsoRegister(llIsoCback_t sendIsoCompCback, llIsoCback_t recvIsoPendCback); /*! \} */ /* LL_API_INIT */ @@ -1600,8 +1838,6 @@ void LlIsoRegister(llIsoCback_t sendCompCback, llIsoCback_t recvPendCback); * * \param pAddr Bluetooth device address. * - * \return None. - * * Set the BD address to be used by LL. */ /*************************************************************************************************/ @@ -1613,8 +1849,6 @@ void LlSetBdAddr(const uint8_t *pAddr); * * \param pAddr Bluetooth device address. * - * \return None. - * * Get the BD address currently used by LL or all zeros if address is not set. */ /*************************************************************************************************/ @@ -1653,8 +1887,6 @@ uint8_t LlGetRandAddr(uint8_t *pAddr); * \param pCompId Company ID. * \param pBtVer Bluetooth version. * \param pImplRev Implementation revision. - * - * \return None. */ /*************************************************************************************************/ void LlGetVersion(uint16_t *pCompId, uint8_t *pBtVer, uint16_t *pImplRev); @@ -1665,8 +1897,6 @@ void LlGetVersion(uint16_t *pCompId, uint8_t *pBtVer, uint16_t *pImplRev); * * \param pStates Supported states bitmask. * - * \return None. - * * Return the states supported by the LL. */ /*************************************************************************************************/ @@ -1678,8 +1908,6 @@ void LlGetSupStates(uint8_t *pStates); * * \param pFeatures Supported features bitmask. * - * \return None. - * * Return the LE features supported by the LL. */ /*************************************************************************************************/ @@ -1701,6 +1929,21 @@ void LlGetFeatures(uint8_t *pFeatures); /*************************************************************************************************/ uint8_t LlSetFeatures(const uint8_t *pFeatures); +/*************************************************************************************************/ +/*! + * \brief Set host feature. + * + * \param bitNum Bit position in the FeatureSet. + * \param bitVal Enable or disable feature. + * + * \return Status error code. + * + * Set or clear a bit in the feature controlled by the Host in the Link Layer FeatureSet + * stored in the Controller. + */ +/*************************************************************************************************/ +uint8_t LlSetHostFeatures(uint8_t bitNum, bool_t bitVal); + /*************************************************************************************************/ /*! * \brief Get random number. @@ -1986,22 +2229,6 @@ uint8_t LlSetValidatePublicKeyMode(uint8_t validateMode); /*************************************************************************************************/ uint8_t LlSetChannelClass(const uint8_t *pChanMap); -/*************************************************************************************************/ -/*! - * \brief Set HCI supported command - * - * \param byte Byte location of command - * \param bit Bit location of command - * \param enable Enable or disable command - * - * \return Status error code - * - * This will not set a command to supported if it is not actually supported by the device. - * It will only "emulate" non-support of supported commands. - */ -/*************************************************************************************************/ -uint8_t LlSetHciSupCmd(uint8_t byte, uint8_t bit, bool_t enable); - /*************************************************************************************************/ /*! * \brief Set operational mode flags. @@ -2022,8 +2249,6 @@ uint8_t LlSetOpFlags(uint32_t flags, bool_t enable); * * \param phyOptions PHY options. * - * \return None. - * * Set the default TX PHY options for extended adv slave primary and secondary channel. */ /*************************************************************************************************/ @@ -2040,8 +2265,6 @@ void LlSetDefaultExtAdvTxPhyOptions(const uint8_t phyOptions); * * \param advTxPwr Advertising transmit power level. * - * \return None. - * * Set the advertising transmit power. */ /*************************************************************************************************/ @@ -2117,8 +2340,6 @@ uint8_t LlSetScanRespData(uint8_t len, const uint8_t *pData); * \brief Advertising enable. * * \param enable Set to TRUE to enable advertising, FALSE to disable advertising. - * - * \return None. * Enable or disable advertising. */ @@ -2239,8 +2460,6 @@ uint8_t LlSetExtScanRespData(uint8_t handle, uint8_t op, uint8_t fragPref, uint8 * \param numAdvSets Number of elements in enaParam[]. * \param enaParam Enable parameter table. * - * \return None. - * * Enable or disable extended advertising. */ /*************************************************************************************************/ @@ -2393,8 +2612,6 @@ uint8_t LlSetExtAdvTxPhyOptions(uint8_t handle, uint8_t priPhyOpts, uint8_t secP * \param pMinTxPwr Return buffer for minimum transmit power. * \param pMaxTxPwr Return buffer for maximum transmit power. * - * \return None. - * * Read the minimum and maximum transmit powers supported by the LL. */ /*************************************************************************************************/ @@ -2407,8 +2624,6 @@ void LlReadSupTxPower(int8_t *pMinTxPwr, int8_t *pMaxTxPwr); * \param pTxPathComp Return buffer for RF transmit path compensation value. * \param pRxPathComp Return buffer for RF receive path compensation value. * - * \return None. - * * Read the RF Path Compensation Values parameter used in the Tx Power Level and RSSI calculation. */ /*************************************************************************************************/ @@ -2435,8 +2650,6 @@ uint8_t LlWriteRfPathComp(int16_t txPathComp, int16_t rxPathComp); * * \param enable Set to TRUE to enable scan reports, FALSE to disable scan reports. * - * \return None. - * * Enable or disable reports about the scanners from which an advertiser receives scan requests. */ /*************************************************************************************************/ @@ -2484,8 +2697,6 @@ uint8_t LlSetScanParam(const LlScanParam_t *pParam); * \param enable Set to TRUE to enable scanning, FALSE to disable scanning. * \param filterDup Set to TRUE to filter duplicates. * - * \return None. - * * Enable or disable scanning. This function is only used when operating in master role. */ /*************************************************************************************************/ @@ -2516,8 +2727,6 @@ uint8_t LlSetExtScanParam(uint8_t ownAddrType, uint8_t scanFiltPolicy, uint8_t s * \param duration Duration. * \param period Period. * - * \return None. - * * Enable or disable extended scanning. */ /*************************************************************************************************/ @@ -2628,8 +2837,6 @@ uint8_t LlSetPeriodicAdvRcvEnable(uint16_t syncHandle, uint8_t enable); /*! * \brief Initialize LL subsystem for PAST(Periodic advertising sync transfer). * - * \return None. - * * This function initializes the LL subsystem for PAST(Periodic advertising sync transfer). */ /*************************************************************************************************/ @@ -2789,17 +2996,42 @@ uint8_t LlGetTxPowerLevel(uint16_t handle, uint8_t type, int8_t *pLevel); /*************************************************************************************************/ /*! - * \brief Set connection's TX power level. + * \brief Get connection's enhanced TX power level and max txPower. + * + * \param handle Connection handle. + * \param phy PHY. + * \param pCurPwr Transmit power level. + * \param pMaxPwr Max power level. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlGetEnhTxPowerLevel(uint16_t handle, uint8_t phy, int8_t *pCurPwr, int8_t *pMaxPwr); + +/*************************************************************************************************/ +/*! + * \brief Set connection's TX power level (all PHYs). * * \param handle Connection handle. * \param level Transmit power level. * * \return Status error code. - * - * Set the TX power of a connection. */ /*************************************************************************************************/ -uint8_t LlSetTxPowerLevel(uint16_t handle, int8_t level); +uint8_t LlSetAllPhyTxPowerLevel(uint16_t handle, int8_t level); + +/*************************************************************************************************/ +/*! + * \brief Set connection's TX power level for a PHY. + * + * \param handle Connection handle. + * \param level Transmit power level. + * \param phy PHY txPower to change. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlSetPhyTxPowerLevel(uint16_t handle, int8_t level, uint8_t phy); /*************************************************************************************************/ /*! @@ -2836,7 +3068,7 @@ uint8_t LlRemoteConnParamReqReply(uint16_t handle, const LlConnSpec_t *pConnSpec * \param handle Connection handle. * \param reason Reason code. * - * \return None. + * \return Status error code. * * Negative reply to a connection parameter request. */ @@ -2894,8 +3126,6 @@ uint8_t LlSetDataLen(uint16_t handle, uint16_t txLen, uint16_t txTime); * \param pMaxTxLen Maximum number of payload bytes for a Data PDU * \param pMaxTxTime Maximum microseconds for a Data PDU * - * \return None. - * * Suggested length and microseconds that the local Controller should use to transmit a * single Link Layer Data Channel PDU. */ @@ -2926,8 +3156,6 @@ uint8_t LlWriteDefaultDataLen(uint16_t maxTxLen, uint16_t maxTxTime); * \param pMaxRxLen Maximum number of payload bytes for a Rx Data PDU * \param pMaxRxTime Maximum microseconds for a Rx Data PDU * - * \return None. - * * Read the Controller's maximum supported payload octets and packet duration times for * transmission and reception. */ @@ -2965,6 +3193,18 @@ uint8_t LlReadPhy(uint16_t handle, uint8_t *pTxPhy, uint8_t *pRxPhy); /*************************************************************************************************/ uint8_t LlSetDefaultPhy(uint8_t allPhys, uint8_t txPhys, uint8_t rxPhys); +/*************************************************************************************************/ +/*! + * \brief Validate if specified PHYs are supported by LL. + * + * \param txPhys Preferred transmitter PHYs. + * \param rxPhys Preferred receiver PHYs. + * + * \return TRUE if all specified PHYs are supported. + */ +/*************************************************************************************************/ +bool_t llValidatePhySupport(uint8_t txPhys, uint8_t rxPhys); + /*************************************************************************************************/ /*! * \brief Set PHY for a connection. @@ -3017,12 +3257,12 @@ uint8_t LlGetPeerMinUsedChan(uint16_t handle, uint8_t *pPeerMinUsedChan); /*! * \brief Used to read the sleep clock accuracy of the peer device. * - * \param aclHandle Handle of the ACL. + * \param handle Handle of the ACL. * * \return Status error code. */ /*************************************************************************************************/ -uint8_t LlRequestPeerSca(uint16_t aclHandle); +uint8_t LlRequestPeerSca(uint16_t handle); /*! \} */ /* LL_API_CONN */ @@ -3064,8 +3304,6 @@ uint8_t LlExtCreateConn(const LlExtInitParam_t *pInitParam, const LlExtInitScanP /*! * \brief Cancel a create connection operation. * - * \return None. - * * Cancel a connection before it is established. This function is only used when operating * in master role. */ @@ -3253,14 +3491,24 @@ uint8_t LlGetIsoTxBufs(void); /*************************************************************************************************/ uint8_t LlGetIsoRxBufs(void); +/*************************************************************************************************/ +/*! + * \brief Read ISO link Quality stats. + * + * \param handle connection handle. + * \param pStats link quality statistics. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlReadIsoLinkQual(uint16_t handle, LlIsoLinkQual_t * pStats); + /*************************************************************************************************/ /*! * \brief Send an ACL data packet. * * \param pData Data buffer * - * \return None. - * * Send an ACL data packet. pData points to an ACL buffer formatted according to [1]; the host * must set the connection handle, flags, and length fields in the buffer. */ @@ -3273,12 +3521,10 @@ void LlSendAclData(uint8_t *pData); * * \return Data buffer. * - * Receive an ACL data packet. This function returns a pointer to an ACL buffer formatted - * according to [1]. The host must parse the header to determine the connection handle, flags, - * and length fields. If no ACL buffers are available this function returns NULL. + * Receive an ACL data packet. If no ACL buffers are available this function returns NULL. * - * The host must deallocate the buffer by calling WsfMsgFree() and call LlRecvBufCmpl() to - * update LL accounting. + * \note The host must deallocate the buffer by calling WsfMsgFree() and call LlRecvBufCmpl() to + * update LL accounting. */ /*************************************************************************************************/ uint8_t *LlRecvAclData(void); @@ -3289,8 +3535,6 @@ uint8_t *LlRecvAclData(void); * * \param numBufs Number of completed packets. * - * \return None. - * * Indicate that received ACL data buffer has been deallocated. */ /*************************************************************************************************/ @@ -3403,6 +3647,133 @@ uint8_t LlSetTxTestErrorPattern(uint32_t pattern); /*************************************************************************************************/ uint8_t LlModifySleepClockAccuracy(uint8_t action); +/*************************************************************************************************/ +/*! + * \brief Enable ISO Tx test. + * + * \param handle CIS or BIS handle. + * \param pldType Payload type. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlIsoTxTest(uint16_t handle, uint8_t pldType); + +/*************************************************************************************************/ +/*! + * \brief Enable ISO Rx test. + * + * \param handle CIS or BIS handle. + * \param pldType Payload type. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlIsoRxTest(uint16_t handle, uint8_t pldType); + +/*************************************************************************************************/ +/*! + * \brief ISO read test counters. + * + * \param handle CIS or BIS handle. + * \param pCtr Test Counter. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlIsoReadTestCounter(uint16_t handle, LlIsoTestCtrs_t *pCtr); + +/*************************************************************************************************/ +/*! + * \brief Terminate ISO Tx or Rx test. + * + * \param handle CIS or BIS handle. + * \param pCtr Test counters. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlIsoTestEnd(uint16_t handle, LlIsoTestCtrs_t *pCtr); + +/*************************************************************************************************/ +/*! + * \brief Set transmit power change reporting enable. + * + * \param handle Connection handle. + * \param enableLocal Enable local reporting. + * \param enableRemote Enable remote reporting. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlSetTxPowerReporting(uint16_t handle, uint8_t enableLocal, uint8_t enableRemote); + +/*************************************************************************************************/ +/*! + * \brief Set enable state for power monitoring. + * + * \param handle Handle identifier for connection. + * \param enable Enable status for power monitor. + * + * \return Status error code. + * + * \note Path loss must be disabled. + */ +/*************************************************************************************************/ +uint8_t LlSetPowerMonitorEnable(uint16_t handle, bool_t enable); + +/*************************************************************************************************/ +/*! + * \brief Set path loss monitoring parameters. + * + * \param handle Handle identifier for connection. + * \param highThresh High extreme threshold. + * \param highHyst High extreme hysteresis. + * \param lowThresh Low extreme threshold. + * \param lowHyst Low extreme hysteresis. + * \param minTime Minimum time spent to trigger event generation. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlSetPathLossReportingParams(uint16_t handle, uint8_t highThresh, uint8_t highHyst, uint8_t lowThresh, uint8_t lowHyst, uint16_t minTime); + +/*************************************************************************************************/ +/*! + * \brief Set path loss enable. + * + * \param handle Connection handle. + * \param enable Enable flag. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlSetPathLossReportingEnable(uint16_t handle, uint8_t enable); + +/*************************************************************************************************/ +/*! + * \brief Request change to or read peer txPower + * + * \param handle Connection handle. + * \param delta Requested change. + * \param phy Phy this change requests the change on. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlPowerCtrlReq(uint16_t handle, int8_t delta, uint8_t phy); + +/*************************************************************************************************/ +/*! + * \brief ISO event complete enable. + * + * \param enable Set to TRUE to enable, FALSE to disable. + * + * Enable or disable reports about the scanners from which an advertiser receives scan requests. + */ +/*************************************************************************************************/ +void LlIsoEventCompleteEnable(uint8_t enable); + /*! \} */ /* LL_API_TEST */ /*! \addtogroup LL_API_DIAG @@ -3503,7 +3874,6 @@ uint16_t LlStatsGetHandlerWatermarkUsec(void); /*! \} */ /* LL_API_DIAG */ - /*! \addtogroup LL_API_CIS * \{ */ @@ -3512,13 +3882,13 @@ uint16_t LlStatsGetHandlerWatermarkUsec(void); * \brief Used by a master host to set the parameters of all connected isochronous streams * associated with a connected isochronous group in the controller. * - * \param pSetCigParam CIG parameters. - * \param pCisHandles Return buffer for the connected isochronous stream handles. + * \param pCigParam CIG parameters. + * \param pCisHandles Return buffer for the connected isochronous handles. * * \return Status error code. */ /*************************************************************************************************/ -uint8_t LlSetCigParams(LlCisCigParams_t *pSetCigParam, uint16_t *pCisHandles); +uint8_t LlSetCigParams(LlCisCigParams_t *pCigParam, uint16_t *pCisHandles); /*************************************************************************************************/ /*! @@ -3526,7 +3896,7 @@ uint8_t LlSetCigParams(LlCisCigParams_t *pSetCigParam, uint16_t *pCisHandles); * associated with a connected isochronous group in the controller for testing purpose. * * \param pSetCigParamTest CIG test parameters. - * \param pCisHandles Return buffer for the connected isochronous stream handles. + * \param pCisHandles Return buffer for the connected isochronous handles. * * \return Status error code. */ @@ -3583,34 +3953,106 @@ uint8_t LlRejectCisReq(uint16_t cisHandle, uint8_t reason); /*************************************************************************************************/ /*! - * \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 by a broadcaster host to command is used to create one or more BISes of a BIG + * in the controller. * - * \param pSetupDataPathParam Parameters for setup ISO data path. + * \param pCreateBig Create BIG parameters. * * \return Status error code. */ /*************************************************************************************************/ -uint8_t LlSetupIsoDataPath(LlIsoSetupDataPathParams_t *pSetupDataPathParam); +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 + * Packet_Sequence_Number on a CIS or BIS identified by the Connection_Handle. + * + * \param handle BIS or CIS handle. + * \param pPktSn Packet sequence number. + * \param pTs Timestamp. + * \param pTimeOffs Time offset. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlReadIsoTxSync(uint16_t handle, uint16_t *pPktSn, uint32_t *pTs, uint32_t *pTimeOffs); + +/*************************************************************************************************/ +/*! + * \brief Used to identify and enable the isochronous data path between the host and the + * controller for each connected isochronous or broadcast isochronous stream. + * + * \param pSetupDataPath Parameters for setup ISO data path. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlSetupIsoDataPath(LlIsoSetupDataPath_t *pSetupDataPath); /*************************************************************************************************/ /*! * \brief Used to remove the isochronous data path associated with the - * connected isochronous stream or broadcast isochronous stream. + * connected isochronous or broadcast isochronous stream. * - * \param isoHandle Handle for CIS or BIS. + * \param handle Handle for CIS or BIS. + * \param dpDir Direction of data path to remove. * * \return Status error code. */ /*************************************************************************************************/ -uint8_t LlRemoveIsoDataPath(uint16_t isoHandle); +uint8_t LlRemoveIsoDataPath(uint16_t handle, uint8_t dpDir); /*************************************************************************************************/ /*! * \brief Initialize LL subsystem for operation for slave connected isochronous stream. * - * \return None. - * * This function initializes the LL subsystem for use as a slave connected isochronous stream. */ /*************************************************************************************************/ @@ -3620,8 +4062,6 @@ void LlCisSlaveInit(void); /*! * \brief Initialize LL subsystem for operation for master connected isochronous stream. * - * \return None. - * * This function initializes the LL subsystem for use as a master connected isochronous stream. */ /*************************************************************************************************/ @@ -3644,6 +4084,41 @@ void LlCisMasterInit(void); /*************************************************************************************************/ uint16_t LlInitCisMem(uint8_t *pFreeMem, uint32_t freeMemSize); +/*************************************************************************************************/ +/*! + * \brief Initialize LL subsystem for operation for slave broadcast isochronous stream. + * + * This function initializes the LL subsystem for use as a slave broadcast isochronous stream. + */ +/*************************************************************************************************/ +void LlBisSlaveInit(void); + +/*************************************************************************************************/ +/*! + * \brief Initialize LL subsystem for operation for master broadcast isochronous stream. + * + * This function initializes the LL subsystem for use as a master broadcast isochronous stream. + */ +/*************************************************************************************************/ +void LlBisMasterInit(void); + +/*************************************************************************************************/ +/*! + * \brief Initialize memory for BIS. + * + * \param pFreeMem Pointer to free memory. + * \param freeMemSize Size of pFreeMem. + * + * \return Amount of free memory consumed. + * + * This function allocates memory for BIS. + * + * \note This routine must be called after LlInitRunTimeCfg() but only once before any + * other initialization routines. + */ +/*************************************************************************************************/ +uint16_t LlInitBisMem(uint8_t *pFreeMem, uint32_t freeMemSize); + /*************************************************************************************************/ /*! * \brief Initialize memory for ISO. @@ -3661,14 +4136,21 @@ uint16_t LlInitCisMem(uint8_t *pFreeMem, uint32_t freeMemSize); /*************************************************************************************************/ uint16_t LlInitIsoMem(uint8_t *pFreeMem, uint32_t freeMemSize); +/*************************************************************************************************/ +/*! + * \brief Initialize LL for use with an audio codec. + * + * Assign codec functions for direct LL audio streaming. + */ +/*************************************************************************************************/ +void LlInitCodec(void); + /*************************************************************************************************/ /*! * \brief Send an ISO data packet. * * \param pData Data buffer * - * \return None. - * * Send an ISO data packet. pData points to an ISO buffer formatted according to [1]; the host * must set the connection handle, flags, and length fields in the buffer. */ @@ -3681,12 +4163,10 @@ void LlSendIsoData(uint8_t *pData); * * \return Data buffer. * - * Receive an ISO data packet. This function returns a pointer to an ISO buffer formatted - * according to [1]. The host must parse the header to determine the connection handle, flags, - * and length fields. If no ISO buffers are available this function returns NULL. + * Receive an ISO data packet. If no ISO buffers are available this function returns NULL. * - * The host must deallocate the buffer by calling WsfMsgFree() and call LlRecvBufCmpl() to - * update LL accounting. + * \note The host must deallocate the buffer by calling WsfMsgFree() and call LlRecvBufCmpl() to + * update LL accounting. */ /*************************************************************************************************/ uint8_t *LlRecvIsoData(void); @@ -3697,55 +4177,11 @@ uint8_t *LlRecvIsoData(void); * * \param numBufs Number of completed packets. * - * \return None. - * * Indicate that received ISO data buffer has been deallocated. */ /*************************************************************************************************/ void LlRecvIsoDataComplete(uint8_t numBufs); -/*************************************************************************************************/ -/*! - * \brief Enable ISO Tx test. - * - * \param isoHandle CIS or BIS handle. - * \param plLen Payload length type. - * - * \return Status error code. - * - */ -/*************************************************************************************************/ -uint8_t LlIsoTxTest(uint16_t isoHandle, uint8_t plLen); - -/*************************************************************************************************/ -/*! - * \brief Enable ISO Rx test. - * - * \param isoHandle CIS or BIS handle. - * \param plLen Payload length type. - * - * \return Status error code. - * - */ -/*************************************************************************************************/ -uint8_t LlIsoRxTest(uint16_t isoHandle, uint8_t plLen); - -/*************************************************************************************************/ -/*! - * \brief ISO read test counter. - * - * \param isoHandle CIS or BIS handle. - * \param pRcvedPlCounter Pointer to the received payload counter as return parameter. - * \param pMissedPlCounter Pointer to the missed payload counter as return parameter. - * \param pFailedPlCounter Pointer to the failed payload counter as return parameter. - * \param termTest TRUE if terminate the test, FALSE otherwise. - * - * \return Status error code. - * - */ -/*************************************************************************************************/ -uint8_t LlIsoReadTestCounter(uint16_t isoHandle, uint32_t *pRcvedPlCounter, uint32_t *pMissedPlCounter, uint32_t *pFailedPlCounter, bool_t termTest); - /*! \} */ /* LL_API_CIS */ #ifdef __cplusplus diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/ll_defs.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/ll_defs.h deleted file mode 100644 index 3e50ac5172..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/ll_defs.h +++ /dev/null @@ -1,492 +0,0 @@ -/* Copyright (c) 2019 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. - */ - -/*************************************************************************************************/ -/*! - * \file - * \brief Link layer constant definitions. - */ -/*************************************************************************************************/ - -#ifndef LL_DEFS_H -#define LL_DEFS_H - -#include "wsf_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/************************************************************************************************** - Constants -**************************************************************************************************/ - -/*** Version ***/ - -#define LL_VER_BT_CORE_SPEC_4_0 0x06 /*!< Bluetooth core specification 4.0 */ -#define LL_VER_BT_CORE_SPEC_4_1 0x07 /*!< Bluetooth core specification 4.1 */ -#define LL_VER_BT_CORE_SPEC_4_2 0x08 /*!< Bluetooth core specification 4.2 */ -#define LL_VER_BT_CORE_SPEC_5_0 0x09 /*!< Bluetooth core specification 5.0 */ -#define LL_VER_BT_CORE_SPEC_5_1 0x0A /*!< Bluetooth core specification 5.1 */ -#define LL_VER_BT_CORE_SPEC_MILAN 0x0B /*!< Bluetooth core specification Milan */ -#define LL_VER_BT_CORE_SPEC_SYDNEY 0x0C /*!< Bluetooth core specification Sydney */ - -#define LL_COMP_ID_ARM 0x005F /*!< ARM Ltd. company ID. */ - -/*** Common ***/ - -#define LL_RSSI_MIN -127 /*!< Minimum RSSI value. */ -#define LL_RSSI_MAX 20 /*!< Maximum RSSI value. */ -#define LL_RSSI_NOT_AVAIL 127 /*!< RSSI is not available. */ - -#define LL_CRC_LEN 3 /*!< CRC length. */ -#define LL_AA_LEN 4 /*!< Access address length. */ -#define LL_PREAMBLE_LEN_1M 1 /*!< Preamble length (LE 1M PHY). */ -#define LL_PREAMBLE_LEN_2M 2 /*!< Preamble length (LE 2M PHY). */ -#define LL_PREAMBLE_LEN_CODED_BITS 10 /*!< Preamble length (LE Coded PHY). */ -#define LL_CI_LEN_BITS 2 /*!< Coding indicator length (LE Coded PHY). */ -#define LL_TERM1_LEN_BITS 3 /*!< TERM1 length (LE Coded PHY). */ -#define LL_TERM2_LEN_BITS 3 /*!< TERM2 length (LE Coded PHY). */ - -#define LL_RAND_ADDR_TYPE_MASK UINT64_C(0xC00000000000) /*!< BD Random Address type mask. */ -#define LL_RAND_ADDR_TYPE_STATIC UINT64_C(0xC00000000000) /*!< Static Random Address type. */ -#define LL_RAND_ADDR_TYPE_RPA UINT64_C(0x400000000000) /*!< Resolvable Private Address type. */ -#define LL_RAND_ADDR_TYPE_NRPA UINT64_C(0x000000000000) /*!< Non-Resolvable Private Address type. */ - -/*** Advertising PDU ***/ - -/*! \brief Advertising channel PDU types. */ -enum -{ - /* --- Core Spec 4.0 --- */ - LL_PDU_ADV_IND = 0, /*!< Connectable undirected advertising PDU. */ - LL_PDU_ADV_DIRECT_IND = 1, /*!< Connectable directed advertising PDU. */ - LL_PDU_ADV_NONCONN_IND = 2, /*!< Non-connectable undirected advertising PDU. */ - LL_PDU_SCAN_REQ = 3, /*!< Scan request PDU. */ - LL_PDU_SCAN_RSP = 4, /*!< Scan response PDU. */ - LL_PDU_CONNECT_IND = 5, /*!< Connect indication PDU. */ - LL_PDU_ADV_SCAN_IND = 6, /*!< Scannable undirected advertising PDU. */ - /* --- Core Spec 5.0 --- */ - LL_PDU_AUX_SCAN_REQ = 3, /*!< Auxiliary scan request PDU. */ - LL_PDU_AUX_CONNECT_REQ = 5, /*!< Auxiliary connect request PDU. */ - LL_PDU_ADV_EXT_IND = 7, /*!< Extended advertising PDU. */ - LL_PDU_AUX_ADV_IND = 7, /*!< Auxiliary advertising PDU. */ - LL_PDU_AUX_SCAN_RSP = 7, /*!< Auxiliary scan response PDU. */ - LL_PDU_AUX_SYNC_IND = 7, /*!< Auxiliary synchronize PDU. */ - LL_PDU_AUX_CHAIN_IND = 7, /*!< Auxiliary chain PDU. */ - LL_PDU_AUX_CONNECT_RSP = 8, /*!< Auxiliary connect response PDU. */ -}; - -#define LL_SCAN_REQ_PDU_LEN 12 /*!< Size of a scan request PDU. */ -#define LL_CONN_IND_PDU_LEN 34 /*!< Size of a connect indication PDU. */ -#define LL_CONN_RSP_PDU_LEN 14 /*!< Size of an auxiliary connect response PDU. */ - -#define LL_CHAN_ADV_MIN_IDX 37 /*!< Minimum advertising channel index. */ -#define LL_CHAN_ADV_MAX_IDX 39 /*!< Maximum advertising channel index. */ -#define LL_NUM_CHAN_ADV 3 /*!< Total number of advertising channels. */ - -#define LL_ADVBU_MAX_LEN 31 /*!< Maximum advertising channel host data length. */ -#define LL_ADVB_MAX_LEN 39 /*!< Maximum advertising channel PDU length. */ -#define LL_ADVB_MIN_LEN (LL_ADVB_MAX_LEN - LL_ADVBU_MAX_LEN) /*!< Minimum advertising channel packet length. */ -#define LL_ADVB_MAX_TIME_1M ((LL_BLE_US_PER_BYTE_1M * (LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_1M) - /*!< Maximum time for a 1M advertising channel PDU. */ -#define LL_ADVB_MAX_TIME_2M ((LL_BLE_US_PER_BYTE_2M * (LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_2M) - /*!< Maximum time for a 2M advertising channel PDU. */ -#define LL_ADVB_MAX_TIME_S2 ((LL_BLE_US_PER_BYTE_CODED_S2 * (LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_CODED_S2) - /*!< Maximum time for a Coded S2 advertising channel PDU. */ -#define LL_ADVB_MAX_TIME_S8 ((LL_BLE_US_PER_BYTE_CODED_S8 * (LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_CODED_S8) - /*!< Maximum time for a Coded S8 advertising channel PDU. */ - -#define LL_ADV_PKT_MAX_USEC LL_ADVB_MAX_TIME_1M /*!< Maximum time in microseconds for an advertising packet. */ -#define LL_SCAN_REQ_MAX_USEC ((8 * (LL_ADV_PREFIX_LEN + LL_SCAN_PREFIX_LEN)) + LL_MIN_PKT_TIME_US_1M) - /*!< Maximum time in microseconds for a scan request packet. */ -#define LL_SCAN_RSP_MAX_USEC LL_ADVB_MAX_TIME_1M /*!< Maximum time in microseconds for a scan response packet. */ - -#define LL_ADV_HDR_LEN 2 /*!< Advertising channel header length. */ -#define LL_ADV_HDR_TYPE_OFFS 0 /*!< Advertising header type offset. */ -#define LL_ADV_HDR_TYPE_MSK 0x0F /*!< Advertising header type mask. */ -#define LL_ADV_HDR_LEN_OFFS 1 /*!< Advertising header length offset. */ -#define LL_ADV_HDR_LEN_MSK 0x3F /*!< Advertising header length mask for 4.2. */ -#define LL_ADV_EXT_HDR_LEN_MSK 0xFF /*!< Advertising extension header length mask for 5.0. */ -#define LL_ADV_PREFIX_LEN 6 /*!< Advertising PDU payload prefix length (AdvA). */ -#define LL_SCAN_PREFIX_LEN 6 /*!< Scan request/response PDU payload prefix length (AdvA). */ - -#define LL_ADV_ACCESS_ADDR UINT32_C(0x8E89BED6) /*!< Advertising channel access address. */ -#define LL_ADV_CRC_INIT UINT32_C(0x555555) /*!< Advertising CRC initial value. */ - -#define LL_DIR_ADV_INTER_TICKS 6 /*!< Advertising interval between directed advertising events (3.75 ms). */ -#define LL_DIR_ADV_DUR_TICKS 2048 /*!< Maximum high duty cycle directed advertising duration (1.28 seconds). */ - -/*! \brief Extended header bit definition. */ -enum -{ - LL_EXT_HDR_ADV_ADDR_BIT = (1 << 0), /*!< Extended header AdvA bit. */ - LL_EXT_HDR_TGT_ADDR_BIT = (1 << 1), /*!< Extended header TargetA bit. */ - LL_EXT_HDR_CTE_INFO_BIT = (1 << 2), /*!< Extended header CTEInfo bit. */ - LL_EXT_HDR_ADI_BIT = (1 << 3), /*!< Extended header AdvDataInfo bit. */ - LL_EXT_HDR_AUX_PTR_BIT = (1 << 4), /*!< Extended header AuxPtr bit. */ - LL_EXT_HDR_SYNC_INFO_BIT = (1 << 5), /*!< Extended header SyncInfo bit. */ - LL_EXT_HDR_TX_PWR_BIT = (1 << 6), /*!< Extended header TxPower bit. */ -}; - -#define LL_MAX_ADV_HANDLE 0xEF /*!< Maximum advertising handle. */ -#define LL_MAX_ADV_SID 0x0F /*!< Maximum advertising SID */ - -#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 */ -#define LL_EXT_ADVBU_MAX_LEN 251 /*!< Maximum extended advertising channel PDU host data length. */ -#define LL_EXT_ADVB_MAX_LEN 257 /*!< Maximum extended advertising channel PDU length. */ -#define LL_EXT_ADVB_NORMAL_LEN 50 /*!< Normal extended advertising channel PDU length. */ - -#define LL_EXT_HDR_ACAD_MAX_LEN LL_EXT_ADV_HDR_MAX_LEN - LL_EXT_ADV_HDR_MIN_LEN - LL_EXT_HDR_FLAG_LEN /*!< Maximum possible ACAD length (Max extended header minus ExtHdrLen, AdvMode, and extended header flag field. */ - -#define LL_EXT_ADVB_MAX_TIME_1M ((LL_BLE_US_PER_BYTE_1M * (LL_EXT_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_1M) - /*!< Maximum time for a 1M advertising channel PDU. */ -#define LL_EXT_ADVB_MAX_TIME_2M ((LL_BLE_US_PER_BYTE_2M * (LL_EXT_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_2M) - /*!< Maximum time for a 2M advertising channel PDU. */ -#define LL_EXT_ADVB_MAX_TIME_S2 ((LL_BLE_US_PER_BYTE_CODED_S2 * (LL_EXT_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_CODED_S2) - /*!< Maximum time for a Coded S2 advertising channel PDU. */ -#define LL_EXT_ADVB_MAX_TIME_S8 ((LL_BLE_US_PER_BYTE_CODED_S8 * (LL_EXT_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_CODED_S8) - /*!< Maximum time for a Coded S8 advertising channel PDU. */ -#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_SYNC_MIN_TIMEOUT 0x000A /*!< Minimum synchronization timeout. */ -#define LL_SYNC_MAX_TIMEOUT 0x4000 /*!< Maximum synchronization timeout. */ -#define LL_SYNC_MAX_SKIP 0x01F3 /*!< Maximum synchronization skip. */ -#define LL_SYNC_MAX_HANDLE 0x0EFF /*!< Maximum synchronization handle. */ - -#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_INFO_LEN 18 /*!< Size of SyncInfo field. */ - -/*! \brief Periodic sync transfer receive mode. */ -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 -}; - -/*** Data PDU ***/ - -/*! \brief Data channel LL Control PDU types. */ -enum -{ - /* --- Core Spec 4.0 --- */ - LL_PDU_CONN_UPDATE_IND = 0x00, /*!< Connection update indication PDU. */ - LL_PDU_CHANNEL_MAP_IND = 0x01, /*!< Channel map indication PDU. */ - LL_PDU_TERMINATE_IND = 0x02, /*!< Terminate indication PDU. */ - LL_PDU_ENC_REQ = 0x03, /*!< Encryption request PDU. */ - LL_PDU_ENC_RSP = 0x04, /*!< Encryption response PDU. */ - LL_PDU_START_ENC_REQ = 0x05, /*!< Start encryption request PDU. */ - LL_PDU_START_ENC_RSP = 0x06, /*!< Start encryption response PDU. */ - LL_PDU_UNKNOWN_RSP = 0x07, /*!< Unknown response PDU. */ - LL_PDU_FEATURE_REQ = 0x08, /*!< Feature request PDU. */ - LL_PDU_FEATURE_RSP = 0x09, /*!< Feature response PDU. */ - LL_PDU_PAUSE_ENC_REQ = 0x0A, /*!< Pause encryption request PDU. */ - LL_PDU_PAUSE_ENC_RSP = 0x0B, /*!< Pause encryption response PDU. */ - LL_PDU_VERSION_IND = 0x0C, /*!< Version indication PDU. */ - LL_PDU_REJECT_IND = 0x0D, /*!< Reject indication PDU. */ - /* --- Core Spec 4.2 --- */ - LL_PDU_SLV_FEATURE_REQ = 0x0E, /*!< Slave feature request PDU. */ - LL_PDU_CONN_PARAM_REQ = 0x0F, /*!< Connection parameter request PDU. */ - LL_PDU_CONN_PARAM_RSP = 0x10, /*!< Connection parameter response PDU. */ - LL_PDU_REJECT_EXT_IND = 0x11, /*!< Reject extended indication PDU. */ - LL_PDU_PING_REQ = 0x12, /*!< Ping request PDU. */ - LL_PDU_PING_RSP = 0x13, /*!< Ping response PDU. */ - LL_PDU_LENGTH_REQ = 0x14, /*!< Data length request PDU. */ - LL_PDU_LENGTH_RSP = 0x15, /*!< Data length response PDU. */ - /* --- Core Spec 5.0 --- */ - LL_PDU_PHY_REQ = 0x16, /*!< PHY request PDU. */ - LL_PDU_PHY_RSP = 0x17, /*!< PHY response PDU. */ - LL_PDU_PHY_UPDATE_IND = 0x18, /*!< PHY update indication PDU. */ - LL_PDU_MIN_USED_CHAN_IND = 0x19, /*!< Minimum used channels indication PDU. */ - /* --- Core Spec 5.1 --- */ - // 0x1A 0x1B for AOA AOD, 0x1C for PAST 0x20 RFU - LL_PDU_PERIODIC_SYNC_IND = 0x1C, /*!< Periodic sync indication PDU. */ - /* --- Core Spec Milan --- */ - LL_PDU_PEER_SCA_REQ = 0x1D, /*!< Peer SCA request PDU. */ - LL_PDU_PEER_SCA_RSP = 0x1E, /*!< Peer SCA response PDU. */ - LL_PDU_CIS_REQ = 0x1F, /*!< CIS request PDU. */ - LL_PDU_CIS_RSP = 0x21, /*!< CIS response PDU. */ - LL_PDU_CIS_IND = 0x22, /*!< CIS indication PDU. */ - LL_PDU_CIS_TERM_IND = 0x23, /*!< CIS terminate indication PDU. */ - - LL_PDU_UNSPECIFIED = 0xFF /*!< Unspecified PDU. */ -}; - -/* Data PDU length */ -/* --- Core Spec 4.0 --- */ -#define LL_CONN_UPD_IND_PDU_LEN 12 /*!< Connection update indication PDU length. */ -#define LL_CHAN_MAP_IND_PDU_LEN 8 /*!< Channel map indication PDU length. */ -#define LL_TERMINATE_IND_PDU_LEN 2 /*!< Terminate indication PDU length. */ -#define LL_ENC_REQ_LEN 23 /*!< Encryption request PDU length. */ -#define LL_ENC_RSP_LEN 13 /*!< Encryption response PDU length. */ -#define LL_START_ENC_LEN 1 /*!< Start encryption request/response PDU length. */ -#define LL_UNKNOWN_RSP_LEN 2 /*!< Unknown response PDU length. */ -#define LL_FEATURE_PDU_LEN 9 /*!< Feature request/response PDU length. */ -#define LL_PAUSE_ENC_LEN 1 /*!< Pause encryption request/response PDU length. */ -#define LL_VERSION_IND_PDU_LEN 6 /*!< Version indication PDU length. */ -#define LL_REJECT_IND_PDU_LEN 2 /*!< Reject indication PDU length. */ -/* --- Core Spec 4.2 --- */ -#define LL_CONN_PARAM_PDU_LEN 24 /*!< Connection parameter request or response PDU length. */ -#define LL_REJECT_EXT_IND_PDU_LEN 3 /*!< Reject extended indication PDU length. */ -#define LL_PING_PDU_LEN 1 /*!< Ping request/response PDU length. */ -#define LL_DATA_LEN_PDU_LEN 9 /*!< Data length request or response PDU length. */ -/* --- Core Spec 5.0 --- */ -#define LL_PHY_PDU_LEN 3 /*!< PHY request/response PDU length. */ -#define LL_PHY_UPD_IND_PDU_LEN 5 /*!< PHY update indication PDU length. */ -#define LL_MIN_USED_CHAN_PDU_LEN 3 /*!< Minimum used channels indication PDU length. */ -/* --- Core Spec 5.1 --- */ -#define LL_PERIODIC_SYNC_PDU_LEN 35 /*!< Periodic sync indication PDU length. */ -/* --- Core Spec Milan --- */ -#define LL_PEER_SCA_REQ_LEN 2 /*!< Peer SCA request PDU length. */ -#define LL_PEER_SCA_RSP_LEN 2 /*!< Peer SCA response PDU length. */ -#define LL_CIS_REQ_LEN 34 /*!< CIS request PDU length. */ -#define LL_CIS_RSP_LEN 9 /*!< CIS response PDU length. */ -#define LL_CIS_IND_LEN 16 /*!< CIS indication PDU length. */ -#define LL_CIS_TERM_LEN 4 /*!< CIS termination PDU length. */ -#define LL_CIS_SDU_CONFIG_REQ_LEN 13 /*!< CIS SDU config request PDU length. */ -#define LL_CIS_SDU_CONFIG_RSP_LEN 4 /*!< CIS SDU config response PDU length. */ - -#define LL_EMPTY_PDU_LEN 2 /*!< Length of an empty data PDU. */ - -#define LL_DATA_HDR_LEN 2 /*!< Data channel header length. */ -#define LL_DATA_MIC_LEN 4 /*!< Data channel PDU MIC length. */ - -#define LL_DATA_HDR_LLID_MSK 0x03 /*!< Data PDU LLID mask. */ -#define LL_DATA_HDR_LEN_MSK 0xFF /*!< Data header length mask. BLE 4.2 data len extension allows 8 bits. */ - -#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. */ - -#define LL_ISO_DATA_HDR_LEN 2 /*!< ISO data PDU header length. */ -#define LL_ISO_DATA_MIC_LEN 4 /*!< ISO data PDU MIC length. */ - -#define LL_ISO_DATA_HDR_LLID_MSK 0x03 /*!< ISO data PDU LLID mask. */ -#define LL_ISO_DATA_HDR_LEN_MSK 0xFF /*!< ISO Data header length mask. */ - -/*! \brief Data PDU LLID types. */ -enum -{ - LL_LLID_VS_PDU = 0x00, /*!< Vendor specific PDU. */ - /* N.B. next two enumerations intentionally use identical values. */ - LL_LLID_EMPTY_PDU = 0x01, /*!< Empty PDU. */ - LL_LLID_CONT_PDU = 0x01, /*!< Data PDU: continuation fragment of an L2CAP message. */ - LL_LLID_START_PDU = 0x02, /*!< Data PDU: start of an L2CAP message or a complete L2CAP message with no fragmentation. */ - LL_LLID_CTRL_PDU = 0x03, /*!< Control PDU. */ -}; - -/*** Encryption ***/ - -#define LL_ECC_KEY_LEN 32 /*!< ECC key length. */ - -#define LL_DEF_RES_ADDR_TO_SEC 900 /*!< Default resolvable address timeout in seconds. */ - -#define LL_RAND_LEN 8 /*!< Length of random number */ -#define LL_KEY_LEN 16 /*!< Encryption key length. */ -#define LL_SKD_LEN LL_KEY_LEN /*!< Session key diversifier length. */ -#define LL_IV_LEN 8 /*!< Initialization vector length. */ - -#define LL_DEF_AUTH_TO_MS 30000 /*!< Default authentication timeout in milliseconds. */ - -/*** LLCP ***/ - -#define LL_DATA_LEN_TO_TIME_1M(len) ((LL_BLE_US_PER_BYTE_1M * ((len) + LL_DATA_MIC_LEN)) + LL_MIN_PKT_TIME_US_1M) - /*!< Convert data length to time. */ -#define LL_DATA_LEN_TO_TIME_2M(len) ((LL_BLE_US_PER_BYTE_2M * ((len) + LL_DATA_MIC_LEN)) + LL_MIN_PKT_TIME_US_2M) - /*!< Convert data length to time. */ -#define LL_DATA_LEN_TO_TIME_CODED_S8(len) ((LL_BLE_US_PER_BYTE_CODED_S8 * ((len) + LL_DATA_MIC_LEN)) + LL_MIN_PKT_TIME_US_CODED_S8) - /*!< Convert data length to time. */ -#define LL_DATA_LEN_TO_TIME_CODED_S2(len) ((LL_BLE_US_PER_BYTE_CODED_S2 * ((len) + LL_DATA_MIC_LEN)) + LL_MIN_PKT_TIME_US_CODED_S2) - /*!< Convert data length to time. */ - -#define LL_MIN_INSTANT 6 /*!< Minimum number of CE to apply a CONN_UPD or CHAN_MAP. */ - -#define LL_MAX_ADV_DATA_LEN 1650 /*!< Maximum advertising data length. */ - -#define LL_MAX_DATA_LEN_MIN 27 /*!< Minimum value for maximum Data PDU length */ -#define LL_MAX_DATA_LEN_ABS_MAX 251 /*!< Absolute maximum limit for maximum Data PDU length */ - -#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 2120 /*!< Absolute maximum limit for maximum Data PDU time (LE 1M PHY) */ -#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. */ - -#define LL_MAX_ADV_DLY_MS 10 /*!< Maximum advertising delay in milliseconds. */ - -#define LL_MIN_CONN_INTERVAL 6 /*!< Minimum value for connection interval. */ -#define LL_MAX_CONN_INTERVAL 3200 /*!< Maximum value for connection interval. */ - -#define LL_MIN_TX_WIN_SIZE 1 /*!< Minimum value for transmit window size. */ -#define LL_MAX_TX_WIN_SIZE 8 /*!< Maximum value for transmit window size. */ - -#define LL_MAX_CONN_LATENCY 499 /*!< Maximum value for connection slave latency. */ - -#define LL_MIN_SUP_TIMEOUT 10 /*!< Minimum value for connection supervision timeout. */ -#define LL_MAX_SUP_TIMEOUT 3200 /*!< Maximum value for connection supervision timeout. */ - -#define LL_MIN_POWER_THRESHOLD -128 /*!< Minimum value for power threshold. */ -#define LL_MAX_POWER_THRESHOLD 127 /*!< Maximum value for power threshold. */ - -#define LL_MAX_PHYS 3 /*!< Number of LE PHYs. */ -#define LL_ALL_PHYS_MSK 0x7 /*!< All supported LE PHYs mask. */ - -/*** ISO ***/ -#define LL_MAX_ISO_DATA_LEN_ABS_MAX 251 /*!< Absolute maximum limit for maximum ISO Data PDU length */ - -#define LL_MAX_CIS_COUNT 0x10 /*!< Maximum count for CIS. */ - -#define LL_MIN_CIG_ID 0x00 /*!< Minimum value for CIG ID. */ -#define LL_MAX_CIG_ID 0xEF /*!< Maximum value for CIG ID. */ - -#define LL_MIN_CIS_ID 0x00 /*!< Minimum value for CIS ID. */ -#define LL_MAX_CIS_ID 0xEF /*!< Maximum value for CIS ID. */ - -#define LL_MIN_ISO_INTERV 0x0004 /*!< Minimum value for ISO interval. */ -#define LL_MAX_ISO_INTERV 0x0C80 /*!< Maximum value for ISO interval. */ - -#define LL_MIN_ISOAL_PDU_TYPE 0x00 /*!< Minimum value for ISOAL PDU type. */ -#define LL_MAX_ISOAL_PDU_TYPE 0x01 /*!< Maximum value for ISOAL PDU type. */ - -#define LL_MIN_SDU_SIZE 0x000 /*!< Minimum value for SDU size. */ -#define LL_MAX_SDU_SIZE 0xFFF /*!< Maximum value for SDU size. */ - -#define LL_MIN_SDU_INTERV 0x000FF /*!< Minimum value for SDU interval. */ -#define LL_MAX_SDU_INTERV 0xFFFFF /*!< Maximum value for SDU interval. */ - -#define LL_MIN_CIS_NSE 0x00 /*!< Minimum value for CIS number of subevent. */ -#define LL_MAX_CIS_NSE 0x1F /*!< Maximum value for CIS number of subevent. */ - -#define LL_MIN_CIS_PL 0x00 /*!< Minimum value for CIS payload. */ -#define LL_MAX_CIS_PL 0xFB /*!< Maximum value for CIS payload. */ - -#define LL_MIN_CIS_PHY_BIT 0x00 /*!< Minimum value for CIS PHY bit. */ -#define LL_MAX_CIS_PHY_BIT 0x02 /*!< Maximum value for CIS PHY bit. */ - -#define LL_MIN_CIS_FT 0x01 /*!< Minimum value for CIS flush time. */ -#define LL_MAX_CIS_FT 0x1F /*!< Maximum value for CIS flush time. */ - -#define LL_MIN_CIS_BN 0x00 /*!< Minimum value for CIS burst number. */ -#define LL_MAX_CIS_BN 0x10 /*!< Maximum value for CIS burst number. */ - -/*! \brief ISO PDU LLID types. */ -enum -{ - LL_ISO_LLID_CIS_DATA_PDU = 0x00, /*!< CIS data PDU. */ - LL_ISO_LLID_BIS_DATA_PDU = 0x00, /*!< BIS data PDU. */ - LL_ISO_LLID_BIS_CTRL_PDU = 0x03, /*!< BIS control PDU. */ -}; - -/*! \brief ISO PDU types. */ -enum -{ - LL_ISO_PDU_TYPE_UNFRAMED = 0x00, /*!< Unframed PDU type. */ - LL_ISO_PDU_TYPE_FRAMED = 0x01, /*!< framed PDU type. */ -}; - -/*! \brief ISO PDU types. */ -enum -{ - LL_ISO_TEST_PL_LEN_MAX = 0x00, /*!< \brief Maximum length test payload */ - LL_ISO_TEST_PL_LEN_VAR = 0x01, /*!< \brief Maximum length test payload */ - LL_ISO_TEST_PL_LEN_ZERO = 0x02, /*!< \brief Maximum length test payload */ -}; - -/*** DTM ***/ - -#define LL_DTM_HDR_LEN 2 /*!< Direct Test Mode PDU header length. */ -#define LL_DTM_SYNC_WORD UINT32_C(0x71764129) /*!< Direct Test Mode sync word. */ -#define LL_DTM_CRC_INIT UINT32_C(0x555555) /*!< Direct Test Mode CRC initial value. */ -#define LL_DTM_MAX_INT_US 12500 /*!< Maximum time interval between packets in microseconds. */ -#define LL_DTM_PDU_ABS_MAX_LEN 255 /*!< Absolute maximum DTM PDU length. */ -#define LL_DTM_MAX_CHAN_IDX 39 /*!< Maximum channel index. */ - -/*** Baseband ***/ - -#define LL_CHAN_DATA_MIN_IDX 0 /*!< Minimum data channel index. */ -#define LL_CHAN_DATA_MAX_IDX 36 /*!< Maximum data channel index. */ -#define LL_CHAN_DATA_ALL UINT64_C(0x0000001FFFFFFFFF) /*!< Maximum data channel index. */ - -#define LL_BLE_BIT_PER_US 1 /*!< BLE PHY rate. */ -#define LL_BLE_US_PER_BYTE_1M 8 /*!< BLE PHY speed (LE 1M PHY). */ -#define LL_BLE_US_PER_BYTE_2M 4 /*!< BLE PHY speed (LE 2M PHY). */ -#define LL_BLE_US_PER_BYTE_CODED_S8 64 /*!< BLE PHY speed (LE Coded PHY, S=8). */ -#define LL_BLE_US_PER_BIT_CODED_S8 8 /*!< BLE PHY speed (LE Coded PHY, S=8). */ -#define LL_BLE_US_PER_BYTE_CODED_S2 16 /*!< BLE PHY speed (LE Coded PHY, S=2). */ -#define LL_BLE_US_PER_BIT_CODED_S2 2 /*!< BLE PHY speed (LE Coded PHY, S=2). */ -#define LL_BLE_TIFS_US 150 /*!< BLE inter-frame space. */ -#define LL_BLE_MAFS_US 300 /*!< BLE minimum AUX frame space. */ -#define LL_BLE_US_PER_TICK 625 /*!< Microseconds per BLE tick. */ -#define LL_BLE_TMSS_US 150 /*!< BLE minimum subevent space. */ - -#define LL_MIN_PKT_TIME_US_1M 80 /*!< Minimum packet time (i.e. empty PDU) on LE 1M PHY. */ -#define LL_MIN_PKT_TIME_US_2M 44 /*!< Minimum packet time (i.e. empty PDU) on LE 2M PHY. */ -#define LL_MIN_PKT_TIME_US_CODED_S8 720 /*!< Minimum packet time (i.e. empty PDU) on LE Coded PHY, S=8. */ -#define LL_MIN_PKT_TIME_US_CODED_S2 462 /*!< Minimum packet time (i.e. empty PDU) on LE Coded PHY, S=2. */ - -#define LL_MIN_ADV_TX_PWR_LVL -20 /*!< Minimum Tx power level for advertising. */ -#define LL_MAX_ADV_TX_PWR_LVL 10 /*!< Maximum Tx power level for advertising. */ - -#define LL_MIN_TX_PWR_LVL -30 /*!< Minimum Tx power level for connections. */ -#define LL_MAX_TX_PWR_LVL 20 /*!< Maximum Tx power level for connections. */ - -#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_30_USEC_OFFS_MAX_USEC 245730 /*!< Maximum value for 30 microseconds offset unit in microseconds. */ - -/*** ACAD ***/ - -/*! \brief ACAD opcodes. */ -enum -{ - LL_ACAD_OPCODE_CHANNEL_MAP_UPDATE = 0x28 /*!< Opcode for acad update periodic channel map ind. */ -}; -#define LL_ACAD_OPCODE_LEN 1 /*!< Length of a single Acad opcode. */ -#define LL_INSTANT_LEN 2 /*!< Length of instant field (event counter). */ -#define LL_ACAD_LEN_FIELD_LEN 1 /*!< Length of Acad length field */ -#define LL_ACAD_CHAN_MAP_LEN 5 /*!< Length of channel map rounded to nearest byte */ - -#define LL_ACAD_DATA_FIELD_MAX_LEN LL_EXT_HDR_ACAD_MAX_LEN - LL_ACAD_OPCODE_LEN - LL_ACAD_LEN_FIELD_LEN /*!< Length of max ACAD field length without opcode and length field */ - -#define LL_ACAD_UPDATE_CHANNEL_MAP_LEN LL_ACAD_OPCODE_LEN + LL_ACAD_CHAN_MAP_LEN + LL_INSTANT_LEN /*!< Length of acad update periodic channel map data field. */ - -/*** Modify Sleep Clock Accuracy ***/ -/*! \brief Action parameter. */ -enum -{ - LL_MODIFY_SCA_MORE_ACCURATE = 0x00, /*!< Modify to more accurate clock accuracy. */ - LL_MODIFY_SCA_LESS_ACCURATE = 0x01, /*!< Modify to less accurate clock accuracy. */ - LL_MODIFY_SCA_NO_ACTION /*!< No action (Used for request sca tester command). */ -}; -#define LL_SCA_MIN_INDEX 0 /*!< Index for lowest accuracy clock. */ -#define LL_SCA_MAX_INDEX 7 /*!< Index for highest accuracy clock. */ - -#ifdef __cplusplus -}; -#endif - -#endif /* LL_DEFS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/ll_init_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/ll_init_api.h index 918df1f0e1..0bf0a9c793 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/ll_init_api.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/ll_init_api.h @@ -1,24 +1,26 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file + * \file + * * \brief LL initialization implementation file. * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. + * + * * Initialization conditional compilation are used to control LL initialization options. * Define one or more of the following to enable roles and features. * @@ -60,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_2 #endif /************************************************************************************************** @@ -94,7 +96,7 @@ uint32_t LlInitSetLlRtCfg(const LlRtCfg_t *pLlRtCfg, uint8_t *pFreeMem, uint32_t void LlInitBbInit(void); void LlInitSchInit(void); void LlInitLlInit(void); -void LlInitChciTrInit(void); +void LlInitChciTrInit(uint16_t maxAclLen, uint16_t maxIsoLen); void LlInitLhciInit(void); void LlMathSetSeed(const uint32_t *pSeed); void LlInitLhciHandler(void); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/ll_math.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/ll_math.h index 7566689e34..0bc5bcad40 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/ll_math.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/ll_math.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link Layer math utilities. + * \file + * + * \brief Link Layer math utilities. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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 LL_MATH_H @@ -34,7 +35,7 @@ extern "C" { **************************************************************************************************/ /*! \brief Binary divide with 1,000 divisor (n[max]=7,999). */ -#define LL_MATH_DIV_10E3(n) (((n) * UINT32_C(536871)) >> 29) +#define LL_MATH_DIV_10E3(n) ((uint32_t)(((uint64_t)(n) * UINT64_C(536871)) >> 29)) /*! \brief Binary divide with 1,000,000 divisor (n[max]=0xFFFFFFFF). */ #define LL_MATH_DIV_10E6(n) ((uint32_t)(((uint64_t)(n) * UINT64_C(4295)) >> 32)) @@ -113,6 +114,18 @@ uint8_t LlMathGetNumBitsSet(uint64_t num); /*************************************************************************************************/ uint32_t LlMathDivideUint32(uint32_t nu32, uint32_t de32); +/*************************************************************************************************/ +/*! + * \brief Return result of a division, rounding up. + * + * \param nu32 Numerator of size 32 bits. + * \param de32 Denominator of size 32 bits. + * + * \return Result of a division. + */ +/*************************************************************************************************/ +uint32_t LlMathDivideUint32RoundUp(uint32_t nu32, uint32_t de32); + #ifdef __cplusplus }; #endif diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/sch_api_ble.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/sch_api_ble.h index c61ba8bd1f..bd8d482a63 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/sch_api_ble.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/ble/sch_api_ble.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer scheduler interface file. + * \file + * + * \brief Link layer scheduler interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ @@ -38,6 +39,9 @@ extern "C" { /*! \brief Preferred periodicity. */ #define SCH_RM_PREF_PER_USEC 10000 +/*! \brief Lowest perferred periodicity (for cases where intervalMax < SCH_RM_PREF_PER_USEC). */ +#define SCH_RM_PREF_PER_USEC_LOWEST 5000 + /*! \brief Preferred periodicity for connections. */ #define SCH_RM_PREF_PER_CONN_USEC (SCH_RM_PREF_PER_USEC) @@ -62,21 +66,27 @@ enum /*! \brief Get reference time callback signature. */ typedef uint32_t (*GetRefTimeCb_t)(uint8_t handle, uint32_t *pDurUsec); +/*! \brief Get topology reference time callback signature. */ +typedef uint32_t (*GetTopRefTimeCb_t)(uint8_t handle); + /************************************************************************************************** Function Declarations **************************************************************************************************/ /* Resource manager */ void SchRmInit(void); -uint32_t SchRmPreferredPeriodUsec(void); uint32_t SchRmCalcCommonPeriodicityUsec(uint32_t peerPerUsec); bool_t SchRmAdd(uint8_t handle, uint8_t pref, uint32_t minUsec, uint32_t maxUsec, uint32_t durUsec, uint32_t *pInterUsec, GetRefTimeCb_t refTimeCb); bool_t SchRmStartUpdate(uint8_t handle, uint32_t minUsec, uint32_t maxUsec, uint32_t perfPerUsec, uint32_t durUsec, uint32_t *pInterUsec); void SchRmCommitUpdate(uint8_t handle); void SchRmRemove(uint8_t handle); -void SchRmSetReference(uint8_t handle); uint32_t SchRmGetOffsetUsec(uint32_t maxOffsUsec, uint8_t handle, uint32_t refTime); +/* Topology manager */ +void SchTmInit(void); +void SchTmAdd(uint8_t handle, uint32_t interUsec, uint32_t durUsec, bool_t movable, GetTopRefTimeCb_t refTimeCb); +void SchTmRemove(uint8_t handle); + /* BLE time utilities */ uint32_t SchBleCalcDataPktDurationUsec(uint8_t phy, uint16_t len); uint32_t SchBleCalcAdvPktDurationUsec(uint8_t phy, uint8_t phyOptions, uint16_t len); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/bb_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/bb_api.h index 5d98e45a52..067f7f639e 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/bb_api.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/bb_api.h @@ -1,24 +1,25 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! * \file + * * \brief Baseband interface file. * + * Copyright (c) 2013-2018 ARM Ltd. All Rights Reserved. + * + * 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. + * * \addtogroup BB_API Baseband (BB) API * \{ * @@ -68,6 +69,7 @@ #include "wsf_types.h" #include "cfg_mac.h" +#include "pal_bb.h" #ifdef __cplusplus extern "C" { @@ -101,6 +103,7 @@ typedef struct /* Scheduler */ uint16_t schSetupDelayUs; /*!< Operation setup delay in microseconds. */ + uint32_t BbTimerBoundaryUs; /*!< BB timer tick boundary translated in microseconds before wraparound. */ } BbRtCfg_t; /*! \} */ /* BB_API_INIT */ @@ -120,12 +123,14 @@ typedef void (*BbBodCback_t)(struct BbOpDesc_tag *pBod); /*! \brief Protocol event callback signature. */ typedef void (*BbProtCback_t)(void); +/*! \brief Low power callback. */ +typedef void (*BbLowPowerCback_t)(void); + /*! \brief BOD rescheduling policy (listed in priority order). */ typedef enum { BB_RESCH_FIXED_PREFERRED, /*!< BOD is fixed (rescheduling has limited recoverable consequences). */ BB_RESCH_FIXED, /*!< BOD is fixed (rescheduling has recoverable consequences). */ - BB_RESCH_PERIODIC, /*!< BOD is periodic (rescheduling has consequences). */ BB_RESCH_MOVEABLE_PREFERRED, /*!< BOD is movable (rescheduling has minor consequences). */ BB_RESCH_MOVEABLE, /*!< BOD is movable (rescheduling has no consequences). */ BB_RESCH_BACKGROUND /*!< BOD is single background task. */ @@ -146,14 +151,13 @@ typedef struct BbOpDesc_tag struct BbOpDesc_tag *pPrev; /*!< Previous BOD. */ struct BbOpDesc_tag *pNext; /*!< Next BOD. */ - uint32_t due; /*!< Absolute clock due time. */ + uint32_t dueUsec; /*!< Absolute clock due time in microseconds. */ uint32_t minDurUsec; /*!< Minimum required duration in microseconds. */ uint32_t maxDurUsec; /*!< Maximum required duration in microseconds. */ - uint16_t dueOffsetUsec; /*!< Due time offset in microseconds. */ - uint8_t reschPolicy; /*!< Rescheduling policy. */ + BbReschPol_t reschPolicy:8; /*!< Rescheduling policy. */ - uint8_t protId; /*!< Protocol type. */ + PalBbProt_t protId:8; /*!< Protocol type. */ BbBodCback_t endCback; /*!< End of BOD callback (when BOD ends). */ BbBodCback_t abortCback; /*!< Abort BOD callback (when BOD is removed before beginning). */ @@ -183,8 +187,6 @@ typedef struct BbOpDesc_tag * * \param pCfg Pointer to runtime configuration parameters (data must be static). * - * \return None. - * * This function initializes the BB subsystem's runtime configuration. * * \note This routine must be called only once before any other initialization routine. @@ -196,8 +198,6 @@ void BbInitRunTimeCfg(const BbRtCfg_t *pCfg); /*! * \brief Initialize the BB. * - * \return None. - * * Initialize baseband resources. */ /*************************************************************************************************/ @@ -209,8 +209,6 @@ void BbInit(void); * * \param eventCback Event callback. * - * \return None. - * * Register operation completion handler. */ /*************************************************************************************************/ @@ -225,12 +223,20 @@ void BbRegister(BbBodCompCback_t eventCback); * \param cancelOpCback Cancel operation callback. * \param startProtCback Start protocol callback. * \param stopProtCback Stop protocol callback. - * - * \return None. */ /*************************************************************************************************/ -void BbRegisterProt(uint8_t protId, BbBodCback_t execOpCback, BbBodCback_t cancelOpCback, - BbProtCback_t startProtCback, BbProtCback_t stopProtCback); +void BbRegisterProt(PalBbProt_t protId, BbBodCback_t execOpCback, BbBodCback_t cancelOpCback, + BbProtCback_t startProtCback, BbProtCback_t stopProtCback); + +/*************************************************************************************************/ +/*! + * \brief Register protocol handlers for low power. + * + * \param protId Protocol ID. + * \param lowPowerOpCback Low power operation callback. + */ +/*************************************************************************************************/ +void BbRegisterProtLowPower(PalBbProt_t protId, BbLowPowerCback_t lowPowerOpCback); /*! \} */ /* BB_API_INIT */ @@ -243,14 +249,12 @@ void BbRegisterProt(uint8_t protId, BbBodCback_t execOpCback, BbBodCback_t cance * * \param protId Protocol ID. * - * \return None. - * * Enable BB and start processing the list of BODs. This routine may be called several times, if * a protocol layers has several simultaneously-enabled operations. However, \ref BbStop() must * be called an equal number of time to disable the baseband. */ /*************************************************************************************************/ -void BbStart(uint8_t protId); +void BbStart(PalBbProt_t protId); /*************************************************************************************************/ /*! @@ -264,7 +268,7 @@ void BbStart(uint8_t protId); * balanced to ensure that the hardware is disabled if and only if appropriate. */ /*************************************************************************************************/ -void BbStop(uint8_t protId); +void BbStop(PalBbProt_t protId); /*************************************************************************************************/ /*! @@ -272,8 +276,6 @@ void BbStop(uint8_t protId); * * \param pBod Pointer to the BOD to execute. * - * \return None. - * * Execute the protocol specific BOD handler. */ /*************************************************************************************************/ @@ -282,8 +284,6 @@ void BbExecuteBod(BbOpDesc_t *pBod); /*************************************************************************************************/ /*! * \brief Cancel current executing BOD. - * - * \return None. */ /*************************************************************************************************/ void BbCancelBod(void); @@ -301,8 +301,6 @@ BbOpDesc_t *BbGetCurrentBod(void); /*! * \brief Set termination flag of current executing BOD. * - * \return None. - * * \note This function is expected to be called during the execution context of the * current executing BOD, typically in the related ISRs. In the end, termination * flag will help to decide if BbTerminateBod() should be called. @@ -323,8 +321,6 @@ bool_t BbGetBodTerminateFlag(void); /*! * \brief Terminate a BOD immediately. * - * \return None. - * * \note This function is expected to be called during the execution context of the * current executing BOD, typically in the related ISRs. */ @@ -342,6 +338,16 @@ void BbTerminateBod(void); /*************************************************************************************************/ uint16_t BbGetClockAccuracy(void); +/*************************************************************************************************/ +/*! + * \brief Get BB timer boundary before wraparound. + * + * \return Time boundary in microseconds. + * + */ +/*************************************************************************************************/ +uint32_t BbGetBbTimerBoundaryUs(void); + /*************************************************************************************************/ /*! * \brief Get scheduler setup delay. @@ -353,6 +359,35 @@ uint16_t BbGetClockAccuracy(void); /*************************************************************************************************/ uint16_t BbGetSchSetupDelayUs(void); +/*************************************************************************************************/ +/*! + * \brief Adjust new time tick with wraparound. + * + * \param dueUsec Time tick without wraparound in microseconds. + + * + * \return Time tick with wraparound. + * + * \note dueUsec can only be at most +/-(BbTimerBoundaryUs/2) out of range. + */ +/*************************************************************************************************/ +uint32_t BbAdjustTime(uint32_t dueUsec); + +/*************************************************************************************************/ +/*! + * \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. + * + * \return Positive number in microseconds if target time is in the future. + * Zero if target time is in the past or same compared with reference time. + * + * \note Caller has to make sure target time and reference time are within SCH_MAX_SPAN. + */ +/*************************************************************************************************/ +uint32_t BbGetTargetTimeDelta(uint32_t targetUsec, uint32_t refUsec); + /*************************************************************************************************/ /*! * \brief Returns the ID of the active protocol. diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/cfg_mac.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/cfg_mac.h index 3b048b84db..44b5660f33 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/cfg_mac.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/cfg_mac.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief MAC system configuration. + * \file + * + * \brief MAC system configuration. + * + * Copyright (c) 2013-2019 ARM Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -32,12 +33,6 @@ extern "C" { Macros **************************************************************************************************/ -/*** Baseband ***/ - -#ifndef BB_CLK_RATE_HZ -#define BB_CLK_RATE_HZ 1000000 /*!< BB clock rate in hertz. */ -#endif - /*** Controller HCI ***/ #ifndef CHCI_BUF_TAILROOM @@ -45,6 +40,7 @@ extern "C" { #endif /*** Scheduler ***/ + #ifndef SCH_TIMER_REQUIRED #define SCH_TIMER_REQUIRED TRUE /*!< If hardware timer is required for radio access scheduler.*/ #endif diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/cfg_mac_ble.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/cfg_mac_ble.h index 8704d9e386..71c1cdd7c5 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/cfg_mac_ble.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/cfg_mac_ble.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief BLE MAC system configuration. + * \file + * + * \brief BLE MAC system configuration. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -42,6 +43,10 @@ extern "C" { #define LL_MAX_CONN 4 /*!< Absolute maximum number of connections (maximum is 32). */ #endif +#ifndef LL_MAX_FRAG +#define LL_MAX_FRAG 8 /*!< Maximum number of Data PDU fragments. */ +#endif + #ifndef LL_NUM_ADV_FILT #define LL_NUM_ADV_FILT 8 /*!< Table size for advertising filter. */ #endif @@ -71,7 +76,19 @@ extern "C" { #endif #ifndef LL_MAX_CIS -#define LL_MAX_CIS 2 /*!< Absolute maximum number of connected isochronous streams per CIG. */ +#define LL_MAX_CIS 6 /*!< Absolute maximum number of connected isochronous streams, it is shared by CIGs. */ +#endif + +#ifndef LL_MAX_BIG +#define LL_MAX_BIG 2 /*!< Absolute maximum number of broadcast isochronous groups. */ +#endif + +#ifndef LL_MAX_BIS +#define LL_MAX_BIS 6 /*!< Absolute maximum number of broadcast isochronous streams, it is shared by BIGs. */ +#endif + +#ifndef LL_MAX_BN +#define LL_MAX_BN 8 /*!< Absolute maximum number of bursts. */ #endif #ifndef LHCI_ENABLE_VS @@ -81,7 +98,7 @@ extern "C" { /*** Scheduler ***/ #ifndef SCH_RM_MAX_RSVN -#define SCH_RM_MAX_RSVN (LL_MAX_CONN + LL_MAX_ADV_SETS + LL_MAX_CIG) /*!< Maximum number of reservations (maximum is 32). */ +#define SCH_RM_MAX_RSVN (LL_MAX_CONN + LL_MAX_ADV_SETS + LL_MAX_CIG + LL_MAX_BIG) /*!< Maximum number of reservations (maximum is 32). */ #endif /*** Baseband ***/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/chci_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/chci_api.h index cb1f61f641..edc4495851 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/chci_api.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/chci_api.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Controller HCI transport API. + * \file + * + * \brief Controller HCI transport API. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -46,7 +47,7 @@ enum enum { CHCI_TR_TYPE_CMD = 0, /*!< Command message (receive only). */ - CHCI_TR_TYPE_DATA, /*!< ACL data message (send or receive). */ + CHCI_TR_TYPE_ACL, /*!< ACL data message (send or receive). */ CHCI_TR_TYPE_EVT, /*!< Event message (send only). */ CHCI_TR_TYPE_ISO, /*!< ISO data message (send or receive). */ CHCI_TR_TYPE_NUM /*!< Number of types. */ @@ -55,8 +56,9 @@ enum /*! \brief Error codes. */ enum { - CHCI_TR_CODE_INVALID_DATA = 0xA0, /*!< Invalid data received. */ - CHCI_TR_CODE_OUT_OF_MEMORY = 0xA1 /*!< Out of memory. */ + CHCI_TR_CODE_INVALID_DATA = 0xA0, /*!< Invalid data received. */ + CHCI_TR_CODE_INVALID_DATA_LEN = 0xA1, /*!< Invalid data length. */ + CHCI_TR_CODE_OUT_OF_MEMORY = 0xA2 /*!< Out of memory. */ }; /*! \brief 802.15.4 protocol command type. */ @@ -101,11 +103,11 @@ typedef void (*ChciTrSendHwErrorCback_t)(uint8_t code); * \brief Initialize the transport handler. * * \param handlerId Handler ID. - * - * \return None. + * \param maxAclLen Maximum ACL data length. + * \param maxIsoSduLen Maximum ISO data length. */ /*************************************************************************************************/ -void ChciTrHandlerInit(wsfHandlerId_t handlerId); +void ChciTrHandlerInit(wsfHandlerId_t handlerId, uint16_t maxAclLen, uint16_t maxIsoSduLen); /*************************************************************************************************/ /*! @@ -113,8 +115,6 @@ void ChciTrHandlerInit(wsfHandlerId_t handlerId); * * \param event WSF event. * \param pMsg WSF message. - * - * \return None. */ /*************************************************************************************************/ void ChciTrHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); @@ -127,8 +127,6 @@ void ChciTrHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); * \param recvCback Message received callback. * \param sendCompleteCback Message send complete callback. * \param serviceCback Service callback. - * - * \return None. */ /*************************************************************************************************/ void ChciTrSetCbacks(uint8_t prot, ChciTrRecvCback_t recvCback, ChciTrSendCompleteCback_t sendCompleteCback, @@ -139,8 +137,6 @@ void ChciTrSetCbacks(uint8_t prot, ChciTrRecvCback_t recvCback, ChciTrSendComple * \brief Set send hardware error callback. * * \param sendHwErrorCback Send hardware error callback. - * - * \return None. */ /*************************************************************************************************/ void ChciTrSetSendHwErrorCback(ChciTrSendHwErrorCback_t sendHwErrorCback); @@ -150,8 +146,6 @@ void ChciTrSetSendHwErrorCback(ChciTrSendHwErrorCback_t sendHwErrorCback); * \brief Flag protocol for needing service. * * \param prot Protocol. - * - * \return None. */ /*************************************************************************************************/ void ChciTrNeedsService(uint8_t prot); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/chci_tr.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/chci_tr.h index 15bffb71fe..591e6452d7 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/chci_tr.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/chci_tr.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Controller HCI transport interface file. + * \file + * + * \brief Controller HCI transport interface file. + * + * Copyright (c) 2013-2019 ARM Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -37,12 +38,12 @@ extern "C" { #ifndef UART_BAUD /*! \brief Default UART baud rate. */ -#define UART_BAUD 1000000 +#define UART_BAUD 1000000 #endif -#ifndef UART_DEFAULT_CONFIG_HWFC +#ifndef UART_HWFC /*! \brief Default Hardware Flow Control. */ -#define UART_DEFAULT_CONFIG_HWFC 1 +#define UART_HWFC 1 #endif /************************************************************************************************** @@ -56,12 +57,17 @@ extern "C" { * \param prot Protocol. * \param type Message type. * \param pBuf Message. - * - * \return None. */ /*************************************************************************************************/ void chciTrRecv(uint8_t prot, uint8_t type, uint8_t *pBuf); +/*************************************************************************************************/ +/*! + * \brief Signal the completion of a message transmission. + */ +/*************************************************************************************************/ +void chciTrSendComplete(void); + /*************************************************************************************************/ /*! * \brief Service the transport device. diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/sch_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/sch_api.h index 4c6d7081fa..c1de5179d9 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/sch_api.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/include/common/sch_api.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Multi-protocol scheduler interface file. + * \file + * + * \brief Multi-protocol scheduler interface file. + * + * Copyright (c) 2013-2019 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ @@ -48,6 +49,8 @@ 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); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_master.c index 578bdf152c..0c584d80e0 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Scanning master BLE baseband porting implementation file. + * \file + * + * \brief Scanning master BLE baseband porting implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,19 +28,12 @@ #include "sch_api.h" #include "wsf_math.h" #include +#include "bb_ble_sniffer_api.h" /************************************************************************************************** Macros **************************************************************************************************/ -/*! \brief Event states for scan operations. */ -enum -{ - BB_EVT_STATE_RX_ADV_IND, - BB_EVT_STATE_TX_SCAN_OR_CONN_IND, - BB_EVT_STATE_RX_SCAN_RSP -}; - /************************************************************************************************** Global Variables **************************************************************************************************/ @@ -67,9 +61,31 @@ extern const BbRtCfg_t *pBbRtCfg; /*************************************************************************************************/ static uint32_t bbBleCalcScanDurationUsec(BbOpDesc_t *pBod, BbBleMstAdvEvent_t *pScan, uint32_t refTime, uint32_t setupUsec) { + BbBleData_t * const pBle = pBod->prot.pBle; + WSF_ASSERT(pBod->maxDurUsec > 0); - const uint32_t totalGapUsec = BB_SCAN_GUARD_US + setupUsec; + /* Guard time at the end of a scan window to the next BOD. */ + /* Backoff for RX of preamble and AA which are compensated in BB driver. */ + uint32_t totalGapUsec = BbGetSchSetupDelayUs() + setupUsec; + + switch (pBle->chan.rxPhy) + { + case BB_PHY_BLE_1M: + totalGapUsec += (LL_BLE_US_PER_BYTE_1M * LL_PREAMBLE_LEN_1M) + \ + (LL_BLE_US_PER_BYTE_1M * LL_AA_LEN); + break; + case BB_PHY_BLE_2M: + totalGapUsec += (LL_BLE_US_PER_BYTE_2M * LL_PREAMBLE_LEN_2M) + \ + (LL_BLE_US_PER_BYTE_2M * LL_AA_LEN); + break; + case BB_PHY_BLE_CODED: + totalGapUsec += (LL_BLE_US_PER_BIT_CODED_S8 * LL_PREAMBLE_LEN_CODED_BITS) + \ + (LL_BLE_US_PER_BYTE_CODED_S8 * LL_AA_LEN); + break; + default: + break; + } if ((pScan->elapsedUsec + totalGapUsec) > pBod->maxDurUsec) { @@ -82,7 +98,8 @@ static uint32_t bbBleCalcScanDurationUsec(BbOpDesc_t *pBod, BbBleMstAdvEvent_t * if (pBod->pNext) { - uint32_t timeToNextOpUsec = BB_TICKS_TO_US(pBod->pNext->due - refTime); + + uint32_t timeToNextOpUsec = BbGetTargetTimeDelta(pBod->pNext->dueUsec, refTime); /* Limit scanning to the edge of neighboring BOD. */ remTimeUsec = WSF_MIN(remTimeUsec, timeToNextOpUsec); @@ -123,9 +140,9 @@ static bool_t bbContScanOp(BbOpDesc_t *pBod, BbBleMstAdvEvent_t *pScan) return TRUE; } - uint32_t curTime = PalBbGetCurrentTime(USE_RTC_BB_CLK); - pScan->elapsedUsec += BB_TICKS_TO_US(curTime - bbBleCb.lastScanStart); - bbBleCb.lastScanStart = curTime; + uint32_t curTime = PalBbGetCurrentTime(); + pScan->elapsedUsec += BbGetTargetTimeDelta(curTime, bbBleCb.lastScanStartUsec); + bbBleCb.lastScanStartUsec = curTime; uint32_t scanDurUsec; @@ -134,8 +151,7 @@ static bool_t bbContScanOp(BbOpDesc_t *pBod, BbBleMstAdvEvent_t *pScan) return TRUE; } - bbBleCb.bbParam.due = bbBleCb.lastScanStart + BB_US_TO_BB_TICKS(BbGetSchSetupDelayUs()); - bbBleCb.bbParam.dueOffsetUsec = 0; + bbBleCb.bbParam.dueUsec = BbAdjustTime(bbBleCb.lastScanStartUsec + BbGetSchSetupDelayUs()); bbBleCb.bbParam.rxTimeoutUsec = scanDurUsec; PalBbBleSetDataParams(&bbBleCb.bbParam); @@ -143,7 +159,7 @@ static bool_t bbContScanOp(BbOpDesc_t *pBod, BbBleMstAdvEvent_t *pScan) if (pScan->pTxReqBuf) { - bbBleSetIfs(); /* active scan or initiating */ + bbBleSetTifs(); /* active scan or initiating */ } else { @@ -160,8 +176,6 @@ static bool_t bbContScanOp(BbOpDesc_t *pBod, BbBleMstAdvEvent_t *pScan) * * \param status Completion status. * - * \return None. - * * Setup for next action in the operation or complete the operation. */ /*************************************************************************************************/ @@ -177,9 +191,19 @@ static void bbMstScanTxCompCback(uint8_t status) bool_t bodComplete = FALSE; bool_t bodCont = FALSE; +#if (BB_SNIFFER_ENABLED == TRUE) + /* Save evtState to be used later in packet forwarding. */ + uint8_t evtState = bbBleCb.evtState; + BbBleSnifferPkt_t * pPkt = NULL; + if (bbSnifferCtx.enabled) + { + pPkt = bbSnifferCtx.snifferGetPktFn(); + } +#endif + switch (bbBleCb.evtState++) { - case BB_EVT_STATE_TX_SCAN_OR_CONN_IND: + case BB_EVT_STATE_TX_SCAN_OR_CONN_INIT: { switch (status) { @@ -254,6 +278,17 @@ static void bbMstScanTxCompCback(uint8_t status) BbTerminateBod(); } +#if (BB_SNIFFER_ENABLED == TRUE) + if (pPkt) + { + pPkt->pktType.meta.type = BB_SNIFF_PKT_TYPE_TX; + pPkt->pktType.meta.status = status; + pPkt->pktType.meta.state = evtState; + + bbBleSnifferMstScanPktHandler(pCur, pPkt); + } +#endif + BB_ISR_MARK(bbScanStats.txIsrUsec); } @@ -264,11 +299,9 @@ static void bbMstScanTxCompCback(uint8_t status) * \param status Reception status. * \param rssi RSSI value. * \param crc CRC value. - * \param timestamp Start of packet timestamp. + * \param timestamp Start of packet timestamp in microseconds. * \param rxPhyOptions Rx PHY options. * - * \return None. - * * Setup for next action in the operation or complete the operation. */ /*************************************************************************************************/ @@ -285,6 +318,16 @@ static void bbMstScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint bool_t bodComplete = FALSE; bool_t bodCont = FALSE; +#if (BB_SNIFFER_ENABLED == TRUE) + /* Save evtState to be used later in packet forwarding. */ + uint8_t evtState = bbBleCb.evtState; + BbBleSnifferPkt_t * pPkt = NULL; + if (bbSnifferCtx.enabled) + { + pPkt = bbSnifferCtx.snifferGetPktFn(); + } +#endif + switch (bbBleCb.evtState++) { case BB_EVT_STATE_RX_ADV_IND: @@ -298,7 +341,7 @@ static void bbMstScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint pScan->advRssi = rssi; pScan->advCrc = crc; - pScan->advStartTs = timestamp; + pScan->advStartTsUsec = timestamp; pScan->advRxPhyOptions = rxPhyOptions; bool_t pduAllow = BbBlePduFiltCheck(pScan->pRxAdvBuf, &pBle->pduFilt, FALSE, &pScan->filtResults); @@ -311,7 +354,7 @@ static void bbMstScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint PalBbBleTxBufDesc_t desc = {.pBuf = pScan->pTxReqBuf, .len = pScan->txReqLen}; - bbBleSetIfs(); + bbBleSetTifs(); PalBbBleTxTifsData(&desc, 1); /* Tx may fail; no more important statements in the !bodComplete code path */ @@ -321,6 +364,14 @@ static void bbMstScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint bodCont = TRUE; } +#if (BB_SNIFFER_ENABLED == TRUE) + /* Pack the rx buffer here before it is overwritten. */ + if (pPkt) + { + memcpy(pPkt->pktType.advPkt.hdr, pScan->pRxAdvBuf, LL_ADV_HDR_LEN); + } +#endif + if (pduAllow && pScan->rxAdvPostCback) { pScan->rxAdvPostCback(pCur, pScan->pRxAdvBuf); @@ -361,7 +412,7 @@ static void bbMstScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint break; } - case BB_EVT_STATE_RX_SCAN_RSP: + case BB_EVT_STATE_RX_SCAN_OR_CONN_RSP: { WSF_ASSERT(pScan->rxRspCback); WSF_ASSERT(pScan->pRxRspBuf); @@ -369,6 +420,14 @@ static void bbMstScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint switch (status) { case BB_STATUS_SUCCESS: +#if (BB_SNIFFER_ENABLED == TRUE) + /* If the rx was successful, pack the rx sniffer header here before it is overwritten. */ + if (pPkt) + { + memcpy(pPkt->pktType.advPkt.hdr, pScan->pRxRspBuf, LL_ADV_HDR_LEN); + } +#endif + if (BbBlePduFiltCheck(pScan->pRxRspBuf, &pBle->pduFilt, FALSE, &pScan->filtResults)) { pScan->rxRspCback(pCur, pScan->pRxRspBuf); @@ -435,6 +494,19 @@ static void bbMstScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint BbTerminateBod(); } +#if (BB_SNIFFER_ENABLED == TRUE) + if (pPkt) + { + pPkt->pktType.meta.type = BB_SNIFF_PKT_TYPE_RX; + pPkt->pktType.meta.rssi = rssi; + pPkt->pktType.meta.timeStamp = timestamp; + pPkt->pktType.meta.status = status; + pPkt->pktType.meta.state = evtState; + + bbBleSnifferMstScanPktHandler(pCur, pPkt); + } +#endif + BB_ISR_MARK(bbScanStats.rxIsrUsec); } @@ -444,8 +516,6 @@ static void bbMstScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint * * \param pBod Pointer to the BOD to execute. * \param pBle BLE operation parameters. - * - * \return None. */ /*************************************************************************************************/ static void bbMstExecuteScanOp(BbOpDesc_t *pBod, BbBleData_t *pBle) @@ -459,28 +529,28 @@ static void bbMstExecuteScanOp(BbOpDesc_t *pBod, BbBleData_t *pBle) uint32_t scanDurUsec; - if ((scanDurUsec = bbBleCalcScanDurationUsec(pBod, pScan, pBod->due, 0)) == 0) + if ((scanDurUsec = bbBleCalcScanDurationUsec(pBod, pScan, pBod->dueUsec, 0)) == 0) { BbSetBodTerminateFlag(); return; } - bbBleCb.lastScanStart = pBod->due; + bbBleCb.lastScanStartUsec = pBod->dueUsec; PalBbBleSetChannelParam(&pBle->chan); bbBleCb.bbParam.txCback = bbMstScanTxCompCback; bbBleCb.bbParam.rxCback = bbMstScanRxCompCback; bbBleCb.bbParam.rxTimeoutUsec = scanDurUsec; - bbBleCb.bbParam.due = pBod->due; - bbBleCb.bbParam.dueOffsetUsec = pBod->dueOffsetUsec; + bbBleCb.bbParam.dueUsec = BbAdjustTime(pBod->dueUsec); + pBod->dueUsec = bbBleCb.bbParam.dueUsec; PalBbBleSetDataParams(&bbBleCb.bbParam); bbBleCb.evtState = 0; if (pScan->pTxReqBuf) { - bbBleSetIfs(); /* active scan or initiating */ + bbBleSetTifs(); /* active scan or initiating */ } else { @@ -493,16 +563,27 @@ static void bbMstExecuteScanOp(BbOpDesc_t *pBod, BbBleData_t *pBle) /*************************************************************************************************/ /*! - * \brief Initialize for scanning master operations. + * \brief Cancel scan BOD. * - * \return None. + * \param pBod Pointer to the BOD to execute. + * \param pBle BLE operation parameters. + */ +/*************************************************************************************************/ +static void bbMstCancelScanOp(BbOpDesc_t *pBod, BbBleData_t *pBle) +{ + PalBbBleCancelData(); +} + +/*************************************************************************************************/ +/*! + * \brief Initialize for scanning master operations. * * Update the operation table with scanning master operations routines. */ /*************************************************************************************************/ void BbBleScanMasterInit(void) { - bbBleRegisterOp(BB_BLE_OP_MST_ADV_EVENT, bbMstExecuteScanOp, NULL); + bbBleRegisterOp(BB_BLE_OP_MST_ADV_EVENT, bbMstExecuteScanOp, bbMstCancelScanOp); memset(&bbScanStats, 0, sizeof(bbScanStats)); } @@ -510,8 +591,6 @@ void BbBleScanMasterInit(void) /*************************************************************************************************/ /*! * \brief Get advertising packet statistics. - * - * \return None. */ /*************************************************************************************************/ void BbBleGetScanStats(BbBleScanPktStats_t *pStats) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_master_ae.c index e9c677c10b..a87da6c7cc 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_master_ae.c @@ -1,43 +1,36 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Extended scanning master BLE baseband porting implementation file. + * \file + * + * \brief Extended scanning master BLE baseband porting implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "bb_ble_int.h" #include "sch_api.h" #include +#include "bb_ble_sniffer_api.h" /************************************************************************************************** Macros **************************************************************************************************/ -/*! \brief Event states for scan operations. */ -enum -{ - BB_EVT_STATE_RX_ADV_IND, /*!< Receive Advertising indication. */ - BB_EVT_STATE_TX_SCAN_OR_CONN_REQ, /*!< Transmit scan or connection request. */ - BB_EVT_STATE_RX_SCAN_OR_CONN_RSP, /*!< Receive scan or connection response. */ - BB_EVT_STATE_RX_CHAIN_IND /*!< Receive chain indication. */ -}; - /************************************************************************************************** Global Variables **************************************************************************************************/ @@ -60,8 +53,6 @@ static uint8_t bbPerScanBuf[LL_EXT_ADVB_MAX_LEN]; * * \param status Completion status. * - * \return None. - * * Setup for next action in the operation or complete the operation. */ /*************************************************************************************************/ @@ -73,9 +64,20 @@ static void bbMstAuxScanTxCompCback(uint8_t status) bool_t bodComplete = FALSE; +#if (BB_SNIFFER_ENABLED == TRUE) + /* Save evtState to be used later in packet forwarding. */ + uint8_t evtState = bbBleCb.evtState; + BbBleSnifferPkt_t * pPkt = NULL; + if (bbSnifferCtx.enabled) + { + pPkt = bbSnifferCtx.snifferGetPktFn(); + } + BbOpDesc_t * const pCur = BbGetCurrentBod(); +#endif + switch (bbBleCb.evtState++) { - case BB_EVT_STATE_TX_SCAN_OR_CONN_REQ: + case BB_EVT_STATE_TX_SCAN_OR_CONN_INIT: { switch (status) { @@ -119,6 +121,17 @@ static void bbMstAuxScanTxCompCback(uint8_t status) BbTerminateBod(); } +#if (BB_SNIFFER_ENABLED == TRUE) + if (pPkt) + { + pPkt->pktType.meta.type = BB_SNIFF_PKT_TYPE_TX; + pPkt->pktType.meta.status = status; + pPkt->pktType.meta.state = evtState; + + bbBleSnifferMstAuxScanPktHandler(pCur, pPkt); + } +#endif + BB_ISR_MARK(bbAuxScanStats.txIsrUsec); } @@ -129,11 +142,9 @@ static void bbMstAuxScanTxCompCback(uint8_t status) * \param status Reception status. * \param rssi RSSI value. * \param crc CRC value. - * \param timestamp Start of packet timestamp. + * \param timestamp Start of packet timestamp in microseconds. * \param rxPhyOptions Rx PHY options. * - * \return None. - * * Setup for next action in the operation or complete the operation. */ /*************************************************************************************************/ @@ -150,6 +161,16 @@ static void bbMstAuxScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u bool_t bodComplete = FALSE; bool_t bodCont = FALSE; +#if (BB_SNIFFER_ENABLED == TRUE) + /* Save evtState to be used later in packet forwarding. */ + uint8_t evtState = bbBleCb.evtState; + BbBleSnifferPkt_t * pPkt = NULL; + if (bbSnifferCtx.enabled) + { + pPkt = bbSnifferCtx.snifferGetPktFn(); + } +#endif + switch (bbBleCb.evtState) { case BB_EVT_STATE_RX_ADV_IND: @@ -162,9 +183,17 @@ static void bbMstAuxScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u pAuxScan->auxAdvRssi = rssi; pAuxScan->auxAdvCrc = crc; - pAuxScan->auxStartTs = timestamp; + pAuxScan->auxStartTsUsec = timestamp; pAuxScan->auxRxPhyOptions = rxPhyOptions; +#if (BB_SNIFFER_ENABLED == TRUE) + /* Pack the rx buffer before it is overwritten. */ + if (pPkt) + { + memcpy(pPkt->pktType.advPkt.hdr, bbAuxAdvBuf, LL_ADV_HDR_LEN); + } +#endif + uint32_t auxOffsetUsec; if (pAuxScan->rxAuxAdvCback(pCur, bbAuxAdvBuf)) { @@ -172,13 +201,13 @@ static void bbMstAuxScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u { /* Tx response PDU. */ - bbBleCb.evtState = BB_EVT_STATE_TX_SCAN_OR_CONN_REQ; + bbBleCb.evtState = BB_EVT_STATE_TX_SCAN_OR_CONN_INIT; BB_ISR_MARK(bbAuxScanStats.txSetupUsec); PalBbBleTxBufDesc_t desc = {.pBuf = pAuxScan->pTxAuxReqBuf, .len = pAuxScan->txAuxReqLen}; - bbBleSetIfs(); + bbBleSetTifs(); PalBbBleTxTifsData(&desc, 1); } } @@ -193,7 +222,7 @@ static void bbMstAuxScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u PalBbBleCancelTifs(); PalBbBleSetChannelParam(&pBle->chan); - bbBleCb.bbParam.due = timestamp + BB_US_TO_BB_TICKS(auxOffsetUsec); + bbBleCb.bbParam.dueUsec = BbAdjustTime(timestamp + auxOffsetUsec); PalBbBleSetDataParams(&bbBleCb.bbParam); BB_ISR_MARK(bbAuxScanStats.rxSetupUsec); @@ -261,9 +290,17 @@ static void bbMstAuxScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u case BB_STATUS_SUCCESS: pAuxScan->auxAdvRssi = rssi; pAuxScan->auxAdvCrc = crc; - pAuxScan->auxStartTs = timestamp; + pAuxScan->auxStartTsUsec = timestamp; pAuxScan->auxRxPhyOptions = rxPhyOptions; +#if (BB_SNIFFER_ENABLED == TRUE) + /* Pack the rx buffer before it is overwritten. */ + if (pPkt) + { + memcpy(pPkt->pktType.advPkt.hdr, bbAuxAdvBuf, LL_ADV_HDR_LEN); + } +#endif + uint32_t auxOffsetUsec; pAuxScan->rxAuxRspCback(pCur, bbAuxAdvBuf); @@ -271,7 +308,7 @@ static void bbMstAuxScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u ((auxOffsetUsec = pAuxScan->rxAuxChainCback(pCur, bbAuxAdvBuf)) > 0)) { PalBbBleSetChannelParam(&pBle->chan); - bbBleCb.bbParam.due = timestamp + BB_US_TO_BB_TICKS(auxOffsetUsec); + bbBleCb.bbParam.dueUsec = BbAdjustTime(timestamp + auxOffsetUsec); PalBbBleSetDataParams(&bbBleCb.bbParam); BB_ISR_MARK(bbAuxScanStats.rxSetupUsec); @@ -340,11 +377,19 @@ static void bbMstAuxScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u { case BB_STATUS_SUCCESS: { +#if (BB_SNIFFER_ENABLED == TRUE) + /* Pack the rx buffer before it is overwritten. */ + if (pPkt) + { + memcpy(pPkt->pktType.advPkt.hdr, bbAuxAdvBuf, LL_ADV_HDR_LEN); + } +#endif + uint32_t auxOffsetUsec; if ((auxOffsetUsec = pAuxScan->rxAuxChainCback(pCur, bbAuxAdvBuf)) > 0) { PalBbBleSetChannelParam(&pBle->chan); - bbBleCb.bbParam.due = timestamp + BB_US_TO_BB_TICKS(auxOffsetUsec); + bbBleCb.bbParam.dueUsec = BbAdjustTime(timestamp + auxOffsetUsec); PalBbBleSetDataParams(&bbBleCb.bbParam); BB_ISR_MARK(bbAuxScanStats.rxSetupUsec); @@ -436,7 +481,21 @@ static void bbMstAuxScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u BbTerminateBod(); } +#if (BB_SNIFFER_ENABLED == TRUE) + if (pPkt) + { + pPkt->pktType.meta.type = BB_SNIFF_PKT_TYPE_RX; + pPkt->pktType.meta.rssi = rssi; + pPkt->pktType.meta.timeStamp = timestamp; + pPkt->pktType.meta.status = status; + pPkt->pktType.meta.state = evtState; + + bbBleSnifferMstAuxScanPktHandler(pCur, pPkt); + } +#endif + BB_ISR_MARK(bbAuxScanStats.rxIsrUsec); + } /*************************************************************************************************/ @@ -445,8 +504,6 @@ static void bbMstAuxScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u * * \param pBod Pointer to the BOD to execute. * \param pBle BLE operation parameters. - * - * \return None. */ /*************************************************************************************************/ static void bbMstExecuteAuxScanOp(BbOpDesc_t *pBod, BbBleData_t *pBle) @@ -458,15 +515,15 @@ static void bbMstExecuteAuxScanOp(BbOpDesc_t *pBod, BbBleData_t *pBle) bbBleCb.bbParam.txCback = bbMstAuxScanTxCompCback; bbBleCb.bbParam.rxCback = bbMstAuxScanRxCompCback; bbBleCb.bbParam.rxTimeoutUsec = pAuxScan->rxSyncDelayUsec; - bbBleCb.bbParam.due = pBod->due; - bbBleCb.bbParam.dueOffsetUsec = pBod->dueOffsetUsec; + bbBleCb.bbParam.dueUsec = BbAdjustTime(pBod->dueUsec); + pBod->dueUsec = bbBleCb.bbParam.dueUsec; PalBbBleSetDataParams(&bbBleCb.bbParam); bbBleCb.evtState = 0; if (pAuxScan->pTxAuxReqBuf) { - bbBleSetIfs(); /* active scan or initiating */ + bbBleSetTifs(); /* active scan or initiating */ } else { @@ -482,11 +539,9 @@ static void bbMstExecuteAuxScanOp(BbOpDesc_t *pBod, BbBleData_t *pBle) * \param status Reception status. * \param rssi RSSI value. * \param crc CRC value. - * \param timestamp Start of packet timestamp. + * \param timestamp Start of packet timestamp in microseconds. * \param rxPhyOptions Rx PHY options. * - * \return None. - * * Setup for next action in the operation or complete the operation. */ /*************************************************************************************************/ @@ -503,6 +558,16 @@ static void bbMstPerScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u bool_t bodComplete = FALSE; bool_t bodCont = FALSE; +#if (BB_SNIFFER_ENABLED == TRUE) + /* Save evtState to be used later in packet forwarding. */ + uint8_t evtState = bbBleCb.evtState; + BbBleSnifferPkt_t * pPkt = NULL; + if (bbSnifferCtx.enabled) + { + pPkt = bbSnifferCtx.snifferGetPktFn(); + } +#endif + switch (bbBleCb.evtState) { case BB_EVT_STATE_RX_ADV_IND: @@ -517,16 +582,24 @@ static void bbMstPerScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u bbBleCb.evtState = BB_EVT_STATE_RX_CHAIN_IND; pPerScan->perAdvRssi = rssi; pPerScan->perAdvCrc = crc; - pPerScan->perStartTs = timestamp; + pPerScan->perStartTsUsec = timestamp; pPerScan->perIsFirstTs = TRUE; pPerScan->perRxPhyOptions = rxPhyOptions; +#if (BB_SNIFFER_ENABLED == TRUE) + /* Pack the rx buffer before it is overwritten. */ + if (pPkt) + { + memcpy(pPkt->pktType.advPkt.hdr, bbPerScanBuf, LL_ADV_HDR_LEN); + } +#endif + uint32_t auxOffsetUsec; if ((auxOffsetUsec = pPerScan->rxPerAdvCback(pCur, bbPerScanBuf, status)) > 0) { PalBbBleSetChannelParam(&pBle->chan); - bbBleCb.bbParam.due = timestamp + BB_US_TO_BB_TICKS(auxOffsetUsec); + bbBleCb.bbParam.dueUsec = BbAdjustTime(timestamp + auxOffsetUsec); PalBbBleSetDataParams(&bbBleCb.bbParam); BB_ISR_MARK(bbPerScanStats.rxSetupUsec); @@ -592,11 +665,19 @@ static void bbMstPerScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u pPerScan->perAdvRssi = rssi; pPerScan->perRxPhyOptions = rxPhyOptions; +#if (BB_SNIFFER_ENABLED == TRUE) + /* Pack the rx buffer before it is overwritten. */ + if (pPkt) + { + memcpy(pPkt->pktType.advPkt.hdr, bbPerScanBuf, LL_ADV_HDR_LEN); + } +#endif + if ((auxOffsetUsec = pPerScan->rxPerAdvCback(pCur, bbPerScanBuf, status)) > 0) { /* Continue BOD with the CHAIN_IND and adjust the channel parameters. */ PalBbBleSetChannelParam(&pBle->chan); - bbBleCb.bbParam.due = timestamp + BB_US_TO_BB_TICKS(auxOffsetUsec); + bbBleCb.bbParam.dueUsec = BbAdjustTime(timestamp + auxOffsetUsec); PalBbBleSetDataParams(&bbBleCb.bbParam); BB_ISR_MARK(bbPerScanStats.rxSetupUsec); @@ -680,6 +761,19 @@ static void bbMstPerScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u BbTerminateBod(); } +#if (BB_SNIFFER_ENABLED == TRUE) + if (pPkt) + { + pPkt->pktType.meta.type = BB_SNIFF_PKT_TYPE_RX; + pPkt->pktType.meta.rssi = rssi; + pPkt->pktType.meta.timeStamp = timestamp; + pPkt->pktType.meta.status = status; + pPkt->pktType.meta.state = evtState; + + bbBleSnifferMstPerScanPktHandler(pCur, pPkt); + } +#endif + BB_ISR_MARK(bbPerScanStats.rxIsrUsec); } @@ -689,8 +783,6 @@ static void bbMstPerScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u * * \param pBod Pointer to the BOD to execute. * \param pBle BLE operation parameters. - * - * \return None. */ /*************************************************************************************************/ static void bbMstExecutePerScanOp(BbOpDesc_t *pBod, BbBleData_t *pBle) @@ -701,8 +793,8 @@ static void bbMstExecutePerScanOp(BbOpDesc_t *pBod, BbBleData_t *pBle) bbBleCb.bbParam.rxCback = bbMstPerScanRxCompCback; bbBleCb.bbParam.rxTimeoutUsec = pPerScan->rxSyncDelayUsec; - bbBleCb.bbParam.due = pBod->due; - bbBleCb.bbParam.dueOffsetUsec = pBod->dueOffsetUsec; + bbBleCb.bbParam.dueUsec = BbAdjustTime(pBod->dueUsec); + pBod->dueUsec = bbBleCb.bbParam.dueUsec; PalBbBleSetDataParams(&bbBleCb.bbParam); bbBleCb.evtState = 0; @@ -716,8 +808,6 @@ static void bbMstExecutePerScanOp(BbOpDesc_t *pBod, BbBleData_t *pBle) /*! * \brief Initialize for scanning master operations. * - * \return None. - * * Update the operation table with scanning master operations routines. */ /*************************************************************************************************/ @@ -733,8 +823,6 @@ void BbBleAuxScanMasterInit(void) * \brief Get advertising packet statistics. * * \param pStats Auxiliary scan statistics. - * - * \return None. */ /*************************************************************************************************/ void BbBleGetAuxScanStats(BbBleAuxScanPktStats_t *pStats) @@ -746,8 +834,6 @@ void BbBleGetAuxScanStats(BbBleAuxScanPktStats_t *pStats) /*! * \brief Initialize for periodic scanning master operations. * - * \return None. - * * Update the operation table with periodic scanning master operations routines. */ /*************************************************************************************************/ @@ -763,8 +849,6 @@ void BbBlePerScanMasterInit(void) * \brief Get periodic scanning packet statistics. * * \param pStats periodic scan statistics. - * - * \return None. */ /*************************************************************************************************/ void BbBleGetPerScanStats(BbBlePerScanPktStats_t *pStats) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_slave.c index 0913760b68..32053c4dc0 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Advertising slave BLE baseband porting implementation file. + * \file + * + * \brief Advertising slave BLE baseband porting implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -29,17 +30,11 @@ #include "ll_api.h" #include "lmgr_api_adv_slave.h" #include +#include "bb_ble_sniffer_api.h" /************************************************************************************************** Macros **************************************************************************************************/ -/*! \brief Event states for advertising operations. */ -enum -{ - BB_EVT_STATE_TX_ADV_IND, /*!< Transmit Advertising PDU. */ - BB_EVT_STATE_RX_SCAN_OR_CONN_IND, /*!< Receive scan or connection indication. */ - BB_EVT_STATE_TX_SCAN_RSP /*!< Transmit scan response. */ -}; /************************************************************************************************** Global Variables @@ -82,7 +77,10 @@ static bool_t bbSetupAdvOp(BbOpDesc_t *pBod, BbBleSlvAdvEvent_t *pAdv, uint8_t s return TRUE; } - bbBleCb.advChIdx = bbBleCb.advChIdx % LL_NUM_CHAN_ADV; + /* Optimized calculation: advChIdx = advChIdx % LL_NUM_CHAN_ADV */ + bbBleCb.advChIdx = (bbBleCb.advChIdx < LL_NUM_CHAN_ADV) ? + bbBleCb.advChIdx : (bbBleCb.advChIdx - LL_NUM_CHAN_ADV); + pBle->chan.chanIdx = LL_CHAN_ADV_MIN_IDX + bbBleCb.advChIdx; bbBleCb.numChUsed++; @@ -107,22 +105,23 @@ static bool_t bbSetupAdvOp(BbOpDesc_t *pBod, BbBleSlvAdvEvent_t *pAdv, uint8_t s if (firstOpInSet) { - bbBleCb.bbParam.due = pBod->due; + bbBleCb.bbParam.dueUsec = BbAdjustTime(pBod->dueUsec); + pBod->dueUsec = bbBleCb.bbParam.dueUsec; } else { if (pAdv->pRxReqBuf) { /* Schedule with relative frame gap. */ - bbBleCb.bbParam.due = PalBbGetCurrentTime(USE_RTC_BB_CLK) + BB_US_TO_BB_TICKS(BbGetSchSetupDelayUs()); + bbBleCb.bbParam.dueUsec = BbAdjustTime(PalBbGetCurrentTime() + BbGetSchSetupDelayUs()); } else { /* Schedule with absolute frame gap. */ - uint32_t advGap = (BB_US_TO_BB_TICKS(SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, pBle->chan.initTxPhyOptions, pAdv->txAdvLen)) + - BB_US_TO_BB_TICKS(BbGetSchSetupDelayUs())); - - bbBleCb.bbParam.due += SchBleGetAlignedAuxOffsUsec(advGap); + uint32_t advGap = SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, pBle->chan.initTxPhyOptions, pAdv->txAdvLen) + + BbGetSchSetupDelayUs(); + uint32_t auxOffsUsec = SchBleGetAlignedAuxOffsUsec(advGap); + bbBleCb.bbParam.dueUsec = BbAdjustTime(bbBleCb.bbParam.dueUsec + auxOffsUsec); } } @@ -130,14 +129,14 @@ static bool_t bbSetupAdvOp(BbOpDesc_t *pBod, BbBleSlvAdvEvent_t *pAdv, uint8_t s if (pAdv->txAdvSetupCback) { - pAdv->txAdvSetupCback(pBod, bbBleCb.bbParam.due); + pAdv->txAdvSetupCback(pBod, BbAdjustTime(bbBleCb.bbParam.dueUsec)); } PalBbBleSetDataParams(&bbBleCb.bbParam); if (pAdv->pRxReqBuf) { - bbBleSetIfs(); /* scannable or connectable advertising */ + bbBleSetTifs(); /* scannable or connectable advertising */ } else { @@ -146,7 +145,7 @@ static bool_t bbSetupAdvOp(BbOpDesc_t *pBod, BbBleSlvAdvEvent_t *pAdv, uint8_t s PalBbBleTxBufDesc_t desc = {.pBuf = pAdv->pTxAdvBuf, .len = pAdv->txAdvLen}; PalBbBleTxData(&desc, 1); - /* Tx may fail; no more important statements in the FALSE code path */ + /* Tx may fail; no more important statements in the FALSE code path. */ return FALSE; } @@ -157,8 +156,6 @@ static bool_t bbSetupAdvOp(BbOpDesc_t *pBod, BbBleSlvAdvEvent_t *pAdv, uint8_t s * * \param status Completion status. * - * \return None. - * * Setup for next action in the operation or complete the operation. */ /*************************************************************************************************/ @@ -173,6 +170,21 @@ static void bbSlvAdvTxCompCback(uint8_t status) bool_t bodComplete = FALSE; +#if (BB_SNIFFER_ENABLED == TRUE) + BbBleData_t * const pBle = pCur->prot.pBle; + + /* Save evtState to be used later in packet forwarding. */ + uint8_t evtState = bbBleCb.evtState; + BbBleSnifferPkt_t * pPkt = NULL; + if (bbSnifferCtx.enabled) + { + pPkt = bbSnifferCtx.snifferGetPktFn(); + } + + /* Save channel before it is overwritten. */ + bbSnifferCtx.chanIdx = pBle->chan.chanIdx; +#endif + if (status != BB_STATUS_SUCCESS) { BB_INC_STAT(bbAdvStats.errAdv); @@ -187,7 +199,7 @@ static void bbSlvAdvTxCompCback(uint8_t status) { BB_ISR_MARK(bbAdvStats.rxSetupUsec); - bbBleSetIfs(); /* set up for Tx SCAN_RSP */ + bbBleSetTifs(); /* set up for Tx SCAN_RSP */ PalBbBleRxTifsData(pAdv->pRxReqBuf, BB_REQ_PDU_MAX_LEN); /* reduce max length requirement */ } else @@ -199,7 +211,7 @@ static void bbSlvAdvTxCompCback(uint8_t status) BB_INC_STAT(bbAdvStats.txAdv); break; - case BB_EVT_STATE_TX_SCAN_RSP: + case BB_EVT_STATE_TX_SCAN_OR_CONN_RSP: /* Operation completed. */ bodComplete = bbSetupAdvOp(pCur, pAdv, status, FALSE); BB_INC_STAT(bbAdvStats.txRsp); @@ -229,6 +241,17 @@ Cleanup: BbTerminateBod(); } +#if (BB_SNIFFER_ENABLED == TRUE) + if (pPkt) + { + pPkt->pktType.meta.type = BB_SNIFF_PKT_TYPE_TX; + pPkt->pktType.meta.status = status; + pPkt->pktType.meta.state = evtState; + + bbBleSnifferSlvAdvPktHandler(pCur, pPkt); + } +#endif + BB_ISR_MARK(bbAdvStats.txIsrUsec); } @@ -239,11 +262,9 @@ Cleanup: * \param status Reception status. * \param rssi RSSI value. * \param crc CRC value. - * \param timestamp Start of packet timestamp. + * \param timestamp Start of packet timestamp in microseconds. * \param rxPhyOptions Rx PHY options. * - * \return None. - * * Setup for next action in the operation or complete the operation. */ /*************************************************************************************************/ @@ -259,9 +280,22 @@ static void bbSlvAdvRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint3 bool_t bodComplete = FALSE; +#if (BB_SNIFFER_ENABLED == TRUE) + /* Save evtState to be used later in packet forwarding. */ + uint8_t evtState = bbBleCb.evtState; + BbBleSnifferPkt_t * pPkt = NULL; + if (bbSnifferCtx.enabled) + { + pPkt = bbSnifferCtx.snifferGetPktFn(); + } + + /* Save channel before it is overwritten. */ + bbSnifferCtx.chanIdx = pBle->chan.chanIdx; +#endif + switch (bbBleCb.evtState++) { - case BB_EVT_STATE_RX_SCAN_OR_CONN_IND: + case BB_EVT_STATE_RX_SCAN_OR_CONN_INIT: switch (status) { case BB_STATUS_SUCCESS: @@ -269,7 +303,15 @@ static void bbSlvAdvRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint3 WSF_ASSERT(pAdv->rxReqCback); WSF_ASSERT(pAdv->pRxReqBuf); - pAdv->reqStartTs = timestamp; + pAdv->reqStartTsUsec = timestamp; + +#if (BB_SNIFFER_ENABLED == TRUE) + /* If the rx was successful, pack the rx buffer here before it is overwritten. */ + if (pPkt) + { + memcpy(pPkt->pktType.advPkt.hdr, pAdv->pRxReqBuf, LL_ADV_HDR_LEN); + } +#endif bool_t pduAllow = BbBlePduFiltCheck(pAdv->pRxReqBuf, &pBle->pduFilt, FALSE, &pAdv->filtResults); if (pduAllow && pAdv->rxReqCback(pCur, pAdv->pRxReqBuf)) @@ -346,6 +388,19 @@ static void bbSlvAdvRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint3 BbTerminateBod(); } +#if (BB_SNIFFER_ENABLED == TRUE) + if (pPkt) + { + pPkt->pktType.meta.type = BB_SNIFF_PKT_TYPE_RX; + pPkt->pktType.meta.rssi = rssi; + pPkt->pktType.meta.timeStamp = timestamp; + pPkt->pktType.meta.status = status; + pPkt->pktType.meta.state = evtState; + + bbBleSnifferSlvAdvPktHandler(pCur, pPkt); + } +#endif + BB_ISR_MARK(bbAdvStats.rxIsrUsec); } @@ -355,8 +410,6 @@ static void bbSlvAdvRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint3 * * \param pBod Pointer to the BOD to execute. * \param pBle BLE operation parameters. - * - * \return None. */ /*************************************************************************************************/ static void bbSlvExecuteAdvOp(BbOpDesc_t *pBod, BbBleData_t *pBle) @@ -366,7 +419,6 @@ static void bbSlvExecuteAdvOp(BbOpDesc_t *pBod, BbBleData_t *pBle) bbBleCb.bbParam.txCback = bbSlvAdvTxCompCback; bbBleCb.bbParam.rxCback = bbSlvAdvRxCompCback; bbBleCb.bbParam.rxTimeoutUsec = 2 * LL_MAX_TIFS_DEVIATION; - bbBleCb.bbParam.dueOffsetUsec = 0; bbBleCb.evtState = 0; bbBleCb.numChUsed = 0; bbBleCb.advChIdx = pAdv->firstAdvChIdx; @@ -383,8 +435,6 @@ static void bbSlvExecuteAdvOp(BbOpDesc_t *pBod, BbBleData_t *pBle) * * \param pBod Pointer to the BOD to cancel. * \param pBle BLE operation parameters. - * - * \return None. */ /*************************************************************************************************/ static void bbSlvCancelAdvOp(BbOpDesc_t *pBod, BbBleData_t *pBle) @@ -396,8 +446,6 @@ static void bbSlvCancelAdvOp(BbOpDesc_t *pBod, BbBleData_t *pBle) /*! * \brief Initialize for advertising slave operations. * - * \return None. - * * Update the operation table with advertising slave operations routines. */ /*************************************************************************************************/ @@ -411,8 +459,6 @@ void BbBleAdvSlaveInit(void) /*************************************************************************************************/ /*! * \brief Get advertising packet statistics. - * - * \return None. */ /*************************************************************************************************/ void BbBleGetAdvStats(BbBleAdvPktStats_t *pStats) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_slave_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_slave_ae.c index b2ebd15004..0d672ed3fe 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_slave_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_adv_slave_ae.c @@ -1,27 +1,29 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Extended advertising slave BLE baseband porting implementation file. + * \file + * + * \brief Extended advertising slave BLE baseband porting implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "bb_ble_int.h" +#include "bb_ble_sniffer_api.h" #include "sch_api.h" #include "sch_api_ble.h" #include @@ -30,21 +32,11 @@ Macros **************************************************************************************************/ -/*! \brief Event states for advertising operations. */ -enum -{ - BB_EVT_STATE_TX_ADV_IND, /*!< Transmit Advertising indication. */ - BB_EVT_STATE_RX_SCAN_OR_CONN_REQ, /*!< Receive scan or connection request. */ - BB_EVT_STATE_TX_SCAN_RSP, /*!< Transmit scan response. */ - BB_EVT_STATE_TX_CHAIN_IND /*!< Transmit chain indication. */ -}; - - /************************************************************************************************** Global Variables **************************************************************************************************/ -BbBleAuxAdvPktStats_t bbAuxAdvStats;/*!< Auxiliary advertising packet statistics. */ +BbBleAuxAdvPktStats_t bbAuxAdvStats; /*!< Auxiliary advertising packet statistics. */ /*************************************************************************************************/ /*! @@ -65,6 +57,7 @@ static bool_t bbSlvAdvSetupTxAuxChainInd(BbOpDesc_t *pCur, BbBleSlvAuxAdvEvent_t } uint32_t auxOffsUsec = pAuxAdv->txAuxSetupCback(pCur, TRUE); + if (auxOffsUsec == 0) { /* Operation completed. */ @@ -75,7 +68,8 @@ static bool_t bbSlvAdvSetupTxAuxChainInd(BbOpDesc_t *pCur, BbBleSlvAuxAdvEvent_t PalBbBleSetChannelParam(&pCur->prot.pBle->chan); /* Offset may be up to 1 unit earlier than actual transmission. */ - bbBleCb.bbParam.due += BB_US_TO_BB_TICKS(auxOffsUsec); + bbBleCb.bbParam.dueUsec = BbAdjustTime(bbBleCb.bbParam.dueUsec + auxOffsUsec); + PalBbBleSetDataParams(&bbBleCb.bbParam); BB_ISR_MARK(bbAuxAdvStats.rxSetupUsec); @@ -92,8 +86,6 @@ static bool_t bbSlvAdvSetupTxAuxChainInd(BbOpDesc_t *pCur, BbBleSlvAuxAdvEvent_t * * \param status Completion status. * - * \return None. - * * Setup for next action in the operation or complete the operation. */ /*************************************************************************************************/ @@ -109,6 +101,16 @@ static void bbSlvAuxAdvTxCompCback(uint8_t status) bool_t bodComplete = FALSE; +#if (BB_SNIFFER_ENABLED == TRUE) + /* Save evtState to be used later in packet forwarding. */ + uint8_t evtState = bbBleCb.evtState; + BbBleSnifferPkt_t * pPkt = NULL; + if (bbSnifferCtx.enabled) + { + pPkt = bbSnifferCtx.snifferGetPktFn(); + } +#endif + if (status != BB_STATUS_SUCCESS) { BB_INC_STAT(bbAuxAdvStats.errAdv); @@ -119,6 +121,14 @@ static void bbSlvAuxAdvTxCompCback(uint8_t status) switch (bbBleCb.evtState) { case BB_EVT_STATE_TX_ADV_IND: +#if (BB_SNIFFER_ENABLED == TRUE) + if (pPkt) + { + /* Save buffer to sniffer packet before it is overwritten. */ + memcpy(pPkt->pktType.advPkt.hdr, pAuxAdv->txAuxAdvPdu->pBuf, LL_ADV_HDR_LEN); + } +#endif + if (!pAuxAdv->pRxAuxReqBuf) { /* Non-connectable and non-scannable operation. */ @@ -128,24 +138,32 @@ static void bbSlvAuxAdvTxCompCback(uint8_t status) else { /* Scannable or connectable operation. */ - bbBleCb.evtState = BB_EVT_STATE_RX_SCAN_OR_CONN_REQ; + bbBleCb.evtState = BB_EVT_STATE_RX_SCAN_OR_CONN_INIT; BB_ISR_MARK(bbAuxAdvStats.rxSetupUsec); - bbBleSetIfs(); /* set up for Tx SCAN_RSP */ + bbBleSetTifs(); /* set up for Tx SCAN_RSP */ PalBbBleRxTifsData(pAuxAdv->pRxAuxReqBuf, BB_REQ_PDU_MAX_LEN); /* reduce max length requirement */ } BB_INC_STAT(bbAuxAdvStats.txAdv); break; - case BB_EVT_STATE_TX_SCAN_RSP: + case BB_EVT_STATE_TX_SCAN_OR_CONN_RSP: bbBleCb.evtState = BB_EVT_STATE_TX_CHAIN_IND; - bbBleCb.bbParam.due = pAuxAdv->auxReqStartTs + - BB_US_TO_BB_TICKS(SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, pAuxAdv->auxRxPhyOptions, LL_ADV_HDR_LEN + LL_SCAN_REQ_PDU_LEN)) + - BB_US_TO_BB_TICKS(LL_BLE_TIFS_US); + bbBleCb.bbParam.dueUsec = BbAdjustTime(pAuxAdv->auxReqStartTsUsec + + SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, pAuxAdv->auxRxPhyOptions, LL_ADV_HDR_LEN + LL_SCAN_REQ_PDU_LEN) + + LL_BLE_TIFS_US); bodComplete = bbSlvAdvSetupTxAuxChainInd(pCur, pAuxAdv); BB_INC_STAT(bbAuxAdvStats.txRsp); break; case BB_EVT_STATE_TX_CHAIN_IND: +#if (BB_SNIFFER_ENABLED == TRUE) + if (pPkt) + { + /* Save buffer to sniffer packet before it is overwritten. */ + memcpy(pPkt->pktType.advPkt.hdr, pAuxAdv->txAuxChainPdu->pBuf, LL_ADV_HDR_LEN); + } +#endif + /* bbBleCb.evtState = BB_EVT_STATE_TX_CHAIN_IND; */ /* Same state. */ bodComplete = bbSlvAdvSetupTxAuxChainInd(pCur, pAuxAdv); BB_INC_STAT(bbAuxAdvStats.txChain); @@ -175,6 +193,18 @@ Cleanup: BbTerminateBod(); } + +#if (BB_SNIFFER_ENABLED == TRUE) + if (pPkt) + { + pPkt->pktType.meta.type = BB_SNIFF_PKT_TYPE_TX; + pPkt->pktType.meta.status = status; + pPkt->pktType.meta.state = evtState; + + bbBleSnifferSlvAuxAdvPktHandler(pCur, pPkt); + } +#endif + BB_ISR_MARK(bbAuxAdvStats.txIsrUsec); } @@ -185,11 +215,9 @@ Cleanup: * \param status Reception status. * \param rssi RSSI value. * \param crc CRC value. - * \param timestamp Start of packet timestamp. + * \param timestamp Start of packet timestamp in microseconds. * \param rxPhyOptions Rx PHY options. * - * \return None. - * * Setup for next action in the operation or complete the operation. */ /*************************************************************************************************/ @@ -204,18 +232,36 @@ static void bbSlvAuxAdvRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, ui bool_t bodComplete = FALSE; +#if (BB_SNIFFER_ENABLED == TRUE) + /* Save evtState to be used later in packet forwarding. */ + uint8_t evtState = bbBleCb.evtState; + BbBleSnifferPkt_t * pPkt = NULL; + if (bbSnifferCtx.enabled) + { + pPkt = bbSnifferCtx.snifferGetPktFn(); + } +#endif + switch (bbBleCb.evtState++) { - case BB_EVT_STATE_RX_SCAN_OR_CONN_REQ: + case BB_EVT_STATE_RX_SCAN_OR_CONN_INIT: switch (status) { case BB_STATUS_SUCCESS: WSF_ASSERT(pAuxAdv->rxAuxReqCback); WSF_ASSERT(pAuxAdv->pRxAuxReqBuf); - pAuxAdv->auxReqStartTs = timestamp; + pAuxAdv->auxReqStartTsUsec = timestamp; pAuxAdv->auxRxPhyOptions = rxPhyOptions; +#if (BB_SNIFFER_ENABLED == TRUE) + /* Pack the rx buffer before it is overwritten. */ + if (pPkt) + { + memcpy(pPkt->pktType.advPkt.hdr, pAuxAdv->pRxAuxReqBuf, LL_ADV_HDR_LEN); + } +#endif + if (pAuxAdv->rxAuxReqCback(pCur, pAuxAdv->pRxAuxReqBuf)) { BB_ISR_MARK(bbAuxAdvStats.txSetupUsec); @@ -286,6 +332,19 @@ static void bbSlvAuxAdvRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, ui BbTerminateBod(); } +#if (BB_SNIFFER_ENABLED == TRUE) + if (pPkt) + { + pPkt->pktType.meta.type = BB_SNIFF_PKT_TYPE_RX; + pPkt->pktType.meta.rssi = rssi; + pPkt->pktType.meta.timeStamp = timestamp; + pPkt->pktType.meta.status = status; + pPkt->pktType.meta.state = evtState; + + bbBleSnifferSlvAuxAdvPktHandler(pCur, pPkt); + } +#endif + BB_ISR_MARK(bbAuxAdvStats.rxIsrUsec); } @@ -295,8 +354,6 @@ static void bbSlvAuxAdvRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, ui * * \param pBod Pointer to the BOD to execute. * \param pBle BLE operation parameters. - * - * \return None. */ /*************************************************************************************************/ static void bbSlvExecuteAuxAdvOp(BbOpDesc_t *pBod, BbBleData_t *pBle) @@ -306,7 +363,6 @@ static void bbSlvExecuteAuxAdvOp(BbOpDesc_t *pBod, BbBleData_t *pBle) bbBleCb.bbParam.txCback = bbSlvAuxAdvTxCompCback; bbBleCb.bbParam.rxCback = bbSlvAuxAdvRxCompCback; bbBleCb.bbParam.rxTimeoutUsec = 2 * LL_MAX_TIFS_DEVIATION; - bbBleCb.bbParam.dueOffsetUsec = 0; bbBleCb.advChIdx = 0; bbBleCb.evtState = 0; @@ -325,14 +381,15 @@ static void bbSlvExecuteAuxAdvOp(BbOpDesc_t *pBod, BbBleData_t *pBle) PalBbBleSetChannelParam(&pBle->chan); - bbBleCb.bbParam.due = pBod->due; + bbBleCb.bbParam.dueUsec = BbAdjustTime(pBod->dueUsec); + pBod->dueUsec = bbBleCb.bbParam.dueUsec; bbBleCb.evtState = BB_EVT_STATE_TX_ADV_IND; PalBbBleSetDataParams(&bbBleCb.bbParam); if (pAuxAdv->pRxAuxReqBuf) { /* Request expected (scannable or connectable operation). */ - bbBleSetIfs(); + bbBleSetTifs(); } else { @@ -349,8 +406,6 @@ static void bbSlvExecuteAuxAdvOp(BbOpDesc_t *pBod, BbBleData_t *pBle) * * \param pBod Pointer to the BOD to execute. * \param pBle BLE operation parameters. - * - * \return None. */ /*************************************************************************************************/ static void bbSlvExecutePerAdvOp(BbOpDesc_t *pBod, BbBleData_t *pBle) @@ -360,7 +415,6 @@ static void bbSlvExecutePerAdvOp(BbOpDesc_t *pBod, BbBleData_t *pBle) bbBleCb.bbParam.txCback = bbSlvAuxAdvTxCompCback; bbBleCb.bbParam.rxCback = bbSlvAuxAdvRxCompCback; bbBleCb.bbParam.rxTimeoutUsec = 2 * LL_MAX_TIFS_DEVIATION; - bbBleCb.bbParam.dueOffsetUsec = 0; bbBleCb.advChIdx = 0; bbBleCb.evtState = 0; @@ -379,14 +433,15 @@ static void bbSlvExecutePerAdvOp(BbOpDesc_t *pBod, BbBleData_t *pBle) PalBbBleSetChannelParam(&pBle->chan); - bbBleCb.bbParam.due = pBod->due; + bbBleCb.bbParam.dueUsec = BbAdjustTime(pBod->dueUsec); + pBod->dueUsec = bbBleCb.bbParam.dueUsec; bbBleCb.evtState = BB_EVT_STATE_TX_ADV_IND; PalBbBleSetDataParams(&bbBleCb.bbParam); if (pAuxAdv->pRxAuxReqBuf) { /* Request expected (scannable or connectable operation). */ - bbBleSetIfs(); + bbBleSetTifs(); } else { @@ -401,8 +456,6 @@ static void bbSlvExecutePerAdvOp(BbOpDesc_t *pBod, BbBleData_t *pBle) /*! * \brief Initialize for advertising slave operations. * - * \return None. - * * Update the operation table with advertising slave operations routines. */ /*************************************************************************************************/ @@ -418,8 +471,6 @@ void BbBleAuxAdvSlaveInit(void) * \brief Get auxiliary advertising packet statistics. * * \param pStats Auxiliary advertising statistics. - * - * \return None. */ /*************************************************************************************************/ void BbBleGetAuxAdvStats(BbBleAuxAdvPktStats_t *pStats) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_bis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_bis_master.c new file mode 100644 index 0000000000..76c4098f4e --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_bis_master.c @@ -0,0 +1,201 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief BIG master baseband porting implementation 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. + */ +/*************************************************************************************************/ + +#include "bb_api.h" +#include "bb_ble_api.h" +#include "pal_bb.h" +#include "bb_ble_int.h" +#include + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/* Combine BIS statistics; use instantiation in bb_ble_bis_slave.c. */ +extern BbBleDataPktStats_t bbBisStats; /*!< BIS packet statistics. */ + +/*************************************************************************************************/ +/*! + * \brief Rx completion for BIS master operation. + * + * \param status Completion 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 bbMstBisRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint32_t timestamp, uint8_t rxPhyOptions) +{ + BB_ISR_START(); + + bbBleCb.evtState += 1; + + WSF_ASSERT(BbGetCurrentBod()); + + BbOpDesc_t * const pCur = BbGetCurrentBod(); + BbBleMstBisEvent_t * const pBis = &pCur->prot.pBle->op.mstBis; + + /* Store initial Rx timestamp, regardless of receive status. */ + pBis->startTsUsec = timestamp; + + WSF_ASSERT(bbBleCb.pRxDataBuf); + uint8_t *pBuf = bbBleCb.pRxDataBuf; + bbBleCb.pRxDataBuf = NULL; + + pBis->rxDataCback(pCur, pBuf, status); + + if (BbGetBodTerminateFlag()) + { + PalBbBleCancelTifs(); + BbTerminateBod(); + } + + /* Update statistics. */ + switch (status) + { + case BB_STATUS_SUCCESS: + BB_INC_STAT(bbBisStats.rxData); + break; + case BB_STATUS_RX_TIMEOUT: + BB_INC_STAT(bbBisStats.rxDataTimeout); + break; + case BB_STATUS_CRC_FAILED: + BB_INC_STAT(bbBisStats.rxDataCrc); + break; + case BB_STATUS_FAILED: + default: + BB_INC_STAT(bbBisStats.errData); + break; + } + + BB_ISR_MARK(bbBisStats.rxIsrUsec); +} + +/*************************************************************************************************/ +/*! + * \brief Cancel BIS master BOD. + * + * \param pBod Pointer to the BOD to cancel. + * \param pBle BLE operation parameters. + */ +/*************************************************************************************************/ +static void bbMstCancelBisOp(BbOpDesc_t *pBod, BbBleData_t *pBle) +{ + PalBbBleCancelData(); +} + +/*************************************************************************************************/ +/*! + * \brief Execute BIS master BOD. + * + * \param pBod Pointer to the BOD to execute. + * \param pBle BLE operation parameters. + */ +/*************************************************************************************************/ +static void bbMstExecuteBisOp(BbOpDesc_t *pBod, BbBleData_t *pBle) +{ + BbBleMstBisEvent_t * const pBis = &pBod->prot.pBle->op.mstBis; + + PalBbBleSetChannelParam(&pBle->chan); + + /* bbBleCb.bbParam.txCback = NULL; */ /* Unused */ + bbBleCb.bbParam.rxCback = bbMstBisRxCompCback; + bbBleCb.bbParam.dueUsec = BbAdjustTime(pBod->dueUsec); + bbBleCb.bbParam.rxTimeoutUsec = pBis->rxSyncDelayUsec; + PalBbBleSetDataParams(&bbBleCb.bbParam); + + bbBleCb.evtState = 0; + + pBis->execCback(pBod); + + if (BbGetBodTerminateFlag() && /* Client signaled cancel. */ + BbGetCurrentBod()) /* Termination still pending. */ + { + BbTerminateBod(); + } +} + +/*************************************************************************************************/ +/*! + * \brief Initialize for BIS master operations. + * + * Update the operation table with BIS master operations routines. + */ +/*************************************************************************************************/ +void BbBleBisMasterInit(void) +{ + bbBleRegisterOp(BB_BLE_OP_MST_BIS_EVENT, bbMstExecuteBisOp, bbMstCancelBisOp); + + memset(&bbBisStats, 0, sizeof(bbBisStats)); +} + +/*************************************************************************************************/ +/*! + * \brief Set receive BIS Data PDU buffer for next receive slot. + * + * \param pBuf Receive data buffer. + * \param len Maximum length of data buffer. + * \param nextPduTime Next PDU time. + * \param pNextChan Next PDU channel. + * \param reAcq Rx train re-acquisition required. + */ +/*************************************************************************************************/ +void BbBleBisRxData(uint8_t *pBuf, uint16_t len, uint32_t nextPduTime, PalBbBleChan_t *pNextChan, bool_t reAcq) +{ + WSF_ASSERT(!bbBleCb.pRxDataBuf); + + bbBleCb.pRxDataBuf = pBuf; + bbBleCb.rxDataLen = len; + + bbBleSetAbsIfs(nextPduTime, pNextChan); + + if ((bbBleCb.evtState == 0) || reAcq) + { + PalBbBleRxData(pBuf, len); + } + else + { + BB_ISR_MARK(bbBisStats.rxSetupUsec); + PalBbBleRxTifsData(pBuf, len); + } +} + +/*************************************************************************************************/ +/*! + * \brief Receive data re-acquisition. + * + * \param syncTime Due time for the next Rx operation. + * + * Update due time for next Rx operation. Called after a missed Rx operation for re-acquisition + * of the receive train. + */ +/*************************************************************************************************/ +void BbBleBisRxDataReAcq(uint32_t syncTime, PalBbBleChan_t *pChan) +{ + PalBbBleCancelTifs(); + bbBleCb.bbParam.dueUsec = syncTime; + PalBbBleSetChannelParam(pChan); + PalBbBleSetDataParams(&bbBleCb.bbParam); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_bis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_bis_slave.c new file mode 100644 index 0000000000..d232cf6e3c --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_bis_slave.c @@ -0,0 +1,151 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief BIG slave baseband porting implementation file. + * + * Copyright (c) 2019 ARM Ltd. All Rights Reserved. + * + * 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 "bb_api.h" +#include "bb_ble_api.h" +#include "pal_bb.h" +#include "bb_ble_int.h" +#include + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +BbBleDataPktStats_t bbBisStats; /*!< BIS packet statistics. */ + +/*************************************************************************************************/ +/*! + * \brief Tx completion for BIS slave operation. + * + * \param status Completion status. + * + * Setup for next action in the operation or complete the operation. + */ +/*************************************************************************************************/ +static void bbSlvBisTxCompCback(uint8_t status) +{ + BB_ISR_START(); + + bbBleCb.evtState += 1; + + WSF_ASSERT(BbGetCurrentBod()); + + BbOpDesc_t * const pCur = BbGetCurrentBod(); + BbBleSlvBisEvent_t * const pBis = &pCur->prot.pBle->op.slvBis; + + pBis->txDataCback(pCur, status); + BB_INC_STAT(bbBisStats.txData); + + if (BbGetBodTerminateFlag()) + { + PalBbBleCancelTifs(); + BbTerminateBod(); + } + + BB_ISR_MARK(bbBisStats.txIsrUsec); +} + +/*************************************************************************************************/ +/*! + * \brief Cancel BIS slave BOD. + * + * \param pBod Pointer to the BOD to cancel. + * \param pBle BLE operation parameters. + */ +/*************************************************************************************************/ +static void bbSlvCancelBisOp(BbOpDesc_t *pBod, BbBleData_t *pBle) +{ + PalBbBleCancelData(); +} + +/*************************************************************************************************/ +/*! + * \brief Execute BIS slave BOD. + * + * \param pBod Pointer to the BOD to execute. + * \param pBle BLE operation parameters. + */ +/*************************************************************************************************/ +static void bbSlvExecuteBisOp(BbOpDesc_t *pBod, BbBleData_t *pBle) +{ + BbBleSlvBisEvent_t * const pBis = &pBod->prot.pBle->op.slvBis; + + PalBbBleSetChannelParam(&pBle->chan); + + bbBleCb.bbParam.txCback = bbSlvBisTxCompCback; + /* bbBleCb.bbParam.rxCback = NULL; */ /* Unused */ + bbBleCb.bbParam.dueUsec = BbAdjustTime(pBod->dueUsec); + pBod->dueUsec = bbBleCb.bbParam.dueUsec; + /* bbBleCb.bbParam.rxTimeoutUsec = 0; */ /* Unused */ + PalBbBleSetDataParams(&bbBleCb.bbParam); + + bbBleCb.evtState = 0; + + pBis->execCback(pBod); + + if (BbGetBodTerminateFlag() && /* Client signaled cancel. */ + BbGetCurrentBod()) /* Termination still pending. */ + { + BbTerminateBod(); + } +} + +/*************************************************************************************************/ +/*! + * \brief Initialize for BIS slave operations. + * + * Update the operation table with BIS slave operations routines. + */ +/*************************************************************************************************/ +void BbBleBisSlaveInit(void) +{ + bbBleRegisterOp(BB_BLE_OP_SLV_BIS_EVENT, bbSlvExecuteBisOp, bbSlvCancelBisOp); + + memset(&bbBisStats, 0, sizeof(bbBisStats)); +} + +/*************************************************************************************************/ +/*! + * \brief Transmit BIS Data PDU at next transmit slot. + * + * \param descs Array of transmit buffer descriptor. + * \param cnt Number of descriptors. + * \param nextPduTime Next PDU time. + * \param pNextChan Next PDU channel. + */ +/*************************************************************************************************/ +void BbBleBisTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt, uint32_t nextPduTime, PalBbBleChan_t *pNextChan) +{ + bbBleSetAbsIfs(nextPduTime, pNextChan); + + if (bbBleCb.evtState == 0) + { + PalBbBleTxData(descs, cnt); + } + else + { + BB_ISR_MARK(bbBisStats.txSetupUsec); + PalBbBleTxTifsData(descs, cnt); + } +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis.c new file mode 100644 index 0000000000..472dd1b9b1 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis.c @@ -0,0 +1,104 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Connected isochronous stream baseband porting implementation file. + * + * Copyright (c) 2013-2019 ARM Ltd. All Rights Reserved. + * + * 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 "bb_api.h" +#include "pal_bb.h" +#include "bb_ble_int.h" +#include "wsf_trace.h" + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +BbBleDataPktStats_t bbCisStats; /*!< CIS packet statistics. */ + +/*************************************************************************************************/ +/*! + * \brief Transmit data PDU at next transmit slot. + * + * \param descs Array of transmit buffer descriptor. + * \param cnt Number of descriptors. + * + * \note This function is expected to be called during the call context of + * \ref BbBleMstCisEvent_t::rxDataCback or \ref BbBleSlvCisEvent_t::rxDataCback + * callback routine. + */ +/*************************************************************************************************/ +void BbBleCisTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) +{ + if ((BbGetCurrentBod()->prot.pBle->chan.opType == BB_BLE_OP_MST_CIS_EVENT) && + (bbBleCb.evtState == 0)) + { + bbBleSetTifs(); /* master always Rx's after Tx */ + PalBbBleTxData(descs, cnt); + } + else + { + BB_ISR_MARK(bbCisStats.txSetupUsec); + /* TODO set only if master or if slave and Rx may follow in CE. */ + bbBleSetTifs(); + PalBbBleTxTifsData(descs, cnt); + } +} + +/*************************************************************************************************/ +/*! + * \brief Set receive data buffer for next receive slot. + * + * \param pBuf Receive data buffer. + * \param len Maximum length of data buffer. + * + * \note This function is expected to be called during the call context of + * \ref BbBleMstCisEvent_t::rxDataCback or + * \ref BbBleSlvCisEvent_t::rxDataCback callback routine. + * + * \note BB must always call the \ref BbBleMstCisEvent_t::rxDataCback or + * \ref BbBleSlvCisEvent_t::rxDataCback callback routine of the + * currently executing BOD with the given buffer. + */ +/*************************************************************************************************/ +void BbBleCisRxData(uint8_t *pBuf, uint16_t len) +{ + WSF_ASSERT(!bbBleCb.pRxCisDataBuf); + + bbBleCb.pRxCisDataBuf = pBuf; + bbBleCb.rxCisDataLen = len; + + if ((BbGetCurrentBod()->prot.pBle->chan.opType == BB_BLE_OP_SLV_CIS_EVENT) && + (bbBleCb.evtState == 0)) + { + bbBleSetTifs(); /* slave always Tx's after Rx */ + PalBbBleRxData(pBuf, len); + } +} + +/*************************************************************************************************/ +/*! + * \brief Get connection packet statistics. + */ +/*************************************************************************************************/ +void BbBleGetCisStats(BbBleDataPktStats_t *pStats) +{ + *pStats = bbCisStats; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis_master.c new file mode 100644 index 0000000000..f259fce35d --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis_master.c @@ -0,0 +1,344 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Connected isochronous stream master baseband porting implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "bb_api.h" +#include "pal_bb.h" +#include "bb_ble_int.h" +#include + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief Event states for scan operations. */ +enum +{ + BB_EVT_STATE_IDLE, /*!< Idle state. */ + BB_EVT_STATE_TERMINATING, /*!< BOD terminating state. */ +}; + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +extern BbBleDataPktStats_t bbCisStats; /*!< CIS packet statistics. */ + +/*************************************************************************************************/ +/*! + * \brief Check whether to continue next operation or not. + * + * \param pCur Current BOD. + * \param pCis Master CIS event. + * \param pNewCisCtx TRUE if switch to a new CIS context. + * + * \return TRUE if operation completed; FALSE if it continues. + */ +/*************************************************************************************************/ +static bool_t bbMstCisCheckContOp(BbOpDesc_t *pCur, BbBleMstCisEvent_t *pCis, bool_t *pNewCisCtx) +{ + if (BbGetBodTerminateFlag()) + { + return TRUE; + } + + /* Update new channel index and due time. */ + uint32_t offsUsec = pCis->checkContOpCback(pCur, pNewCisCtx); + + if (offsUsec == 0) + { + /* Operation completed. */ + return TRUE; + } + + /* Updated channel parameter. */ + BbBleData_t *pBle = pCur->prot.pBle; + PalBbBleSetChannelParam(&pBle->chan); + + /* Updated due time and data parameters. */ + bbBleCb.bbParam.dueUsec = BbAdjustTime(bbBleCb.bbParam.dueUsec + offsUsec); + PalBbBleSetDataParams(&bbBleCb.bbParam); + + /* Update the header field and start Tx. */ + pCis->contExecCback(pCur); + + /* Operation continues. */ + return FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Post subevent operation activities. + * + * \param pCur Current BOD. + * \param pCis Master CIS event. + * \param status Baseband status code. + */ +/*************************************************************************************************/ +static void bbMstCisPostSubEvt(BbOpDesc_t *pCur, BbBleMstCisEvent_t *pCis, uint8_t status) +{ + /* Calculate the next sub-event channel index and also setup Rx resource. */ + pCis->postSubEvtCback(pCur, status); +} + +/*************************************************************************************************/ +/*! + * \brief Tx completion for CIS master operation. + * + * \param status Transmission status + * + * Setup for next action in the operation or complete the operation. + */ +/*************************************************************************************************/ +static void bbMstCisTxCompCback(uint8_t status) +{ + BB_ISR_START(); + + WSF_ASSERT(BbGetCurrentBod()); + + BbOpDesc_t * const pCur = BbGetCurrentBod(); + BbBleMstCisEvent_t * const pCis = &pCur->prot.pBle->op.mstCis; + + pCis->txDataCback(pCur, status); + + if (bbBleCb.pRxCisDataBuf && + (status == BB_STATUS_SUCCESS)) + { + BB_ISR_MARK(bbCisStats.rxSetupUsec); + + bbBleSetTifs(); /* TODO set only if Tx may follow in CE */ + PalBbBleRxTifsData(bbBleCb.pRxCisDataBuf, bbBleCb.rxDataLen); + } + else + { + /* Cancel TIFS timer if active. */ + switch (status) + { + case BB_STATUS_SUCCESS: + PalBbBleCancelTifs(); + break; + case BB_STATUS_FAILED: + default: + /* Free Rx data buffer before BOD end. */ + if (bbBleCb.pRxCisDataBuf != NULL) /* buffer should always exist, but still check */ + { + uint8_t *pBuf = bbBleCb.pRxCisDataBuf; + bbBleCb.pRxCisDataBuf = NULL; + pCis->rxDataCback(pCur, pBuf, BB_STATUS_CANCELED); + } + break; + } + + if (bbBleCb.evtState == BB_EVT_STATE_IDLE) + { + /* Avoid double terminating BOD */ + BbTerminateBod(); + bbBleCb.evtState = BB_EVT_STATE_TERMINATING; + } + } + + /* Update statistics. */ + switch (status) + { + case BB_STATUS_SUCCESS: + BB_INC_STAT(bbCisStats.txData); + break; + case BB_STATUS_FAILED: + default: + BB_INC_STAT(bbCisStats.errData); + break; + } + + BB_ISR_MARK(bbCisStats.txIsrUsec); +} + +/*************************************************************************************************/ +/*! + * \brief Rx completion for CIS 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 bbMstCisRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint32_t timestamp, uint8_t rxPhyOptions) +{ + BB_ISR_START(); + + WSF_ASSERT(BbGetCurrentBod()); + + BbOpDesc_t * const pCur = BbGetCurrentBod(); + BbBleMstCisEvent_t * const pCis = &pCur->prot.pBle->op.mstCis; + bool_t bodComplete = FALSE; + bool_t newCisCtx = FALSE; + + pCis->rssi = rssi; + pCis->rxPhyOptions = rxPhyOptions; + + WSF_ASSERT(bbBleCb.pRxCisDataBuf); + uint8_t *pBuf = bbBleCb.pRxCisDataBuf; + bbBleCb.pRxCisDataBuf = NULL; + + pCis->rxDataCback(pCur, pBuf, status); + + /* If continue current operation, need to setup the channel parameter here. */ + bodComplete = bbMstCisCheckContOp(pCur, pCis, &newCisCtx); + + if (BbGetBodTerminateFlag() || bodComplete) + { + WSF_ASSERT(!bbBleCb.pRxCisDataBuf); + + /* Cancel TIFS timer if active. */ + switch (status) + { + case BB_STATUS_SUCCESS: + case BB_STATUS_CRC_FAILED: + PalBbBleCancelTifs(); + break; + default: + break; + } + + if (bbBleCb.evtState == BB_EVT_STATE_IDLE) + { + /* Avoid double terminating BOD */ + BbTerminateBod(); + bbBleCb.evtState = BB_EVT_STATE_TERMINATING; + } + } + + /* Skip the post subevent callback if switching to the new CIS context. */ + if (newCisCtx == FALSE) + { + bbMstCisPostSubEvt(pCur, pCis, status); + } + + /* Update statistics. */ + switch (status) + { + case BB_STATUS_SUCCESS: + BB_INC_STAT(bbCisStats.rxData); + break; + case BB_STATUS_RX_TIMEOUT: + BB_INC_STAT(bbCisStats.rxDataTimeout); + break; + case BB_STATUS_CRC_FAILED: + BB_INC_STAT(bbCisStats.rxDataCrc); + break; + case BB_STATUS_FAILED: + default: + BB_INC_STAT(bbCisStats.errData); + break; + } + + BB_ISR_MARK(bbCisStats.rxIsrUsec); +} + +/*************************************************************************************************/ +/*! + * \brief Execute CIS master BOD. + * + * \param pBod Pointer to the BOD to execute. + * \param pBle BLE operation parameters. + */ +/*************************************************************************************************/ +static void bbMstExecuteCisOp(BbOpDesc_t *pBod, BbBleData_t *pBle) +{ + BbBleMstCisEvent_t * const pCis = &pBod->prot.pBle->op.mstCis; + + if (BbGetBodTerminateFlag()) + { + /* Client terminated. */ + return; + } + + WSF_ASSERT(pBle->op.mstCis.txDataCback); + WSF_ASSERT(pBle->op.mstCis.rxDataCback); + WSF_ASSERT(pBle->op.mstCis.execCback); + WSF_ASSERT(pBle->op.mstCis.checkContOpCback); + + #if(LL_ENABLE_TESTER) + pBle->chan.txPower += pBle->chan.txPwrOffset; + #endif + PalBbBleSetChannelParam(&pBle->chan); + + bbBleCb.bbParam.txCback = bbMstCisTxCompCback; + bbBleCb.bbParam.rxCback = bbMstCisRxCompCback; + bbBleCb.bbParam.dueUsec = BbAdjustTime(pBod->dueUsec); + pBod->dueUsec = bbBleCb.bbParam.dueUsec; + bbBleCb.bbParam.rxTimeoutUsec = 2 * LL_MAX_TIFS_DEVIATION; + + PalBbBleSetDataParams(&bbBleCb.bbParam); + + bbBleCb.evtState = BB_EVT_STATE_IDLE; + + if (pCis->execCback) + { + pCis->execCback(pBod); + } +} + +/*************************************************************************************************/ +/*! + * \brief Cancel CIS master BOD. + * + * \param pBod Pointer to the BOD to cancel. + * \param pBle BLE operation parameters. + */ +/*************************************************************************************************/ +static void bbMstCancelCisOp(BbOpDesc_t *pBod, BbBleData_t *pBle) +{ + WSF_ASSERT(pBod && pBle); + WSF_ASSERT(pBle->op.mstCis.rxDataCback); + + PalBbBleCancelData(); + + if (bbBleCb.pRxCisDataBuf) + { + uint8_t *pBuf = bbBleCb.pRxCisDataBuf; + bbBleCb.pRxCisDataBuf = NULL; + + /* Buffer free expected to be called during this routine. */ + pBle->op.mstCis.rxDataCback(pBod, pBuf, BB_STATUS_CANCELED); + } + + pBle->op.mstCis.cancelCback(pBod); +} + +/*************************************************************************************************/ +/*! + * \brief Initialize for CIS master operations. + * + * Update the operation table with CIS master operations routines. + */ +/*************************************************************************************************/ +void BbBleCisMasterInit(void) +{ + bbBleRegisterOp(BB_BLE_OP_MST_CIS_EVENT, bbMstExecuteCisOp, bbMstCancelCisOp); + + memset(&bbCisStats, 0, sizeof(bbCisStats)); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis_slave.c new file mode 100644 index 0000000000..5a38d7bfb6 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_cis_slave.c @@ -0,0 +1,384 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Connected isochronous stream slave baseband porting implementation file. + * + * Copyright (c) 2013-2019 ARM Ltd. All Rights Reserved. + * + * 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 "bb_api.h" +#include "pal_bb.h" +#include "bb_ble_int.h" +#include "wsf_trace.h" +#include + +/*! \brief Event states for scan operations. */ +enum +{ + BB_EVT_STATE_IDLE, /*!< Idle state. */ + BB_EVT_STATE_TERMINATING, /*!< BOD terminating state. */ +}; + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +extern BbBleDataPktStats_t bbCisStats; /*!< Connection packet statistics. */ + +/*************************************************************************************************/ +/*! + * \brief Post subevent operation activities. + * + * \param pCur Current BOD. + * \param pCis Slave CIS event. + * \param status status. + */ +/*************************************************************************************************/ +static void bbSlvCisPostSubEvt(BbOpDesc_t *pCur, BbBleSlvCisEvent_t *pCis, uint8_t status) +{ + /* Calculate the next sub-event channel index. */ + pCis->postSubEvtCback(pCur, status); +} + +/*************************************************************************************************/ +/*! + * \brief Check whether to continue next operation or not. + * + * \param pCur Current BOD. + * \param pCis Slave CIS event. + * \param pNewCisCtx TRUE if switch to a new CIS context. + * + * \return TRUE if operation completed; FALSE if it continues. + */ +/*************************************************************************************************/ +static bool_t bbSlvCisCheckNextOp(BbOpDesc_t *pCur, BbBleSlvCisEvent_t *pCis, bool_t *pNewCisCtx) +{ + if (BbGetBodTerminateFlag()) + { + return TRUE; + } + + /* Update new channel index and due time. */ + uint32_t offsUsec = pCis->checkContOpCback(pCur, pNewCisCtx); + + if (offsUsec == 0) + { + /* Operation completed. */ + return TRUE; + } + + /* Update channel parameter. */ + BbBleData_t *pBle = pCur->prot.pBle; + PalBbBleSetChannelParam(&pBle->chan); + + /* Note setting radio requires setting up the channel and due time, need to be done first. */ + pCis->rxTsUsec = BbAdjustTime(pCis->rxTsUsec + offsUsec); + pCur->dueUsec = pCis->rxTsUsec; + + bbBleCb.bbParam.dueUsec = pCur->dueUsec; + bbBleCb.bbParam.rxTimeoutUsec = pCis->rxSyncDelayUsec; + + PalBbBleSetDataParams(&bbBleCb.bbParam); + + /* Update the header field and start Rx. */ + pCis->contExecCback(pCur); + + /* Operation continues. */ + return FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Tx completion for CIS slave operation. + * + * \param status Transmission status + * + * Setup for next action in the operation or complete the operation. + */ +/*************************************************************************************************/ +static void bbSlvCisTxCompCback(uint8_t status) +{ + BB_ISR_START(); + + WSF_ASSERT(BbGetCurrentBod()); + + BbOpDesc_t * const pCur = BbGetCurrentBod(); + BbBleSlvCisEvent_t * const pCis = &pCur->prot.pBle->op.slvCis; + + pCis->txDataCback(pCur, status); + + bool_t bodComplete = FALSE; + bool_t newCisCtx = FALSE; + + bodComplete = bbSlvCisCheckNextOp(pCur, pCis, &newCisCtx); + + if (status == BB_STATUS_SUCCESS) + { + if (BbGetBodTerminateFlag() || bodComplete) + { + /* Cancel TIFS timer if active. */ + PalBbBleCancelTifs(); + + /* Tx completion is end of BOD. */ + if (bbBleCb.evtState == BB_EVT_STATE_IDLE) + { + /* Avoid double terminating BOD */ + BbTerminateBod(); + bbBleCb.evtState = BB_EVT_STATE_TERMINATING; + } + } + } + else if (status == BB_STATUS_FAILED) + { + if (bodComplete) + { + if (bbBleCb.pRxCisDataBuf != NULL) + { + uint8_t *pBuf = bbBleCb.pRxCisDataBuf; + bbBleCb.pRxCisDataBuf = NULL; + pCis->rxDataCback(pCur, pBuf, BB_STATUS_CANCELED); + } + + /* Cancel TIFS timer if active. */ + PalBbBleCancelTifs(); + + if (bbBleCb.evtState == BB_EVT_STATE_IDLE) + { + /* Avoid double terminating BOD */ + BbTerminateBod(); + bbBleCb.evtState = BB_EVT_STATE_TERMINATING; + } + } + } + else + { + if (bbBleCb.pRxCisDataBuf != NULL) + { + uint8_t *pBuf = bbBleCb.pRxCisDataBuf; + bbBleCb.pRxCisDataBuf = NULL; + pCis->rxDataCback(pCur, pBuf, BB_STATUS_CANCELED); + } + + if (bbBleCb.evtState == BB_EVT_STATE_IDLE) + { + /* Avoid double terminating BOD */ + BbTerminateBod(); + bbBleCb.evtState = BB_EVT_STATE_TERMINATING; + } + } + + /* Skip the post subevent callback if switching to the new CIS context. */ + if (newCisCtx == FALSE) + { + bbSlvCisPostSubEvt(pCur, pCis, status); + } + + /* Update statistics. */ + switch (status) + { + case BB_STATUS_SUCCESS: + BB_INC_STAT(bbCisStats.txData); + break; + case BB_STATUS_FAILED: + default: + BB_INC_STAT(bbCisStats.errData); + break; + } + + BB_ISR_MARK(bbCisStats.txIsrUsec); +} + +/*************************************************************************************************/ +/*! + * \brief Rx completion for CIS slave 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 bbSlvCisRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint32_t timestamp, uint8_t rxPhyOptions) +{ + BB_ISR_START(); + + WSF_ASSERT(BbGetCurrentBod()); + + BbOpDesc_t * const pCur = BbGetCurrentBod(); + BbBleSlvCisEvent_t * const pCis = &pCur->prot.pBle->op.slvCis; + + pCis->rssi = rssi; + pCis->rxPhyOptions = rxPhyOptions; + + if (pCis->isFirstTs == TRUE) + { + /* Update startTs for the successful rx, otherwise use the due time. */ + if (status == BB_STATUS_SUCCESS) + { + pCis->startTsUsec = timestamp; + } + else + { + pCis->startTsUsec = pCur->dueUsec; + } + pCis->isFirstTs = FALSE; + pCis->rxTsUsec = pCis->startTsUsec; + } + else + { + /* Update rxTs for the successful rx, otherwise use the due time. */ + if (status == BB_STATUS_SUCCESS) + { + pCis->rxTsUsec = timestamp; + } + } + + WSF_ASSERT(bbBleCb.pRxCisDataBuf); + + uint8_t *pBuf = bbBleCb.pRxCisDataBuf; + bbBleCb.pRxCisDataBuf = 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()) + { + WSF_ASSERT(!bbBleCb.pRxCisDataBuf); + + /* Cancel TIFS timer if active. */ + switch (status) + { + case BB_STATUS_SUCCESS: + PalBbBleCancelTifs(); + break; + default: + break; + } + + if (bbBleCb.evtState == BB_EVT_STATE_IDLE) + { + /* Avoid double terminating BOD */ + BbTerminateBod(); + bbBleCb.evtState = BB_EVT_STATE_TERMINATING; + } + } + + /* Update statistics. */ + switch (status) + { + case BB_STATUS_SUCCESS: + BB_INC_STAT(bbCisStats.rxData); + break; + case BB_STATUS_RX_TIMEOUT: + BB_INC_STAT(bbCisStats.rxDataTimeout); + break; + case BB_STATUS_CRC_FAILED: + BB_INC_STAT(bbCisStats.rxDataCrc); + break; + case BB_STATUS_FAILED: + default: + BB_INC_STAT(bbCisStats.errData); + break; + } + + BB_ISR_MARK(bbCisStats.rxIsrUsec); +} + +/*************************************************************************************************/ +/*! + * \brief Execute CIS slave BOD. + * + * \param pBod Pointer to the BOD to execute. + * \param pBle BLE operation parameters. + */ +/*************************************************************************************************/ +static void bbSlvExecuteCisOp(BbOpDesc_t *pBod, BbBleData_t *pBle) +{ + BbBleSlvCisEvent_t * const pCis = &pBod->prot.pBle->op.slvCis; + + WSF_ASSERT(pCis->txDataCback); + WSF_ASSERT(pCis->rxDataCback); + WSF_ASSERT(pCis->execCback); + WSF_ASSERT(pCis->checkContOpCback); + + pCis->isFirstTs = TRUE; + pCis->rxTsUsec = pBod->dueUsec; + + #if(LL_ENABLE_TESTER) + pBle->chan.txPower += pBle->chan.txPwrOffset; + #endif + PalBbBleSetChannelParam(&pBle->chan); + + bbBleCb.bbParam.txCback = bbSlvCisTxCompCback; + bbBleCb.bbParam.rxCback = bbSlvCisRxCompCback; + bbBleCb.bbParam.dueUsec = BbAdjustTime(pCis->rxTsUsec); + pCis->rxTsUsec = bbBleCb.bbParam.dueUsec; + bbBleCb.bbParam.rxTimeoutUsec = pCis->rxSyncDelayUsec; + + PalBbBleSetDataParams(&bbBleCb.bbParam); + + bbBleCb.evtState = BB_EVT_STATE_IDLE; + + pBle->op.slvCis.execCback(pBod); +} + +/*************************************************************************************************/ +/*! + * \brief Cancel CIS slave BOD. + * + * \param pBod Pointer to the BOD to cancel. + * \param pBle BLE operation parameters. + */ +/*************************************************************************************************/ +static void bbSlvCancelCisOp(BbOpDesc_t *pBod, BbBleData_t *pBle) +{ + WSF_ASSERT(pBod && pBle); + WSF_ASSERT(pBle->op.slvCis.rxDataCback); + + PalBbBleCancelData(); + + if (bbBleCb.pRxCisDataBuf) + { + uint8_t *pBuf = bbBleCb.pRxCisDataBuf; + bbBleCb.pRxCisDataBuf = NULL; + + /* Buffer free expected to be called during this routine. */ + pBle->op.slvCis.rxDataCback(pBod, pBuf, BB_STATUS_CANCELED); + } + + pBle->op.slvCis.cancelCback(pBod); +} + +/*************************************************************************************************/ +/*! + * \brief Initialize for connected isochronous stream slave operations. + * + * Update the operation table with onnected isochronous stream slave operations routines. + */ +/*************************************************************************************************/ +void BbBleCisSlaveInit(void) +{ + bbBleRegisterOp(BB_BLE_OP_SLV_CIS_EVENT, bbSlvExecuteCisOp, bbSlvCancelCisOp); + + memset(&bbCisStats, 0, sizeof(bbCisStats)); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_conn.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_conn.c index 8b5f509be3..e19a92d901 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_conn.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_conn.c @@ -1,29 +1,32 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Connectable BLE baseband porting implementation file. + * \file + * + * \brief Connectable BLE baseband porting implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 #include "bb_api.h" #include "pal_bb.h" #include "bb_ble_int.h" +#include "bb_ble_sniffer_api.h" #if BB_DATA_PLD_MAX_LEN < LL_MAX_DATA_LEN_MIN #error "Unsupported BB_DATA_PLD_MAX_LEN value, must be greater than 27 bytes" @@ -46,8 +49,6 @@ BbBleDataPktStats_t bbConnStats; /*!< Connection packet statistics. */ * \param descs Array of transmit buffer descriptor. * \param cnt Number of descriptors. * - * \return None. - * * \note This function is expected to be called during the call context of * \ref BbBleMstConnEvent_t::rxDataCback or \ref BbBleSlvConnEvent_t::rxDataCback * callback routine. @@ -55,10 +56,16 @@ BbBleDataPktStats_t bbConnStats; /*!< Connection packet statistics. */ /*************************************************************************************************/ void BbBleTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) { +#if (BB_SNIFFER_ENABLED == TRUE) + if (bbSnifferCtx.enabled) + { + memcpy(bbSnifferCtx.txBuf, descs->pBuf, LL_DATA_HDR_MAX_LEN); + } +#endif if ((BbGetCurrentBod()->prot.pBle->chan.opType == BB_BLE_OP_MST_CONN_EVENT) && (bbBleCb.evtState == 0)) { - bbBleSetIfs(); /* master always Rx's after Tx */ + bbBleSetTifs(); /* master always Rx's after Tx */ PalBbBleTxData(descs, cnt); } else @@ -66,7 +73,7 @@ void BbBleTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) BB_ISR_MARK(bbConnStats.txSetupUsec); /* TODO set only if master or if slave and Rx may follow in CE. */ - bbBleSetIfs(); + bbBleSetTifs(); PalBbBleTxTifsData(descs, cnt); } } @@ -78,8 +85,6 @@ void BbBleTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) * \param pBuf Receive data buffer. * \param len Maximum length of data buffer. * - * \return None. - * * \note This function is expected to be called during the call context of * \ref BbBleMstConnEvent_t::rxDataCback or * \ref BbBleSlvConnEvent_t::rxDataCback callback routine. @@ -99,7 +104,7 @@ void BbBleRxData(uint8_t *pBuf, uint16_t len) if ((BbGetCurrentBod()->prot.pBle->chan.opType == BB_BLE_OP_SLV_CONN_EVENT) && (bbBleCb.evtState == 0)) { - bbBleSetIfs(); /* slave always Tx's after Rx */ + bbBleSetTifs(); /* slave always Tx's after Rx */ PalBbBleRxData(pBuf, len); } } @@ -107,8 +112,6 @@ void BbBleRxData(uint8_t *pBuf, uint16_t len) /*************************************************************************************************/ /*! * \brief Get connection packet statistics. - * - * \return None. */ /*************************************************************************************************/ void BbBleGetConnStats(BbBleDataPktStats_t *pStats) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_conn_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_conn_master.c index 4a9b220280..2d8f2fa13a 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_conn_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_conn_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Connectable master BLE baseband porting implementation file. + * \file + * + * \brief Connectable master BLE baseband porting implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -25,6 +26,7 @@ #include "pal_bb.h" #include "bb_ble_int.h" #include +#include "bb_ble_sniffer_api.h" /************************************************************************************************** Global Variables @@ -38,8 +40,6 @@ extern BbBleDataPktStats_t bbConnStats; /*!< Connection packet statistics. * * * \param status Transmission status * - * \return None. - * * Setup for next action in the operation or complete the operation. */ /*************************************************************************************************/ @@ -52,6 +52,16 @@ static void bbMstConnTxCompCback(uint8_t status) BbOpDesc_t * const pCur = BbGetCurrentBod(); BbBleMstConnEvent_t * const pConn = &pCur->prot.pBle->op.mstConn; + +#if (BB_SNIFFER_ENABLED == TRUE) + uint8_t evtState = bbBleCb.evtState; + BbBleSnifferPkt_t * pPkt = NULL; + if (bbSnifferCtx.enabled) + { + pPkt = bbSnifferCtx.snifferGetPktFn(); + } +#endif + WSF_ASSERT(pCur); pConn->txDataCback(pCur, status); @@ -61,7 +71,7 @@ static void bbMstConnTxCompCback(uint8_t status) { BB_ISR_MARK(bbConnStats.rxSetupUsec); - bbBleSetIfs(); /* TODO set only if Tx may follow in CE */ + bbBleSetTifs(); /* TODO set only if Tx may follow in CE */ PalBbBleRxTifsData(bbBleCb.pRxDataBuf, bbBleCb.rxDataLen); } else @@ -99,6 +109,17 @@ static void bbMstConnTxCompCback(uint8_t status) break; } +#if (BB_SNIFFER_ENABLED == TRUE) + if (pPkt) + { + pPkt->pktType.meta.type = BB_SNIFF_PKT_TYPE_TX; + pPkt->pktType.meta.state = evtState; + pPkt->pktType.meta.status = status; + + bbBleSnifferConnPktHandler(pCur, pPkt); + } +#endif + BB_ISR_MARK(bbConnStats.txIsrUsec); } @@ -109,11 +130,9 @@ static void bbMstConnTxCompCback(uint8_t status) * \param status Reception status. * \param rssi RSSI value. * \param crc CRC value. - * \param timestamp Start of packet timestamp. + * \param timestamp Start of packet timestamp in microseconds. * \param rxPhyOptions Rx PHY options. * - * \return None. - * * Setup for next action in the operation or complete the operation. */ /*************************************************************************************************/ @@ -126,6 +145,21 @@ static void bbMstConnRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint BbOpDesc_t * const pCur = BbGetCurrentBod(); BbBleMstConnEvent_t * const pConn = &pCur->prot.pBle->op.mstConn; +#if (BB_SNIFFER_ENABLED == TRUE) + uint8_t evtState = bbBleCb.evtState; + BbBleSnifferPkt_t * pPkt = NULL; + if (bbSnifferCtx.enabled) + { + pPkt = bbSnifferCtx.snifferGetPktFn(); + } + + /* Copy to sniffer packet buffer before overwriting. */ + if (pPkt) + { + memcpy(pPkt->pktType.dataPkt.hdr, bbBleCb.pRxDataBuf, LL_DATA_HDR_MAX_LEN); + } +#endif + pConn->rssi = rssi; pConn->rxPhyOptions = rxPhyOptions; @@ -177,6 +211,19 @@ static void bbMstConnRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint break; } +#if (BB_SNIFFER_ENABLED == TRUE) + if (pPkt) + { + pPkt->pktType.meta.type = BB_SNIFF_PKT_TYPE_RX; + pPkt->pktType.meta.rssi = rssi; + pPkt->pktType.meta.timeStamp = timestamp; + pPkt->pktType.meta.state = evtState; + pPkt->pktType.meta.status = status; + + bbBleSnifferConnPktHandler(pCur, pPkt); + } +#endif + BB_ISR_MARK(bbConnStats.rxIsrUsec); } @@ -186,12 +233,14 @@ static void bbMstConnRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint * * \param pBod Pointer to the BOD to execute. * \param pBle BLE operation parameters. - * - * \return None. */ /*************************************************************************************************/ static void bbMstExecuteConnOp(BbOpDesc_t *pBod, BbBleData_t *pBle) { +#if(LL_ENABLE_TESTER) + pBle->chan.txPower += pBle->chan.txPwrOffset; +#endif + PalBbBleSetChannelParam(&pBle->chan); WSF_ASSERT(pBle->op.mstConn.txDataCback); @@ -199,8 +248,8 @@ static void bbMstExecuteConnOp(BbOpDesc_t *pBod, BbBleData_t *pBle) bbBleCb.bbParam.txCback = bbMstConnTxCompCback; bbBleCb.bbParam.rxCback = bbMstConnRxCompCback; - bbBleCb.bbParam.due = pBod->due; - bbBleCb.bbParam.dueOffsetUsec = pBod->dueOffsetUsec; + bbBleCb.bbParam.dueUsec = BbAdjustTime(pBod->dueUsec); + pBod->dueUsec = bbBleCb.bbParam.dueUsec; bbBleCb.bbParam.rxTimeoutUsec = 2 * LL_MAX_TIFS_DEVIATION; PalBbBleSetDataParams(&bbBleCb.bbParam); @@ -216,8 +265,6 @@ static void bbMstExecuteConnOp(BbOpDesc_t *pBod, BbBleData_t *pBle) * * \param pBod Pointer to the BOD to cancel. * \param pBle BLE operation parameters. - * - * \return None. */ /*************************************************************************************************/ static void bbMstCancelConnOp(BbOpDesc_t *pBod, BbBleData_t *pBle) @@ -244,8 +291,6 @@ static void bbMstCancelConnOp(BbOpDesc_t *pBod, BbBleData_t *pBle) /*! * \brief Initialize for connectable master operations. * - * \return None. - * * Update the operation table with connectable master operations routines. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_conn_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_conn_slave.c index 19a6497e9c..07d67c860b 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_conn_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_conn_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Connectable slave BLE baseband porting implementation file. + * \file + * + * \brief Connectable slave BLE baseband porting implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -25,6 +26,7 @@ #include "pal_bb.h" #include "bb_ble_int.h" #include +#include "bb_ble_sniffer_api.h" /************************************************************************************************** Global Variables @@ -38,8 +40,6 @@ extern BbBleDataPktStats_t bbConnStats; /*!< Connection packet statistics. * * * \param status Transmission status * - * \return None. - * * Setup for next action in the operation or complete the operation. */ /*************************************************************************************************/ @@ -52,6 +52,15 @@ static void bbSlvConnTxCompCback(uint8_t status) BbOpDesc_t * const pCur = BbGetCurrentBod(); BbBleSlvConnEvent_t * const pConn = &pCur->prot.pBle->op.slvConn; +#if (BB_SNIFFER_ENABLED == TRUE) + uint8_t evtState = bbBleCb.evtState; + BbBleSnifferPkt_t * pPkt = NULL; + if (bbSnifferCtx.enabled) + { + pPkt = bbSnifferCtx.snifferGetPktFn(); + } +#endif + pConn->txDataCback(pCur, status); if (status == BB_STATUS_SUCCESS) @@ -60,7 +69,7 @@ static void bbSlvConnTxCompCback(uint8_t status) { BB_ISR_MARK(bbConnStats.rxSetupUsec); - bbBleSetIfs(); /* slave always Tx's after Rx */ + bbBleSetTifs(); /* slave always Tx's after Rx */ PalBbBleRxTifsData(bbBleCb.pRxDataBuf, bbBleCb.rxDataLen); } else @@ -97,6 +106,17 @@ static void bbSlvConnTxCompCback(uint8_t status) break; } +#if (BB_SNIFFER_ENABLED == TRUE) + if (pPkt) + { + pPkt->pktType.meta.type = BB_SNIFF_PKT_TYPE_TX; + pPkt->pktType.meta.state = evtState; + pPkt->pktType.meta.status = status; + + bbBleSnifferConnPktHandler(pCur, pPkt); + } +#endif + BB_ISR_MARK(bbConnStats.txIsrUsec); } @@ -107,11 +127,9 @@ static void bbSlvConnTxCompCback(uint8_t status) * \param status Reception status. * \param rssi RSSI value. * \param crc CRC value. - * \param timestamp Start of packet timestamp. + * \param timestamp Start of packet timestamp in microseconds. * \param rxPhyOptions Rx PHY options. * - * \return None. - * * Setup for next action in the operation or complete the operation. */ /*************************************************************************************************/ @@ -124,6 +142,21 @@ static void bbSlvConnRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint BbOpDesc_t * const pCur = BbGetCurrentBod(); BbBleSlvConnEvent_t * const pConn = &pCur->prot.pBle->op.slvConn; +#if (BB_SNIFFER_ENABLED == TRUE) + uint8_t evtState = bbBleCb.evtState; + BbBleSnifferPkt_t * pPkt = NULL; + if (bbSnifferCtx.enabled) + { + pPkt = bbSnifferCtx.snifferGetPktFn(); + } + + /* Copy to sniffer packet buffer before overwriting. */ + if (pPkt) + { + memcpy(pPkt->pktType.dataPkt.hdr, bbBleCb.pRxDataBuf, LL_DATA_HDR_MAX_LEN); + } +#endif + pConn->rssi = rssi; pConn->rxPhyOptions = rxPhyOptions; @@ -131,7 +164,7 @@ static void bbSlvConnRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint { bbBleCb.evtState = 1; - pConn->startTs = timestamp; + pConn->startTsUsec = timestamp; } WSF_ASSERT(bbBleCb.pRxDataBuf); @@ -178,6 +211,19 @@ static void bbSlvConnRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint break; } +#if (BB_SNIFFER_ENABLED == TRUE) + if (pPkt) + { + pPkt->pktType.meta.type = BB_SNIFF_PKT_TYPE_RX; + pPkt->pktType.meta.rssi = rssi; + pPkt->pktType.meta.timeStamp = timestamp; + pPkt->pktType.meta.state = evtState; + pPkt->pktType.meta.status = status; + + bbBleSnifferConnPktHandler(pCur, pPkt); + } +#endif + BB_ISR_MARK(bbConnStats.rxIsrUsec); } @@ -187,8 +233,6 @@ static void bbSlvConnRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint * * \param pBod Pointer to the BOD to execute. * \param pBle BLE operation parameters. - * - * \return None. */ /*************************************************************************************************/ static void bbSlvExecuteConnOp(BbOpDesc_t *pBod, BbBleData_t *pBle) @@ -198,12 +242,16 @@ static void bbSlvExecuteConnOp(BbOpDesc_t *pBod, BbBleData_t *pBle) WSF_ASSERT(pConn->txDataCback); WSF_ASSERT(pConn->rxDataCback); +#if(LL_ENABLE_TESTER) + pBle->chan.txPower += pBle->chan.txPwrOffset; +#endif + PalBbBleSetChannelParam(&pBle->chan); bbBleCb.bbParam.txCback = bbSlvConnTxCompCback; bbBleCb.bbParam.rxCback = bbSlvConnRxCompCback; - bbBleCb.bbParam.due = pBod->due; - bbBleCb.bbParam.dueOffsetUsec = pBod->dueOffsetUsec; + bbBleCb.bbParam.dueUsec = BbAdjustTime(pBod->dueUsec); + pBod->dueUsec = bbBleCb.bbParam.dueUsec; bbBleCb.bbParam.rxTimeoutUsec = pConn->rxSyncDelayUsec; PalBbBleSetDataParams(&bbBleCb.bbParam); @@ -219,8 +267,6 @@ static void bbSlvExecuteConnOp(BbOpDesc_t *pBod, BbBleData_t *pBle) * * \param pBod Pointer to the BOD to cancel. * \param pBle BLE operation parameters. - * - * \return None. */ /*************************************************************************************************/ static void bbSlvCancelConnOp(BbOpDesc_t *pBod, BbBleData_t *pBle) @@ -247,8 +293,6 @@ static void bbSlvCancelConnOp(BbOpDesc_t *pBod, BbBleData_t *pBle) /*! * \brief Initialize for connectable slave operations. * - * \return None. - * * Update the operation table with connectable slave operations routines. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_test.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_dtm.c similarity index 80% rename from features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_test.c rename to features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_dtm.c index bf2f8f2a2b..31aa43f3bf 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_test.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_dtm.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Generic BLE baseband driver implementation file. + * \file + * + * \brief Generic BLE baseband driver implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -39,8 +40,6 @@ extern BbRtCfg_t *pBbRtCfg; * * \param status Completion status. * - * \return None. - * * Completion handler for the BLE transmit test operation. */ /*************************************************************************************************/ @@ -57,6 +56,9 @@ static void bbTestTxCompCback(uint8_t status) switch (status) { case BB_STATUS_SUCCESS: + PalBbBleCancelTifs(); + + /* Terminate BOD if new channel parameters are required. */ bodComplete = !pTx->testCback(pCur, status); break; @@ -73,14 +75,9 @@ static void bbTestTxCompCback(uint8_t status) } else { - const uint32_t pktInterUsec = pTx->pktInterUsec + bbBleCb.bbParam.dueOffsetUsec; - const uint32_t pktInter = BB_US_TO_BB_TICKS(pktInterUsec); - int16_t dueOffsetUsec = pktInterUsec - BB_TICKS_TO_US(pktInter); + const uint32_t pktInterUsec = pTx->pktInterUsec; - PalBbBleCancelTifs(); - - bbBleCb.bbParam.due = bbBleCb.bbParam.due + pktInter; - bbBleCb.bbParam.dueOffsetUsec = WSF_MAX(dueOffsetUsec, 0); + bbBleCb.bbParam.dueUsec = BbAdjustTime(bbBleCb.bbParam.dueUsec + pktInterUsec); PalBbBleSetChannelParam(&pBle->chan); PalBbBleSetDataParams(&bbBleCb.bbParam); @@ -111,8 +108,6 @@ static void bbTestTxCompCback(uint8_t status) * \param timestamp Start of packet timestamp. * \param rxPhyOptions Rx PHY options. * - * \return None. - * * Completion handler for the BLE receive test operation. */ /*************************************************************************************************/ @@ -150,11 +145,8 @@ static void bbTestRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint32_ PalBbBleCancelTifs(); const uint32_t pktInterUsec = pBbRtCfg->rfSetupDelayUs; - const uint32_t pktInter = BB_US_TO_BB_TICKS(pktInterUsec); - int16_t dueOffsetUsec = pktInterUsec - BB_TICKS_TO_US(pktInter); - bbBleCb.bbParam.due = PalBbGetCurrentTime(USE_RTC_BB_CLK) + pktInter; - bbBleCb.bbParam.dueOffsetUsec = WSF_MAX(dueOffsetUsec, 0); + bbBleCb.bbParam.dueUsec = BbAdjustTime(PalBbGetCurrentTime() + pktInterUsec); bbBleCb.bbParam.rxTimeoutUsec = pRx->rxSyncDelayUsec; PalBbBleSetChannelParam(&pBle->chan); PalBbBleSetDataParams(&bbBleCb.bbParam); @@ -187,8 +179,6 @@ static void bbTestRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint32_ * * \param pBod Pointer to the BOD to execute. * \param pBle BLE operation parameters. - * - * \return None. */ /*************************************************************************************************/ static void bbTestCleanupOp(BbOpDesc_t *pBod, BbBleData_t *pBle) @@ -203,8 +193,6 @@ static void bbTestCleanupOp(BbOpDesc_t *pBod, BbBleData_t *pBle) * * \param pBod Pointer to the BOD to execute. * \param pBle BLE operation parameters. - * - * \return None. */ /*************************************************************************************************/ static void bbSlvExecuteTestTxOp(BbOpDesc_t *pBod, BbBleData_t *pBle) @@ -213,8 +201,8 @@ static void bbSlvExecuteTestTxOp(BbOpDesc_t *pBod, BbBleData_t *pBle) bbBleCb.bbParam.txCback = bbTestTxCompCback; bbBleCb.bbParam.rxCback = bbTestRxCompCback; - bbBleCb.bbParam.due = pBod->due; - bbBleCb.bbParam.dueOffsetUsec = pBod->dueOffsetUsec; + bbBleCb.bbParam.dueUsec = BbAdjustTime(pBod->dueUsec); + pBod->dueUsec = bbBleCb.bbParam.dueUsec; PalBbBleSetChannelParam(&pBle->chan); PalBbBleSetDataParams(&bbBleCb.bbParam); @@ -230,8 +218,6 @@ static void bbSlvExecuteTestTxOp(BbOpDesc_t *pBod, BbBleData_t *pBle) * * \param pBod Pointer to the BOD to execute. * \param pBle BLE operation parameters. - * - * \return None. */ /*************************************************************************************************/ static void bbSlvExecuteTestRxOp(BbOpDesc_t *pBod, BbBleData_t *pBle) @@ -240,8 +226,8 @@ static void bbSlvExecuteTestRxOp(BbOpDesc_t *pBod, BbBleData_t *pBle) bbBleCb.bbParam.txCback = bbTestTxCompCback; bbBleCb.bbParam.rxCback = bbTestRxCompCback; - bbBleCb.bbParam.due = pBod->due; - bbBleCb.bbParam.dueOffsetUsec = pBod->dueOffsetUsec; + bbBleCb.bbParam.dueUsec = BbAdjustTime(pBod->dueUsec); + pBod->dueUsec = bbBleCb.bbParam.dueUsec; bbBleCb.bbParam.rxTimeoutUsec = pRx->rxSyncDelayUsec; PalBbBleSetChannelParam(&pBle->chan); @@ -255,8 +241,6 @@ static void bbSlvExecuteTestRxOp(BbOpDesc_t *pBod, BbBleData_t *pBle) /*! * \brief Initialize for direct test mode operations. * - * \return None. - * * Update the operation table with direct test mode operations routines. */ /*************************************************************************************************/ @@ -271,8 +255,6 @@ void BbBleTestInit(void) /*************************************************************************************************/ /*! * \brief Get test mode packet statistics. - * - * \return None. */ /*************************************************************************************************/ void BbBleGetTestStats(BbBleDataPktStats_t *pStats) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_int.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_int.h index d37c770c6a..d9ded94f9c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_int.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_int.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal BLE baseband interface file. + * \file + * + * \brief Internal BLE baseband interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -45,10 +46,28 @@ extern "C" { #define BB_ADVB_MAX_LEN WSF_MAX(BB_FIXED_ADVB_PKT_LEN, LL_ADVB_MAX_LEN) /*! \brief Mark the start of an ISR. */ -#define BB_ISR_START() bbIsrStartTime = PalBbGetCurrentTime(USE_RTC_BB_CLK) +#define BB_ISR_START() bbIsrStartTime = PalBbGetCurrentTime() /*! \brief Mark the ISR duration, recording the high watermark. */ -#define BB_ISR_MARK(x) x = WSF_MAX(x, BB_TICKS_TO_US(PalBbGetCurrentTime(USE_RTC_BB_CLK) - bbIsrStartTime)) +#define BB_ISR_MARK(x) x = WSF_MAX(x, PalBbGetCurrentTime() - bbIsrStartTime) + +/*! \brief Event states for advertising operations. */ +enum +{ + BB_EVT_STATE_TX_ADV_IND, /*!< Advertising indication. */ + BB_EVT_STATE_RX_SCAN_OR_CONN_INIT, /*!< Scan or connection init packet. */ + BB_EVT_STATE_TX_SCAN_OR_CONN_RSP, /*!< Scan or connection response. */ + BB_EVT_STATE_TX_CHAIN_IND /*!< Chain indication. */ +}; + +/*! \brief Event states for scanning operations. */ +enum +{ + BB_EVT_STATE_RX_ADV_IND, /*!< Advertising indication. */ + BB_EVT_STATE_TX_SCAN_OR_CONN_INIT, /*!< Scan or connection init packet. */ + BB_EVT_STATE_RX_SCAN_OR_CONN_RSP, /*!< Scan or connection response. */ + BB_EVT_STATE_RX_CHAIN_IND /*!< Chain indication. */ +}; /************************************************************************************************** Data Types @@ -69,13 +88,14 @@ typedef struct uint8_t evtState; /*!< Action state of the currently operating BOD. */ uint8_t advChIdx; /*!< Current advertising channel index. */ uint8_t numChUsed; /*!< Total number of channels visited. */ - uint32_t lastScanStart; /*!< Last scan start time. */ + uint32_t lastScanStartUsec; /*!< Last scan start time in microseconds. */ PalBbBleDataParam_t bbParam; /*!< Baseband data parameters. */ 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; @@ -97,8 +117,6 @@ extern uint32_t bbIsrStartTime; * \param opType Operation type. * \param execOpCback Execute operation callback. * \param cancelOpCback Cancel operation callback. - * - * \return None. */ /*************************************************************************************************/ void bbBleRegisterOp(uint8_t opType, bbBleExecOpFn_t execOpCback, bbBleExecOpFn_t cancelOpCback); @@ -111,29 +129,42 @@ void bbBleRegisterOp(uint8_t opType, bbBleExecOpFn_t execOpCback, bbBleExecOpFn_ /*! * \brief Clear IFS in operation. * - * \return None. - * * The BB may choose not to enable IFS after the next Tx or Rx. */ /*************************************************************************************************/ static inline void bbBleClrIfs(void) { - PalBbBleOpParam_t opParams = { .ifsSetup = FALSE, .ifsUsec = 0 }; + /* PalBbBleOpParam_t opParams = { .ifsMode = PAL_BB_IFS_MODE_CLR, .ifsTime = 0, .pIfsChan = NULL }; */ + PalBbBleOpParam_t opParams = { 0 }; PalBbBleSetOpParams(&opParams); } /*************************************************************************************************/ /*! - * \brief Set IFS in operation. + * \brief Set TIFS in operation. * - * \return None. - * - * The BB must enable IFS after the next Tx or Rx. + * The BB must enable TIFS after the next Tx or Rx. */ /*************************************************************************************************/ -static inline void bbBleSetIfs(void) +static inline void bbBleSetTifs(void) { - PalBbBleOpParam_t opParams = { .ifsSetup = TRUE, .ifsUsec = LL_BLE_TIFS_US }; + PalBbBleOpParam_t opParams = { .ifsMode = PAL_BB_IFS_MODE_TOGGLE_TIFS, .ifsTime = 0, .pIfsChan = NULL }; + PalBbBleSetOpParams(&opParams); +} + +/*************************************************************************************************/ +/*! + * \brief Set absolute time IFS in operation. + * + * \param ifsTime Due time of the next PDU. + * \param pIfsChan Channel of the next PDU. + * + * The BB must enable IFS with absolute time after the next Tx or Rx. + */ +/*************************************************************************************************/ +static inline void bbBleSetAbsIfs(uint32_t ifsTime, PalBbBleChan_t *pIfsChan) +{ + PalBbBleOpParam_t opParams = { .ifsMode = PAL_BB_IFS_MODE_SAME_ABS, .ifsTime = ifsTime, .pIfsChan = pIfsChan }; PalBbBleSetOpParams(&opParams); } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_main.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_main.c index 8802961676..733b15fe42 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_main.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_main.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Generic BLE baseband driver implementation file. + * \file + * + * \brief Generic BLE baseband driver implementation file. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -39,8 +40,6 @@ bbBleCtrlBlk_t bbBleCb; /*!< BB BLE control block. */ /*************************************************************************************************/ /*! * \brief Start BB processing of BLE protocol. - * - * \return None. */ /*************************************************************************************************/ static void bbBleStartBle(void) @@ -52,8 +51,6 @@ static void bbBleStartBle(void) /*************************************************************************************************/ /*! * \brief Start BB processing of BLE protocol. - * - * \return None. */ /*************************************************************************************************/ static void bbBleStopBle(void) @@ -64,8 +61,6 @@ static void bbBleStopBle(void) /*************************************************************************************************/ /*! * \brief Start BB processing of BLE DTM protocol. - * - * \return None. */ /*************************************************************************************************/ static void bbBleStartBleDtm(void) @@ -77,8 +72,6 @@ static void bbBleStartBleDtm(void) /*************************************************************************************************/ /*! * \brief Start BB processing of PRBS15 protocol. - * - * \return None. */ /*************************************************************************************************/ static void bbBleStartPrbs15(void) @@ -91,8 +84,6 @@ static void bbBleStartPrbs15(void) /*************************************************************************************************/ /*! * \brief Start BB processing of PRBS15 protocol. - * - * \return None. */ /*************************************************************************************************/ static void bbBleStopPrbs15(void) @@ -106,8 +97,6 @@ static void bbBleStopPrbs15(void) * \brief Execute operation. * * \param pBod Pointer to the BOD to execute. - * - * \return None. */ /*************************************************************************************************/ static void bbBleExecOp(BbOpDesc_t *pBod) @@ -127,8 +116,6 @@ static void bbBleExecOp(BbOpDesc_t *pBod) * \brief Cancel operation. * * \param pBod Pointer to the BOD to cancel. - * - * \return None. */ /*************************************************************************************************/ static void bbBleCancelOp(BbOpDesc_t *pBod) @@ -142,12 +129,22 @@ static void bbBleCancelOp(BbOpDesc_t *pBod) bbBleCb.opCbacks[pBle->chan.opType].cancelOpCback(pBod, pBle); } } + +/*************************************************************************************************/ +/*! + * \brief Low power operation. + * + */ +/*************************************************************************************************/ +static void bbBleLowPower(void) +{ + PalBbBleLowPower(); +} + /*************************************************************************************************/ /*! * \brief Initialize the BLE BB. * - * \return None. - * * Initialize baseband resources. */ /*************************************************************************************************/ @@ -157,6 +154,7 @@ void BbBleInit(void) BbRegisterProt(BB_PROT_BLE, bbBleExecOp, bbBleCancelOp, bbBleStartBle, bbBleStopBle); BbRegisterProt(BB_PROT_BLE_DTM, bbBleExecOp, bbBleCancelOp, bbBleStartBleDtm, bbBleStopBle); BbRegisterProt(BB_PROT_PRBS15, NULL, bbBleCancelOp, bbBleStartPrbs15, bbBleStopPrbs15); + BbRegisterProtLowPower(BB_PROT_BLE, bbBleLowPower); memset(&bbBleCb, 0, sizeof(bbBleCb)); } @@ -168,8 +166,6 @@ void BbBleInit(void) * \param opType Operation type. * \param execOpCback Execute operation callback. * \param cancelOpCback Cancel operation callback. - * - * \return None. */ /*************************************************************************************************/ void bbBleRegisterOp(uint8_t opType, bbBleExecOpFn_t execOpCback, bbBleExecOpFn_t cancelOpCback) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_pdufilt.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_pdufilt.c index 1638e68a7f..d52f9e7c8e 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_pdufilt.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_pdufilt.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Generic BLE device filtering implementation file. + * \file + * + * \brief Generic BLE device filtering implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -154,6 +155,37 @@ static inline uint8_t bbBlePduFiltResolvePeer(bool_t peerAddrResEna, bool_t forc } } } + else if (!(*pPeerAddrRand && BDA64_ADDR_IS_RPA(*pPeerAddr))) + { + /* Even if address resolution is disabled, filter PDU if network privacy is enabled. */ + switch (BbBleResListPeerStatus(*pPeerAddrRand, *pPeerAddr)) + { + /*** other than RPA that cannot have RPA ***/ + + case BB_BLE_RESLIST_STATUS_ZERO_IRK: + case BB_BLE_RESLIST_STATUS_ID_ADDR_NOT_IN_LIST: + default: + return BB_BLE_PDU_FILT_OK; + + /*** other than RPA that can have RPA ***/ + + case BB_BLE_RESLIST_STATUS_RES_ADDR_ASSIGNED: + case BB_BLE_RESLIST_STATUS_RES_ADDR_UNASSIGNED: + { + uint8_t privMode; + + /* Refuse to accept peer identity address. */ + if (!BbBleResListGetPrivacyMode(*pPeerAddrRand, *pPeerAddr, &privMode) || + (privMode == BB_BLE_RESLIST_PRIV_MODE_NETWORK)) + { + BB_INC_PDUFILT_STAT(failPeerPrivAddrReq); + return BB_BLE_PDU_FILT_NOT_OK; + } + + return BB_BLE_PDU_FILT_OK; + } + } + } /* Address will be accepted based upon match. */ return BB_BLE_PDU_FILT_OK; @@ -172,8 +204,8 @@ static inline uint8_t bbBlePduFiltResolvePeer(bool_t peerAddrResEna, bool_t forc * \return Tri-state result (OK, NOT_OK, UNKNOWN). */ /*************************************************************************************************/ -static inline bool_t bbBlePduFiltMatchPeer(bool_t addrMatchEna, bool_t idAddrRand, uint64_t idAddr, - bool_t addrMatchRand, uint64_t addrMatch) +static inline uint8_t bbBlePduFiltMatchPeer(bool_t addrMatchEna, bool_t idAddrRand, uint64_t idAddr, + bool_t addrMatchRand, uint64_t addrMatch) { if (addrMatchEna) { @@ -202,8 +234,8 @@ static inline bool_t bbBlePduFiltMatchPeer(bool_t addrMatchEna, bool_t idAddrRan * \return Tri-state result (OK, NOT_OK, UNKNOWN). */ /*************************************************************************************************/ -static inline bool_t bbBlePduFiltWhiteList(bool_t peerWhiteListEna, bool_t peerIdAddrRand, - uint64_t peerIdAddr) +static inline uint8_t bbBlePduFiltWhiteList(bool_t peerWhiteListEna, bool_t peerIdAddrRand, + uint64_t peerIdAddr) { if (peerWhiteListEna) { @@ -311,8 +343,8 @@ static inline uint8_t bbBlePduFiltResolveLocal(bool_t localAddrResEna, bool_t fo * \return Tri-state result (OK, NOT_OK, UNKNOWN). */ /*************************************************************************************************/ -static inline bool_t bbBlePduFiltMatchLocal(bool_t addrMatchEna, bool_t idAddrRand, uint64_t idAddr, - bool_t addrMatchRand, uint64_t addrMatch) +static inline uint8_t bbBlePduFiltMatchLocal(bool_t addrMatchEna, bool_t idAddrRand, uint64_t idAddr, + bool_t addrMatchRand, uint64_t addrMatch) { if (addrMatchEna) { @@ -389,7 +421,7 @@ bool_t BbBlePduFiltCheck(const uint8_t *pBuf, const bbBlePduFiltParams_t *pFiltP /* Resolve peer address to pass through filters. */ switch (bbBlePduFiltResolvePeer(BB_BLE_PDU_FILT_FLAG_IS_SET(pFiltParams, PEER_ADDR_RES_ENA), forceRes, - &pFiltResults->peerIdAddrRand, + (uint8_t *)&pFiltResults->peerIdAddrRand, &pFiltResults->peerIdAddr)) { case BB_BLE_PDU_FILT_OK: @@ -549,6 +581,7 @@ bool_t BbBleExtPduFiltCheck(const bbBlePduExtFiltParams_t *pExtFiltParams, #endif /*** Filter PDU by PDU type. ***/ + if ((pFiltParams->pduTypeFilt & (1 << pExtFiltParams->pduType)) == 0) { BB_INC_PDUFILT_STAT(failPduTypeFilt); @@ -566,7 +599,7 @@ bool_t BbBleExtPduFiltCheck(const bbBlePduExtFiltParams_t *pExtFiltParams, /* Resolve peer address to pass through filters. */ switch (bbBlePduFiltResolvePeer(BB_BLE_PDU_FILT_FLAG_IS_SET(pFiltParams, PEER_ADDR_RES_ENA), forceRes, - &pFiltResults->peerIdAddrRand, + (uint8_t *)&pFiltResults->peerIdAddrRand, &pFiltResults->peerIdAddr)) { case BB_BLE_PDU_FILT_OK: @@ -695,8 +728,6 @@ bool_t BbBleExtPduFiltCheck(const bbBlePduExtFiltParams_t *pExtFiltParams, * \brief Get PDU filter statistics. * * \param pStats PDU filter statistics. - * - * \return None. */ /*************************************************************************************************/ void BbBleGetPduFiltStats(BbBlePduFiltStats_t *pStats) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_periodiclist.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_periodiclist.c index e1684340d1..e821ec924f 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_periodiclist.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_periodiclist.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Generic BLE whitelist implementation file. + * \file + * + * \brief Generic BLE whitelist implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -102,7 +103,7 @@ uint16_t BbBleInitPeriodicList(uint8_t numEntries, uint8_t *pFreeMem, uint32_t f /*************************************************************************************************/ bool_t BbBlePeriodicListCheckAddr(uint8_t addrType, uint64_t addr, uint8_t SID) { - for (uint8_t i = 0; i < bbBlePeriodicListNumEntries; i++) + for (unsigned int i = 0; i < bbBlePeriodicListNumEntries; i++) { if ((pBbBlePeriodicListFilt[i].addrType == addrType) && (pBbBlePeriodicListFilt[i].addr == addr) && @@ -135,8 +136,6 @@ uint8_t BbBlePeriodicListGetSize(void) /*! * \brief Clear all periodic list entries. * - * \return None. - * * Clear all periodic list entries stored in the BB. * * \note No resource synchronization is required to modify the periodic list resource as diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_reslist.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_reslist.c index 4da6eb99c4..66b2f4516f 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_reslist.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_reslist.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Generic BLE resolving list implementation file. + * \file + * + * \brief Generic BLE resolving list implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -25,8 +26,8 @@ #include "bb_ble_api.h" #include "bb_ble_api_reslist.h" #include "bb_ble_api_pdufilt.h" -#include "stack/platform/include/pal_bb_ble.h" -#include "stack/platform/include/pal_crypto.h" +#include "pal_bb_ble.h" +#include "pal_crypto.h" #include "wsf_assert.h" #include "ll_math.h" #include "util/bda.h" @@ -125,8 +126,6 @@ uint16_t BbBleInitResolvingList(uint8_t numEntries, uint8_t *pFreeMem, uint32_t * \brief Set address resolution needed callback. * * \param cback Callback. - * - * \return None. */ /*************************************************************************************************/ void BbBleResListSetAddrResNeededCback(bbBleResListAddrResNeeded_t cback) @@ -263,8 +262,6 @@ uint8_t BbBleResListGetSize(void) /*! * \brief Clear resolving list. * - * \return None. - * * Clear all resolving list entries stored in the BB. */ /*************************************************************************************************/ @@ -788,7 +785,7 @@ bool_t BbBleResListResolveLocal(uint64_t rpa, uint8_t *pPeerAddrType, uint64_t * * Get the peer resolvable private address status */ /*************************************************************************************************/ -bool_t BbBleResListPeerStatus(bool_t peerAddrRand, uint64_t peerIdentityAddr) +uint8_t BbBleResListPeerStatus(bool_t peerAddrRand, uint64_t peerIdentityAddr) { bbBleResListEntry_t *pEntry; @@ -824,7 +821,7 @@ bool_t BbBleResListPeerStatus(bool_t peerAddrRand, uint64_t peerIdentityAddr) * Get the peer resolvable private address status */ /*************************************************************************************************/ -bool_t BbBleResListLocalStatus(bool_t peerAddrRand, uint64_t peerIdentityAddr) +uint8_t BbBleResListLocalStatus(bool_t peerAddrRand, uint64_t peerIdentityAddr) { bbBleResListEntry_t *pEntry; @@ -852,8 +849,6 @@ bool_t BbBleResListLocalStatus(bool_t peerAddrRand, uint64_t peerIdentityAddr) /*! * \brief Handle timeout of local resolvable addresses. * - * \return None. - * * A new local resolvable address will be generated for each entry in the resolving list. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_sniffer.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_sniffer.c new file mode 100644 index 0000000000..f69df88d1c --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_sniffer.c @@ -0,0 +1,397 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief BB BLE Sniffer utility function definition file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 "bb_ble_sniffer_api.h" +#include "wsf_types.h" +#include "pal_bb_ble.h" +#include "bb_api.h" +#include "ll_api.h" +#include "bb_ble_api_op.h" +#include "wsf_trace.h" +#include "wsf_assert.h" +#include "pal_bb.h" +#include "bb_ble_int.h" +#include + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*! brief Sniffer VS output packet function placeholder. */ +static void bbSnifferOutputVendorSpec(BbBleSnifferPkt_t * pPktData); + +/*! brief Sniffer output table. */ +bbSnifferFn_t bbSnifferOutTbl[BB_SNIFFER_OUTPUT_TOTAL_METHODS] = +{ + bbSnifferOutputVendorSpec /* BB_SNIFFER_OUTPUT_HCI_TOKEN */ +}; + +/*! brief Sniffer VS get packet function placeholder. */ +static BbBleSnifferPkt_t * bbSnifferGetPktVendorSpec(); + +/*! brief Sniffer get packet table. */ +bbSnifferGetPktFn_t bbSnifferGetPktTbl[BB_SNIFFER_OUTPUT_TOTAL_METHODS] = +{ + bbSnifferGetPktVendorSpec /* BB_SNIFFER_OUTPUT_HCI_TOKEN */ +}; +/*! brief Sniffer context. */ +bbSnifferCtx_t bbSnifferCtx; + +/************************************************************************************************** + Packet retrival methods +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Retrive packet for processing. + * + * \return Pointer to packet to be packed. + * + */ +/*************************************************************************************************/ +static BbBleSnifferPkt_t * bbSnifferGetPktVendorSpec() +{ + BbBleSnifferHciCtx_t * pHci = &bbSnifferCtx.outputCtx.hci; + + if ((pHci->bufIdx == BB_SNIFFER_MAX_NUM_BUF) || + (bbSnifferCtx.enabled == FALSE)) + { + return NULL; + } + + return &pHci->pktBuf[pHci->bufIdx]; +} + + +/************************************************************************************************** + Output methods +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Finalize sniffer packet by incrementing index. + * + * \param pPktData Packet to be pushed. + * + */ +/*************************************************************************************************/ +static void bbSnifferOutputVendorSpec(BbBleSnifferPkt_t * pPktData) +{ + BbBleSnifferHciCtx_t * pHci = &bbSnifferCtx.outputCtx.hci; + + pHci->bufIdx++; +} +/*************************************************************************************************/ +/*! + * \brief Master primary scan sniffer packet handler. + * + * \param pBod Pointer to BOD. + * \param pPktData Pointer to sniffer packet. + * + * Pack sniffer packet and call to output method function. + */ +/*************************************************************************************************/ +void bbBleSnifferMstScanPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t * pPktData) +{ + BbBleMstAdvEvent_t * pScan = &pBod->prot.pBle->op.mstAdv; + + /* Pack channelization data. */ + memcpy(&pPktData->pktType.meta.chan, &pBod->prot.pBle->chan, sizeof(pPktData->pktType.meta.chan)); + + /* Pack metadata. */ + pPktData->pktType.meta.timeStamp = bbSnifferCtx.packetCtr++; + + /* Pack header. */ + switch (pPktData->pktType.meta.state) + { + case BB_EVT_STATE_RX_ADV_IND: + /* Handled in the Rx Callback. */ + break; + + case BB_EVT_STATE_TX_SCAN_OR_CONN_INIT: + memcpy(pPktData->pktType.advPkt.hdr, pScan->pTxReqBuf, LL_ADV_HDR_LEN); + break; + + case BB_EVT_STATE_RX_SCAN_OR_CONN_RSP: + /* Handled in the Rx Callback. */ + break; + + default: + break; + } + + WSF_ASSERT(bbSnifferCtx.snifferOutCb); + + bbSnifferCtx.snifferOutCb(pPktData); +} + +/*************************************************************************************************/ +/*! + * \brief Master auxiliary scan sniffer packet handler + * + * \param pBod Pointer to BOD. + * \param pPktData Pointer to sniffer packet. + * + * Pack sniffer packet and call to output method function. + */ +/*************************************************************************************************/ +void bbBleSnifferMstAuxScanPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t *pPktData) +{ + BbBleMstAuxAdvEvent_t * pScan = &pBod->prot.pBle->op.mstAuxAdv; + + /* Pack channelization data. */ + memcpy(&pPktData->pktType.meta.chan, &pBod->prot.pBle->chan, sizeof(pPktData->pktType.meta.chan)); + + /* Pack metadata. */ + pPktData->pktType.meta.timeStamp = bbSnifferCtx.packetCtr++; + + /* Pack header. */ + switch (pPktData->pktType.meta.state) + { + case BB_EVT_STATE_RX_ADV_IND: + /* Handled in the Rx Callback. */ + break; + + case BB_EVT_STATE_TX_SCAN_OR_CONN_INIT: + memcpy(pPktData->pktType.advPkt.hdr, pScan->pTxAuxReqBuf, LL_ADV_HDR_LEN); + break; + + case BB_EVT_STATE_RX_SCAN_OR_CONN_RSP: + /* Handled in the Rx Callback. */ + break; + + case BB_EVT_STATE_RX_CHAIN_IND: + /* Handled in the Rx callback. */ + break; + + default: + break; + } + + WSF_ASSERT(bbSnifferCtx.snifferOutCb); + + bbSnifferCtx.snifferOutCb(pPktData); +} + +/*************************************************************************************************/ +/*! + * \brief Master periodic scan sniffer packet handler. + * + * \param pBod Pointer to BOD. + * \param pPktData Pointer to sniffer packet. + * + * Pack sniffer packet and call to output method function. + */ +/*************************************************************************************************/ +void bbBleSnifferMstPerScanPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t *pPktData) +{ + /* Pack channelization data. */ + memcpy(&pPktData->pktType.meta.chan, &pBod->prot.pBle->chan, sizeof(pPktData->pktType.meta.chan)); + + /* Pack metadata. */ + pPktData->pktType.meta.timeStamp = bbSnifferCtx.packetCtr++; + + /* Pack header. */ + switch (pPktData->pktType.meta.state) + { + case BB_EVT_STATE_RX_ADV_IND: + /* Handled in the Rx Callback. */ + break; + + case BB_EVT_STATE_RX_CHAIN_IND: + /* Handled in the Rx callback. */ + break; + + default: + break; + } + + WSF_ASSERT(bbSnifferCtx.snifferOutCb); + + bbSnifferCtx.snifferOutCb(pPktData); +} + +/*************************************************************************************************/ +/*! + * \brief Slave primary advertising sniffer packet handler. + * + * \param pBod Pointer to BOD. + * \param pPktData Pointer to sniffer packet. + * + * Pack sniffer packet and call to output method function. + */ +/*************************************************************************************************/ +void bbBleSnifferSlvAdvPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t * pPktData) +{ + BbBleSlvAdvEvent_t * pAdv = &pBod->prot.pBle->op.slvAdv; + + /* Pack channelization data. */ + memcpy(&pPktData->pktType.meta.chan, &pBod->prot.pBle->chan, sizeof(pPktData->pktType.meta.chan)); + + /* Pack saved channel index. */ + pPktData->pktType.meta.chan.chanIdx = bbSnifferCtx.chanIdx; + + /* Pack metadata. */ + pPktData->pktType.meta.timeStamp = bbSnifferCtx.packetCtr++; + + /* Pack header. */ + switch (pPktData->pktType.meta.state) + { + case BB_EVT_STATE_TX_ADV_IND: + memcpy(pPktData->pktType.advPkt.hdr, pAdv->pTxAdvBuf, LL_ADV_HDR_LEN); + break; + + case BB_EVT_STATE_RX_SCAN_OR_CONN_INIT: + /* Handled in the Rx Callback. */ + break; + + case BB_EVT_STATE_TX_SCAN_OR_CONN_RSP: + memcpy(pPktData->pktType.advPkt.hdr, pAdv->pTxRspBuf, LL_ADV_HDR_LEN); + break; + + default: + break; + } + + WSF_ASSERT(bbSnifferCtx.snifferOutCb); + + bbSnifferCtx.snifferOutCb(pPktData); +} + +/*************************************************************************************************/ +/*! + * \brief Slave auxiliary advertising sniffer packet handler. + * + * \param pBod Pointer to BOD. + * \param pPktData Pointer to sniffer packet. + * + * Pack sniffer packet and call to output method function. + */ +/*************************************************************************************************/ +void bbBleSnifferSlvAuxAdvPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t * pPktData) +{ + BbBleSlvAuxAdvEvent_t * pAdv = &pBod->prot.pBle->op.slvAuxAdv; + + /* Pack channelization data. */ + memcpy(&pPktData->pktType.meta.chan, &pBod->prot.pBle->chan, sizeof(pPktData->pktType.meta.chan)); + + /* Pack metadata. */ + pPktData->pktType.meta.timeStamp = bbSnifferCtx.packetCtr++; + + /* Pack header. */ + switch (pPktData->pktType.meta.state) + { + case BB_EVT_STATE_TX_ADV_IND: + /* Handled in the Tx Callback. */ + break; + + case BB_EVT_STATE_RX_SCAN_OR_CONN_INIT: + /* Handled in the Rx Callback. */ + break; + + case BB_EVT_STATE_TX_SCAN_OR_CONN_RSP: + memcpy(pPktData->pktType.advPkt.hdr, pAdv->txAuxRspPdu[0].pBuf, LL_ADV_HDR_LEN); + break; + + case BB_EVT_STATE_TX_CHAIN_IND: + /* Handled in the Tx Callback. */ + break; + + default: + break; + } + + WSF_ASSERT(bbSnifferCtx.snifferOutCb); + + bbSnifferCtx.snifferOutCb(pPktData); +} + +/*************************************************************************************************/ +/*! + * \brief Connection sniffer packet handler. + * + * \param pBod Pointer to BOD. + * \param pPktData Pointer to sniffer packet. + * + * Pack sniffer packet and call to output method function. + */ +/*************************************************************************************************/ +void bbBleSnifferConnPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t * pPktData) +{ + /* BbBleMstConnEvent_t * pConn = &pBod->prot.pBle->op.mstConn; */ + + /* Pack channelization data. */ + memcpy(&pPktData->pktType.meta.chan, &pBod->prot.pBle->chan, sizeof(pPktData->pktType.meta.chan)); + + /* Pack metadata. */ + pPktData->pktType.meta.timeStamp = bbSnifferCtx.packetCtr++; + + /* Pack Header. */ + if (pPktData->pktType.meta.type == BB_SNIFF_PKT_TYPE_TX) + { + memcpy(pPktData->pktType.dataPkt.hdr, bbSnifferCtx.txBuf, LL_DATA_HDR_MAX_LEN); + } + else /* (type == BB_SNIFF_PKT_TYPE_RX) */ + { + /* Header copy is done in the Rx comp callback. */ + } + + WSF_ASSERT(bbSnifferCtx.snifferOutCb); + + bbSnifferCtx.snifferOutCb(pPktData); +} + +/*************************************************************************************************/ +/*! + * \brief Initialize packet sniffer + * + * \param outMethod Output method. + * \param enable Enable. + * + * \return Status error code. + * + * Initialize packet sniffer with specified output method. + */ +/*************************************************************************************************/ +uint8_t BbBleInitSniffer(uint8_t outMethod, bool_t enable) +{ + memset(&bbSnifferCtx, 0, sizeof(bbSnifferCtx)); + + if (enable == FALSE) + { + return LL_SUCCESS; + } + + if (outMethod >= BB_SNIFFER_OUTPUT_TOTAL_METHODS) + { + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + + bbSnifferCtx.snifferGetPktFn = bbSnifferGetPktTbl[outMethod]; + bbSnifferCtx.snifferOutCb = bbSnifferOutTbl[outMethod]; + bbSnifferCtx.enabled = enable; + + return LL_SUCCESS; +} + diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_whitelist.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_whitelist.c index dd55b28fbd..7be8a5c68a 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_whitelist.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/bb/bb_ble_whitelist.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Generic BLE whitelist implementation file. + * \file + * + * \brief Generic BLE whitelist implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -135,8 +136,6 @@ uint8_t BbBleWhiteListGetSize(void) /*! * \brief Clear all white list entries. * - * \return None. - * * Clear all white list entries stored in the BB. * * \note No resource synchronization is required to modify the white list resource as @@ -226,8 +225,6 @@ bool_t BbBleWhiteListRemove(bool_t randAddr, uint64_t addr) /*************************************************************************************************/ /*! * \brief Add anonymous device to the white list. - * - * \return None. */ /*************************************************************************************************/ void BbBleWhiteListAddAnonymous(void) @@ -238,8 +235,6 @@ void BbBleWhiteListAddAnonymous(void) /*************************************************************************************************/ /*! * \brief Remove anonymous device from the white list. - * - * \return None. */ /*************************************************************************************************/ void BbBleWhiteListRemoveAnonymous(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api.h index b34d9f7cf0..2f7e97d61d 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller common interface file. + * \file + * + * \brief Link layer controller common interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -59,7 +60,9 @@ enum LCTR_DISP_TRANFER_SYNC, /*!< Periodic Sync Transfer message dispatch handler type. */ LCTR_DISP_PER_SCAN, /*!< Periodic Scanning message dispatch handler type. */ LCTR_DISP_ACAD, /*!< ACAD message dispatch handler type (currently only used by slave). */ - LCTR_DISP_CIS, /*!< Connected isochronous stream dispatch handler type. */ + LCTR_DISP_CIS, /*!< Connected Isochronous Stream dispatch handler type. */ + LCTR_DISP_BIG_BCST, /*!< Broadcast Isochronous Group broadcasting message dispatch handler type. */ + LCTR_DISP_BIG_SYNC, /*!< Broadcast Isochronous Group synchronization message dispatch handler type. */ LCTR_DISP_TOTAL, /*!< Total number of dispatch handlers. */ /* Special IDs */ LCTR_DISP_FIRST_SM = LCTR_DISP_CONN_IND+1, /*!< First state machine. */ @@ -81,7 +84,7 @@ enum LCTR_EVENT_TX_COMPLETE, /*!< Transmit data PDU completed. */ LCTR_EVENT_CIS_TX_PENDING, /*!< Transmit data PDU pending. */ LCTR_EVENT_CIS_RX_PENDING, /*!< Receive data PDU pending. */ - LCTR_EVENT_CIS_TX_COMPLETE, /*!< Transmit data PDU completed. */ + LCTR_EVENT_ISO_TX_COMPLETE, /*!< Transmit ISO SDU completed. */ LCTR_EVENT_RX_ADVB, /*!< Receive AdvB PDU completed. */ LCTR_EVENT_RX_DIRECT_ADVB, /*!< Receive direct AdvB PDU completed. */ LCTR_EVENT_RX_SCAN_REQ, /*!< Receive scan request PDU completed. */ @@ -107,7 +110,7 @@ typedef struct { uint16_t handle; /*!< Handle. */ uint8_t dispId; /*!< Dispatch ID. */ - uint8_t event; /*!< PDU ID. */ + uint8_t event; /*!< Event ID. */ } lctrMsgHdr_t; /*! \brief Channel map update message. */ @@ -117,6 +120,13 @@ typedef struct uint64_t chanMap; /*!< Channel map. */ } lctrChanMapUpdate_t; +/*! \brief BIG created message. */ +typedef struct +{ + lctrMsgHdr_t hdr; /*!< Message header. */ + uint8_t bigHandle; /*!< BIG handle. */ +} lctrBigCreated_t; + /*! \brief Connect request PDU. */ typedef struct { @@ -140,7 +150,7 @@ typedef struct { lctrMsgHdr_t hdr; /*!< Message header. */ lctrConnInd_t connInd; /*!< Connection indication. */ - uint32_t connIndEndTs; /*!< Connection indication packet end timestamp. */ + uint32_t connIndEndTsUsec; /*!< Connection indication packet end timestamp in microseconds. */ uint8_t peerIdAddrType; /*!< Peer identity address type. */ uint8_t usedChSel; /*!< Used channel selection. */ uint8_t phy; /*!< PHY selection. */ @@ -156,22 +166,34 @@ typedef struct Global Variables **************************************************************************************************/ -/* \brief Call signature for periodic enabled check function */ +/*! \brief Call signature for periodic enabled check function */ typedef bool_t (*LctrIsPerAdvEnabledFn_t)(uint8_t handle); -/* Function pointer for periodic advertising enable check */ +/*! \brief Function pointer for periodic advertising enable check */ extern LctrIsPerAdvEnabledFn_t LctrPerAdvEnabled; -/* \brief Call signature for extended scan enabled check function. */ +/*! \brief Call signature to update CIS channel map */ +typedef void (*LctrUpdateCisChanMapFn_t)(uint16_t aclHandle); + +/*! \brief Function pointer to update CIS channel map */ +extern LctrUpdateCisChanMapFn_t LctrUpdateCisChanMapFn; + +/*! \brief Call signature for extended scan enabled check function. */ typedef bool_t (*LctrExtCheckFn_t)(uint8_t scanPhy); -/* Function pointer for extended scan enable check. */ +/*! \brief Function pointer for extended scan enable check. */ extern LctrExtCheckFn_t LctrMstExtScanEnabled; -/* Function pointer for extended advertising init enable check. */ +/*! \brief Function pointer for extended advertising init enable check. */ extern LctrExtCheckFn_t LctrMstExtInitEnabled; -/* Runtime configuration. */ +/*! \brief Call signature for periodic sync pending check. */ +typedef bool_t (*LctrPerSyncPendFn_t)(void); + +/*! \brief Function pointer for periodic sync pending check. */ +extern LctrPerSyncPendFn_t LctrMstPerSyncPending; + +/*! \brief Runtime configuration. */ extern const LlRtCfg_t *pLctrRtCfg; /************************************************************************************************** @@ -188,6 +210,9 @@ void LctrSetSupStates(void); void LctrMsgDispatcher(lctrMsgHdr_t *pMsg); void LctrEventHandler(uint8_t event); +/* Control */ +uint8_t LctrSetChannelClass(uint64_t chanMap); + /*! \} */ /* LL_LCTR_API */ #ifdef __cplusplus diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_acad.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_acad.h new file mode 100644 index 0000000000..f038fcf00c --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_acad.h @@ -0,0 +1,85 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller ACAD definitions. + * + * Copyright (c) 2019 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 LCTR_API_ADV_ACAD_H +#define LCTR_API_ADV_ACAD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief ACAD header */ +typedef struct +{ + uint8_t state; /*!< State of ACAD. */ + uint8_t opcode; /*!< Opcode of ACAD. */ + uint8_t len; /*!< Length of ACAD data field. */ +} LctrAcadHdr_t; + +/*! \brief ACAD data field for channel map update */ +typedef struct +{ + LctrAcadHdr_t hdr; /*!< ACAD header. */ + uint64_t chanMask; /*!< Channel mask for the update. */ + uint16_t instant; /*!< Instant for the update. */ +} LctrAcadChanMapUpd_t; + +/*! \brief ACAD data field for channel map update */ +typedef struct +{ + LctrAcadHdr_t hdr; /*!< ACAD header. */ + /* Reference values. */ + uint32_t bigAnchorPoint; /*!< BIG Anchor Point time. */ + /* ACAD fields. */ + uint16_t bigOffs; /*!< BIG offset. */ + uint8_t bigOffsUnits; /*!< BIG offset units. */ + uint16_t isoInter; /*!< ISO interval in units of 1.25ms. */ + uint8_t numBis; /*!< Number of BISs. */ + uint8_t nse; /*!< Number of subevents. */ + uint8_t bn; /*!< Burst number. */ + uint32_t subEvtInterUsec; /*!< Subevent interval in microseconds. */ + uint8_t pto; /*!< Pre-transmission offset. */ + uint32_t bisSpaceUsec; /*!< BIS spacing in microseconds. */ + uint8_t irc; /*!< Immediate repetition count. */ + uint16_t maxPdu; /*!< Maximum PDU size. */ + uint32_t seedAccAddr; /*!< Seed access address. */ + uint32_t sduInterUsec; /*!< SDU interval in microseconds. */ + uint16_t maxSdu; /*!< Maximum SDU size. */ + uint16_t baseCrcInit; /*!< Base CRC init. */ + uint64_t chanMap; /*!< Channel map. */ + uint8_t phy; /*!< PHY used by BIG. */ + uint64_t bisPldCtr; /*!< BIS payload counter. */ + uint8_t framing; /*!< BIG carries framed or unframed data. */ + uint8_t encrypt; /*!< Encryption mode of the BISes in the BIG. */ + uint8_t giv[LL_GIV_LEN]; /*!< GIV. */ + uint8_t gskd[LL_GSKD_LEN]; /*!< GSKD. */ +} LctrAcadBigInfo_t; + +#ifdef __cplusplus +}; +#endif + +#endif /* LCTR_API_ADV_ACAD_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_master.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_master.h index fb4cc22802..ec92af3ba8 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_master.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_master.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller scanning master interface file. + * \file + * + * \brief Link layer controller scanning master interface file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_master_ae.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_master_ae.h index 40f666dcea..daf7cc85a9 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_master_ae.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_master_ae.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller extended scanning master interface file. + * \file + * + * \brief Link layer controller extended scanning master interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ @@ -195,7 +196,6 @@ void LctrMstExtScanSetScanPhy(uint8_t scanPhy); void LctrMstExtScanClearScanPhy(uint8_t scanPhy); void LctrMstExtScanSetParam(uint8_t scanPhy, uint8_t ownAddrType, uint8_t scanFiltPolicy, const LlExtScanParam_t *pParam); bool_t LctrMstExtScanIsEnabled(uint8_t scanPhy); -bool_t LctrMstExtScanIsPrivAddr(uint8_t scanPhy); bool_t LctrMstPerIsSyncPending(void); bool_t LctrMstPerIsSyncDisabled(void); bool_t LctrMstPerIsSync(uint8_t advSID, uint8_t advAddrType, uint64_t advAddr); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_slave.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_slave.h index a84a647aef..9b3f29d926 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_slave.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_slave.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller advertising slave interface file. + * \file + * + * \brief Link layer controller advertising slave interface file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_slave_ae.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_slave_ae.h index 03f09ce6b5..058335e96b 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_slave_ae.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_adv_slave_ae.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller extended advertising slave interface file. + * \file + * + * \brief Link layer controller extended advertising slave interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -44,7 +45,7 @@ enum /* Advertising events */ LCTR_EXT_ADV_MSG_START, /*!< Extended advertising start API event. */ LCTR_EXT_ADV_MSG_STOP, /*!< Extended advertising stop API event. */ - LCTR_EXT_ADV_MSG_INT_START, /*!< Extended advertising start internal event. */ // TODO not needed + LCTR_EXT_ADV_MSG_INT_START, /*!< Extended advertising start internal event. */ LCTR_EXT_ADV_MSG_TERMINATE, /*!< Extended advertising BOD terminated event. */ LCTR_EXT_ADV_MSG_TMR_DUR_EXP, /*!< Extended advertising duration timer expired event. */ LCTR_EXT_ADV_MSG_TOTAL /*!< Total number of extended advertising events. */ @@ -62,14 +63,24 @@ enum LCTR_PER_ADV_MSG_TOTAL /*!< Total number of periodic advertising events. */ }; -/*! \brief Acad dispatcher messages */ +/*! \brief ACAD dispatcher messages */ enum { LCTR_ACAD_MSG_CHAN_UPDATE, /* Start a channel map update */ LCTR_ACAD_MSG_CHAN_UPDATE_FINISH, /* Finish a channel map update */ + LCTR_ACAD_MSG_BIG_CREATED, /* BIG is created*/ + LCTR_ACAD_MSG_BIG_TERMINATED, /* BIG is terminated */ LCTR_ACAD_MSG_TOTAL }; +/*! \brief Link layer controller message data. */ +typedef union +{ + lctrMsgHdr_t hdr; /*!< Message header. */ + lctrChanMapUpdate_t chanMapUpd; /*!< ACAD channel map update. */ + lctrBigCreated_t bigCreated; /*!< ACAD BIG created. */ +} lctrAcadSlvMsg_t; + /************************************************************************************************** Data Types **************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_bis_master.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_bis_master.h new file mode 100644 index 0000000000..43c367cac0 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_bis_master.h @@ -0,0 +1,102 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller BIS slave interface file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 LCTR_API_BIS_H +#define LCTR_API_BIS_H + +#include "lctr_api.h" +#include "lctr_api_adv_acad.h" +#include "cfg_mac_ble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \addtogroup LL_LCTR_API_BIS + * \{ + */ + +/************************************************************************************************** + Constants +**************************************************************************************************/ + +/*! \brief BIG task messages for \a LCTR_DISP_BIG_SYNC dispatcher. */ +typedef enum +{ + /* Broadcast events */ + LCTR_MST_BIG_MSG_RESET = LCTR_MSG_RESET, + /* Host/API events */ + LCTR_MST_BIG_API_CREATE_SYNC, /*!< BIG Create Sync API event. */ + LCTR_MST_BIG_API_TERMINATE_SYNC, /*!< BIG Terminate Sync API event. */ + /* Receive remote events */ + LCTR_MST_BIG_ACAD_BIG_INFO, /*!< BIG Info received. */ + LCTR_MST_BIG_PDU_TERM, /*!< Remote terminate received. */ + /* Internal events */ + LCTR_MST_BIG_INT_SYNC_TIMEOUT, /*!< BIG Sync timeout expired. */ + LCTR_MST_BIG_INT_MIC_FAILED, /*!< BIS PDU received with MIC failure. */ + LCTR_MST_BIG_INT_TERMINATED_SYNC, /*!< BIG Sync termination complete. */ + + LCTR_MST_BIG_MSG_TOTAL /*!< Total number of BIG events. */ +} LctrMstBigMsg_t; + +/*! \brief Minimum BIS Handle number. */ +#define LL_MIN_BIS 0x01 + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief ACAD BIG Info message. */ +typedef struct +{ + lctrMsgHdr_t hdr; /*!< Message header. */ + LctrAcadBigInfo_t data; /*!< BIG Info data. */ +} LctrBigInfoMsg_t; + +/*! \brief BIG messages. */ +typedef union +{ + lctrMsgHdr_t hdr; /*!< Common message header. */ + LctrBigInfoMsg_t bigInfo; /*!< BIG Info message. */ +} lctrMstBigMsg_t; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/* Initialization */ +void LctrMstBisInit(void); + +/* Control */ +uint8_t LctrMstBigCreateSync(LlBigCreateSync_t *pParam); +void LctrMstBigTerminateSync(uint8_t bisHandle); + +#ifdef __cplusplus +}; +#endif + +/*! \} */ /* LL_LCTR_API_BIS */ + +#endif /* LCTR_API_BIS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_bis_slave.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_bis_slave.h new file mode 100644 index 0000000000..d43acb8b88 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_bis_slave.h @@ -0,0 +1,82 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller BIS slave interface file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 LCTR_API_BIS_SLAVE_H +#define LCTR_API_BIS_SLAVE_H + +#include "lctr_api.h" +#include "cfg_mac_ble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Constants +**************************************************************************************************/ + +/*! \brief Slave BIS broadcasting task messages for \a LCTR_DISP_BIG_BCST dispatcher. */ +enum +{ + /* Broadcast events */ + LCTR_SLV_BIG_MSG_RESET = LCTR_MSG_RESET, /*!< Reset API message. */ + /* Host/API events */ + LCTR_SLV_BIG_MSG_CREATE_BIG, /*!< BIG slave creates BIG API event. */ + LCTR_SLV_BIG_MSG_CH_MAP_UPD, /*!< BIG channel map update. */ + LCTR_SLV_BIG_MSG_TERMINATE_BIG, /*!< BIG slave terminates BIG API event. */ + /* Internal events */ + LCTR_SLV_BIG_MSG_TERMINATED, /*!< BIG slave terminated internal event. */ + + LCTR_SLV_BIG_MSG_TOTAL /*!< Total number of BIG slave broadcasting events. */ +}; + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief BIG slave message data. */ +typedef union +{ + lctrMsgHdr_t hdr; /*!< Message header. */ + lctrMsgHdr_t term; /*!< Terminate BIG message data. */ +} LctrSlvBigMsg_t; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/* Initialization */ +uint16_t LctrInitBisMem(uint8_t *pFreeMem, uint32_t freeMemSize); +void LctrSlvBisInit(void); + +/* Control */ +uint8_t LctrSlvBisCreateBig(LlCreateBig_t *pCreateBit); +uint8_t LctrSlvBisCreateBigTest(LlCreateBigTest_t *pCreateBigTest); +uint8_t LctrSlvBisTerminateBig(uint8_t bigHandle, uint8_t reason); + +#ifdef __cplusplus +}; +#endif + +#endif /* LCTR_API_BIS_SLAVE_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_cis.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_cis.h new file mode 100644 index 0000000000..638c96f89d --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_cis.h @@ -0,0 +1,98 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller CIS slave interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 LCTR_API_CIS_H +#define LCTR_API_CIS_H + +#include "lctr_api.h" +#include "lmgr_api_cis_slave.h" +#include "cfg_mac_ble.h" +#include "lmgr_api_iso.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Constants +**************************************************************************************************/ + +/*! \brief Maximum value for maximum Data PDU length (spec limit is 251) */ +#define LCTR_CIS_MAX_DATA_LEN_MAX BB_DATA_PLD_MAX_LEN + +/*! \brief Data channel PDU length (header + payload + MIC). */ +#define LCTR_CIS_DATA_PDU_LEN(len) ((len) + LL_DATA_HDR_LEN + LL_DATA_MIC_LEN) + +/*! \brief Maximum data channel PDU length (header + payload + MIC). */ +#define LCTR_CIS_DATA_PDU_MAX_LEN LCTR_CIS_DATA_PDU_LEN(LCTR_CIS_MAX_DATA_LEN_MAX) + +/*! \brief Minimum data channel PDU length (header + payload + MIC). */ +#define LCTR_CIS_DATA_PDU_MIN_LEN LCTR_CIS_DATA_PDU_LEN(0) + +/*! \brief CIS messages. */ +enum +{ + /* Broadcast events */ + LCTR_CIS_MSG_RESET = LCTR_MSG_RESET, /*!< Reset API message. */ + /* Scan events */ + LCTR_CIS_MSG_CIS_EST, /*!< CIS established event. */ + LCTR_CIS_MSG_CIS_EST_FAIL, /*!< CIS establishment failed event. */ + LCTR_CIS_MSG_CIS_DISC, /*!< CIS disconnect event. */ + LCTR_CIS_MSG_CIS_CONN_FAIL, /*!< CIS connection fail to maintain event. */ + LCTR_CIS_MSG_CIS_CLOSED, /*!< CIS closed event. */ + LCTR_CIS_MSG_CIS_TERM_MIC_FAILED, /*!< CIS terminated due to MIC failiure event. */ + LCTR_CIS_MSG_TOTAL, /*!< Total number of CIS slave events. */ + LCTR_CIS_MSG_INVALID= 0xFF, /*!< Invalid CIS message. */ +}; + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief Disconnect message. Make sure it has the same structure as lctrDisconnect_t. */ +typedef struct +{ + lctrMsgHdr_t hdr; /*!< Message header. */ + uint8_t reason; /*!< Disconnect reason. */ +} lctrCisDisconnect_t; + +/*! \brief Link layer controller message data. */ +typedef union +{ + lctrMsgHdr_t hdr; /*!< Message header. */ + lctrCisDisconnect_t disc; /*!< Disconnect message data. */ +} lctrCisMsg_t; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/* Initialization */ +void LctrCisSlvInit(); + +#ifdef __cplusplus +}; +#endif + +#endif /* LCTR_API_CIS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_cis_master.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_cis_master.h new file mode 100644 index 0000000000..5ff3fae961 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_cis_master.h @@ -0,0 +1,52 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller CIS master interface file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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 LCTR_API_CIS_MASTER_H +#define LCTR_API_CIS_MASTER_H + +#include "lctr_api.h" +#include "wsf_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/* Initialization */ +void LctrMstCisInit(); + +/* Control */ +uint8_t LctrSetCigParam(LlCisCigParams_t *pSetCigParam, uint16_t *pCisHandles); +uint8_t LctrSetCigParamTest(LlCisCigParamsTest_t *pSetCigParamTest, uint16_t *pCisHandles); +uint8_t LctrRemoveCig(uint8_t cigId); +uint8_t LctrCreateCis(uint8_t numCis, LlCisCreateCisParams_t *pCreateCisParam); + +#ifdef __cplusplus +}; +#endif + +#endif /* LCTR_API_CIS_MASTER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_cis_slave.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_cis_slave.h new file mode 100644 index 0000000000..f2f6f82719 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_cis_slave.h @@ -0,0 +1,50 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller CIS slave interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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 LCTR_API_CIS_SLAVE_H +#define LCTR_API_CIS_SLAVE_H + +#include "lctr_api.h" +#include "cfg_mac_ble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/* Initialization */ +uint16_t LctrInitCisMem(uint8_t *pFreeMem, uint32_t freeMemSize); + +/* Control */ +uint8_t LctrRejectCisReq(uint16_t cisHandle, uint8_t reason); +uint8_t LctrAcceptCisReq(uint16_t cisHandle); + +#ifdef __cplusplus +}; +#endif + +#endif /* LCTR_API_CIS_SLAVE_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_conn.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_conn.h index 3c1d6ceb3a..578e96c126 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_conn.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_conn.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller connection interface file. + * \file + * + * \brief Link layer controller connection interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -52,6 +53,9 @@ extern "C" { /*! \brief Maximum value for maximum Data PDU length (spec limit is 251) */ #define LCTR_MAX_DATA_LEN_MAX BB_DATA_PLD_MAX_LEN +/*! \brief Maximum handle index (CIS included). */ +#define LCTR_MAX_HANDLE_INDEX (pLctrRtCfg->maxConn + pLctrRtCfg->maxCis) + /*! \brief Connected task messages for \a LCTR_DISP_CONN dispatcher. */ enum { @@ -83,6 +87,7 @@ enum LCTR_CONN_MSG_API_CIS_REQ, /*!< CIS request API event. */ 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. */ /* Internal events */ _LCTR_CONN_INT_EVENTS = 40, @@ -95,6 +100,7 @@ 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_TERM, /*!< LL initiated termination. */ LCTR_CONN_LLCP_PROC_CMPL, /*!< LLCP procedure completed. */ LCTR_CONN_LLCP_START_PENDING, /*!< Start pending LLCP procedure. */ @@ -106,6 +112,7 @@ enum LCTR_CONN_TERM_INST_PASSED, /*!< Terminate connection due to instant passed. */ LCTR_CONN_TERM_CIS_LOCAL_RESOURCE, /*!< Terminate CIS connection due to local resource limitation. */ LCTR_CONN_TERMINATED, /*!< Connection event terminated. */ + LCTR_CONN_INIT_CANCELED, /*!< Connection cancelled event. */ _LCTR_CONN_TMR_EVENTS = 80, LCTR_CONN_TMR_LLCP_RSP_EXP, /*!< LLCP response timer expired. */ LCTR_CONN_TMR_CIS_LLCP_RSP_EXP, /*!< CIS LLCP response timer expired. */ @@ -214,7 +221,6 @@ typedef struct typedef struct { lctrMsgHdr_t hdr; /*!< Message header. */ -// uint16_t cisHandle; /*!< CIS handle. */ uint8_t reason; /*!< Reject reason. */ } lctrRejCisReq_t; @@ -226,6 +232,14 @@ typedef struct uint16_t cisHandle; /*!< CIS handle. */ } lctrCisDisc_t; +/*! \brief Internal power control request message. */ +typedef struct +{ + lctrMsgHdr_t hdr; /*!< Message Header. */ + int8_t delta; /*!< Delta requested. */ + uint8_t phy; /*!< PHY requested. */ +} lctrMsgPwrCtrlReq_t; + /*! \brief Link layer controller message data. */ typedef union { @@ -243,6 +257,7 @@ typedef union lctrSetMinUsedChan_t setMinUsedChan; /*!< Set minimum number of used channels message data. */ lctrPerAdvSyncTrsf_t perAdvSyncTrsf; /*!< Periodic advertising sync transfer data. */ lctrScaReq_t scaReq; /*!< Sleep clock accuracy request. */ + lctrMsgPwrCtrlReq_t pwrCtrlReq; /*!< Power control request. */ /* CIS */ lctrCreateCis_t createCis; /*!< Create CIS message data. */ @@ -305,6 +320,7 @@ bool_t LctrIsConnHandleEnabled(uint16_t handle); bool_t LctrIsCisConnHandleEnabled(uint16_t handle); uint8_t LctrGetRole(uint16_t handle); int8_t LctrGetRssi(uint16_t handle); +uint8_t lctrSetTxPowerReporting(uint16_t handle, uint8_t enableLocal, uint8_t enableRemote); int8_t LctrGetTxPowerLevel(uint16_t handle); uint64_t LctrGetChannelMap(uint16_t handle); uint64_t LctrGetUsedFeatures(uint16_t handle); @@ -314,14 +330,17 @@ void LctrGetPeerMinUsedChan(uint16_t handle, uint8_t *pPeerMinUsedChan); bool_t LctrIsWaitingForReply(uint16_t handle, uint8_t reply); bool_t LctrIsCisEnabled(uint16_t handle); - /* Control */ void LctrSetTxPowerLevel(uint16_t handle, int8_t level); +void LctrSetPhyTxPowerLevel(uint16_t handle, int8_t level, uint8_t phy); +int8_t LctrGetPhyTxPowerLevel(uint16_t handle, uint8_t phy); uint32_t LctrGetAuthPayloadTimeout(uint16_t handle); bool_t LctrSetAuthPayloadTimeout(uint16_t handle, uint32_t timeoutMs); void LctrGetEncMode(uint16_t handle, LlEncMode_t *pMode); 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); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_conn_cs2.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_conn_cs2.h index e58eca5ae3..b58f617022 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_conn_cs2.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_conn_cs2.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller channel selection interface file. + * \file + * + * \brief Link layer controller channel selection interface file. + * + * Copyright (c) 2013-2017 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_init_master.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_init_master.h index ecabac3faf..562f16b26c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_init_master.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_init_master.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller initiating master interface file. + * \file + * + * \brief Link layer controller initiating master interface file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_init_master_ae.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_init_master_ae.h index 2c31f7fab8..5bc5c211cf 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_init_master_ae.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_init_master_ae.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller extended initiating master interface file. + * \file + * + * \brief Link layer controller extended initiating master interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ @@ -40,11 +41,6 @@ extern "C" { /************************************************************************************************** Constants **************************************************************************************************/ -/*! \brief Change supervision timeout value to us. */ -#define LL_SUP_TIMEOUT_VAL_TO_US(x) x * 10000 - -/*! \brief Change connection interval value to us. */ -#define LL_CONN_INTERVAL_VAL_TO_US(x) x * 1250 /*! \brief Master extended initiate task messages for \a LCTR_DISP_EXT_INIT dispatcher. */ enum diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_iso.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_iso.h new file mode 100644 index 0000000000..c7b6904bea --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_iso.h @@ -0,0 +1,60 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller common ISO interface file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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 LCTR_API_ISO_H +#define LCTR_API_ISO_H + +#include "lctr_api.h" +#include "cfg_mac_ble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/* Initialization */ +uint16_t LctrInitIsoMem(uint8_t *pFreeMem, uint32_t freeMemSize); +void LctrInitCodec(void); + +/* Data path */ +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 LctrSetupIsoDataPath(LlIsoSetupDataPath_t *pSetupDataPath); +uint8_t LctrRemoveIsoDataPath(uint16_t handle, uint8_t dpDir); +uint8_t LctrIsoTxTest(uint16_t handle, uint8_t pldType); +uint8_t LctrIsoRxTest(uint16_t handle, uint8_t pldType); +uint8_t LctrIsoReadTestCounter(uint16_t handle, LlIsoTestCtrs_t *pStats); +uint8_t LctrIsoTestEnd(uint16_t handle, LlIsoTestCtrs_t *pStats); +uint8_t LctrReadIsoLinkQual(uint16_t handle, LlIsoLinkQual_t *pStats); + +#ifdef __cplusplus +}; +#endif + +#endif /* LCTR_API_ISO_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_pc.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_pc.h new file mode 100644 index 0000000000..4bfb8b8a3e --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_pc.h @@ -0,0 +1,47 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller power control interface file. + * + * Copyright (c) 2019 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 LCTR_API_PC_H +#define LCTR_API_PC_H + +#include "lctr_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/* Initialization functions. */ +void LctrPowerControlInit(void); + +/* HCI functions. */ +uint8_t lctrSetPathLossReportingParams(uint16_t handle, uint8_t highThresh, uint8_t highHyst, uint8_t lowThresh, uint8_t lowHyst, uint16_t minTime); +uint8_t lctrSetPathLossReportingEnable(uint16_t handle, uint8_t enable); + +#ifdef __cplusplus +}; +#endif + +#endif /* LCTR_API_PC_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_phy.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_phy.h index aca0792686..8b1fdb8306 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_phy.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_phy.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller PHY features interface file. + * \file + * + * \brief Link layer controller PHY features interface file. + * + * Copyright (c) 2016-2019 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_priv.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_priv.h index 5cf1b16808..f4645b2770 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_priv.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_priv.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller privacy interface file. + * \file + * + * \brief Link layer controller privacy interface file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_sc.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_sc.h index a2ce015a28..731d6e77c0 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_sc.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lctr_api_sc.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller secure connections interface file. + * \file + * + * \brief Link layer controller secure connections interface file. + * + * Copyright (c) 2013-2018 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api.h index 06a17e6e9c..c9a6b202d1 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer manager common interface file. + * \file + * + * \brief Link layer manager common interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -74,6 +75,8 @@ typedef struct uint16_t perScanCtxSize; /*!< Size of the periodic scanning context. */ uint16_t cisCtxSize; /*!< Size of the CIS context. */ uint16_t cigCtxSize; /*!< Size of the CIG context. */ + uint16_t bisCtxSize; /*!< Size of the BIS context. */ + uint16_t bigCtxSize; /*!< Size of the BIG context. */ uint64_t featuresDefault; /*!< Default supported features. */ llIsoCback_t sendIsoCompCback; /*!< ISO data send complete callback. */ @@ -126,22 +129,22 @@ typedef struct int8_t powerThreshold[LL_MAX_PHYS]; /*!< Power threshold for each PHY. */ uint8_t localMinUsedChan[LL_MAX_PHYS]; /*!< Local minimum number of used channels for each PHY. */ - uint8_t hciSupCommands[HCI_SUP_CMD_LEN]; /*!< Supported HCI commands bit mask. */ + /* Isochronous channels. */ + bool_t sendIsoCmplEvt; /*!< ISO event completion notification generation enable. */ } lmgrCtrlBlk_t; /*! \brief Channel parameters. */ typedef struct { /* Channel parameters */ - uint8_t lastChanIdx; /*!< Current channel index. */ - uint8_t numUsedChan; /*!< Number of used channels. */ uint64_t chanMask; /*!< Channel mask. */ uint8_t chanRemapTbl[LL_CHAN_DATA_MAX_IDX + 1]; /*!< Channel remapping table. */ + uint8_t numUsedChan; /*!< Number of used channels. */ uint8_t usedChSel; /*!< Used channel selection. */ uint16_t chIdentifier; /*!< Channel identifier. */ - /* For subevent calculation only */ + /* Subevent parameters */ uint16_t prnLast; /*!< Last used permutation. */ uint8_t subEvtIdx; /*!< Subevent index. */ } lmgrChanParam_t; @@ -178,9 +181,7 @@ bool_t LmgrIsExtCommandAllowed(void); /* Utility */ void LmgrBuildRemapTable(lmgrChanParam_t *pChanParam); uint8_t LmgrSelectNextChannel(lmgrChanParam_t *pChanParam, uint16_t eventCounter, uint16_t numSkip, bool_t calSubEvt); -uint32_t LmgrCalcWindowWideningUsec(uint32_t unsyncTimeUsec, uint32_t caPpm); uint8_t LmgrSelectNextSubEvtChannel(lmgrChanParam_t *pChanParam); -uint8_t * LmgrReadHciSupCmd(void); /* Event Messages */ void LmgrSendAdvEnableCnf(uint8_t status); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_adv_master.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_adv_master.h index f3504c0947..21f202cd89 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_adv_master.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_adv_master.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer manager advertising master interface file. + * \file + * + * \brief Link layer manager advertising master interface file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ @@ -42,8 +43,8 @@ extern "C" { /*! \brief Scan parameters. */ typedef struct { - uint16_t scanInterval; /*!< Scan interval in BB ticks. */ - uint16_t scanWindow; /*!< Scan window duration in BB ticks. */ + uint16_t scanInterval; /*!< Scan interval in BLE ticks. */ + uint16_t scanWindow; /*!< Scan window duration in BLE ticks. */ uint8_t scanType; /*!< Advertising type. */ uint8_t ownAddrType; /*!< Address type used by this device. */ uint8_t scanFiltPolicy; /*!< Scanning filter policy. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_adv_master_ae.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_adv_master_ae.h index c39d8c01a6..15329b885b 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_adv_master_ae.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_adv_master_ae.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer manager advertising extension interface file. + * \file + * + * \brief Link layer manager advertising extension interface file. + * + * Copyright (c) 2013-2017 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_adv_slave.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_adv_slave.h index 6c323adb8b..565d00dd9a 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_adv_slave.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_adv_slave.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer manager advertising slave interface file. + * \file + * + * \brief Link layer manager advertising slave interface file. + * + * Copyright (c) 2013-2017 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ @@ -42,8 +43,8 @@ extern "C" { /*! \brief Advertising parameters. */ typedef struct { - uint32_t advInterMin; /*!< Minimum advertising interval. */ - uint32_t advInterMax; /*!< Maximum advertising interval. */ + uint32_t advInterMinUsec; /*!< Minimum advertising interval in microseconds. */ + uint32_t advInterMaxUsec; /*!< Maximum advertising interval in microseconds. */ uint8_t advType; /*!< Advertising type. */ uint8_t ownAddrType; /*!< Address type used by this device. */ uint8_t peerAddrType; /*!< Address type of peer device. Only used for directed advertising. */ @@ -55,7 +56,7 @@ typedef struct /*! \brief Slave role device parameter definition. */ typedef struct { - uint32_t advTermCntDown; /*!< Advertising termination count down. */ + uint32_t advTermCntDownUsec; /*!< Advertising termination count down in microseconds. */ lmgrAdvParam_t advParam; /*!< Advertising parameters. */ lmgrAdvbUser_t advData; /*!< Advertising host data buffer. */ lmgrAdvbUser_t scanRspData; /*!< Scan response host data buffer. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_adv_slave_ae.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_adv_slave_ae.h index e59e0fc8bf..592378bbb1 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_adv_slave_ae.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_adv_slave_ae.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer manager advertising extension interface file. + * \file + * + * \brief Link layer manager advertising extension interface file. + * + * Copyright (c) 2013-2017 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_cis_master.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_cis_master.h new file mode 100644 index 0000000000..3c71dccfd0 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_cis_master.h @@ -0,0 +1,72 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer manager connected isochronous stream master interface file. + * + * Copyright (c) 2013-2018 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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 LMGR_API_CIS_MASTER_H +#define LMGR_API_CIS_MASTER_H + +#include "lmgr_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \addtogroup LL_LMGR_API_CIS_MST + * \{ + */ + +/************************************************************************************************** + Data Types +**************************************************************************************************/ +/*! \brief Master role device parameter definition. */ +typedef struct +{ + uint8_t maxNumCis; /*!< Maximum number of CIS. */ + + bool_t createCisPend; /*!< TRUE if create CIS command is pending. */ + +} lmgrCisMstCtrlBlk_t; + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ +extern lmgrCisMstCtrlBlk_t lmgrCisMstCb; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/* Initialization */ +void LmgrMstCisInit(void); + +/* Status */ +uint8_t LmgrMstCisGetMaxNumCis(void); + +/*! \} */ /* LL_LMGR_API_CIS_MST */ + +#ifdef __cplusplus +}; +#endif + +#endif /* LMGR_API_CIS_MASTER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_cis_slave.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_cis_slave.h new file mode 100644 index 0000000000..7b03a9f42d --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_cis_slave.h @@ -0,0 +1,64 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer manager connected isochronous stream slave interface file. + * + * Copyright (c) 2013-2018 ARM Ltd. All Rights Reserved. + * + * 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 LMGR_API_CIS_SLAVE_H +#define LMGR_API_CIS_SLAVE_H + +#include "lmgr_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \addtogroup LL_LMGR_API_ADV_MST + * \{ + */ + +/************************************************************************************************** + Data Types +**************************************************************************************************/ +/*! \brief Slave role device parameter definition. */ +typedef struct +{ + uint8_t maxNumCis; /*!< Maximum number of CIS. */ +} lmgrCisSlvCtrlBlk_t; + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ +/* Initialization */ +void LmgrMstInit(void); + +/*! \} */ /* LL_LMGR_API_CIS_SLV */ + +#ifdef __cplusplus +}; +#endif + +#endif /* LMGR_API_CIS_SLAVE_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_conn.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_conn.h index d723560c43..c600a6982f 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_conn.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_conn.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer manager connection interface file. + * \file + * + * \brief Link layer manager connection interface file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_iso.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_iso.h new file mode 100644 index 0000000000..654b02383f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_iso.h @@ -0,0 +1,80 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer manager connection interface file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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 LMGR_API_ISO_H +#define LMGR_API_ISO_H + +#include "lmgr_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \addtogroup LL_LMGR_API_ISO + * \{ + */ + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief Slave role device parameter definition. */ +typedef struct +{ + uint8_t availTxBuf; /*!< Available number of transmit buffers. */ + uint8_t availRxBuf; /*!< Available number of receive buffers. */ + + uint16_t maxTxLen; /*!< Default maximum number of Data PDU bytes. */ + uint16_t maxTxTime; /*!< Default maximum microseconds for a Data PDU. */ + + wsfQueue_t rxDataQ; /*!< Receive Data PDU queue. */ + + uint32_t dataPendMsk; /*!< Bitmask of connection handles with new pending data. */ + + uint8_t allPhys; /*!< Default all PHYs. */ + uint8_t txPhys; /*!< Default transmitter PHYs. */ + uint8_t rxPhys; /*!< Default receiver PHYs. */ + +} lmgrIsoCtrlBlk_t; + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ +extern lmgrIsoCtrlBlk_t lmgrIsoCb; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/* Initialization */ +void LmgrIsoInit(void); + +/*! \} */ /* LMGR_API_ISO_H */ + +#ifdef __cplusplus +}; +#endif + +#endif /* LMGR_API_ISO_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_priv.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_priv.h index b7979ac24c..269bc08585 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_priv.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_priv.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer manager privacy interface file. + * \file + * + * \brief Link layer manager privacy interface file. + * + * Copyright (c) 2013-2017 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_sc.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_sc.h index acf7401ef0..a7201f878e 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_sc.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/include/lmgr_api_sc.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer manager secure connections interface file. + * \file + * + * \brief Link layer manager secure connections interface file. + * + * Copyright (c) 2013-2018 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/init/init.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/init/init.c index 45df5eda24..abd7457505 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/init/init.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/init/init.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief LL initialization for SoC configuration. + * \file + * + * \brief LL initialization for SoC configuration. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -26,6 +27,7 @@ #include "pal_bb_ble.h" #include "pal_radio.h" #include "sch_api.h" +#include "bb_ble_sniffer_api.h" /************************************************************************************************** Functions @@ -34,8 +36,6 @@ /*************************************************************************************************/ /*! * \brief Initialize BB. - * - * \return None. */ /*************************************************************************************************/ void LlInitBbInit(void) @@ -74,32 +74,31 @@ void LlInitBbInit(void) #endif #endif - #if (BT_VER >= LL_VER_BT_CORE_SPEC_MILAN) + #if (BT_VER >= LL_VER_BT_CORE_SPEC_5_2) #ifdef INIT_CENTRAL BbBleCisMasterInit(); - #else - #ifdef INIT_OBSERVER - /* TODO BIS observer */ - #endif #endif - #ifdef INIT_PERIPHERAL BbBleCisSlaveInit(); - #else - #ifdef INIT_BROADCASTER - /* TODO BIS broadcaster */ - #endif + #endif + #ifdef INIT_OBSERVER + BbBleBisMasterInit(); + #endif + #ifdef INIT_BROADCASTER + BbBleBisSlaveInit(); #endif #endif BbBleTestInit(); + +#if (BB_SNIFFER_ENABLED == TRUE) + BbBleInitSniffer(BB_SNIFFER_OUTPUT_NULL_METHOD, FALSE); +#endif } /*************************************************************************************************/ /*! * \brief Initialize scheduler. - * - * \return None. */ /*************************************************************************************************/ void LlInitSchInit(void) @@ -111,8 +110,6 @@ void LlInitSchInit(void) /*************************************************************************************************/ /*! * \brief Initialize LL. - * - * \return None. */ /*************************************************************************************************/ void LlInitLlInit(void) @@ -154,24 +151,34 @@ void LlInitLlInit(void) LlExtScanMasterInit(); LlExtInitMasterInit(); LlPhyMasterInit(); - #if (BT_VER >= LL_VER_BT_CORE_SPEC_MILAN) + #if (BT_VER >= LL_VER_BT_CORE_SPEC_5_2) LlCisMasterInit(); + LlBisMasterInit(); + LlPowerControlInit(); #endif #else #ifdef INIT_OBSERVER LlExtScanMasterInit(); + #if (BT_VER >= LL_VER_BT_CORE_SPEC_5_2) + LlBisMasterInit(); + #endif #endif #endif #ifdef INIT_PERIPHERAL LlExtAdvSlaveInit(); LlPhySlaveInit(); - #if (BT_VER >= LL_VER_BT_CORE_SPEC_MILAN) + #if (BT_VER >= LL_VER_BT_CORE_SPEC_5_2) LlCisSlaveInit(); + LlBisSlaveInit(); + LlPowerControlInit(); #endif #else #ifdef INIT_BROADCASTER LlExtAdvSlaveInit(); + #if (BT_VER >= LL_VER_BT_CORE_SPEC_5_2) + LlBisSlaveInit(); + #endif #endif #endif @@ -274,15 +281,20 @@ uint32_t LlInitSetLlRtCfg(const LlRtCfg_t *pLlRtCfg, uint8_t *pFreeMem, uint32_t totalMemUsed += memUsed; #endif - #if (BT_VER >= LL_VER_BT_CORE_SPEC_MILAN) + #if (BT_VER >= LL_VER_BT_CORE_SPEC_5_2) memUsed = LlInitCisMem(pFreeMem, freeMemAvail); pFreeMem += memUsed; freeMemAvail -= memUsed; totalMemUsed += memUsed; + memUsed = LlInitBisMem(pFreeMem, freeMemAvail); + pFreeMem += memUsed; + freeMemAvail -= memUsed; + totalMemUsed += memUsed; + memUsed = LlInitIsoMem(pFreeMem, freeMemAvail); - /* pFreeMem += memUsed; - freeMemAvail -= memUsed; */ + /* pFreeMem += memUsed; */ + /* freeMemAvail -= memUsed; */ totalMemUsed += memUsed; #endif diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/init/init_ctr.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/init/init_ctr.c index 98a8fa4300..9bab8d3186 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/init/init_ctr.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/init/init_ctr.c @@ -2,15 +2,16 @@ /*! * \brief LL initialization for controller configuration. * - * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. - * Arm Ltd. confidential and proprietary. + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. * + * 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. @@ -27,21 +28,16 @@ Functions **************************************************************************************************/ -/*! \brief Extended VS command decoder. */ -extern bool_t lhciVsExtDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf); - /*************************************************************************************************/ /*! * \brief Initialize controller LHCI handler. - * - * \return None. */ /*************************************************************************************************/ void LlInitLhciHandler(void) { wsfHandlerId_t handlerId; -#if (BT_VER >= LL_VER_BT_CORE_SPEC_MILAN) +#if (BT_VER >= LL_VER_BT_CORE_SPEC_5_2) handlerId = WsfOsSetNextHandler(LhciIsoHandler); LhciIsoHandlerInit(handlerId); #else @@ -54,20 +50,19 @@ void LlInitLhciHandler(void) /*! * \brief Initialize controller HCI transport. * - * \return None. + * \param maxAclLen Maximum ACL data length. + * \param maxIsoSduLen Maximum ISO SDU data length. */ /*************************************************************************************************/ -void LlInitChciTrInit(void) +void LlInitChciTrInit(uint16_t maxAclLen, uint16_t maxIsoSduLen) { wsfHandlerId_t handlerId = WsfOsSetNextHandler(ChciTrHandler); - ChciTrHandlerInit(handlerId); + ChciTrHandlerInit(handlerId, maxAclLen, maxIsoSduLen); } /*************************************************************************************************/ /*! * \brief Initialize LL HCI. - * - * \return None. */ /*************************************************************************************************/ void LlInitLhciInit(void) @@ -102,15 +97,10 @@ void LlInitLhciInit(void) LhciScInit(); #endif - LhciVsExtInit(lhciVsExtDecodeCmdPkt); - #if (BT_VER >= LL_VER_BT_CORE_SPEC_5_0) #ifdef INIT_CENTRAL LhciExtScanMasterInit(); LhciExtConnMasterInit(); - #if (BT_VER >= LL_VER_BT_CORE_SPEC_MILAN) - LhciCisMasterInit(); - #endif #else #ifdef INIT_OBSERVER LhciExtScanMasterInit(); @@ -121,12 +111,6 @@ void LlInitLhciInit(void) LhciExtAdvSlaveInit(); #endif - #ifdef INIT_PERIPHERAL - #if (BT_VER >= LL_VER_BT_CORE_SPEC_MILAN) - LhciCisSlaveInit(); - #endif - #endif - #if defined(INIT_PERIPHERAL) || defined(INIT_CENTRAL) LhciChannelSelection2Init(); LhciPhyInit(); @@ -138,7 +122,24 @@ void LlInitLhciInit(void) #endif #endif - #if (BT_VER >= LL_VER_BT_CORE_SPEC_MILAN) + #if (BT_VER >= LL_VER_BT_CORE_SPEC_5_2) + #ifdef INIT_CENTRAL + LhciCisMasterInit(); + LhciBisMasterInit(); + #else + #ifdef INIT_OBSERVER + LhciBisMasterInit(); + #endif + #endif + + #ifdef INIT_BROADCASTER + LhciBisSlaveInit(); + #endif + + #ifdef INIT_PERIPHERAL + LhciCisSlaveInit(); + #endif + LhciIsoInit(); #endif } @@ -158,9 +159,10 @@ uint32_t LlInitControllerInit(LlInitRtCfg_t *pCfg) totalMemUsed = LlInit(pCfg); - LlInitChciTrInit(); + LlInitChciTrInit(pCfg->pLlRtCfg->maxAclLen, pCfg->pLlRtCfg->maxIsoSduLen); LlInitLhciInit(); LlInitLhciHandler(); + LhciInitFinalize(); return totalMemUsed; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_master.c index 2019a46260..7c80ff4720 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master scan action routines. + * \file + * + * \brief Link layer controller master scan action routines. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -37,8 +38,6 @@ WSF_CT_ASSERT((LL_NUM_ADV_FILT <= 32)); * \brief Common scan resource cleanup. * * \param pCtx Scan context. - * - * \return None. */ /*************************************************************************************************/ void lctrScanCleanup(lctrMstScanCtx_t *pCtx) @@ -81,8 +80,6 @@ void lctrScanCleanup(lctrMstScanCtx_t *pCtx) /*************************************************************************************************/ /*! * \brief Start scan discovery. - * - * \return None. */ /*************************************************************************************************/ void lctrScanActDiscover(void) @@ -117,8 +114,6 @@ void lctrScanActDiscover(void) /*************************************************************************************************/ /*! * \brief Shutdown active scan operation. - * - * \return None. */ /*************************************************************************************************/ void lctrScanActShutdown(void) @@ -139,8 +134,6 @@ void lctrScanActShutdown(void) /*************************************************************************************************/ /*! * \brief Send scan operation confirm. - * - * \return None. */ /*************************************************************************************************/ void lctrScanActScanCnf(void) @@ -151,8 +144,6 @@ void lctrScanActScanCnf(void) /*************************************************************************************************/ /*! * \brief Send disallow scan host notification. - * - * \return None. */ /*************************************************************************************************/ void lctrScanActDisallowScan(void) @@ -163,8 +154,6 @@ void lctrScanActDisallowScan(void) /*************************************************************************************************/ /*! * \brief Operation self terminated (e.g. on connection indication). - * - * \return None. */ /*************************************************************************************************/ void lctrScanActSelfTerm(void) @@ -176,8 +165,6 @@ void lctrScanActSelfTerm(void) /*************************************************************************************************/ /*! * \brief Terminated scan after host scan disable. - * - * \return None. */ /*************************************************************************************************/ void lctrScanActScanTerm(void) @@ -191,8 +178,6 @@ void lctrScanActScanTerm(void) /*************************************************************************************************/ /*! * \brief Terminated scan after host reset. - * - * \return None. */ /*************************************************************************************************/ void lctrScanActResetTerm(void) @@ -204,8 +189,6 @@ void lctrScanActResetTerm(void) /*************************************************************************************************/ /*! * \brief Update scan parameters. - * - * \return None. */ /*************************************************************************************************/ void lctrScanActUpdateScanParam(void) @@ -218,8 +201,6 @@ void lctrScanActUpdateScanParam(void) /*************************************************************************************************/ /*! * \brief Update scan filter. - * - * \return None. */ /*************************************************************************************************/ void lctrScanActUpdateScanFilt(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_master_ae.c index 0b0c40ba97..e9923bc177 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master scan action routines. + * \file + * + * \brief Link layer controller master scan action routines. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -26,6 +27,7 @@ #include "lctr_api_adv_master_ae.h" #include "lmgr_api_adv_master_ae.h" #include "sch_api.h" +#include "sch_api_ble.h" #include "wsf_assert.h" #include "wsf_msg.h" #include "wsf_trace.h" @@ -38,7 +40,8 @@ * \brief Setup periodic scanning context. * * \param pPerCreateSync Create sync control block. - * \param pMsg Create sync messgae. + * \param pMsg Create sync message. + * \param createDispId Dispatcher ID. * * \return TRUE if successful, FALSE otherwise. */ @@ -83,7 +86,7 @@ static bool_t lctrPerAdvSyncEstRptPack(lctrPerScanCtx_t *pPerScanCtx, lmgrPerAdv Bda64ToBstream(pRpt->addr, pPerScanCtx->advAddr); pRpt->addrType = pPerScanCtx->advAddrType; pRpt->advPhy = pPerScanCtx->rxPhys; - pRpt->advInterval = LCTR_PER_INTER_TO_MS(BB_TICKS_TO_US(pPerScanCtx->perInter)); + pRpt->advInterval = LCTR_PER_INTER_TO_MS(pPerScanCtx->perInterUsec); pRpt->advClkAccuracy = pPerScanCtx->sca; return TRUE; @@ -94,14 +97,19 @@ static bool_t lctrPerAdvSyncEstRptPack(lctrPerScanCtx_t *pPerScanCtx, lmgrPerAdv * \brief Common periodic scan resource cleanup. * * \param pPerScanCtx Periodic scan context. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstPerScanCleanupOp(lctrPerScanCtx_t *pPerScanCtx) { BbStop(BB_PROT_BLE); + if (pPerScanCtx->termCback) + { + pPerScanCtx->termCback(LCTR_GET_PER_SCAN_HANDLE(pPerScanCtx)); + } + + SchTmRemove(LCTR_GET_PER_SCAN_TM_HANDLE(pPerScanCtx)); + if (pPerScanCtx->filtParam.filterPolicy) { LmgrDecPeriodiclistRefCount(); @@ -117,8 +125,6 @@ static void lctrMstPerScanCleanupOp(lctrPerScanCtx_t *pPerScanCtx) * \brief Common scan resource cleanup. * * \param pExtScanCtx Extended scan context. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstExtScanCleanupOp(lctrExtScanCtx_t *pExtScanCtx) @@ -157,8 +163,6 @@ static void lctrMstExtScanCleanupOp(lctrExtScanCtx_t *pExtScanCtx) * \brief Start scan discovery. * * \param pExtScanCtx Extended scan context. - * - * \return None. */ /*************************************************************************************************/ void lctrExtScanActDiscover(lctrExtScanCtx_t *pExtScanCtx) @@ -206,8 +210,6 @@ void lctrExtScanActDiscover(lctrExtScanCtx_t *pExtScanCtx) * \brief Update scan discovery. * * \param pExtScanCtx Extended scan context. - * - * \return None. */ /*************************************************************************************************/ void lctrExtScanActUpdateDiscover(lctrExtScanCtx_t *pExtScanCtx) @@ -220,24 +222,33 @@ void lctrExtScanActUpdateDiscover(lctrExtScanCtx_t *pExtScanCtx) * \brief Shutdown active scan operation. * * \param pExtScanCtx Extended scan context. - * - * \return None. */ /*************************************************************************************************/ void lctrExtScanActShutdown(lctrExtScanCtx_t *pExtScanCtx) { + const uint8_t scanPhyIndex = (LCTR_GET_EXT_SCAN_HANDLE(pExtScanCtx) == LCTR_SCAN_PHY_CODED) ? LCTR_SCAN_PHY_CODED : LCTR_SCAN_PHY_1M; + pExtScanCtx->shutdown = TRUE; - if (!pExtScanCtx->auxOpPending) + if (scanPhyIndex == lctrActiveExtScan.scanIndex) { - SchRemove(&pExtScanCtx->scanBod); + if (!pExtScanCtx->auxOpPending) + { + SchRemove(&pExtScanCtx->scanBod); + } + else + { + SchRemove(&pExtScanCtx->auxScanBod); + } + + /* Shutdown completes with events generated in BOD end callback. */ } else { - SchRemove(&pExtScanCtx->auxScanBod); + /* BOD of this scan context is not scheduled. No need to remove it. */ + lctrActiveExtScan.scanMask &= ~(1 << scanPhyIndex); + lctrSendExtScanMsg(pExtScanCtx, LCTR_EXT_SCAN_MSG_TERMINATE); } - - /* Shutdown completes with events generated in BOD end callback. */ } /*************************************************************************************************/ @@ -245,8 +256,6 @@ void lctrExtScanActShutdown(lctrExtScanCtx_t *pExtScanCtx) * \brief Send scan operation confirm. * * \param pExtScanCtx Extended scan context. - * - * \return None. */ /*************************************************************************************************/ void lctrExtScanActScanCnf(lctrExtScanCtx_t *pExtScanCtx) @@ -254,13 +263,31 @@ void lctrExtScanActScanCnf(lctrExtScanCtx_t *pExtScanCtx) LmgrSendExtScanEnableCnf(LL_SUCCESS); } +/*************************************************************************************************/ +/*! + * \brief Terminate a restarting scan (scan in terminate state due to controller-issued terminate). + * + * \param pExtScanCtx Extended scan context. + */ +/*************************************************************************************************/ +void lctrExtScanHostDisable(lctrExtScanCtx_t *pExtScanCtx) +{ + if (lctrMstExtScan.scanTermByHost > 1) + { + LmgrSendExtScanEnableCnf(LL_ERROR_CODE_CMD_DISALLOWED); + return; + } + + /* Start/Restart timers. */ + WsfTimerStop(&lctrMstExtScan.tmrScanDur); + WsfTimerStop(&lctrMstExtScan.tmrScanPer); +} + /*************************************************************************************************/ /*! * \brief Send disallow scan host notification. * * \param pExtScanCtx Extended scan context. - * - * \return None. */ /*************************************************************************************************/ void lctrExtScanActDisallowScan(lctrExtScanCtx_t *pExtScanCtx) @@ -271,13 +298,31 @@ void lctrExtScanActDisallowScan(lctrExtScanCtx_t *pExtScanCtx) } } +/*************************************************************************************************/ +/*! + * \brief Send enable during terminate state. + * + * \param pExtScanCtx Extended scan context. + */ +/*************************************************************************************************/ +void lctrExtScanActHostEnable(lctrExtScanCtx_t *pExtScanCtx) +{ + if (lctrMstExtScan.scanTermByHost) + { + LmgrSendExtScanEnableCnf(LL_ERROR_CODE_CMD_DISALLOWED); + } + else + { + LmgrSendExtScanEnableCnf(LL_SUCCESS); + } + +} + /*************************************************************************************************/ /*! * \brief Terminated scan after host scan disable. * * \param pExtScanCtx Extended scan context. - * - * \return None. */ /*************************************************************************************************/ void lctrExtScanActScanTerm(lctrExtScanCtx_t *pExtScanCtx) @@ -295,8 +340,6 @@ void lctrExtScanActScanTerm(lctrExtScanCtx_t *pExtScanCtx) * \brief Terminated scan after internal scan disable. * * \param pExtScanCtx Extended scan context. - * - * \return None. */ /*************************************************************************************************/ void lctrExtScanActSelfTerm(lctrExtScanCtx_t *pExtScanCtx) @@ -307,8 +350,6 @@ void lctrExtScanActSelfTerm(lctrExtScanCtx_t *pExtScanCtx) /*************************************************************************************************/ /*! * \brief Create sync action function. - * - * \return None. */ /*************************************************************************************************/ void lctrCreateSyncActCreate(void) @@ -336,8 +377,6 @@ void lctrCreateSyncActCreate(void) /*************************************************************************************************/ /*! * \brief Create sync done action function. - * - * \return None. */ /*************************************************************************************************/ void lctrCreateSyncActDone(void) @@ -351,8 +390,6 @@ void lctrCreateSyncActDone(void) /*************************************************************************************************/ /*! * \brief Create sync cancel action function. - * - * \return None. */ /*************************************************************************************************/ void lctrCreateSyncActCancel(void) @@ -370,8 +407,6 @@ void lctrCreateSyncActCancel(void) /*************************************************************************************************/ /*! * \brief Create sync failed action function. - * - * \return None. */ /*************************************************************************************************/ void lctrCreateSyncActFailed(void) @@ -394,8 +429,6 @@ void lctrCreateSyncActFailed(void) /*************************************************************************************************/ /*! * \brief Create sync terminate action function. - * - * \return None. */ /*************************************************************************************************/ void lctrCreateSyncActTerminate(void) @@ -418,8 +451,6 @@ void lctrCreateSyncActTerminate(void) /*************************************************************************************************/ /*! * \brief Transfer sync start action function. - * - * \return None. */ /*************************************************************************************************/ void lctrTransferSyncActStart(void) @@ -449,7 +480,7 @@ void lctrTransferSyncActStart(void) /* Decode syncInfo */ lctrUnpackSyncInfo(&trsfSyncInfo, pMsg->bSyncInfo); - pPerScanCtx->perInter = BB_US_TO_BB_TICKS(LCTR_PER_INTER_TO_US(trsfSyncInfo.syncInter)); + pPerScanCtx->perInterUsec = LCTR_PER_INTER_TO_US(trsfSyncInfo.syncInter); pPerScanCtx->advSID = pMsg->advSID; pPerScanCtx->advAddrType = pMsg->advAddrType; pPerScanCtx->advAddr = pMsg->advAddr; @@ -492,8 +523,6 @@ void lctrTransferSyncActStart(void) /*************************************************************************************************/ /*! * \brief Transfer sync done action function. - * - * \return None. */ /*************************************************************************************************/ void lctrTransferSyncActDone(void) @@ -503,8 +532,6 @@ void lctrTransferSyncActDone(void) /*************************************************************************************************/ /*! * \brief Transfer sync failed action function. - * - * \return None. */ /*************************************************************************************************/ void lctrTransferSyncActFailed(void) @@ -519,8 +546,6 @@ void lctrTransferSyncActFailed(void) /*************************************************************************************************/ /*! * \brief Transfer sync cancel action function. - * - * \return None. */ /*************************************************************************************************/ void lctrTransferSyncActCancel(void) @@ -532,8 +557,6 @@ void lctrTransferSyncActCancel(void) /*************************************************************************************************/ /*! * \brief Transfer sync terminate action function. - * - * \return None. */ /*************************************************************************************************/ void lctrTransferSyncActTerminate(void) @@ -551,8 +574,6 @@ void lctrTransferSyncActTerminate(void) * \brief Periodic scanning sync established action function. * * \param pPerScanCtx Periodic scan context. - * - * \return None. */ /*************************************************************************************************/ void lctrPerScanActSyncEstd(lctrPerScanCtx_t *pPerScanCtx) @@ -577,8 +598,6 @@ void lctrPerScanActSyncEstd(lctrPerScanCtx_t *pPerScanCtx) * \brief Periodic scanning sync terminate action function. * * \param pPerScanCtx Periodic scan context. - * - * \return None. */ /*************************************************************************************************/ void lctrPerScanActSyncTerminate(lctrPerScanCtx_t *pPerScanCtx) @@ -595,8 +614,6 @@ void lctrPerScanActSyncTerminate(lctrPerScanCtx_t *pPerScanCtx) * \brief Periodic scanning sync terminate done action function. * * \param pPerScanCtx Periodic scan context. - * - * \return None. */ /*************************************************************************************************/ void lctrPerScanActSyncTerminateDone(lctrPerScanCtx_t *pPerScanCtx) @@ -609,8 +626,6 @@ void lctrPerScanActSyncTerminateDone(lctrPerScanCtx_t *pPerScanCtx) * \brief Periodic scanning sync terminate action function. * * \param pPerScanCtx Periodic scan context. - * - * \return None. */ /*************************************************************************************************/ void lctrPerScanActSyncTimeout(lctrPerScanCtx_t *pPerScanCtx) @@ -628,31 +643,38 @@ void lctrPerScanActSyncTimeout(lctrPerScanCtx_t *pPerScanCtx) /*************************************************************************************************/ /*! - * \brief Process acad that need to be serviced. + * \brief Process ACAD that need to be serviced. * - * \param pMsg Acad message. - * - * \return None + * \param pMsg ACAD message. */ /*************************************************************************************************/ void lctrPerScanActProcessAcad(lctrAcadMsg_t *pMsg) { lctrPerScanCtx_t *pPerScanCtx = LCTR_GET_PER_SCAN_CTX(pMsg->hdr.handle); - switch(pMsg->hdr.acadId) + + switch (pMsg->hdr.acadId) { case LCTR_ACAD_ID_CHAN_MAP_UPDATE: { - lctrAcadChanMapUpd_t *pData = &pPerScanCtx->acadParams[pMsg->hdr.acadId].chanMapUpdate; + LctrAcadChanMapUpd_t *pChanMapUpd = &pPerScanCtx->acadParams[LCTR_ACAD_ID_CHAN_MAP_UPDATE].chanMapUpdate; - if ((pData->instant - pMsg->hdr.eventCtr) <= pMsg->hdr.skip) + if ((pChanMapUpd->instant - pMsg->hdr.eventCtr) <= pMsg->hdr.skip) { - pPerScanCtx->chanParam.chanMask = pData->chanMask; + pPerScanCtx->chanParam.chanMask = pChanMapUpd->chanMask; LmgrBuildRemapTable(&pPerScanCtx->chanParam); - pData->hdr.state = LCTR_ACAD_STATE_DISABLED; + pChanMapUpd->hdr.state = LCTR_ACAD_STATE_DISABLED; } break; } + case LCTR_ACAD_ID_BIG_INFO: + { + LctrAcadBigInfo_t *pBigInfo = &pPerScanCtx->acadParams[LCTR_ACAD_ID_BIG_INFO].bigInfo; + /* No action required. */ + pBigInfo->hdr.state = LCTR_ACAD_STATE_DISABLED; + break; + } + default: break; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_slave.c index a70282b20b..6d8ab37422 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave advertising action routines. + * \file + * + * \brief Link layer controller slave advertising action routines. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -33,8 +34,6 @@ /*************************************************************************************************/ /*! * \brief Notify host of direct connect timeout failure. - * - * \return None. */ /*************************************************************************************************/ static void lctrNotifyHostDirectConnectTimeout(void) @@ -69,8 +68,6 @@ static void lctrNotifyHostDirectConnectTimeout(void) /*************************************************************************************************/ /*! * \brief Common advertise resource cleanup. - * - * \return None. */ /*************************************************************************************************/ static void lctrAdvCleanup(void) @@ -86,8 +83,6 @@ static void lctrAdvCleanup(void) /*************************************************************************************************/ /*! * \brief Start advertising. - * - * \return None. */ /*************************************************************************************************/ void lctrAdvActStart(void) @@ -108,8 +103,6 @@ void lctrAdvActStart(void) /*************************************************************************************************/ /*! * \brief Start advertising. - * - * \return None. */ /*************************************************************************************************/ void lctrAdvActSelfStart(void) @@ -128,8 +121,6 @@ void lctrAdvActSelfStart(void) /*************************************************************************************************/ /*! * \brief Shutdown active advertising operation. - * - * \return None. */ /*************************************************************************************************/ void lctrAdvActShutdown(void) @@ -150,8 +141,6 @@ void lctrAdvActShutdown(void) /*************************************************************************************************/ /*! * \brief Send advertising operation confirm. - * - * \return None. */ /*************************************************************************************************/ void lctrAdvActAdvCnf(void) @@ -162,8 +151,6 @@ void lctrAdvActAdvCnf(void) /*************************************************************************************************/ /*! * \brief Send advertising operation command disallowed. - * - * \return None. */ /*************************************************************************************************/ void lctrAdvActDisallowAdvCnf(void) @@ -175,8 +162,6 @@ void lctrAdvActDisallowAdvCnf(void) /*! * \brief Operation self terminated (e.g. on connection indication). * - * \return None. - * * Slave self-termination is a result of the reception of a CONN_IND. */ /*************************************************************************************************/ @@ -219,11 +204,15 @@ void lctrAdvActSelfTerm(void) WsfMsgFree(pMsg); } - /* Reuse message. */ - lctrMsgHdr_t *pResMsg = (lctrMsgHdr_t *)pBuf - 1; - pResMsg->dispId = LCTR_DISP_ADV; - pResMsg->event = LCTR_ADV_MSG_INT_START; - WsfMsgSend(lmgrPersistCb.handlerId, pResMsg); + /* Cannot reuse pBuf message. */ + lctrMsgHdr_t *pResMsg = WsfMsgAlloc(sizeof(lctrMsgHdr_t)); + + if (pResMsg) + { + pResMsg->dispId = LCTR_DISP_ADV; + pResMsg->event = LCTR_ADV_MSG_INT_START; + WsfMsgSend(lmgrPersistCb.handlerId, pResMsg); + } BbStop(BB_PROT_BLE); } @@ -235,7 +224,7 @@ void lctrAdvActSelfTerm(void) pMsg->hdr.dispId = LCTR_DISP_CONN_IND; /* pMsg->hdr.event = 0; */ - pMsg->connIndEndTs = lctrSlvAdv.reqEndTs; + pMsg->connIndEndTsUsec = lctrSlvAdv.reqEndTsUsec; BbBlePduFiltResultsGetPeerIdAddr(&pAdv->filtResults, &pMsg->peerIdAddr, &pMsg->peerIdAddrType); BbBlePduFiltResultsGetPeerRpa(&pAdv->filtResults, &pMsg->peerRpa); @@ -250,8 +239,6 @@ void lctrAdvActSelfTerm(void) WsfMsgSend(lmgrPersistCb.handlerId, pMsg); } - - WsfMsgFree((lctrMsgHdr_t *)pBuf - 1); } } } @@ -278,8 +265,6 @@ void lctrAdvActSelfTerm(void) /*************************************************************************************************/ /*! * \brief Terminated advertising after host advertising disable. - * - * \return None. */ /*************************************************************************************************/ void lctrAdvActAdvTerm(void) @@ -295,8 +280,6 @@ void lctrAdvActAdvTerm(void) /*************************************************************************************************/ /*! * \brief Terminated advertising after host reset. - * - * \return None. */ /*************************************************************************************************/ void lctrAdvActResetTerm(void) @@ -309,8 +292,6 @@ void lctrAdvActResetTerm(void) /*************************************************************************************************/ /*! * \brief Update advertising parameters. - * - * \return None. */ /*************************************************************************************************/ void lctrAdvActUpdateAdvParam(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_slave_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_slave_ae.c index 13351e7970..d05fe958b1 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_slave_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_adv_slave_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave extended advertising action routines. + * \file + * + * \brief Link layer controller slave extended advertising action routines. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -35,28 +36,11 @@ #include -/*************************************************************************************************/ -/*! - * \brief Disable and clean a generic acad parameter - * - * \param pAcadParam Generic acad parameter type - * - * \return None. - */ -/*************************************************************************************************/ -static void lctrSlvAcadDisable(lctrAcadParam_t *pAcadParam) -{ - memset(pAcadParam, 0, sizeof(*pAcadParam)); - pAcadParam->hdr.state = LCTR_ACAD_STATE_DISABLED; -} - /*************************************************************************************************/ /*! * \brief Common advertise resource cleanup. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ static void lctrExtAdvCleanup(lctrAdvSet_t *pAdvSet) @@ -94,8 +78,6 @@ static void lctrExtAdvCleanup(lctrAdvSet_t *pAdvSet) * \brief Common periodic advertising cleanup. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ static void lctrPeriodicAdvACleanup(lctrAdvSet_t *pAdvSet) @@ -111,8 +93,6 @@ static void lctrPeriodicAdvACleanup(lctrAdvSet_t *pAdvSet) * \brief Start extended advertising. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrExtAdvActStart(lctrAdvSet_t *pAdvSet) @@ -131,7 +111,7 @@ void lctrExtAdvActStart(lctrAdvSet_t *pAdvSet) uint8_t status; if ((status = lctrSlvExtAdvBuildOp(pAdvSet, pLctrSlvExtAdvMsg->enable.durMs)) != LL_SUCCESS) { - // TODO suppress terminate event on failed start + /* TODO suppress terminate event on failed start */ LmgrSendExtAdvEnableCnf(pAdvSet->handle, status); lctrSendAdvSetMsg(pAdvSet, LCTR_EXT_ADV_MSG_TERMINATE); return; @@ -157,8 +137,6 @@ void lctrExtAdvActStart(lctrAdvSet_t *pAdvSet) * \brief Start extended advertising internally. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrExtAdvActSelfStart(lctrAdvSet_t *pAdvSet) @@ -177,7 +155,7 @@ void lctrExtAdvActSelfStart(lctrAdvSet_t *pAdvSet) uint8_t status; if ((status = lctrSlvExtAdvBuildOp(pAdvSet, pLctrSlvExtAdvMsg->enable.durMs)) != LL_SUCCESS) { - // TODO suppress terminate event on failed start + /* TODO suppress terminate event on failed start */ LmgrSendExtAdvEnableCnf(pAdvSet->handle, status); lctrSendAdvSetMsg(pAdvSet, LCTR_EXT_ADV_MSG_TERMINATE); return; @@ -194,8 +172,6 @@ void lctrExtAdvActSelfStart(lctrAdvSet_t *pAdvSet) * \brief Restart extended advertising. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrExtAdvActRestart(lctrAdvSet_t *pAdvSet) @@ -218,8 +194,6 @@ void lctrExtAdvActRestart(lctrAdvSet_t *pAdvSet) * \brief Shutdown active advertising operation. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrExtAdvActShutdown(lctrAdvSet_t *pAdvSet) @@ -239,8 +213,6 @@ void lctrExtAdvActShutdown(lctrAdvSet_t *pAdvSet) * \brief Shutdown active advertising operation due to host reset. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrExtAdvActResetShutdown(lctrAdvSet_t *pAdvSet) @@ -262,8 +234,6 @@ void lctrExtAdvActResetShutdown(lctrAdvSet_t *pAdvSet) * \brief Send advertising operation confirm. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrExtAdvActAdvCnf(lctrAdvSet_t *pAdvSet) @@ -276,8 +246,6 @@ void lctrExtAdvActAdvCnf(lctrAdvSet_t *pAdvSet) * \brief Send advertising operation command disallowed. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrExtAdvActDisallowAdvCnf(lctrAdvSet_t *pAdvSet) @@ -291,8 +259,6 @@ void lctrExtAdvActDisallowAdvCnf(lctrAdvSet_t *pAdvSet) * * \param pAdvSet Advertising set. * - * \return None. - * * Slave self-termination is a result of the expiration of the duration timer, numEvents reached, * or reception of an AUX_CONN_REQ. */ @@ -396,7 +362,7 @@ void lctrExtAdvActSelfTerm(lctrAdvSet_t *pAdvSet) pMsg->phy = pAdvSet->auxBleData.chan.rxPhy; /* Same PHY as received CONN_IND. */ } - pMsg->connIndEndTs = pAdvSet->connIndEndTs; + pMsg->connIndEndTsUsec = pAdvSet->connIndEndTsUsec; pMsg->localRpa = lmgrSlvAdvCb.localRpa; pMsg->usedChSel = pAdvSet->usedChSel; @@ -439,8 +405,6 @@ void lctrExtAdvActSelfTerm(lctrAdvSet_t *pAdvSet) * \brief Terminated advertising after host advertising disable. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrExtAdvActAdvTerm(lctrAdvSet_t *pAdvSet) @@ -456,8 +420,6 @@ void lctrExtAdvActAdvTerm(lctrAdvSet_t *pAdvSet) * \brief Cleanup Advertising Set after host reset. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrExtAdvActReset(lctrAdvSet_t *pAdvSet) @@ -481,8 +443,6 @@ void lctrExtAdvActReset(lctrAdvSet_t *pAdvSet) * \brief Terminated advertising and cleanup Advertising Set after host reset. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrExtAdvActResetTerm(lctrAdvSet_t *pAdvSet) @@ -500,8 +460,6 @@ void lctrExtAdvActResetTerm(lctrAdvSet_t *pAdvSet) * \brief Advertising set duration timer expired. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrExtAdvActDurationExpired(lctrAdvSet_t *pAdvSet) @@ -517,8 +475,6 @@ void lctrExtAdvActDurationExpired(lctrAdvSet_t *pAdvSet) * \brief Build channel remapping table. * * \param pChanParam Channel parameters. - * - * \return None. */ /*************************************************************************************************/ void lctrPeriodicBuildRemapTable(lmgrChanParam_t *pChanParam) @@ -544,8 +500,6 @@ void lctrPeriodicBuildRemapTable(lmgrChanParam_t *pChanParam) * \brief Start periodic advertising. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrPeriodicAdvActStart(lctrAdvSet_t *pAdvSet) @@ -596,14 +550,12 @@ void lctrPeriodicAdvActStart(lctrAdvSet_t *pAdvSet) * \brief Restart periodic advertising. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrPeriodicAdvActUpdate(lctrAdvSet_t *pAdvSet) { LmgrSendPeriodicAdvEnableCnf(pAdvSet->handle, LL_SUCCESS); - // TODO cause random address to change + /* TODO cause random address to change */ } /*************************************************************************************************/ @@ -611,8 +563,6 @@ void lctrPeriodicAdvActUpdate(lctrAdvSet_t *pAdvSet) * \brief Send periodic advertising operation confirm. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrPeriodicAdvActAdvCnf(lctrAdvSet_t *pAdvSet) @@ -625,8 +575,6 @@ void lctrPeriodicAdvActAdvCnf(lctrAdvSet_t *pAdvSet) * \brief Send periodic advertising operation command disallowed. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrPeriodicAdvActDisallowAdvCnf(lctrAdvSet_t *pAdvSet) @@ -639,8 +587,6 @@ void lctrPeriodicAdvActDisallowAdvCnf(lctrAdvSet_t *pAdvSet) * \brief Shutdown active periodic advertising operation. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrPeriodicAdvActShutdown(lctrAdvSet_t *pAdvSet) @@ -666,8 +612,6 @@ void lctrPeriodicAdvActShutdown(lctrAdvSet_t *pAdvSet) * \brief Terminated advertising after host periodic advertising disable. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrPeriodicAdvActAdvTerm(lctrAdvSet_t *pAdvSet) @@ -682,8 +626,6 @@ void lctrPeriodicAdvActAdvTerm(lctrAdvSet_t *pAdvSet) * \brief Terminated periodc advertising after host reset. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrPeriodicAdvActResetTerm(lctrAdvSet_t *pAdvSet) @@ -693,16 +635,14 @@ void lctrPeriodicAdvActResetTerm(lctrAdvSet_t *pAdvSet) /*************************************************************************************************/ /*! - * \brief Acad channel map start handler + * \brief ACAD channel map start handler * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvAcadActChanMapUpdateStart(lctrAdvSet_t *pAdvSet) { - lctrAcadChanMapUpd_t *pAcadParam = &pAdvSet->acadParams[LCTR_ACAD_ID_CHAN_MAP_UPDATE].chanMapUpdate; + LctrAcadChanMapUpd_t *pAcadParam = &pAdvSet->acadParams[LCTR_ACAD_ID_CHAN_MAP_UPDATE].chanMapUpdate; /* A new channel map update cannot replace a currently running one. */ if (pAcadParam->hdr.state == LCTR_ACAD_STATE_ENABLED) @@ -710,22 +650,65 @@ void lctrSlvAcadActChanMapUpdateStart(lctrAdvSet_t *pAdvSet) return; } + pAdvSet->perParam.updChanMask = pLctrAcadSlvMsg->chanMapUpd.chanMap; + pAcadParam->chanMask = pAdvSet->perParam.updChanMask; pAcadParam->instant = pAdvSet->perParam.perEventCounter + LL_MIN_INSTANT; - pAcadParam->hdr.len = LL_ACAD_UPDATE_CHANNEL_MAP_LEN; + pAcadParam->hdr.len = LL_ACAD_CHAN_MAP_UPD_LEN; pAcadParam->hdr.state = LCTR_ACAD_STATE_ENABLED; } /*************************************************************************************************/ /*! - * \brief Acad channel map finish handler + * \brief ACAD channel map finish handler * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvAcadActChanMapUpdateFinish(lctrAdvSet_t *pAdvSet) { lctrSlvAcadDisable(&pAdvSet->acadParams[LCTR_ACAD_ID_CHAN_MAP_UPDATE]); } + +/*************************************************************************************************/ +/*! + * \brief ACAD BIG created handler + * + * \param pAdvSet Advertising set. + */ +/*************************************************************************************************/ +void lctrSlvAcadActBigCreated(lctrAdvSet_t *pAdvSet) +{ + if (pAdvSet->bigCreated) + { + pAdvSet->bigCreated(pAdvSet->handle); + } +} + +/*************************************************************************************************/ +/*! + * \brief ACAD BIG terminated handler + * + * \param pAdvSet Advertising set. + */ +/*************************************************************************************************/ +void lctrSlvAcadActBigTerminated(lctrAdvSet_t *pAdvSet) +{ + if (pAdvSet->bigTerminated) + { + pAdvSet->bigTerminated(pAdvSet->handle); + } +} + +/*************************************************************************************************/ +/*! + * \brief Disable and clean a generic ACAD parameter + * + * \param pAcadParam Generic ACAD parameter type + */ +/*************************************************************************************************/ +void lctrSlvAcadDisable(lctrAcadParam_t *pAcadParam) +{ + memset(pAcadParam, 0, sizeof(*pAcadParam)); + pAcadParam->hdr.state = LCTR_ACAD_STATE_DISABLED; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_bis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_bis_master.c new file mode 100644 index 0000000000..301aed27cd --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_bis_master.c @@ -0,0 +1,271 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller master BIG action routines. + * + * 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 "lctr_int_bis_master.h" +#include "sch_api.h" + +/*************************************************************************************************/ +/*! + * \brief Notify host with BIG Create Sync Complete event + * + * \param pBigCtx BIG context. + * \param status Status. + */ +/*************************************************************************************************/ +static void lctrNotifyHostBigCreateSyncComplete(lctrBigCtx_t *pBigCtx, LlStatus_t status) +{ + LlBigSyncEstInd_t evt = { 0 }; + + evt.hdr.param = pBigCtx->handle; + evt.hdr.event = LL_BIG_SYNC_EST_IND; + evt.hdr.status = status; + + evt.status = status; + evt.bigHandle = pBigCtx->handle; + + if (evt.status == LL_SUCCESS) + { + evt.transLatUsec = pBigCtx->transLatUsec; + evt.nse = pBigCtx->nse; + evt.bn = pBigCtx->bn; + evt.pto = pBigCtx->pto; + 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++) + { + evt.bisHandle[i] = pBigCtx->pBisCtx[i]->handle; + } + } + + LL_TRACE_INFO2("### LlEvent ### LL_BIG_SYNC_EST_IND, bigHandle=%u, status=%u", pBigCtx->handle, status); + + LmgrSendEvent((LlEvt_t *)&evt); +} + +/*************************************************************************************************/ +/*! + * \brief Notify host with BIG Terminate Sync Complete event + * + * \param bigHandle BIG handle. + * \param status Status. + */ +/*************************************************************************************************/ +void lctrNotifyHostBigTerminateComplete(LlStatus_t status, uint8_t bigHandle) +{ + LlBigTermSyncCnf_t evt; + + /* Clear not required; all values are written. */ + /* memset(&evt, 0, sizeof(LlBigTermSyncCnf_t)); */ + + evt.hdr.param = bigHandle; + evt.hdr.event = LL_BIG_TERM_SYNC_CNF; + evt.hdr.status = status; + + evt.status = status; + evt.bigHandle = bigHandle; + + LL_TRACE_INFO2("### LlEvent ### LL_BIG_TERM_SYNC_CNF, status=%u, bigHandle=%u", status, bigHandle); + + LmgrSendEvent((LlEvt_t *)&evt); +} + +/*************************************************************************************************/ +/*! + * \brief Notify host with BIG Terminate Sync Complete event + * + * \param bigHandle BIG handle. + * \param reason Status. + */ +/*************************************************************************************************/ +void lctrNotifyHostSyncLost(uint8_t bigHandle, LlStatus_t reason) +{ + LlBigSyncLostInd_t evt; + + /* Clear not required; all values are written. */ + /* memset(&evt, 0, sizeof(LlBigTermSyncCnf_t)); */ + + evt.hdr.param = bigHandle; + evt.hdr.event = LL_BIG_SYNC_LOST_IND; + evt.hdr.status = LL_SUCCESS; + + evt.bigHandle = bigHandle; + evt.reason = reason; + + LL_TRACE_INFO2("### LlEvent ### LL_BIG_SYNC_LOST_IND, bigHandle=%u, reason=%u", bigHandle, reason); + + LmgrSendEvent((LlEvt_t *)&evt); +} + +/*************************************************************************************************/ +/*! + * \brief Start BIG Synchronization. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +void lctrMstBigActStart(lctrBigCtx_t *pBigCtx) +{ + /* Defer until BIG Info received. */ + /* lctrMstBigBuildOp(pBigCtx); */ + + BbStart(BB_PROT_BLE); + + LmgrIncResetRefCount(); +} + +/*************************************************************************************************/ +/*! + * \brief Synchronize to BIG. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +void lctrMstBigActBigSync(lctrBigCtx_t *pBigCtx) +{ + LctrAcadBigInfo_t *pBigInfo = &pLctrMstBigMsg->bigInfo.data; + + lctrMstSetupBigContext(pBigCtx, pBigInfo); + lctrMstSetupBigChannel(pBigCtx, pBigInfo); + + for (unsigned int i = 0; i < pBigInfo->numBis; i++) + { + lctrBisCtx_t *pBisCtx; + + /* Availability is verified on BIG Create Sync command. */ + pBisCtx = lctrAllocBisCtx(pBigCtx); + WSF_ASSERT(pBisCtx); + + lctrSetupBisContext(pBisCtx, pBigInfo->seedAccAddr, pBigInfo->baseCrcInit, pBigInfo->chanMap, pBigInfo->phy); + } + + lctrMstBigBuildOp(pBigCtx, &pLctrMstBigMsg->bigInfo.data); + + WsfTimerStartMs(&pBigCtx->roleData.mst.bigSyncTmr, pBigCtx->roleData.mst.bigSyncTimeoutMs); + + lctrNotifyHostBigCreateSyncComplete(pBigCtx, LL_SUCCESS); +} + +/*************************************************************************************************/ +/*! + * \brief Sync Lost due to BIG Terminated PDU received. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +void lctrMstBigActTerm(lctrBigCtx_t *pBigCtx) +{ + BbStop(BB_PROT_BLE); + + lctrFreeBigCtx(pBigCtx); + + LmgrDecResetRefCount(); + + lctrNotifyHostSyncLost(pBigCtx->handle, pBigCtx->bcp.term.reason); +} + +/*************************************************************************************************/ +/*! + * \brief Shutdown active BIS operation. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +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); + } + + if (pBigCtx->state == LCTR_MST_BIG_STATE_SYNCING) + { + lctrNotifyHostBigCreateSyncComplete(pBigCtx, LL_ERROR_CODE_CONN_TERM_BY_LOCAL_HOST); + } +} + +/*************************************************************************************************/ +/*! + * \brief Synchronization with broadcaster lost. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +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); + } + + pBigCtx->roleData.mst.syncLostReason = LL_ERROR_CODE_CONN_TIMEOUT; +} + +/*************************************************************************************************/ +/*! + * \brief Drop synchronization due to MIC failure. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +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); + } + + pBigCtx->roleData.mst.syncLostReason = LL_ERROR_CODE_CONN_TERM_MIC_FAILURE; +} + +/*************************************************************************************************/ +/*! + * \brief Terminated advertising after host periodic advertising disable. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +void lctrMstBigActCleanup(lctrBigCtx_t *pBigCtx) +{ + BbStop(BB_PROT_BLE); + + lctrFreeBigCtx(pBigCtx); + + LmgrDecResetRefCount(); + + if (pBigCtx->roleData.mst.syncLostReason != LL_SUCCESS) + { + lctrNotifyHostSyncLost(pBigCtx->handle, pBigCtx->roleData.mst.syncLostReason); + } + else + { + lctrNotifyHostBigTerminateComplete(LL_SUCCESS, pBigCtx->handle); + } +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_bis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_bis_slave.c new file mode 100644 index 0000000000..d6498a04f5 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_bis_slave.c @@ -0,0 +1,211 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller slave BIG action routines. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_bis_slave.h" +#include "lctr_int_iso.h" +#include "sch_api.h" +#include "sch_api_ble.h" +#include "wsf_assert.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include + +/*************************************************************************************************/ +/*! + * \brief Start BIS slave advertising. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +void lctrSlvBigActStart(lctrBigCtx_t *pBigCtx) +{ + uint8_t status; + + if ((status = lctrSlvBigBuildOp(pBigCtx)) != LL_SUCCESS) + { + lctrSlvBigSendMsg(pBigCtx, LCTR_SLV_BIG_MSG_TERMINATED); + lctrNotifyHostCreateBigComplete(pBigCtx, status); + return; + } + + BbStart(BB_PROT_BLE); + + lctrAdvSet_t * const pAdvSet = pBigCtx->roleData.slv.pAdvSet; + + if (pAdvSet) + { + pAdvSet->perParam.perAdvEnabled = TRUE; + + /* Add SyncInfo to the Extended Advertising. */ + if (pAdvSet->state == LCTR_EXT_ADV_STATE_ENABLED) + { + if ((pAdvSet->auxBodUsed == FALSE)) + { + pAdvSet->perParam.perAuxStart = TRUE; + } + + /* The Advertising DID is required to change when a SyncInfo field is added to or removed. */ + pAdvSet->advData.alt.ext.did = lctrCalcDID(pAdvSet->advData.pBuf, pAdvSet->advData.len); + pAdvSet->didPerUpdate = TRUE; + } + } + + lctrSlvBigSendAcadMsg(pBigCtx, LCTR_ACAD_MSG_BIG_CREATED); + + LmgrIncResetRefCount(); +} + +/*************************************************************************************************/ +/*! + * \brief Broadcast channel map updates. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +void lctrSlvBigActSendChMapUpd(lctrBigCtx_t *pBigCtx) +{ + if (pBigCtx->bcp.actMsk) + { + LL_TRACE_INFO1("BIG Control Procedure in progress; pend BIG Channel Map Update, bigHandle=%u", pBigCtx->handle); + pBigCtx->bcp.pendMsk |= 1 << LL_BIG_OPCODE_CHAN_MAP_IND; + return; + } + + uint8_t *pPdu; + + if ((pPdu = lctrBigTxCtrlAlloc(LL_BIG_CHAN_MAP_IND_PDU_LEN)) != NULL) + { + uint16_t inst = pBigCtx->eventCounter + LL_BIG_MIN_INSTANT; + + uint8_t *pBuf = pPdu; + + lctrBisDataPduHdr_t hdr = + { + .llid = LL_LLID_BIG_CTRL_PDU, + .cssn = 0, /* Completed in ISR. */ + .cstf = 0, /* Always 0. */ + .len = LL_BIG_OPCODE_LEN + LL_BIG_CHAN_MAP_IND_PDU_LEN + }; + + pBuf += lctrBisPackDataPduHdr(pBuf, &hdr); + lctrBisPackBigChannelMapInd(pBuf, lmgrCb.chanClass, inst); + + lctrBigTxCtrlQueue(pBigCtx, pPdu, LL_MIN_INSTANT); + + pBigCtx->bcp.actMsk |= 1 << LL_BIG_OPCODE_CHAN_MAP_IND; + pBigCtx->bcp.chanMapUpd.chanMap = lmgrCb.chanClass; + pBigCtx->bcp.chanMapUpd.inst = inst; + + LL_TRACE_INFO2("BIG Channel Map Procedure, bigHandle=%u, instant=%u", pBigCtx->handle, inst); + + if (pBigCtx->roleData.slv.pAdvSet) + { + /* Temporarily disable BIG Info transmissions. */ + LctrAcadBigInfo_t *pBigInfo = &pBigCtx->roleData.slv.pAdvSet->acadParams[LCTR_ACAD_ID_BIG_INFO].bigInfo; + pBigInfo->hdr.state = LCTR_ACAD_STATE_DISABLED; + } + } +} + +/*************************************************************************************************/ +/*! + * \brief Broadcast terminate. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +void lctrSlvBigActSendTerm(lctrBigCtx_t *pBigCtx) +{ + if (pBigCtx->bcp.actMsk) + { + LL_TRACE_INFO1("BIG Control Procedure in progress; pend BIG Terminate, bigHandle=%u", pBigCtx->handle); + pBigCtx->bcp.pendMsk |= 1 << LL_BIG_OPCODE_BIG_TERM_IND; + return; + } + + uint8_t *pBuf; + + if ((pBuf = lctrBigTxCtrlAlloc(LL_BIG_TERMINATE_IND_PDU_LEN)) != NULL) + { + uint16_t inst = pBigCtx->eventCounter + LL_BIG_MIN_INSTANT; + + uint8_t *pPdu = pBuf; + + lctrBisDataPduHdr_t hdr = + { + .llid = LL_LLID_BIG_CTRL_PDU, + .cssn = 0, /* Completed in ISR. */ + .cstf = 0, /* Always 0. */ + .len = LL_BIG_OPCODE_LEN + LL_BIG_TERMINATE_IND_PDU_LEN + }; + + pBuf += lctrBisPackDataPduHdr(pBuf, &hdr); + lctrBisPackBigTerminateInd(pBuf, pBigCtx->bcp.term.reason, inst); + + lctrBigTxCtrlQueue(pBigCtx, pPdu, LL_BIG_MIN_INSTANT); + + pBigCtx->bcp.actMsk |= 1 << LL_BIG_OPCODE_BIG_TERM_IND; + pBigCtx->bcp.term.inst = inst; + + LL_TRACE_INFO2("BIG Terminate Procedure, bigHandle=%u, instant=%u", pBigCtx->handle, inst); + } + + lctrSlvBigSendAcadMsg(pBigCtx, LCTR_ACAD_MSG_BIG_TERMINATED); +} + +/*************************************************************************************************/ +/*! + * \brief Shutdown active BIS operation. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +void lctrSlvBigActShutdown(lctrBigCtx_t *pBigCtx) +{ + /* By removing BOD from scheduler, BOD end callback will be called. */ + /* Shutdown completes with events generated in BOD end callback. */ + SchRemove(&pBigCtx->bod); + + lctrSlvBigSendAcadMsg(pBigCtx, LCTR_ACAD_MSG_BIG_TERMINATED); +} + +/*************************************************************************************************/ +/*! + * \brief Cleanup BIG contexts. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +void lctrSlvBigActCleanup(lctrBigCtx_t *pBigCtx) +{ + lctrNotifyHostTerminateBigComplete(pBigCtx); + + SchRmRemove(LCTR_BIG_TO_RM_HANDLE(pBigCtx)); + + lctrFreeBigCtx(pBigCtx); + + BbStop(BB_PROT_BLE); + + LmgrDecResetRefCount(); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis.c new file mode 100644 index 0000000000..b333ca26d2 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis.c @@ -0,0 +1,538 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller master connected isochronous stream state machine action routines. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_cis.h" +#include "lctr_int_iso.h" +#include "lmgr_api_cis_master.h" +#include "sch_api.h" +#include "sch_api_ble.h" +#include "wsf_trace.h" +#include "wsf_assert.h" +#include "util/bstream.h" +#include + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Send CIS termination indication PDU. + * + * \param pCtx Connection context. + * \param opcode Pdu Opcode. + * \param pCisCtx CIS context. + * \param reason Termination reason. + */ +/*************************************************************************************************/ +static void lctrSendCisTermIndPdu(lctrConnCtx_t *pCtx, uint8_t opcode, lctrCisCtx_t *pCisCtx, uint8_t reason) +{ + uint8_t *pPdu; + + if ((pPdu = lctrTxCtrlPduAlloc(LL_CIS_TERM_LEN)) != NULL) + { + uint8_t *pBuf = pPdu; + + /*** Assemble control PDU. ***/ + UINT8_TO_BSTREAM (pBuf, opcode); + UINT8_TO_BSTREAM (pBuf, pCisCtx->cigId); + UINT8_TO_BSTREAM (pBuf, pCisCtx->cisId); + UINT8_TO_BSTREAM (pBuf, reason); + + /*** Queue for transmit. ***/ + lctrTxCtrlPduQueue(pCtx, pPdu); + } +} + +/*************************************************************************************************/ +/*! + * \brief Send CIS termination indication. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + * \param reason Termination reason. + */ +/*************************************************************************************************/ +static void lctrSendCisTermInd(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx, uint8_t reason) +{ + lctrSendCisTermIndPdu(pCtx, LL_PDU_CIS_TERM_IND, pCisCtx, reason); +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Notify host of CIS disconnected event + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrNotifyHostCisTerm(lctrCisCtx_t *pCisCtx) +{ + LlDisconnectInd_t evt = + { + .hdr = + { + .param = pCisCtx->cisHandle, + .event = LL_DISCONNECT_IND, + .status = LL_SUCCESS + }, + + .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); + + LmgrSendEvent((LlEvt_t *)&evt); +} + +/*************************************************************************************************/ +/*! + * \brief Notify host of CIS established event + * + * \param pCisCtx CIS context. + * \param status Status. + * \param cigSyncDelayUsec CIG synchronization delayn in usec. + */ +/*************************************************************************************************/ +void lctrNotifyHostCisEst(lctrCisCtx_t *pCisCtx, uint8_t status, uint32_t cigSyncDelayUsec) +{ + LlCisEstInd_t evt = + { + .hdr = + { + .param = pCisCtx->cisHandle, + .event = LL_CIS_EST_IND, + .status = status + } + }; + + evt.cisHandle = pCisCtx->cisHandle; + evt.status = status; + evt.cigSyncDelayUsec = cigSyncDelayUsec; + evt.cisSyncDelayUsec = pCisCtx->cisSyncDelayUsec; + evt.transLatUsecMToS = pCisCtx->transLatUsec; /* For now it is 0, update it when ISOAL is supported. */ + evt.transLatUsecSToM = pCisCtx->transLatUsec; /* For now it is 0, update it when ISOAL is supported. */ + evt.phyMToS = pCisCtx->phyMToS; + evt.phySToM = pCisCtx->phySToM; + evt.nse = pCisCtx->nse; + evt.bnMToS = pCisCtx->bnMToS; + evt.bnSToM = pCisCtx->bnSToM; + evt.ftMToS = pCisCtx->ftMToS; + evt.ftSToM = pCisCtx->ftSToM; + evt.isoInterval = pCisCtx->isoInterval; + + LL_TRACE_INFO2("### LlEvent ### LL_CIS_EST_IND, cisHandle=%u, status=%u", pCisCtx->cisHandle, status); + + LmgrSendEvent((LlEvt_t *)&evt); +} + +/*************************************************************************************************/ +/*! + * \brief Send internal CIS subsystem message. + * + * \param pCisCtx CIS context. + * \param event CIS event. + */ +/*************************************************************************************************/ +void lctrSendCisMsg(lctrCisCtx_t *pCisCtx, uint8_t event) +{ + lctrMsgHdr_t *pMsg; + + if ((pMsg = (lctrMsgHdr_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->handle = pCisCtx->cisHandle; + pMsg->dispId = LCTR_DISP_CIS; + pMsg->event = event; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } +} + +/*************************************************************************************************/ +/*! + * \brief Send internal CIS LLCP subsystem message. + * + * \param pCisCtx CIS context. + * \param event Connection event. + */ +/*************************************************************************************************/ +void lctrSendCisLlcpMsg(lctrCisCtx_t *pCisCtx, uint8_t event) +{ + lctrMsgHdr_t *pMsg; + + if ((pMsg = (lctrMsgHdr_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->handle = pCisCtx->aclHandle; + pMsg->dispId = LCTR_DISP_CONN; + pMsg->event = event; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } +} + +/*************************************************************************************************/ +/*! + * \brief Store LLCP termination reason. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisStoreTerminateReason(lctrCisCtx_t *pCisCtx) +{ + pCisCtx->reason = lctrDataPdu.pld.cisTerm.reason; +} + +/*************************************************************************************************/ +/*! + * \brief Store host initiated disconnect termination reason. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisStoreDisconnectReason(lctrCisCtx_t *pCisCtx) +{ + pCisCtx->reason = pLctrCisMsg->disc.reason; +} + +/*************************************************************************************************/ +/*! + * \brief Store connection failed to establish termination reason. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisStoreConnFailEstablishTerminateReason(lctrCisCtx_t *pCisCtx) +{ + pCisCtx->reason = LL_ERROR_CODE_CONN_FAILED_TO_ESTABLISH; +} + +/*************************************************************************************************/ +/*! + * \brief Store connection timeout termination reason. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisStoreConnTimeoutTerminateReason(lctrCisCtx_t *pCisCtx) +{ + pCisCtx->reason = LL_ERROR_CODE_CONN_TIMEOUT; +} + +/*************************************************************************************************/ +/*! + * \brief Store LLCP timeout termination reason. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisStoreLlcpTimeoutTerminateReason(lctrCisCtx_t *pCisCtx) +{ + pCisCtx->reason = LL_ERROR_CODE_LMP_LL_RESP_TIMEOUT; +} + +/*************************************************************************************************/ +/*! + * \brief Store local resource limitation reason. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisStoreLocalLowResourceTerminateReason(lctrCisCtx_t *pCisCtx) +{ + pCisCtx->reason = LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES; +} + +/*************************************************************************************************/ +/*! + * \brief Store LLCP peer reject reason. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisStoreLlcpPeerRejTerminateReason(lctrCisCtx_t *pCisCtx) +{ + pCisCtx->reason = lctrDataPdu.pld.rejInd.reason; +} + +/*************************************************************************************************/ +/*! + * \brief Store invalid request termination reason. + * + * \param pCisCtx CIS connection context. + */ +/*************************************************************************************************/ +void lctrCisStoreMicFailedTerminateReason(lctrCisCtx_t *pCisCtx) +{ + pCisCtx->reason = LL_ERROR_CODE_CONN_TERM_MIC_FAILURE; +} + +/************************************************************************************************** + CIS main state machine action functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Action function for CIS established. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisActCisEst(lctrCisCtx_t *pCisCtx) +{ + lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); + lctrConnCtx_t *pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); + + 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) + { + 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 */ + if (pConnCtx->usedFeatSet & LL_FEAT_POWER_CHANGE_IND) + { + pCisCtx->powerIndReq = TRUE; + } + } + else + { + LL_TRACE_INFO1(" txPower = %d", txPwr); + pCisCtx->bleData.chan.txPower = txPwr; + } + +} + +/*************************************************************************************************/ +/*! + * \brief Action function for CIS fail to establish. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisActCisEstFail(lctrCisCtx_t *pCisCtx) +{ + /* LLCP timeout for the LL_CIS_REQ indicates peer doesn't support CIS feature. */ + if (pCisCtx->isCisReqPend && + pCisCtx->reason == LL_ERROR_CODE_LMP_LL_RESP_TIMEOUT) + { + pCisCtx->isCisReqPend = FALSE; + lctrNotifyHostCisEst(pCisCtx, LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE, 0 /* cigSyncDelayUsec */); + return; + } + + lctrNotifyHostCisEst(pCisCtx, pCisCtx->reason, 0 /* cigSyncDelayUsec */); + + lctrCleanupCtx(pCisCtx); +} + +/*************************************************************************************************/ +/*! + * \brief Action function for received host disconnect CIS. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisActDisc(lctrCisCtx_t *pCisCtx) +{ + lctrCisDisc_t *pMsg; + + 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); + } +} + +/*************************************************************************************************/ +/*! + * \brief Action function for received internal CIS closed. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +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; + } + + LL_TRACE_INFO1("lctrCisActClosed, pCisCtx->cisHandle=%u", pCisCtx->cisHandle); + + lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); + lctrConnCtx_t *pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); + + WSF_ASSERT(pCigCtx); + WSF_ASSERT(pConnCtx); + + WsfTimerStop(&pCisCtx->tmrSupTimeout); + + pCisCtx->isClosing = TRUE; /* Close the context in the CIG BOD end callback. */ + + /* Fast supervision timeout case. */ + if (pCisCtx->isClosing == TRUE && + pCisCtx->reason == LL_ERROR_CODE_CONN_FAILED_TO_ESTABLISH) + { + pCisCtx->isClosing = FALSE; + lctrCleanupCtx(pCisCtx); + } +} + +/*************************************************************************************************/ +/*! + * \brief Action function for received internal CIS connection fail to maintain event. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisActFail(lctrCisCtx_t *pCisCtx) +{ + lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); + WSF_ASSERT(pCigCtx); + + LL_TRACE_INFO2("lctrCisActFail, pCisCtx->cisHandle=%u pCisCtx->state=%u", pCisCtx->cisHandle, pCisCtx->state); + + /* Supervision 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); + } +} + +/************************************************************************************************** + CIS LLCP state machine action functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Action function for LLCP received host disconnect. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisLlcpActHostDisc(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); + WSF_ASSERT(pCigCtx); + + lctrSendCisTermInd(pCtx, pCisCtx, pCisCtx->reason); + lctrCisStartLlcpTimer(pCtx, pCisCtx); +} + +/*************************************************************************************************/ +/*! + * \brief Action function for LLCP received CIS peer disconnect. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisLlcpActPeerDisc(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); + WSF_ASSERT(pCigCtx); + + lctrCisStoreTerminateReason(pCisCtx); + + pCtx->termAckReqd = TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Action function for LLCP received CIS terminated event. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisLlcpActCisTerm(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_CLOSED); +} + +/*************************************************************************************************/ +/*! + * \brief Action function for LLCP received internal host disconnect. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisLlcpActIntHostDisc(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + lctrSendCisTermInd(pCtx, pCisCtx, pCisCtx->reason); + lctrCisStartLlcpTimer(pCtx, pCisCtx); +} + +/*************************************************************************************************/ +/*! + * \brief Action function for LLCP received internal CIS peer disconnect. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisLlcpActIntPeerDisc(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + pCtx->termAckReqd = TRUE; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis_master.c new file mode 100644 index 0000000000..71e1e2f327 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis_master.c @@ -0,0 +1,481 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer connected isochronous stream master state machine action routines. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_cis_master.h" +#include "lctr_api_conn.h" +#include "lctr_api_cis_master.h" +#include "sch_api.h" +#include "sch_api_ble.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Calculate the next referenced connection event for the first CIS. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static void lctrCalCeRefFirstCis(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + BbOpDesc_t *pConnBod = &pCtx->connBod; + lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); + uint32_t refTime; + + pCisCtx->ceRef = pCtx->eventCounter + + LL_MIN_INSTANT + 1 + /* +1 for next CE */ + pCtx->maxLatency; /* ensure slave will listen to this packet */ + pCisCtx->cisCeRef = 0; + + refTime = pConnBod->dueUsec + (pCisCtx->ceRef - pCtx->eventCounter) * LCTR_CONN_IND_US(pCtx->connInterval); + pCisCtx->offsetUsec = SchRmGetOffsetUsec(LCTR_ISO_INT_TO_US(pCigCtx->isoInterval), + LCTR_GET_CIG_RM_HANDLE(pCigCtx), refTime); + + /* Adjust offset make sure CisOffMaxUsec shall be less than + * (connInterval – ((NSE – 1) × Sub_Interval + MPTM + T_IFS + MPTS + T_MSS)) */ + while (pCisCtx->offsetUsec >= (LCTR_CONN_IND_US(pCtx->connInterval) - (pCisCtx->nse * pCisCtx->subIntervUsec - pLctrRtCfg->cisSubEvtSpaceDelay))) + { + pCisCtx->offsetUsec -= LCTR_CONN_IND_US(pCtx->connInterval); + pCisCtx->ceRef++; + } + +#if (LL_ENABLE_TESTER) + if (llTesterCb.cisRspEnabled) + { + pCisCtx->offsetUsec = llTesterCb.cisOffMinUsec; + pCisCtx->ceRef += llTesterCb.cisCeRef; + + llTesterCb.cisRspEnabled = FALSE; + } +#endif +} + +/*************************************************************************************************/ +/*! + * \brief Calculate the next referenced connection event for CIS after first one. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static void lctrCalCeRefNotFirstCis(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + BbOpDesc_t *pConnBod = &pCtx->connBod; + lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); + uint32_t aclRefTime, cigRefTime; + bool_t result = FALSE; + 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 */ + + aclRefTime = pConnBod->dueUsec + (pCisCtx->ceRef - pCtx->eventCounter) * LCTR_CONN_IND_US(pCtx->connInterval); + + /* Find the reference event when CIS shall be transfered. */ + pCisCtx->cisCeRef = 0; + + while (result == FALSE) + { + pCisCtx->cisCeRef++; + cigRefTime = pCigCtx->cigBod.dueUsec + pCisCtx->cisCeRef * LCTR_ISO_INT_TO_US(pCigCtx->isoInterval); + + if (BbGetTargetTimeDelta(cigRefTime, aclRefTime) > 0) + { + result = TRUE; + } + } + + pCisCtx->offsetUsec = BbGetTargetTimeDelta(cigRefTime, aclRefTime); + + /* Adjust offset make sure CisOffMaxUsec shall be less than + * (connInterval – ((NSE – 1) × Sub_Interval + MPTM + T_IFS + MPTS + T_MSS)) */ + while (pCisCtx->offsetUsec >= (LCTR_CONN_IND_US(pCtx->connInterval) - (pCisCtx->nse * pCisCtx->subIntervUsec - pLctrRtCfg->cisSubEvtSpaceDelay))) + { + pCisCtx->offsetUsec -= LCTR_CONN_IND_US(pCtx->connInterval); + pCisCtx->ceRef++; + } + + if (pCigCtx->packing == LL_PACKING_SEQUENTIAL) + { + lctrCisNode_t *pTempNode = pCigCtx->list.pHead; + WSF_ASSERT(pTempNode); /* There is at least one CIS in the list. */ + + while (pTempNode) + { + lctrCisCtx_t *pTempCtx = pTempNode->pCisCtx; + + offsetUsec += pTempCtx->subIntervUsec * pTempCtx->nse; + pTempNode = pTempNode->pNext; + } + + } + else if (pCigCtx->packing == LL_PACKING_INTERLEAVED) + { + lctrCisNode_t *pTempNode = pCigCtx->list.pHead; + WSF_ASSERT(pTempNode); /* There is at least one CIS in the list. */ + + while (pTempNode) + { + lctrCisCtx_t *pTempCtx = pTempNode->pCisCtx; + + offsetUsec += pTempCtx->delayUsec; + pTempNode = pTempNode->pNext; + } + } + else + { + LL_TRACE_WARN1("Invalid packing scheme=%d", pCigCtx->packing); + } + + pCisCtx->cisSyncDelayUsec = pCisCtx->cigSyncDelayUsec - offsetUsec; + pCisCtx->offsetUsec += offsetUsec; +} + +/*************************************************************************************************/ +/*! + * \brief Check whether the value in the CIS_RSP is valid or not + * + * \param pCisCtx CIS context. + * + * \return TRUE if valid, otherwise FALSE. + */ +/*************************************************************************************************/ +static bool_t lctrCheckPeerCisRsp(lctrCisCtx_t *pCisCtx) +{ + if (lctrDataPdu.pld.cisRsp.cisOffMaxUsec < lctrDataPdu.pld.cisRsp.cisOffMinUsec) + { + return FALSE; + } + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Send CIS request. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + * \param numCis Total number of CIS in CIG. + */ +/*************************************************************************************************/ +static void lctrSendCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx, uint8_t numCis) +{ + uint8_t *pPdu; + + if ((pPdu = lctrTxCtrlPduAlloc(LL_CIS_REQ_LEN)) != NULL) + { + uint8_t *pBuf = pPdu; + + /*** Assemble control PDU ***/ + + UINT8_TO_BSTREAM (pBuf, LL_PDU_CIS_REQ); + UINT8_TO_BSTREAM (pBuf, pCisCtx->cigId); + UINT8_TO_BSTREAM (pBuf, pCisCtx->cisId); + + /* PHY_Info */ + UINT8_TO_BSTREAM (pBuf, lctrPhyToPhysBit(pCisCtx->phyMToS)); + UINT8_TO_BSTREAM (pBuf, lctrPhyToPhysBit(pCisCtx->phySToM)); + + /* SDU_Parameters */ + UINT16_TO_BSTREAM(pBuf, (pCisCtx->sduSizeMToS & 0x0FFF) | + ((pCisCtx->framing & 0x01) << 15)); /* Max_SDU_Size_M_To_S | ISOAL_PDU_Type */ + UINT16_TO_BSTREAM(pBuf, (pCisCtx->sduSizeSToM & 0x0FFF)); /* Max_SDU_Size_S_To_M */ + UINT24_TO_BSTREAM(pBuf, (pCisCtx->sduIntervalMToS & 0xFFFFF)); /* SDU_Interval_M_To_S */ + UINT24_TO_BSTREAM(pBuf, (pCisCtx->sduIntervalSToM & 0xFFFFF)); /* SDU_Interval_M_To_S */ + + /* CIS_Parameters */ + UINT16_TO_BSTREAM(pBuf, pCisCtx->localDataPdu.maxTxLen); + UINT16_TO_BSTREAM(pBuf, pCisCtx->localDataPdu.maxRxLen); + UINT8_TO_BSTREAM (pBuf, pCisCtx->nse); + UINT24_TO_BSTREAM(pBuf, pCisCtx->subIntervUsec); /* Subevent interval */ + UINT8_TO_BSTREAM (pBuf, ((pCisCtx->bnSToM & 0x0F) << 4) | + (pCisCtx->bnMToS & 0x0F)); /* BN_M_To_S */ /* BN_S_To_M */ + UINT8_TO_BSTREAM (pBuf, pCisCtx->ftMToS); + UINT8_TO_BSTREAM (pBuf, pCisCtx->ftSToM); + UINT16_TO_BSTREAM(pBuf, pCisCtx->isoInterval); + + /* CIS_Offset */ + UINT24_TO_BSTREAM(pBuf, pCisCtx->offsetUsec); /* CIS_OFFSET_MIN */ + UINT24_TO_BSTREAM(pBuf, pCisCtx->offsetUsec +#if (LL_ENABLE_TESTER) + + llTesterCb.cisOffMaxUsec +#endif + ); /* CIS_OFFSET_MAX */ + + /* ACL_Conn_Event_Count */ + UINT16_TO_BSTREAM(pBuf, pCisCtx->ceRef); /* Event counter */ + + /*** Queue for transmit ***/ + + lctrTxCtrlPduQueue(pCtx, pPdu); + } + + pCisCtx->isCisReqPend = TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Send CIS indication PDU. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static void lctrSendCisInd(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + uint8_t *pPdu; + + if ((pPdu = lctrTxCtrlPduAlloc(LL_CIS_IND_LEN)) != NULL) + { + uint8_t *pBuf = pPdu; + + /*** Assemble control PDU ***/ + + UINT8_TO_BSTREAM (pBuf, LL_PDU_CIS_IND); + UINT32_TO_BSTREAM(pBuf, pCisCtx->accessAddr); /* Access address */ + UINT24_TO_BSTREAM(pBuf, pCisCtx->offsetUsec); /* CIS offset */ + UINT24_TO_BSTREAM(pBuf, pCisCtx->cigSyncDelayUsec); /* CIG sync delay */ + UINT24_TO_BSTREAM(pBuf, pCisCtx->cisSyncDelayUsec); /* CIS sync delay */ + UINT16_TO_BSTREAM(pBuf, pCisCtx->ceRef); /* CE */ + + /*** Queue for transmit ***/ + + lctrTxCtrlPduQueue(pCtx, pPdu); + } +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/************************************************************************************************** + CIS master LLCP state machine action functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Action function for received host CIS request command. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrMstCisLlcpActHostCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); + WSF_ASSERT(pCigCtx); + + if (pCigCtx->numCisEsted == 0) + { + bool_t result = TRUE; + + /* 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"); + lctrCisStoreLocalLowResourceTerminateReason(pCisCtx); + result = FALSE; + } + + /* Check whether the BOD can be scheduled or not. */ + if ((result == TRUE) && (pCigCtx->isRmAdded == FALSE)) + { + if (!SchRmAdd(LCTR_GET_CIG_RM_HANDLE(pCigCtx), + SCH_RM_PREF_PERFORMANCE, + LCTR_ISO_INT_TO_US(pCigCtx->isoInterval), + LCTR_ISO_INT_TO_US(pCigCtx->isoInterval), + pCigCtx->cigSyncDelayUsec, NULL, lctrGetCigRefTime)) + { + LL_TRACE_WARN0("Fail to create CIS due to scheduling limitation"); + lctrCisStoreLocalLowResourceTerminateReason(pCisCtx); + result = FALSE; + } + else + { + pCigCtx->isRmAdded = TRUE; + } + } + + if (!result) + { + lctrMsgHdr_t *pTermMsg; + + /* Send SM a terminate event. */ + if ((pTermMsg = (lctrMsgHdr_t *)WsfMsgAlloc(sizeof(*pTermMsg))) != NULL) + { + pTermMsg->handle = pCisCtx->aclHandle; + pTermMsg->dispId = LCTR_DISP_CONN; + pTermMsg->event = LCTR_CONN_TERM_CIS_LOCAL_RESOURCE; + + WsfMsgSend(lmgrPersistCb.handlerId, pTermMsg); + } + return; + } + + lctrCalCeRefFirstCis(pCtx, pCisCtx); + + lctrCisInsertHead(&pCigCtx->list, pCisCtx); + } + else + { + lctrCalCeRefNotFirstCis(pCtx, pCisCtx); + + lctrCisInsertTail(&pCigCtx->list, pCisCtx); + } + + /* Each ACL may have different check CIS link termination function. */ + pCtx->checkCisTerm = lctrCheckForCisLinkTerm; + pCtx->checkCisEstAcl = lctrCheckIsCisEstAcl; + lctrCheckCisEstCisFn = lctrCheckIsCisEstCis; + + pCisCtx->aclHandle = pLctrConnMsg->createCis.hdr.handle; /* Save ACL handle to the CIS context. */ + /* Update CRCInit and supervision timeout from the ACL the CIS is on. */ + pCisCtx->crcInit = pCtx->crcInit; + pCisCtx->supTimeoutMs = pCtx->supTimeoutMs; + + lctrCisSetupChanParam(pCisCtx, pCtx->chanMask); + + lctrSendCisReq(pCtx, pCisCtx, pCigCtx->roleData.mst.numCis); + lctrCisStartLlcpTimer(pCtx, pCisCtx); +} + +/*************************************************************************************************/ +/*! + * \brief Action function for received peer LL_CIS_REJ_EXT command. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrMstCisLlcpActPeerRej(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); + WSF_ASSERT(pCigCtx); + + pCisCtx->isCisReqPend = FALSE; + lctrCisStoreLlcpPeerRejTerminateReason(pCisCtx); + + lctrMstCreateCisDone(pCisCtx); + lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_EST_FAIL); +} + +/*************************************************************************************************/ +/*! + * \brief Action function for received peer LL_CIS_RSP command. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrMstCisLlcpActPeerCisRsp(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); + WSF_ASSERT(pCigCtx); + + if (lctrCheckPeerCisRsp(pCisCtx) == FALSE) + { + /* CIS establishment fails when values in the CIS_RSP are invalid. */ + lctrSendRejectInd(pCtx, LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES, TRUE); + lctrCisStopLlcpTimer(pCtx, pCisCtx); + + pCisCtx->isCisReqPend = FALSE; + lctrCisStoreLocalLowResourceTerminateReason(pCisCtx); + lctrCisRemove(&pCigCtx->list, pCisCtx); + lctrMstCreateCisDone(pCisCtx); + + lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_EST_FAIL); + return; + } + + if (pCigCtx->isBodBuilt == FALSE) + { + WSF_ASSERT(pCisCtx->cisCeRef == 0) + + lctrMstCisBuildCigOp(pCigCtx); + } + else + { + lctrMstCisBuildCisData(pCisCtx); + } + + lctrCisSetupEncrypt(pCisCtx); + + if (pCigCtx->isBodStarted == FALSE) + { + /* Commit the BOD and calculate the offset. */ + lctrMstCisCigOpCommit(pCigCtx, pCtx, pCisCtx); + } + else + { + /* TODO */ + /* BOD is already committed, calculate the offset. */ + } + + pCisCtx->isCisReqPend = FALSE; + lctrSendCisInd(pCtx, pCisCtx); + lctrCisStopLlcpTimer(pCtx, pCisCtx); + lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_EST); +} + +/*************************************************************************************************/ +/*! + * \brief Action function for received internal LLCP response timeout. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrMstCisLlcpActRspTimeout(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); + WSF_ASSERT(pCigCtx); + + lctrCisStopLlcpTimer(pCtx, pCisCtx); + lctrCisStoreLlcpTimeoutTerminateReason(pCisCtx); + lctrCisRemove(&pCigCtx->list, pCisCtx); + lctrMstCreateCisDone(pCisCtx); + lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_EST_FAIL); +} + +/*************************************************************************************************/ +/*! + * \brief Action function for received internal LLCP reject. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrMstCisLlcpActLocalReject(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + lctrMstCreateCisDone(pCisCtx); + lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_EST_FAIL); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis_slave.c new file mode 100644 index 0000000000..133d1ba1d2 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_cis_slave.c @@ -0,0 +1,508 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer connected isochronous stream slave state machine action routines. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_cis_slave.h" +#include "lhci_api.h" +#include "sch_api.h" +#include "sch_api_ble.h" +#include "wsf_trace.h" +#include "wsf_assert.h" +#include "wsf_math.h" +#include "util/bstream.h" +#include + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Check if CIS request parameters are in range or not. + * + * \param pCtx ACL connection context. + * \param pCisCtx CIS connection context. + * \param pCisReq CIS request parameter. + * + * \return Status error code. + */ +/*************************************************************************************************/ +static uint8_t LctrCheckCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx, const lctrCisReq_t *pCisReq) +{ + if ((pCisReq->isoInterval < LL_MIN_ISO_INTERV) || + (pCisReq->isoInterval > LL_MAX_ISO_INTERV) || + (pCisReq->nse > LL_MAX_CIS_NSE) || + (pCisReq->framing > LL_MAX_ISOAL_PDU_TYPE) || + (pCisReq->sduSizeMToS > LL_MAX_SDU_SIZE) || + (pCisReq->sduSizeSToM > LL_MAX_SDU_SIZE) || + (pCisReq->sduIntervalMToS > LL_MAX_SDU_INTERV) || + (pCisReq->sduIntervalSToM > LL_MAX_SDU_INTERV) || + (pCisReq->plMToS > LL_MAX_CIS_PL) || + (pCisReq->plSToM > LL_MAX_CIS_PL) || + (pCisReq->phyMToS > (1 << LL_MAX_CIS_PHY_BIT)) || + (pCisReq->phySToM > (1 << LL_MAX_CIS_PHY_BIT)) || + (pCisReq->ftMToS < LL_MIN_CIS_FT) || + (pCisReq->ftMToS > LL_MAX_CIS_FT) || + (pCisReq->ftSToM < LL_MIN_CIS_FT) || + (pCisReq->ftSToM > LL_MAX_CIS_FT) || + (pCisReq->bnMToS > LL_MAX_CIS_BN) || + (pCisReq->bnSToM > LL_MAX_CIS_BN)) + { + LL_TRACE_WARN0("LctrCheckCisReq: invalid parameters, parameter out of range"); + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + + /* CisOffMaxUsec shall be greater than or equal to CIS_Offset_Min */ + if (pCisReq->cisOffMaxUsec < pCisReq->cisOffMinUsec) + { + LL_TRACE_WARN0("LctrCheckCisReq: invalid parameters, cisOffMaxUsec shall be greater than cisOffMinUsec"); + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + + + /* CisOffMaxUsec shall be less than (connInterval – ((NSE – 1) × Sub_Interval + MPTM + T_IFS + MPTS + T_MSS)) */ + if (pCisReq->cisOffMaxUsec > (LCTR_CONN_IND_US(pCtx->connInterval) - (pCisReq->nse * pCisReq->subIntervUsec - pLctrRtCfg->cisSubEvtSpaceDelay))) + { + LL_TRACE_WARN0("LctrCheckCisReq: invalid parameters, cisOffMaxUsec is too big"); + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Send CIS response PDU. + * + * \param pCtx Connection context. + * \param opcode PDU Opcode. + */ +/*************************************************************************************************/ +static void lctrSendCisRspPdu(lctrConnCtx_t *pCtx, uint8_t opcode) +{ + uint8_t *pPdu; + + if ((pPdu = lctrTxCtrlPduAlloc(LL_CIS_RSP_LEN)) != NULL) + { + uint8_t *pBuf = pPdu; + uint32_t cisOffMinUsec = lctrDataPdu.pld.cisReq.cisOffMinUsec; + uint32_t cisOffMaxUsec = lctrDataPdu.pld.cisReq.cisOffMaxUsec; + uint16_t ceRef = lctrDataPdu.pld.cisReq.ceRef; + + if (cisOffMinUsec != cisOffMaxUsec) + { + cisOffMinUsec = WSF_MAX(cisOffMinUsec, pCtx->connBod.minDurUsec + BbGetSchSetupDelayUs()); + + if (cisOffMinUsec > cisOffMaxUsec) + { + /* Cannot schedule the CIS. */ + LL_TRACE_WARN1("lctrSendCisRspPdu: Proposed offset cannot be scheduled within cisOffMaxUsec=%d", cisOffMaxUsec); + lctrSendRejectInd(pCtx, LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE, TRUE); + return; + } + } + + /*** Assemble control PDU ***/ + + UINT8_TO_BSTREAM (pBuf, opcode); + + #if (LL_ENABLE_TESTER) + if (llTesterCb.cisRspEnabled) + { + cisOffMinUsec = llTesterCb.cisOffMinUsec; + cisOffMaxUsec = llTesterCb.cisOffMaxUsec; + ceRef = llTesterCb.cisCeRef; + + llTesterCb.cisRspEnabled = FALSE; + } + #endif + UINT24_TO_BSTREAM (pBuf, cisOffMinUsec); + UINT24_TO_BSTREAM (pBuf, cisOffMaxUsec); + UINT16_TO_BSTREAM (pBuf, ceRef); + + /*** Queue for transmit ***/ + + lctrTxCtrlPduQueue(pCtx, pPdu); + } +} + +/*************************************************************************************************/ +/*! + * \brief Send CIS response. + * + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +static void lctrSendCisRsp(lctrConnCtx_t *pCtx) +{ + lctrSendCisRspPdu(pCtx, LL_PDU_CIS_RSP); +} + +/*************************************************************************************************/ +/*! + * \brief Notify host of peer CIS request event. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static void lctrNotifyHostCisReq(lctrCisCtx_t *pCisCtx) +{ + LlCisReqInd_t evt = + { + .hdr = + { + .param = pCisCtx->cisHandle, + .event = LL_CIS_REQ_IND, + .status = LL_SUCCESS + } + }; + + evt.aclHandle = pCisCtx->aclHandle; + evt.cisHandle = pCisCtx->cisHandle; + evt.cigId = pCisCtx->cigId; + evt.cisId = pCisCtx->cisId; + + LL_TRACE_INFO1("### LlEvent ### LL_CIS_REQ_IND, cisHandle=%u", pCisCtx->cisHandle); + + bool_t evtSent = LmgrSendEvent((LlEvt_t *)&evt); + + if (!evtSent) + { + LlRejectCisReq(pCisCtx->cisHandle, LL_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE); + LL_TRACE_WARN1("Host event masked; reply with reason=UNSUPPORTED_REMOTE_FEATURE, cisHandle=%u", pCisCtx->cisHandle); + } +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/************************************************************************************************** + CIS slave LLCP state machine action functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Action function for received peer CIS request. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrSlvCisLlcpActPeerCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); + + WSF_ASSERT(pCigCtx); + + if (LctrCheckCisReq(pCtx, pCisCtx, &lctrDataPdu.pld.cisReq) != LL_SUCCESS) + { + lctrSendRejectInd(pCtx, LL_ERROR_CODE_INVALID_LMP_PARAMS, TRUE); + lctrFreeCisCtx(pCisCtx); + LL_TRACE_WARN1("Invalid CIS request parameters; reply with reason=INVALID_LMP_PARAMS, cisHandle=%u", pCisCtx->cisHandle); + return; + } + + if ((lmgrCb.features & LL_FEAT_ISO_HOST_SUPPORT) == 0) + { + lctrSendRejectInd(pCtx, LL_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE, TRUE); + lctrFreeCisCtx(pCisCtx); + LL_TRACE_WARN0("Host did not set ISO channel support"); + return; + } + + lctrCisStorePeerCisReq(pCtx, pCisCtx); + + lctrNotifyHostCisReq(pCisCtx); +} + +/*************************************************************************************************/ +/*! + * \brief Action function for received reject peer CIS request. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrSlvCisLlcpActRejCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + lctrSendRejectInd(pCtx, pLctrConnMsg->rejCisReq.reason, TRUE); + + lctrCleanupCtx(pCisCtx); +} + +/*************************************************************************************************/ +/*! + * \brief Action function for received accept peer CIS request. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrSlvCisLlcpActAcpCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + lctrSendCisRsp(pCtx); + lctrCisStartLlcpTimer(pCtx, pCisCtx); +} + +/*************************************************************************************************/ +/*! + * \brief Action function for received peer CIS indication. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrSlvCisLlcpActPeerCisInd(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + pCisCtx->accessAddr = lctrDataPdu.pld.cisInd.accessAddr; + pCisCtx->ceRef = lctrDataPdu.pld.cisInd.ceRef; + pCisCtx->crcInit = pCtx->crcInit; + pCisCtx->supTimeoutMs = pCtx->supTimeoutMs; + pCisCtx->offsetUsec = lctrDataPdu.pld.cisInd.cisOffUsec; + pCisCtx->cigSyncDelayUsec = lctrDataPdu.pld.cisInd.cigSyncDelayUsec; + pCisCtx->cisSyncDelayUsec = lctrDataPdu.pld.cisInd.cisSyncDelayUsec; + + lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); + + WSF_ASSERT(pCigCtx); + + if (pCigCtx->isBodBuilt == FALSE) + { + pCigCtx->cigSyncDelayUsec = lctrDataPdu.pld.cisInd.cigSyncDelayUsec; + pCigCtx->isoInterval = pCisCtx->isoInterval; /* All CISs have the same ISO interval. */ + + lctrCisSetupChanParam(pCisCtx, pCtx->chanMask); + lctrCisInsertHead(&pCigCtx->list, pCisCtx); + lctrSlvCisBuildCigOp(pCigCtx); + lctrCisSetupEncrypt(pCisCtx); + } + else + { + lctrCisSetupChanParam(pCisCtx, pCtx->chanMask); + lctrCisInsertTail(&pCigCtx->list, pCisCtx); + lctrSlvCisBuildCisData(pCisCtx); + lctrCisSetupEncrypt(pCisCtx); + } + + /* Calculate the offset for the stream. */ + if (pCisCtx->ceRef - pCtx->eventCounter >= 0x8000) + { + LL_TRACE_INFO0("lctrSlvCisLlcpActPeerCisInd, first anchor in the past"); + } + else + { + LL_TRACE_INFO0("lctrSlvCisLlcpActPeerCisInd, first anchor in the future"); + pCisCtx->data.slv.anchorOffsetUsec = (pCisCtx->ceRef - pCtx->eventCounter) * LCTR_CONN_IND_US(pCtx->connInterval) + pCisCtx->offsetUsec; + } + + if (pCigCtx->isBodStarted == FALSE) + { + pCigCtx->packing = LL_PACKING_SEQUENTIAL; /* One stream is the same as sequential. */ + + /* Commit BOD */ + lctrSlvCisCigOpCommit(pCigCtx, pCtx, pCisCtx); + pCisCtx->cisCeRef = 0; + } + else + { + /* Find the CIS reference event when CIS shall start transfer the CIS. */ + bool_t result = FALSE; + uint32_t aclRefTime, cigRefTime; + + aclRefTime = pCtx->data.slv.anchorPointUsec + (pCisCtx->ceRef - pCtx->eventCounter + 1) * LCTR_CONN_IND_US(pCtx->connInterval); /* Reference from the */ + pCisCtx->cisCeRef = 0; + + while (result == FALSE) + { + pCisCtx->cisCeRef++; + + if (pCigCtx->roleData.slv.cigEvtCounter == 0) + { + /* BOD is not started yet. */ + cigRefTime = pCigCtx->roleData.slv.anchorPointUsec + pCisCtx->cisCeRef * LCTR_ISO_INT_TO_US(pCigCtx->isoInterval); + } + else + { + cigRefTime = pCigCtx->roleData.slv.anchorPointUsec + (pCisCtx->cisCeRef + 1) * LCTR_ISO_INT_TO_US(pCigCtx->isoInterval); + } + + if (cigRefTime > aclRefTime) + { + result = TRUE; + } + } + + uint8_t cisCount = lctrCisGetListCount(&pCigCtx->list); + + /* Set packing scheme once when the second CISs is added, since all the rest follow the same scheme. */ + if (cisCount >= 2) + { + lctrCisCtx_t *pHeadCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + + if (cisCount == 2) + { + /* 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) + { + pCigCtx->packing = LL_PACKING_INTERLEAVED; + } + } + + /* Adjust delayUsec for two or more interleaved CISs, one for the original last one and one for the new last one. */ + if (pCigCtx->packing == LL_PACKING_INTERLEAVED) + { + lctrCisCtx_t *pCurCisCtx = lctrCisGetHeadCis(&pCigCtx->list); /* original last CIS */ + lctrCisCtx_t *pNextCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCurCisCtx); /* new last last CIS */ + + uint32_t prevDelayUsec = 0; + + while (cisCount > 2) + { + prevDelayUsec += pCurCisCtx->delayUsec; + pCurCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCurCisCtx); /* original last CIS */ + pNextCisCtx = lctrCisGetNextCis(&pCigCtx->list, pNextCisCtx); /* new last last CIS */ + + cisCount--; + } + + pCurCisCtx->delayUsec = pCisCtx->data.slv.anchorOffsetUsec + pCtx->data.slv.anchorPointUsec + LCTR_CONN_IND_US(pCtx->connInterval) - cigRefTime - prevDelayUsec; + pNextCisCtx->delayUsec = cigRefTime + pHeadCisCtx->subIntervUsec - (pCisCtx->data.slv.anchorOffsetUsec + pCtx->data.slv.anchorPointUsec + LCTR_CONN_IND_US(pCtx->connInterval)); + + LL_TRACE_ERR2("lctrSlvCisLlcpActPeerCisInd, handle=%d pCurCisCtx->delayUsec=%d", pCurCisCtx->cisHandle, pCurCisCtx->delayUsec); + LL_TRACE_ERR2("lctrSlvCisLlcpActPeerCisInd, handle=%d pNextCisCtx->delayUsec=%d", pNextCisCtx->cisHandle, pNextCisCtx->delayUsec); + } + else + { + lctrCisCtx_t *pPreCisCtx = lctrCisGetPreCis(&pCigCtx->list, pCisCtx); + lctrCisCtx_t *pTempCisCtx = pPreCisCtx; + + uint32_t prevDelayUsec = 0; + + while (cisCount > 2) + { + pTempCisCtx = lctrCisGetPreCis(&pCigCtx->list, pTempCisCtx); /* new last last CIS */ + prevDelayUsec += pTempCisCtx->nextCisOffsetUsec; + cisCount--; + } + + pPreCisCtx->nextCisOffsetUsec = pCisCtx->cigSyncDelayUsec - pCisCtx->cisSyncDelayUsec - prevDelayUsec; + + LL_TRACE_ERR1("lctrSlvCisLlcpActPeerCisInd, pPreCisCtx->nextCisOffsetUsec=%d", pPreCisCtx->nextCisOffsetUsec); + } + } + + + /* BOD is already committed, do nothing. */ + } + + lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_EST); +} + +/*************************************************************************************************/ +/*! + * \brief Action function for store peer CIS request. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisStorePeerCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + memcpy(&pCisCtx->data.slv.cisReq, &lctrDataPdu.pld.cisReq, sizeof(lctrCisReq_t)); + + pCisCtx->cisId = lctrDataPdu.pld.cisReq.cisId; + pCisCtx->phyMToS = lctrPhysBitToPhy(lctrDataPdu.pld.cisReq.phyMToS); + pCisCtx->phySToM = lctrPhysBitToPhy(lctrDataPdu.pld.cisReq.phySToM); + pCisCtx->framing = lctrDataPdu.pld.cisReq.framing; + pCisCtx->sduSizeMToS = lctrDataPdu.pld.cisReq.sduSizeMToS; + pCisCtx->sduSizeSToM = lctrDataPdu.pld.cisReq.sduSizeSToM; + pCisCtx->sduIntervalMToS = lctrDataPdu.pld.cisReq.sduIntervalMToS; + pCisCtx->sduIntervalSToM = lctrDataPdu.pld.cisReq.sduIntervalSToM; + pCisCtx->localDataPdu.maxRxLen = lctrDataPdu.pld.cisReq.plMToS; + pCisCtx->localDataPdu.maxTxLen = lctrDataPdu.pld.cisReq.plSToM; + pCisCtx->nse = lctrDataPdu.pld.cisReq.nse; + pCisCtx->subIntervUsec = lctrDataPdu.pld.cisReq.subIntervUsec; + pCisCtx->bnMToS = lctrDataPdu.pld.cisReq.bnMToS; + pCisCtx->bnSToM = lctrDataPdu.pld.cisReq.bnSToM; + pCisCtx->ftMToS = lctrDataPdu.pld.cisReq.ftMToS; + pCisCtx->ftSToM = lctrDataPdu.pld.cisReq.ftSToM; + pCisCtx->isoInterval = lctrDataPdu.pld.cisReq.isoInterval; + pCisCtx->delayUsec = pCisCtx->subIntervUsec; /* If LL_PACKING_INTERLEAVED, delayUsec will be updated in lctrSlvCisLlcpActPeerCisInd */ +} + +/*************************************************************************************************/ +/*! + * \brief Action function for received peer CIS rejection. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrSlvCisLlcpActPeerCisRej(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + pCisCtx->reason = lctrDataPdu.pld.rejInd.reason; + + lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_EST_FAIL); +} + +/*************************************************************************************************/ +/*! + * \brief Action function for internal received peer CIS request. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrSlvCisLlcpActIntPeerCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + if (LctrCheckCisReq(pCtx, pCisCtx, &pCisCtx->data.slv.cisReq) != LL_SUCCESS) + { + lctrSendRejectInd(pCtx, LL_ERROR_CODE_INVALID_LMP_PARAMS, TRUE); + lctrFreeCisCtx(pCisCtx); + LL_TRACE_ERR1("Invalid CIS request parameters; reply with reason=INVALID_LMP_PARAMS, cisHandle=%u", pCisCtx->cisHandle); + return; + } + + if ((lmgrCb.features & LL_FEAT_ISO_HOST_SUPPORT) == 0) + { + lctrSendRejectInd(pCtx, LL_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE, TRUE); + lctrFreeCisCtx(pCisCtx); + LL_TRACE_WARN0("Host did not set ISO channel support"); + return; + } + + lctrCigCtx_t *pCigCtx; + if ((pCigCtx = lctrFindCigById(lctrDataPdu.pld.cisReq.cigId)) == NULL) + { + if ((pCigCtx = lctrAllocCigCtx(lctrDataPdu.pld.cisReq.cigId)) == NULL) + { + lctrSendRejectInd(pCtx, LL_ERROR_CODE_LIMIT_REACHED, TRUE); + lctrFreeCisCtx(pCisCtx); + LL_TRACE_WARN0("Not able to allocate a CIG context"); + return; + } + } + + lctrNotifyHostCisReq(pCisCtx); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn.c index 4e42d52172..8456c14f02 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn.c @@ -1,32 +1,35 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller connection state machine action routines. + * \file + * + * \brief Link layer controller connection state machine action routines. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "ll_defs.h" #include "lctr_int_conn.h" #include "lctr_int_adv_slave.h" #include "lctr_int_adv_master_ae.h" #include "sch_api.h" #include "sch_api_ble.h" #include "lmgr_api_conn.h" +#include "pal_radio.h" #include "wsf_assert.h" #include "wsf_math.h" #include "wsf_msg.h" @@ -39,9 +42,6 @@ Macros **************************************************************************************************/ -/*! \brief Use special token to indicate no notification is required. */ -#define LCTR_RESET_TERM_REASON 0xFF - /*! \brief Valid feature bits applicable between controllers */ #define LCTR_FEAT_PEER_MASK (LL_FEAT_ENCRYPTION | \ LL_FEAT_CONN_PARAM_REQ_PROC | \ @@ -64,16 +64,17 @@ LL_FEAT_CIS_MASTER_ROLE | \ LL_FEAT_CIS_SLAVE_ROLE | \ LL_FEAT_ISO_BROADCASTER | \ - LL_FEAT_ISO_SYNC) + LL_FEAT_ISO_SYNC | \ + LL_FEAT_ISO_HOST_SUPPORT | \ + LL_FEAT_POWER_CONTROL_REQUEST | \ + LL_FEAT_POWER_CHANGE_IND | \ + LL_FEAT_PATH_LOSS_MONITOR) -/*! \brief Used feature bitmask, i.e. FeatureSet[0]. */ -#define LCTR_USED_FEAT_SET_MASK 0xFF - -/*! \brief Used feature bitmask, i.e. FeatureSet[0]. */ -#define LCTR_USED_FEAT_SET_MASK 0xFF +/*! \brief Used feature bitmask. */ +#define LCTR_USED_FEAT_SET_MASK 0x000000FFFF /*! \brief Features bits mask over the air */ -#define LCTR_OTA_FEAT_MASK (~LL_FEAT_REMOTE_PUB_KEY_VALIDATION & LL_FEAT_ALL_MASK) +#define LCTR_OTA_FEAT_MASK (~LL_FEAT_REMOTE_PUB_KEY_VALIDATION & LCTR_FEAT_PEER_MASK) /*************************************************************************************************/ /*! @@ -138,8 +139,6 @@ static uint8_t lctrComputeConnSca(lctrConnCtx_t *pCtx) * \param localRpa Local RPA. * \param status Status. * \param usedChSel Used channel selection algorithm. - * - * \return None. */ /*************************************************************************************************/ void lctrNotifyHostConnectInd(uint16_t handle, uint8_t role, lctrConnInd_t *pConnInd, @@ -208,8 +207,6 @@ void lctrNotifyHostConnectInd(uint16_t handle, uint8_t role, lctrConnInd_t *pCon * \brief Store connection update connection specification. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreConnUpdateSpec(lctrConnCtx_t *pCtx) @@ -222,8 +219,6 @@ void lctrStoreConnUpdateSpec(lctrConnCtx_t *pCtx) * \brief Store connect update parameters. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreConnUpdate(lctrConnCtx_t *pCtx) @@ -243,8 +238,6 @@ void lctrStoreConnUpdate(lctrConnCtx_t *pCtx) * * \param pCtx Connection context. * \param status Status. - * - * \return None. */ /*************************************************************************************************/ void lctrNotifyHostConnUpdateInd(lctrConnCtx_t *pCtx, uint8_t status) @@ -281,8 +274,6 @@ void lctrNotifyHostConnUpdateInd(lctrConnCtx_t *pCtx, uint8_t status) * \brief Store channel map parameters. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreChanMapUpdate(lctrConnCtx_t *pCtx) @@ -295,8 +286,6 @@ void lctrStoreChanMapUpdate(lctrConnCtx_t *pCtx) * \brief Send channel map update indication PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendChanMapUpdateInd(lctrConnCtx_t *pCtx) @@ -339,8 +328,6 @@ void lctrSendChanMapUpdateInd(lctrConnCtx_t *pCtx) * \brief Store channel map parameters. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreChanMap(lctrConnCtx_t *pCtx) @@ -360,8 +347,6 @@ void lctrStoreChanMap(lctrConnCtx_t *pCtx) * \brief Send feature request PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendFeatureReq(lctrConnCtx_t *pCtx) @@ -389,8 +374,6 @@ void lctrSendFeatureReq(lctrConnCtx_t *pCtx) * \brief Send feature response PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendFeatureRsp(lctrConnCtx_t *pCtx) @@ -405,9 +388,9 @@ void lctrSendFeatureRsp(lctrConnCtx_t *pCtx) UINT8_TO_BSTREAM(pBuf, LL_PDU_FEATURE_RSP); - uint64_t featSet = (pCtx->usedFeatSet & LCTR_USED_FEAT_SET_MASK) | /* FeatureSet[0] used by master and slave */ - (lmgrCb.features & ~LCTR_USED_FEAT_SET_MASK); /* FeatureSet[1..7] used by sender */ - UINT64_TO_BSTREAM(pBuf, (featSet & LCTR_OTA_FEAT_MASK)); /* Only send valid features bits between controllers. */ + uint64_t featSet = (pCtx->usedFeatSet & LCTR_USED_FEAT_SET_MASK) | /* FeatureSet[0] used by master and slave */ + (lmgrCb.features & ~LCTR_USED_FEAT_SET_MASK); /* FeatureSet[1..7] used by sender */ + UINT64_TO_BSTREAM(pBuf, (featSet & LCTR_OTA_FEAT_MASK)); /* Only send valid features bits between controllers. */ /*** Queue for transmit. ***/ @@ -420,8 +403,6 @@ void lctrSendFeatureRsp(lctrConnCtx_t *pCtx) * \brief Store remote feature data. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreUsedFeatures(lctrConnCtx_t *pCtx) @@ -441,8 +422,6 @@ void lctrStoreUsedFeatures(lctrConnCtx_t *pCtx) * \brief Send version indication PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendVersionInd(lctrConnCtx_t *pCtx) @@ -481,8 +460,6 @@ void lctrSendVersionInd(lctrConnCtx_t *pCtx) * \brief Store remote version data. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreRemoteVer(lctrConnCtx_t *pCtx) @@ -499,8 +476,6 @@ void lctrStoreRemoteVer(lctrConnCtx_t *pCtx) * \brief Notify host of read remote version confirm. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrNotifyHostReadRemoteVerCnf(lctrConnCtx_t *pCtx) @@ -533,8 +508,6 @@ void lctrNotifyHostReadRemoteVerCnf(lctrConnCtx_t *pCtx) * \brief Send terminate indication PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendTerminateInd(lctrConnCtx_t *pCtx) @@ -562,8 +535,6 @@ void lctrSendTerminateInd(lctrConnCtx_t *pCtx) * \brief Notify host of disconnect indication. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrNotifyHostDisconnectInd(lctrConnCtx_t *pCtx) @@ -603,8 +574,6 @@ void lctrNotifyHostDisconnectInd(lctrConnCtx_t *pCtx) * \brief Store LLCP termination reason. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreTerminateReason(lctrConnCtx_t *pCtx) @@ -620,8 +589,6 @@ void lctrStoreTerminateReason(lctrConnCtx_t *pCtx) * \brief Store host initiated disconnect termination reason. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreDisconnectReason(lctrConnCtx_t *pCtx) @@ -634,8 +601,6 @@ void lctrStoreDisconnectReason(lctrConnCtx_t *pCtx) * \brief Store connection failed to establish termination reason. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreConnFailEstablishTerminateReason(lctrConnCtx_t *pCtx) @@ -648,8 +613,6 @@ void lctrStoreConnFailEstablishTerminateReason(lctrConnCtx_t *pCtx) * \brief Store LLCP timeout termination reason. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreLlcpTimeoutTerminateReason(lctrConnCtx_t *pCtx) @@ -662,8 +625,6 @@ void lctrStoreLlcpTimeoutTerminateReason(lctrConnCtx_t *pCtx) * \brief Store reset termination reason. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreResetTerminateReason(lctrConnCtx_t *pCtx) @@ -676,8 +637,6 @@ void lctrStoreResetTerminateReason(lctrConnCtx_t *pCtx) * \brief Store invalid request termination reason. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreInstantPassedTerminateReason(lctrConnCtx_t *pCtx) @@ -690,8 +649,6 @@ void lctrStoreInstantPassedTerminateReason(lctrConnCtx_t *pCtx) * \brief Store invalid request termination reason. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreMicFailedTerminateReason(lctrConnCtx_t *pCtx) @@ -704,8 +661,6 @@ void lctrStoreMicFailedTerminateReason(lctrConnCtx_t *pCtx) * \brief Store connection parameter request. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreConnParamReq(lctrConnCtx_t *pCtx) @@ -718,8 +673,6 @@ void lctrStoreConnParamReq(lctrConnCtx_t *pCtx) * \brief Store connection parameter request. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreConnParamRsp(lctrConnCtx_t *pCtx) @@ -779,8 +732,6 @@ void lctrStoreConnParamRsp(lctrConnCtx_t *pCtx) * \brief Store connection parameter connection specification. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreConnParamSpec(lctrConnCtx_t *pCtx) @@ -796,8 +747,6 @@ void lctrStoreConnParamSpec(lctrConnCtx_t *pCtx) * \param opcode Pdu Opcode. * \param pConnSpec Connection specification. * \param prefPeriod Preferred periodicity. - * - * \return None. */ /*************************************************************************************************/ static void lctrSendConnParamPdu(lctrConnCtx_t *pCtx, uint8_t opcode, LlConnSpec_t *pConnSpec, uint8_t prefPeriod) @@ -837,8 +786,6 @@ static void lctrSendConnParamPdu(lctrConnCtx_t *pCtx, uint8_t opcode, LlConnSpec * \brief Send connection parameter request PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendConnParamReq(lctrConnCtx_t *pCtx) @@ -861,7 +808,10 @@ void lctrSendConnParamReq(lctrConnCtx_t *pCtx) } #endif - lctrSendConnParamPdu(pCtx, LL_PDU_CONN_PARAM_REQ, &pCtx->connUpdSpec, LCTR_US_TO_CONN_IND(SchRmPreferredPeriodUsec())); + uint8_t prefPeriod = (LCTR_US_TO_CONN_IND(SCH_RM_PREF_PER_USEC) <= pCtx->connUpdSpec.connIntervalMax) ? + LCTR_US_TO_CONN_IND(SCH_RM_PREF_PER_USEC) + : LCTR_US_TO_CONN_IND(SCH_RM_PREF_PER_USEC_LOWEST); + lctrSendConnParamPdu(pCtx, LL_PDU_CONN_PARAM_REQ, &pCtx->connUpdSpec, prefPeriod); } /*************************************************************************************************/ @@ -869,8 +819,6 @@ void lctrSendConnParamReq(lctrConnCtx_t *pCtx) * \brief Send connection parameter response PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendConnParamRsp(lctrConnCtx_t *pCtx) @@ -889,8 +837,6 @@ void lctrSendConnParamRsp(lctrConnCtx_t *pCtx) * \brief Notify host of remote connection parameter change indication. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrNotifyHostConnParamInd(lctrConnCtx_t *pCtx) @@ -913,7 +859,7 @@ void lctrNotifyHostConnParamInd(lctrConnCtx_t *pCtx) return; } - if ((pCtx->connParam.connIntervalMin != pCtx->connInterval) || // TODO compare to original conn min/max? + if ((pCtx->connParam.connIntervalMin != pCtx->connInterval) || /* TODO compare to original conn min/max? */ (pCtx->connParam.connIntervalMax != pCtx->connInterval) || (pCtx->connParam.connLatency != pCtx->maxLatency) || (LCTR_CONN_IND_TO_MS(pCtx->connParam.supTimeout) != pCtx->supTimeoutMs)) @@ -955,8 +901,6 @@ void lctrNotifyHostConnParamInd(lctrConnCtx_t *pCtx) * \brief Store local data length parameters. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreLocalDataLength(lctrConnCtx_t *pCtx) @@ -983,8 +927,6 @@ void lctrStoreLocalDataLength(lctrConnCtx_t *pCtx) * * \param pCtx Connection context. * \param opcode PDU opcode. - * - * \return None. */ /*************************************************************************************************/ static void lctrSendDataLengthPdu(lctrConnCtx_t *pCtx, uint8_t opcode) @@ -1003,8 +945,9 @@ 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 2120. */ - if (!(pCtx->usedFeatSet & LL_FEAT_LE_CODED_PHY)) + /* If LL_FEAT_LE_CODED_PHY is not supported, maxRxTime and maxTxTime can not be more than 2128.*/ + if (!pCtx->featExchFlag || + !(pCtx->usedFeatSet & LL_FEAT_LE_CODED_PHY)) { maxRxTime = WSF_MIN(pCtx->localDataPdu.maxRxTime, LL_MAX_DATA_TIME_ABS_MAX_1M); maxTxTime = WSF_MIN(pCtx->localDataPdu.maxTxTime, LL_MAX_DATA_TIME_ABS_MAX_1M); @@ -1037,8 +980,6 @@ static void lctrSendDataLengthPdu(lctrConnCtx_t *pCtx, uint8_t opcode) * \brief Send data length request PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendDataLengthReq(lctrConnCtx_t *pCtx) @@ -1051,8 +992,6 @@ void lctrSendDataLengthReq(lctrConnCtx_t *pCtx) * \brief Send data length response PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendDataLengthRsp(lctrConnCtx_t *pCtx) @@ -1065,8 +1004,6 @@ void lctrSendDataLengthRsp(lctrConnCtx_t *pCtx) * \brief Store remote data length parameters. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreRemoteDataLength(lctrConnCtx_t *pCtx) @@ -1086,8 +1023,9 @@ 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 2120. */ - if (!(pCtx->usedFeatSet & LL_FEAT_LE_CODED_PHY)) + /* If LL_FEAT_LE_CODED_PHY is not supported, maxRxTime and maxTxTime can not be more than 2128. */ + if (!pCtx->featExchFlag || + !(pCtx->usedFeatSet & LL_FEAT_LE_CODED_PHY)) { maxRxTime = WSF_MIN(pCtx->localDataPdu.maxRxTime, LL_MAX_DATA_TIME_ABS_MAX_1M); maxTxTime = WSF_MIN(pCtx->localDataPdu.maxTxTime, LL_MAX_DATA_TIME_ABS_MAX_1M); @@ -1129,8 +1067,6 @@ void lctrStoreRemoteDataLength(lctrConnCtx_t *pCtx) * * \param pCtx Connection context. * \param status Status. - * - * \return None. */ /*************************************************************************************************/ void lctrNotifyHostDataLengthInd(lctrConnCtx_t *pCtx, uint8_t status) @@ -1164,8 +1100,6 @@ void lctrNotifyHostDataLengthInd(lctrConnCtx_t *pCtx, uint8_t status) * \brief Send set minimum number of used channels indication PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrSendSetMinUsedChanPdu(lctrConnCtx_t *pCtx) @@ -1193,8 +1127,6 @@ static void lctrSendSetMinUsedChanPdu(lctrConnCtx_t *pCtx) * \brief Send set minimum number of used channels indication PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendSetMinUsedChanInd(lctrConnCtx_t *pCtx) @@ -1211,8 +1143,6 @@ void lctrSendSetMinUsedChanInd(lctrConnCtx_t *pCtx) * \brief Store remote minimum number of used channels parameters. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreSetMinUsedChan(lctrConnCtx_t *pCtx) @@ -1236,8 +1166,6 @@ void lctrStoreSetMinUsedChan(lctrConnCtx_t *pCtx) * * \param pCtx Connection context. * \param opcode PDU opcode. - * - * \return None. */ /*************************************************************************************************/ static void lctrSendPeerScaReqPdu(lctrConnCtx_t *pCtx, uint8_t opcode) @@ -1262,8 +1190,6 @@ static void lctrSendPeerScaReqPdu(lctrConnCtx_t *pCtx, uint8_t opcode) * \brief Update action for sca processing. * * \param pCtx Connection Context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreScaAction(lctrConnCtx_t *pCtx) @@ -1276,8 +1202,6 @@ void lctrStoreScaAction(lctrConnCtx_t *pCtx) * \brief Send peer SCA request. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendPeerScaReq(lctrConnCtx_t *pCtx) @@ -1312,8 +1236,6 @@ void lctrSendPeerScaReq(lctrConnCtx_t *pCtx) * * \param pCtx Connection context. * \param opcode PDU opcode. - * - * \return None. */ /*************************************************************************************************/ static void lctrSendPeerScaRspPdu(lctrConnCtx_t *pCtx, uint8_t opcode) @@ -1338,8 +1260,6 @@ static void lctrSendPeerScaRspPdu(lctrConnCtx_t *pCtx, uint8_t opcode) * \brief Send peer SCA response. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendPeerScaRsp(lctrConnCtx_t *pCtx) @@ -1352,8 +1272,6 @@ void lctrSendPeerScaRsp(lctrConnCtx_t *pCtx) * \brief Store peer SCA. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStorePeerSca(lctrConnCtx_t *pCtx) @@ -1373,8 +1291,6 @@ void lctrStorePeerSca(lctrConnCtx_t *pCtx) * \brief Notify host of peer SCA request confirmation. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrNotifyHostPeerScaCnf(lctrConnCtx_t *pCtx) @@ -1405,8 +1321,6 @@ void lctrNotifyHostPeerScaCnf(lctrConnCtx_t *pCtx) * \brief Send unknown response PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendUnknownRsp(lctrConnCtx_t *pCtx) @@ -1435,8 +1349,6 @@ void lctrSendUnknownRsp(lctrConnCtx_t *pCtx) * \param pCtx Connection context. * \param reason Reason code. * \param forceRejectExtInd TRUE to force using LL_REJECT_EXT_IND. - * - * \return None. */ /*************************************************************************************************/ void lctrSendRejectInd(lctrConnCtx_t *pCtx, uint8_t reason, bool_t forceRejectExtInd) @@ -1488,8 +1400,6 @@ void lctrSendRejectInd(lctrConnCtx_t *pCtx, uint8_t reason, bool_t forceRejectEx * \brief Start LLCP timer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStartLlcpTimer(lctrConnCtx_t *pCtx) @@ -1512,8 +1422,6 @@ void lctrStartLlcpTimer(lctrConnCtx_t *pCtx) * \brief Stop LLCP timer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStopLlcpTimer(lctrConnCtx_t *pCtx) @@ -1529,8 +1437,6 @@ void lctrStopLlcpTimer(lctrConnCtx_t *pCtx) * \brief Start pending LLCP procedure. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStartPendingLlcp(lctrConnCtx_t *pCtx) @@ -1543,8 +1449,6 @@ void lctrStartPendingLlcp(lctrConnCtx_t *pCtx) * \brief Pause Tx data PDUs. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrPauseTxData(lctrConnCtx_t *pCtx) @@ -1558,8 +1462,6 @@ void lctrPauseTxData(lctrConnCtx_t *pCtx) * \brief Unpause Tx data PDUs. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrUnpauseTxData(lctrConnCtx_t *pCtx) @@ -1594,8 +1496,6 @@ void lctrUnpauseTxData(lctrConnCtx_t *pCtx) * \brief Check if Tx data pending. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrCheckPauseComplete(lctrConnCtx_t *pCtx) @@ -1611,8 +1511,6 @@ void lctrCheckPauseComplete(lctrConnCtx_t *pCtx) * \brief Pause Rx data PDUs. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrPauseRxData(lctrConnCtx_t *pCtx) @@ -1626,8 +1524,6 @@ void lctrPauseRxData(lctrConnCtx_t *pCtx) * \brief Unpause Rx data PDUs. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrUnpauseRxData(lctrConnCtx_t *pCtx) @@ -1641,8 +1537,6 @@ void lctrUnpauseRxData(lctrConnCtx_t *pCtx) * \brief Store periodic advertising sync transfer parameters. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrActStorePeriodicSyncTrsf(lctrConnCtx_t *pCtx) @@ -1658,8 +1552,6 @@ void lctrActStorePeriodicSyncTrsf(lctrConnCtx_t *pCtx) * \brief Send periodic sync indication PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrActSendPeriodicSyncInd(lctrConnCtx_t *pCtx) @@ -1675,8 +1567,6 @@ void lctrActSendPeriodicSyncInd(lctrConnCtx_t *pCtx) * \brief Handle received periodic sync indication PDU. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrActReceivePeriodicSyncInd(lctrConnCtx_t *pCtx) @@ -1686,3 +1576,4 @@ void lctrActReceivePeriodicSyncInd(lctrConnCtx_t *pCtx) lctrReceivePeriodicSyncIndFn(pCtx); } } + diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn_master.c index 877b5d79f5..10283eb71e 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master connection state machine action routines. + * \file + * + * \brief Link layer controller master connection state machine action routines. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -35,8 +36,6 @@ * \brief Send connection update request PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendConnUpdateInd(lctrConnCtx_t *pCtx) @@ -59,7 +58,7 @@ void lctrSendConnUpdateInd(lctrConnCtx_t *pCtx) uint32_t interMinUsec = LCTR_CONN_IND_US(pCtx->connUpdSpec.connIntervalMin); uint32_t interMaxUsec = LCTR_CONN_IND_US(pCtx->connUpdSpec.connIntervalMax); - uint32_t durUsec = pCtx->localConnDurUsec; + uint32_t durUsec = pCtx->effConnDurUsec; uint32_t connIntervalUsec; /* Accommodate peer PreferredPeriodicity. */ @@ -83,8 +82,6 @@ void lctrSendConnUpdateInd(lctrConnCtx_t *pCtx) * \brief Reload an empty BOD with a data PDU. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrMstReloadDataPdu(lctrConnCtx_t *pCtx) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn_master_ae.c index 6244a302ad..f51c6074c3 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master connection state machine action routines. + * \file + * + * \brief Link layer controller master connection state machine action routines. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -51,7 +52,7 @@ static uint8_t lctrExtInitSetupConn(lctrExtScanCtx_t *pExtInitCtx, LlConnSpec_t uint32_t interMinUsec = LCTR_CONN_IND_US(pConnSpec->connIntervalMin); uint32_t interMaxUsec = LCTR_CONN_IND_US(pConnSpec->connIntervalMax); - uint32_t durUsec = pCtx->localConnDurUsec; + uint32_t durUsec = pCtx->effConnDurUsec; if (!SchRmAdd(LCTR_GET_CONN_HANDLE(pCtx), SCH_RM_PREF_PERFORMANCE, interMinUsec, interMaxUsec, durUsec, &connInterUsec, lctrGetConnRefTime)) { @@ -97,7 +98,6 @@ uint8_t lctrExtInitSetupInitiate(lctrExtScanCtx_t *pExtInitCtx, uint8_t peerAddr pExtInitCtx->bodTermCnt = 0; pExtInitCtx->data.init.filtPolicy = filtPolicy; pExtInitCtx->data.init.ownAddrType = ownAddrType; - pExtInitCtx->data.init.connBodLoaded = FALSE; BbStart(BB_PROT_BLE); @@ -137,8 +137,6 @@ uint8_t lctrExtInitSetupInitiate(lctrExtScanCtx_t *pExtInitCtx, uint8_t peerAddr * \brief Establish connection. * * \param pExtInitCtx Extended initiate context. - * - * \return None. */ /*************************************************************************************************/ void lctrExtInitActConnect(lctrExtScanCtx_t *pExtInitCtx) @@ -195,8 +193,6 @@ void lctrExtInitActConnect(lctrExtScanCtx_t *pExtInitCtx) * \brief Common initiate resource cleanup. * * \param pExtInitCtx Extended initiate context. - * - * \return None. */ /*************************************************************************************************/ void lctrMstExtInitCleanupOp(lctrExtScanCtx_t *pExtInitCtx) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn_past.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn_past.c index f400f3a303..4e5965808a 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn_past.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_conn_past.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller connection state machine action routines for PAST feature. + * \file + * + * \brief Link layer controller connection state machine action routines for PAST feature. + * + * Copyright (c) 2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -41,8 +42,6 @@ * * \param pCtx Connection context. * - * \return None. - * * This function is called from BOD end callback of master/slave connection. */ /*************************************************************************************************/ @@ -71,33 +70,33 @@ void lctrSendPerSyncFromScan(lctrConnCtx_t *pCtx) /* Find PEa, event counter of PE whose starting time is after CEref. */ uint16_t paEventCounter = pPerScanCtx->lastActiveEvent; - uint32_t paAnchor = pPerScanCtx->lastAnchorPoint; + uint32_t paAnchor = pPerScanCtx->lastAnchorPointUsec; uint32_t ceRefStart, ceRefEnd; /* Calculate the end time of CEref. */ ceRefStart = lctrConnGetAnchorPoint(pCtx, (pCtx->eventCounter + ceOffset)); - ceRefEnd = ceRefStart + BB_US_TO_BB_TICKS(pCtx->localConnDurUsec + BbGetSchSetupDelayUs()); + ceRefEnd = ceRefStart + pCtx->effConnDurUsec + BbGetSchSetupDelayUs(); /* paAnchor is for the first PE in the future from ceRefEnd. */ - if ((ceRefEnd - paAnchor) < LCTR_SCH_MAX_SPAN) + if (BbGetTargetTimeDelta(ceRefEnd, paAnchor) > 0) { - uint16_t numPE = (ceRefEnd - paAnchor) / pPerScanCtx->perInter + 1; + uint16_t numPE = BbGetTargetTimeDelta(ceRefEnd, paAnchor) / pPerScanCtx->perInterUsec + 1; - paAnchor += numPE * pPerScanCtx->perInter; + paAnchor += numPE * pPerScanCtx->perInterUsec; paEventCounter += numPE; } else { - uint16_t numPE = (paAnchor - ceRefEnd) / pPerScanCtx->perInter; + uint16_t numPE = BbGetTargetTimeDelta(paAnchor, ceRefEnd) / pPerScanCtx->perInterUsec; - paAnchor -= numPE * pPerScanCtx->perInter; + paAnchor -= numPE * pPerScanCtx->perInterUsec; paEventCounter -= numPE; } uint8_t offsUnits; uint8_t offsAdjust = 0; uint16_t offs; - uint32_t offsUsec = BB_TICKS_TO_US(paAnchor - ceRefStart); + uint32_t offsUsec = BbGetTargetTimeDelta(paAnchor, ceRefStart); if (offsUsec < LL_30_USEC_OFFS_MAX_USEC) { @@ -117,7 +116,7 @@ void lctrSendPerSyncFromScan(lctrConnCtx_t *pCtx) } LL_TRACE_INFO1("LL_PERIODIC_SYNC_IND from SCAN ceRef anchor point = %u", ceRefStart); - LL_TRACE_INFO1(" PA lastAnchorPoint = %u", pPerScanCtx->lastAnchorPoint); + LL_TRACE_INFO1(" PA lastAnchorPoint = %u", pPerScanCtx->lastAnchorPointUsec); LL_TRACE_INFO1(" PA REF paAnchor = %u", paAnchor); LL_TRACE_INFO1(" offsUsec = %u", offsUsec); @@ -130,7 +129,7 @@ void lctrSendPerSyncFromScan(lctrConnCtx_t *pCtx) (offsUnits << 13) | /* Offset units. */ (offsAdjust << 14)); /* Offset adjust. */ - UINT16_TO_BSTREAM(pBuf, LCTR_PER_INTER_TO_MS(BB_TICKS_TO_US(pPerScanCtx->perInter))); /* Interval */ + UINT16_TO_BSTREAM(pBuf, LCTR_PER_INTER_TO_MS(pPerScanCtx->perInterUsec)); /* Interval */ uint64_t temp = pPerScanCtx->chanParam.chanMask | /* SyncInfo - ChMap */ ((uint64_t)pPerScanCtx->sca << 37); /* SyncInfo - SCA of the device sending AUX_SYNC_IND. */ @@ -161,8 +160,6 @@ void lctrSendPerSyncFromScan(lctrConnCtx_t *pCtx) * * \param pCtx Connection context. * - * \return None. - * * This function is called from BOD end callback of master/slave connection. */ /*************************************************************************************************/ @@ -194,33 +191,33 @@ void lctrSendPerSyncFromBcst(lctrConnCtx_t *pCtx) /* Find PEa, event counter of PE whose starting time is after CEref. */ uint16_t paEventCounter = pAdvSet->perParam.perEventCounter; - uint32_t paAnchor = pPerOp->due; + uint32_t paAnchor = pPerOp->dueUsec; uint32_t ceRefStart, ceRefEnd; /* Calculate the end time of CEref. */ ceRefStart = lctrConnGetAnchorPoint(pCtx, (pCtx->eventCounter + ceOffset)); - ceRefEnd = ceRefStart + BB_US_TO_BB_TICKS(pCtx->localConnDurUsec + BbGetSchSetupDelayUs()); + ceRefEnd = ceRefStart + pCtx->effConnDurUsec + BbGetSchSetupDelayUs(); /* paAnchor is for the first PE in the future from ceRefEnd. */ - if ((ceRefEnd - paAnchor) < LCTR_SCH_MAX_SPAN) + if (BbGetTargetTimeDelta(ceRefEnd, paAnchor) > 0) { - uint16_t numPE = (ceRefEnd - paAnchor) / pAdvSet->perParam.perAdvInter + 1; + uint16_t numPE = BbGetTargetTimeDelta(ceRefEnd, paAnchor) / pAdvSet->perParam.perAdvInterUsec + 1; - paAnchor += numPE * pAdvSet->perParam.perAdvInter; + paAnchor += numPE * pAdvSet->perParam.perAdvInterUsec; paEventCounter += numPE; } else { - uint16_t numPE = (paAnchor - ceRefEnd) / pAdvSet->perParam.perAdvInter; + uint16_t numPE = BbGetTargetTimeDelta(paAnchor, ceRefEnd) / pAdvSet->perParam.perAdvInterUsec; - paAnchor -= numPE * pAdvSet->perParam.perAdvInter; + paAnchor -= numPE * pAdvSet->perParam.perAdvInterUsec; paEventCounter -= numPE; } uint8_t offsUnits; uint8_t offsAdjust = 0; uint16_t offs; - uint32_t offsUsec = BB_TICKS_TO_US(paAnchor - ceRefStart); + uint32_t offsUsec = BbGetTargetTimeDelta(paAnchor, ceRefStart); if (offsUsec < LL_30_USEC_OFFS_MAX_USEC) { @@ -240,7 +237,7 @@ void lctrSendPerSyncFromBcst(lctrConnCtx_t *pCtx) } LL_TRACE_INFO1("LL_PERIODIC_SYNC_IND from BCST ceRef anchor point = %u", ceRefStart); - LL_TRACE_INFO1(" PA lastAnchorPoint = %u", pPerOp->due); + LL_TRACE_INFO1(" PA lastAnchorPoint = %u", pPerOp->dueUsec); LL_TRACE_INFO1(" PA REF paAnchor = %u", paAnchor); LL_TRACE_INFO1(" offsUsec = %u", offsUsec); @@ -253,7 +250,7 @@ void lctrSendPerSyncFromBcst(lctrConnCtx_t *pCtx) (offsUnits << 13) | /* Offset units. */ (offsAdjust << 14)); /* Offset adjust. */ - UINT16_TO_BSTREAM(pBuf, LCTR_PER_INTER_TO_MS(BB_TICKS_TO_US(pAdvSet->perParam.perAdvInter))); /* Interval */ + UINT16_TO_BSTREAM(pBuf, LCTR_PER_INTER_TO_MS(pAdvSet->perParam.perAdvInterUsec)); /* Interval */ uint64_t temp = pAdvSet->perParam.perChanParam.chanMask | /* SyncInfo - ChMap */ ((uint64_t)lctrComputeSca() << 37); /* SyncInfo - SCA of the device sending AUX_SYNC_IND. */ @@ -295,8 +292,6 @@ void lctrSendPerSyncFromBcst(lctrConnCtx_t *pCtx) * \brief Store periodic advertising sync transfer parameters. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStorePeriodicSyncTrsf(lctrConnCtx_t *pCtx) @@ -311,8 +306,6 @@ void lctrStorePeriodicSyncTrsf(lctrConnCtx_t *pCtx) * \brief Send periodic sync indication PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendPeriodicSyncInd(lctrConnCtx_t *pCtx) @@ -333,8 +326,6 @@ void lctrSendPeriodicSyncInd(lctrConnCtx_t *pCtx) * \brief Handle received periodic sync indication PDU. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrReceivePeriodicSyncInd(lctrConnCtx_t *pCtx) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_enc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_enc.c index 8aabf6cf05..f574180096 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_enc.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_enc.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave encryption action routines. + * \file + * + * \brief Link layer controller slave encryption action routines. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,7 +28,7 @@ #include "wsf_msg.h" #include "wsf_trace.h" #include "util/bstream.h" -#include "stack/platform/include/pal_crypto.h" +#include "pal_crypto.h" #include /*************************************************************************************************/ @@ -35,8 +36,6 @@ * \brief Modify encryption mode. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrModifyEncMode(lctrConnCtx_t *pCtx) @@ -68,8 +67,6 @@ static void lctrModifyEncMode(lctrConnCtx_t *pCtx) * \brief Enable Tx data encryption. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrEnableTxDataEnc(lctrConnCtx_t *pCtx) @@ -85,8 +82,6 @@ void lctrEnableTxDataEnc(lctrConnCtx_t *pCtx) * \brief Enable Tx data encryption. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrDisableTxDataEnc(lctrConnCtx_t *pCtx) @@ -100,8 +95,6 @@ void lctrDisableTxDataEnc(lctrConnCtx_t *pCtx) * \brief Enable Rx data encryption. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrEnableRxDataEnc(lctrConnCtx_t *pCtx) @@ -117,8 +110,6 @@ void lctrEnableRxDataEnc(lctrConnCtx_t *pCtx) * \brief Enable Rx data encryption. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrDisableRxDataEnc(lctrConnCtx_t *pCtx) @@ -132,8 +123,6 @@ void lctrDisableRxDataEnc(lctrConnCtx_t *pCtx) * \brief Generate slave encryption vectors. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrGenerateSlvVectors(lctrConnCtx_t *pCtx) @@ -157,8 +146,6 @@ void lctrGenerateSlvVectors(lctrConnCtx_t *pCtx) * \brief Store LTK reply. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreLtkReply(lctrConnCtx_t *pCtx) @@ -171,8 +158,6 @@ void lctrStoreLtkReply(lctrConnCtx_t *pCtx) * \brief Store LTK negative reply termination reason. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreLtkNegRepTerminateReason(lctrConnCtx_t *pCtx) @@ -185,8 +170,6 @@ void lctrStoreLtkNegRepTerminateReason(lctrConnCtx_t *pCtx) * \brief Calculate session keys. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrCalcSessionKey(lctrConnCtx_t *pCtx) @@ -198,9 +181,11 @@ void lctrCalcSessionKey(lctrConnCtx_t *pCtx) WSF_ASSERT(lctrInitCipherBlkHdlr); memcpy(pEnc->iv, pCtx->iv, sizeof(pEnc->iv)); - uint8_t dir = (pCtx->role == LL_ROLE_MASTER) ? 1 : 0; /* master = 1; slave = 0 */ + pEnc->dir = (pCtx->role == LL_ROLE_MASTER) ? 1 : 0; /* master = 1; slave = 0 */ pEnc->type = PAL_BB_TYPE_ACL; - lctrInitCipherBlkHdlr(pEnc, LCTR_GET_CONN_HANDLE(pCtx), dir); + pCtx->txPktCounter = 0; + pCtx->rxPktCounter = 0; + lctrInitCipherBlkHdlr(pEnc, LCTR_GET_CONN_HANDLE(pCtx), pEnc->dir); } /*************************************************************************************************/ @@ -208,8 +193,6 @@ void lctrCalcSessionKey(lctrConnCtx_t *pCtx) * \brief Send feature response PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrInvalidEncPduSeq(lctrConnCtx_t *pCtx) @@ -223,8 +206,6 @@ void lctrInvalidEncPduSeq(lctrConnCtx_t *pCtx) * \brief Send feature response PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendEncRsp(lctrConnCtx_t *pCtx) @@ -255,8 +236,6 @@ void lctrSendEncRsp(lctrConnCtx_t *pCtx) * \brief Send start encryption request PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendStartEncReq(lctrConnCtx_t *pCtx) @@ -282,8 +261,6 @@ void lctrSendStartEncReq(lctrConnCtx_t *pCtx) * \brief Send start encryption response PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendStartEncRsp(lctrConnCtx_t *pCtx) @@ -309,8 +286,6 @@ void lctrSendStartEncRsp(lctrConnCtx_t *pCtx) * \brief Send pause encryption request PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendPauseEncReq(lctrConnCtx_t *pCtx) @@ -336,8 +311,6 @@ void lctrSendPauseEncReq(lctrConnCtx_t *pCtx) * \brief Send pause encryption response PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendPauseEncRsp(lctrConnCtx_t *pCtx) @@ -363,8 +336,6 @@ void lctrSendPauseEncRsp(lctrConnCtx_t *pCtx) * \brief Send ping request PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendPingReq(lctrConnCtx_t *pCtx) @@ -390,8 +361,6 @@ void lctrSendPingReq(lctrConnCtx_t *pCtx) * \brief Send ping response PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendPingRsp(lctrConnCtx_t *pCtx) @@ -417,8 +386,6 @@ void lctrSendPingRsp(lctrConnCtx_t *pCtx) * \brief Notify slave host of connect indication. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrEncNotifyHostLtkReqInd(lctrConnCtx_t *pCtx) @@ -451,8 +418,6 @@ void lctrEncNotifyHostLtkReqInd(lctrConnCtx_t *pCtx) * * \param pCtx Connection context. * \param status Status code. - * - * \return None. */ /*************************************************************************************************/ void lctrNotifyEncChangeInd(lctrConnCtx_t *pCtx, uint8_t status) @@ -484,8 +449,6 @@ void lctrNotifyEncChangeInd(lctrConnCtx_t *pCtx, uint8_t status) * \brief Notify host of key refreshed. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrNotifyEncKeyRefreshInd(lctrConnCtx_t *pCtx) @@ -515,8 +478,6 @@ void lctrNotifyEncKeyRefreshInd(lctrConnCtx_t *pCtx) * \brief Notify host of authentication payload timeout expired. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrNotifyAuthPayloadTimeout(lctrConnCtx_t *pCtx) @@ -545,8 +506,6 @@ void lctrNotifyAuthPayloadTimeout(lctrConnCtx_t *pCtx) * \brief Restart authentication payload timeout timer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrRestartAuthPayloadTimer(lctrConnCtx_t *pCtx) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_enc_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_enc_master.c index ad41679dd7..9a54a02e7a 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_enc_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_enc_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master encryption action routines. + * \file + * + * \brief Link layer controller master encryption action routines. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -35,8 +36,6 @@ * \brief Generate master encryption vectors. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrGenerateMstVectors(lctrConnCtx_t *pCtx) @@ -58,8 +57,6 @@ void lctrGenerateMstVectors(lctrConnCtx_t *pCtx) * \brief Generate master encryption vectors. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreSlvVectors(lctrConnCtx_t *pCtx) @@ -74,8 +71,6 @@ void lctrStoreSlvVectors(lctrConnCtx_t *pCtx) * \brief Send encryption request PDU to peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrSendEncReq(lctrConnCtx_t *pCtx) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_init_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_init_master.c index af4f09235d..d917f110be 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_init_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_init_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master connection state machine action routines. + * \file + * + * \brief Link layer controller master connection state machine action routines. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -26,13 +27,12 @@ #include "sch_api_ble.h" #include "wsf_trace.h" #include "util/bstream.h" +#include "lctr_int_conn.h" #include /*************************************************************************************************/ /*! * \brief Start initiate connection scan. - * - * \return None. */ /*************************************************************************************************/ void lctrInitActInitiate(void) @@ -54,7 +54,7 @@ void lctrInitActInitiate(void) uint32_t interMinUsec = LCTR_CONN_IND_US(pInitMsg->connSpec.connIntervalMin); uint32_t interMaxUsec = LCTR_CONN_IND_US(pInitMsg->connSpec.connIntervalMax); - uint32_t durUsec = pCtx->localConnDurUsec; + uint32_t durUsec = pCtx->effConnDurUsec; if (!SchRmAdd(LCTR_GET_CONN_HANDLE(pCtx), SCH_RM_PREF_PERFORMANCE, interMinUsec, interMaxUsec, durUsec, &connInterUsec, lctrGetConnRefTime)) { @@ -83,7 +83,6 @@ void lctrInitActInitiate(void) lctrMstInit.data.init.connHandle = LCTR_GET_CONN_HANDLE(pCtx); lctrMstInit.data.init.connInterval = LCTR_US_TO_CONN_IND(connInterUsec); - lctrMstInit.data.init.connBodLoaded = FALSE; lctrMstInit.scanParam = pInitMsg->scanParam; BbStart(BB_PROT_BLE); @@ -113,8 +112,6 @@ void lctrInitActInitiate(void) /*************************************************************************************************/ /*! * \brief Establish connection. - * - * \return None. */ /*************************************************************************************************/ void lctrInitActConnect(void) @@ -169,8 +166,6 @@ void lctrInitActConnect(void) /*************************************************************************************************/ /*! * \brief Shutdown active initiation operation. - * - * \return None. */ /*************************************************************************************************/ void lctrInitActShutdown(void) @@ -191,19 +186,17 @@ void lctrInitActShutdown(void) /*************************************************************************************************/ /*! * \brief Terminated scan after host initiate disable. - * - * \return None. */ /*************************************************************************************************/ void lctrInitActScanTerm(void) { + lctrConnCtx_t *pConnCtx = LCTR_GET_CONN_CTX(lctrMstInit.data.init.connHandle); + lctrSendConnMsg(pConnCtx, LCTR_CONN_INIT_CANCELED); + BbStop(BB_PROT_BLE); lctrScanCleanup(&lctrMstInit); - SchRmRemove(lctrMstInit.data.init.connHandle); - lctrFreeConnCtx(LCTR_GET_CONN_CTX(lctrMstInit.data.init.connHandle)); - LlCreateConnCancelCnf_t evt = { .hdr = @@ -228,21 +221,22 @@ void lctrInitActScanTerm(void) /*************************************************************************************************/ /*! * \brief Terminated scan after host reset. - * - * \return None. */ /*************************************************************************************************/ void lctrInitActResetTerm(void) { + + lctrConnCtx_t *pConnCtx = LCTR_GET_CONN_CTX(lctrMstInit.data.init.connHandle); + lctrSendConnMsg(pConnCtx, LCTR_CONN_TERMINATED); + BbStop(BB_PROT_BLE); + lctrScanCleanup(&lctrMstInit); } /*************************************************************************************************/ /*! * \brief Notify host disallowing initiate. - * - * \return None. */ /*************************************************************************************************/ void lctrInitActDisallowInitiate(void) @@ -255,8 +249,6 @@ void lctrInitActDisallowInitiate(void) /*************************************************************************************************/ /*! * \brief Notify host disallowing initiate cancel. - * - * \return None. */ /*************************************************************************************************/ void lctrInitActDisallowCancel(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_init_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_init_master_ae.c index 35c0cccb71..6efe08a6f3 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_init_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_init_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master connection state machine action routines. + * \file + * + * \brief Link layer controller master connection state machine action routines. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_init_master_ae.h" @@ -32,8 +33,6 @@ * \brief Shutdown active initiation operation. * * \param pExtInitCtx Extended scan context of the initiator. - * - * \return None. */ /*************************************************************************************************/ void lctrExtInitActShutdown(lctrExtScanCtx_t *pExtInitCtx) @@ -56,8 +55,6 @@ void lctrExtInitActShutdown(lctrExtScanCtx_t *pExtInitCtx) * \brief Terminated scan after host initiate disable. * * \param pExtInitCtx Extended scan context of the initiator. - * - * \return None. */ /*************************************************************************************************/ void lctrExtInitActScanTerm(lctrExtScanCtx_t *pExtInitCtx) @@ -68,13 +65,12 @@ void lctrExtInitActScanTerm(lctrExtScanCtx_t *pExtInitCtx) { if ((lctrMstExtInit.estConnPhys & (1 << i)) == 0) { - lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(lctrMstExtInitTbl[i].data.init.connHandle); + lctrConnCtx_t *pConnCtx = LCTR_GET_CONN_CTX(lctrMstExtInitTbl[i].data.init.connHandle); - if (pCtx->enabled == TRUE) + if (pConnCtx->enabled == TRUE) { /* Cleanup unused initiate PHY connection context. */ - SchRmRemove(lctrMstExtInitTbl[i].data.init.connHandle); - lctrFreeConnCtx(pCtx); + lctrSendConnMsg(pConnCtx, LCTR_CONN_INIT_CANCELED); } } } @@ -110,8 +106,6 @@ void lctrExtInitActScanTerm(lctrExtScanCtx_t *pExtInitCtx) * \brief Send disallow initiate host notification. * * \param pExtInitCtx Extended scan context of the initiator. - * - * \return None. */ /*************************************************************************************************/ void lctrExtInitActDisallowInitiate(lctrExtScanCtx_t *pExtInitCtx) @@ -126,8 +120,6 @@ void lctrExtInitActDisallowInitiate(lctrExtScanCtx_t *pExtInitCtx) * \brief Send disallow create connection cancel host notification. * * \param pExtInitCtx Extended scan context of the initiator. - * - * \return None. */ /*************************************************************************************************/ void lctrExtInitActDisallowCancel(lctrExtScanCtx_t *pExtInitCtx) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_pc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_pc.c new file mode 100644 index 0000000000..c8854126b2 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_pc.c @@ -0,0 +1,650 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller connection power control state machine action routines. + * + * 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 "ll_defs.h" +#include "lctr_int_conn.h" +#include "lctr_int_adv_slave.h" +#include "lctr_int_adv_master_ae.h" +#include "sch_api.h" +#include "sch_api_ble.h" +#include "lmgr_api_conn.h" +#include "pal_radio.h" +#include "wsf_assert.h" +#include "wsf_math.h" +#include "wsf_msg.h" +#include "wsf_timer.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include +#include "lctr_int_pc.h" + +/*************************************************************************************************/ +/*! + * \brief Return the power control index of a phy bit. + * + * \param phyBit Phy bit. + * + * \return Power control phy index, or invalid if not valid. + */ +/*************************************************************************************************/ +static uint8_t lctrPhyBitToPclPhyIndex(uint8_t phyBit) +{ + uint8_t phyIndex; + for (phyIndex = LL_PC_PHY_1M; phyIndex <= LL_PC_PHY_TOTAL; phyIndex++) + { + if ((1 << (phyIndex - 1)) == phyBit) + { + return phyIndex; + } + } + return LL_PC_PHY_INVALID; +} + +/*************************************************************************************************/ +/*! + * \brief Attempt a Tx power change. + * + * \param pCtx Connection context. + * \param phy PHY. + * \param delta Delta to current PHY txPower. + * + * \return Delta of the new txPower. + */ +/*************************************************************************************************/ +int8_t lctrAttemptTxPowerChange(lctrConnCtx_t *pCtx, uint8_t phy, int8_t delta) +{ + BbBleData_t * pBle = &pCtx->bleData; + + uint8_t option = (phy > LL_PHY_LE_CODED) ? BB_PHY_OPTIONS_BLE_S2 : BB_PHY_OPTIONS_BLE_S8; + if (phy > LL_PHY_LE_CODED) + { + phy = LL_PHY_LE_CODED; + } + + 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. */ + return 0; + } + else if (LCTR_GET_TXPOWER(pCtx, phy, option) == LL_PWR_CTRL_TXPOWER_UNMANAGED) + { + curTxPower = pLctrRtCfg->defTxPwrLvl; + reqTxPower = pLctrRtCfg->defTxPwrLvl + delta; + } + else + { + curTxPower = PalRadioGetActualTxPower(LCTR_GET_TXPOWER(pCtx, phy, option), FALSE); + reqTxPower = LCTR_GET_TXPOWER(pCtx, phy, option) + delta; + } + + /* Overflow catch condition. */ + if ((delta > 0) && + (reqTxPower < curTxPower)) + { + reqTxPower = LL_PWR_CTRL_TXPOWER_MAX; + } + + 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_SET_TXPOWER(pCtx, phy + (((phy == LL_PHY_LE_CODED) && (option == BB_PHY_OPTIONS_BLE_S2)) ? 1 : 0), newTxPower); + + /* Update current txPower if necessary. */ + if (phy == pBle->chan.txPhy) + { + pBle->chan.txPower = LCTR_GET_TXPOWER(pCtx, phy, option); + } + + return newTxPower - curTxPower; +} + +/*************************************************************************************************/ +/*! + * \brief Send peer power control request PDU. + * + * \param pCtx Connection context. + * \param delta Requested delta. + */ +/*************************************************************************************************/ +static void lctrSendPowerCtrlReqPdu(lctrConnCtx_t *pCtx, int8_t delta) +{ + uint8_t *pPdu; + + if ((pPdu = lctrTxCtrlPduAlloc(LL_PWR_CTRL_REQ_LEN)) != NULL) + { + uint8_t *pBuf = pPdu; + + /*** Assemble control PDU. ***/ + UINT8_TO_BSTREAM (pBuf, LL_PDU_PWR_CTRL_REQ); + UINT8_TO_BSTREAM (pBuf, (1 << (pCtx->reqPhy - 1))); + UINT8_TO_BSTREAM (pBuf, delta); + UINT8_TO_BSTREAM (pBuf, LCTR_GET_TXPOWER(pCtx, pCtx->reqPhy, pCtx->bleData.chan.initTxPhyOptions)); + + /*** Queue for transmit. ***/ + lctrTxCtrlPduQueue(pCtx, pPdu); + } + return; +} + +/*************************************************************************************************/ +/*! + * \brief Calculate Apr field for a power control response. + * + * \param pCtx Connection context. + * + * \return APR to be packed in response PDU. + */ +/*************************************************************************************************/ +static uint8_t lctrCalculateAprField(lctrConnCtx_t *pCtx) +{ + return LL_PWR_CTRL_APR_UNDEF; +} + +/*************************************************************************************************/ +/*! + * \brief Send peer power control response PDU. + * + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +static void lctrSendPowerCtrlRspPdu(lctrConnCtx_t *pCtx) +{ + uint8_t *pPdu; + uint8_t option = (pCtx->reqPhy == LL_PC_PHY_CODED_S2) ? BB_PHY_OPTIONS_BLE_S2 : BB_PHY_OPTIONS_BLE_S8; + uint8_t txPhy = (pCtx->reqPhy < LL_PC_PHY_CODED_S2) ? pCtx->reqPhy : LL_PHY_LE_CODED; + int8_t txPower = LCTR_GET_TXPOWER(pCtx, txPhy, option); + + if ((pPdu = lctrTxCtrlPduAlloc(LL_PWR_CTRL_RSP_LEN)) != NULL) + { + uint8_t *pBuf = pPdu; + + /*** Assemble control PDU. ***/ + UINT8_TO_BSTREAM (pBuf, LL_PDU_PWR_CTRL_RSP); + UINT8_TO_BSTREAM (pBuf, lctrGetPowerLimits(txPower)); + UINT8_TO_BSTREAM (pBuf, pCtx->delta); + UINT8_TO_BSTREAM (pBuf, txPower); + UINT8_TO_BSTREAM (pBuf, lctrCalculateAprField(pCtx)); + + /*** Queue for transmit. ***/ + lctrTxCtrlPduQueue(pCtx, pPdu); + } + return; +} + +/*************************************************************************************************/ +/*! + * \brief Update action for power control processing. + * + * \param pCtx Connection Context. + */ +/*************************************************************************************************/ +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); + + /* 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) + { + LCTR_SET_TXPOWER(pCtx, pCtx->reqPhy, pLctrRtCfg->defTxPwrLvl); + + if (pCtx->reqPhy >= LL_PC_PHY_CODED_S8) + { + LCTR_SET_TXPOWER(pCtx, (pCtx->reqPhy == LL_PC_PHY_CODED_S8) ? LL_PC_PHY_CODED_S2 : LL_PC_PHY_CODED_S8, pLctrRtCfg->defTxPwrLvl); + } + } + + if (!pCtx->controllerInitRead && (pCtx->delta == 0)) + { + pCtx->readRemoteTxPower = TRUE; + } +} + +/*************************************************************************************************/ +/*! + * \brief Send peer power control request. + * + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +void lctrSendPeerPowerControlReq(lctrConnCtx_t *pCtx) +{ + lctrSendPowerCtrlReqPdu(pCtx, pCtx->delta); +} + +/*************************************************************************************************/ +/*! + * \brief Store peer power control request. + * + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +void lctrStorePeerPowerControlReq(lctrConnCtx_t *pCtx) +{ + lctrPwrCtrlReq_t pld = lctrDataPdu.pld.pwrCtrlReq; + + pCtx->reqErrCode = LL_SUCCESS; + + uint8_t phyIdx = lctrPhyBitToPclPhyIndex(pld.phy); + + /* Verify txPower field is valid. */ + if (phyIdx == LL_PC_PHY_INVALID) + { + pCtx->reqErrCode = LL_ERROR_CODE_UNSUPPORTED_LMP_PARAM_VAL; + return; + } + + if (pld.txPower == LL_PWR_CTRL_TXPOWER_UNMANAGED) + { + pCtx->reqErrCode = LL_ERROR_CODE_INVALID_LMP_PARAMS; + return; + } + + /* Notify host of remote change if needed. */ + if ((pCtx->powerRptRemote) && + (pCtx->bleData.chan.rxPhy == phyIdx) && + (pCtx->peerTxPower != pld.txPower)) + { + lctrNotifyPowerReportInd(pCtx, LL_POWER_REPORT_REASON_REMOTE, phyIdx, pld.txPower, + lctrGetPowerLimits(pld.txPower), + pld.txPower - pCtx->peerTxPower); + } + + /* Update peer Tx power. */ + if (pCtx->bleData.chan.rxPhy == phyIdx) + { + pCtx->peerTxPower = pld.txPower; + + 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); + } + else + { + LL_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower=%d", pCtx->peerTxPower); + } + } + +#if (LL_ENABLE_TESTER == TRUE) + if (llTesterCb.powerLimits) + { + pCtx->delta = 0; + return; + } +#endif + + /* Attempt the txPower change, store delta for the response. */ + pCtx->delta = lctrAttemptTxPowerChange(pCtx, phyIdx, lctrDataPdu.pld.pwrCtrlReq.delta); + pCtx->reqPhy = phyIdx; + + /* Notify host of local change if needed. */ + if ((pCtx->delta != 0) && + (pCtx->powerRptLocal)) + { + uint8_t option = BB_PHY_OPTIONS_BLE_S8; + uint8_t phy = phyIdx; + + if (phy == LL_PC_PHY_CODED_S2) + { + option = BB_PHY_OPTIONS_BLE_S2; + phy = LL_PHY_LE_CODED; + } + + int8_t newTxPower = LCTR_GET_TXPOWER(pCtx, phy, option); + lctrNotifyPowerReportInd(pCtx, LL_POWER_REPORT_REASON_LOCAL, phyIdx, newTxPower, + lctrGetPowerLimits(newTxPower), + pCtx->delta); + } +} + +/*************************************************************************************************/ +/*! + * \brief Send peer power control response. + * + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +void lctrSendPeerPowerControlRsp(lctrConnCtx_t *pCtx) +{ + if (pCtx->reqErrCode == LL_SUCCESS) + { + lctrSendPowerCtrlRspPdu(pCtx); + + pCtx->peerReqRecvd = TRUE; + } + else + { + LL_TRACE_WARN0("lctrSendPeerPowerControlRsp: Peer sent invalid parameters for power control request."); + lctrSendRejectInd(pCtx, pCtx->reqErrCode, TRUE); + pCtx->reqErrCode = LL_SUCCESS; + } +} + +/*************************************************************************************************/ +/*! + * \brief Store peer power control response. + * + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +void lctrStorePeerPowerControlRsp(lctrConnCtx_t *pCtx) +{ + lctrPwrCtrlRsp_t pld = lctrDataPdu.pld.pwrCtrlRsp; + + /* Notify host if needed. */ + if ((pCtx->powerRptRemote) && + (pCtx->peerTxPower != pld.txPower)) + { + lctrNotifyPowerReportInd(pCtx, LL_POWER_REPORT_REASON_REMOTE, pCtx->reqPhy, pld.txPower, + pld.limits, + pld.txPower - pCtx->peerTxPower); + } + + /* Update peer information, if needed. */ + if (pCtx->bleData.chan.rxPhy == pCtx->reqPhy) + { + pCtx->peerTxPower = pld.txPower; + pCtx->peerPwrLimits = pld.limits; + pCtx->peerApr[pCtx->reqPhy] = pld.apr; + + 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); + } + else + { + LL_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower=%d", pCtx->peerTxPower); + + if (pCtx->controllerInitRead) + { + pCtx->controllerInitRead = FALSE; + } + + if (pCtx->monitoringState == LCTR_PC_MONITOR_PATH_LOSS) + { + if (pCtx->pclMonitorParam.pathLoss.initialPathLossRead) + { + pCtx->pclMonitorParam.pathLoss.initialPathLossRead = FALSE; + pCtx->pclMonitorParam.pathLoss.curZone = lctrCalcPathLossZone(pCtx); + lctrNotifyHostPathLossRpt(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); +} + +/*************************************************************************************************/ +/*! + * \brief Notify host of power report indication. + * + * \param pCtx Connection context. + * \param reason Reason this indication was sent. + * \param phy PHY. + * \param txPower Current txPower. + * \param limits Power limits. + * \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) +{ + const uint16_t handle = LCTR_GET_CONN_HANDLE(pCtx); + + LlPowerReportInd_t evt = + { + .hdr = + { + .param = handle, + .event = LL_TX_POWER_REPORTING_IND, + .status = LL_SUCCESS + }, + + .status = LL_SUCCESS, + .connHandle = handle, + .reason = reason, + .phy = phy, + .txPower = txPower, + .txPowerLimits = limits, + .delta = delta + }; + + LL_TRACE_INFO2("### LlEvent ### lctrNotifyPowerReportInd , handle=%u, reason=%d, status=LL_SUCCESS", handle, reason); + + LmgrSendEvent((LlEvt_t *)&evt); +} + +/*************************************************************************************************/ +/*! + * \brief Send power change indication. + * + * \param pCtx Connection context. + * \param opcode PDU opcode. + * \param phyVal PHY. + * \param delta Delta from previous txPower. + * \param txPower Current txPower. + * \param phyChange The indication was caused by a PHY change. + */ +/*************************************************************************************************/ +static void lctrSendPowerChangePdu(lctrConnCtx_t *pCtx, uint8_t opcode, uint8_t phyVal, int8_t delta, int8_t txPower, bool_t phyChange) +{ + if (pCtx->peerReqRecvd == FALSE) /* Shall not be sent without a request received. */ + { + return; + } + + uint8_t *pPdu; + + if ((pPdu = lctrTxCtrlPduAlloc(LL_PWR_CHNG_IND_LEN)) != NULL) + { + bool_t seperateIndNeeded = FALSE; + uint8_t *pBuf = pPdu; + uint8_t phy = (1 << (phyVal - 1)); + + /* Attempt to pack coded ind in one ind. */ + if ((phy == LL_PC_CODED_S8_BIT) && (phyChange == TRUE)) + { + if (LCTR_GET_TXPOWER(pCtx, LL_PHY_LE_CODED, BB_PHY_OPTIONS_BLE_S2) == LCTR_GET_TXPOWER(pCtx, LL_PHY_LE_CODED, BB_PHY_OPTIONS_BLE_S8)) + { + phy |= LL_PC_CODED_S2_BIT; + } + else + { + seperateIndNeeded = TRUE; + } + } + + /*** Assemble control PDU. ***/ + UINT8_TO_BSTREAM (pBuf, opcode); + UINT8_TO_BSTREAM (pBuf, phy); + UINT8_TO_BSTREAM (pBuf, lctrGetPowerLimits(txPower)); + UINT8_TO_BSTREAM (pBuf, delta); + UINT8_TO_BSTREAM (pBuf, txPower); + + /*** Queue for transmit. ***/ + lctrTxCtrlPduQueue(pCtx, pPdu); + + /* For coded, we need to send S2 txPower as well. */ + if (seperateIndNeeded) + { + txPower = LCTR_GET_TXPOWER(pCtx, LL_PHY_LE_CODED, BB_PHY_OPTIONS_BLE_S2); + pBuf = pPdu + 1; + UINT8_TO_BSTREAM (pBuf, LL_PC_CODED_S2_BIT); + UINT8_TO_BSTREAM (pBuf, lctrGetPowerLimits(txPower)); + UINT8_TO_BSTREAM (pBuf, delta); + UINT8_TO_BSTREAM (pBuf, txPower); + + /*** Queue for transmit. ***/ + lctrTxCtrlPduQueue(pCtx, pPdu); + } + } +} + +/*************************************************************************************************/ +/*! + * \brief Send power control indication. + * + * \param pCtx Connection context. + * \param phy PHY. + * \param delta Delta from previous txPower. + * \param txPower Current txPower. + * \param phyChange The indication was a result of a PHY change. + */ +/*************************************************************************************************/ +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); +} + +/*************************************************************************************************/ +/*! + * \brief Store peer power indication. + * + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +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); + + if (pPdu->phy & (1 << (pCtx->bleData.chan.rxPhy - 1))) + { + if ((pCtx->peerTxPower != pPdu->txPower) && + (pCtx->powerRptRemote)) + { + lctrNotifyPowerReportInd(pCtx, LL_POWER_REPORT_REASON_REMOTE, pCtx->bleData.chan.rxPhy, pPdu->txPower, + pPdu->limits, + pPdu->txPower - pCtx->peerTxPower); + } + + if (pPdu->phy == pCtx->bleData.chan.rxPhy) + { + pCtx->peerTxPower = pPdu->txPower; + + 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); + } + else + { + LL_TRACE_INFO1("lctrStorePeerPowerInd: txPower=%d", pCtx->peerTxPower); + } + } + } +} + +/*************************************************************************************************/ +/*! + * \brief Send peer power indication response (Included for state machine conformance). + * + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +void lctrSendPeerPowerRsp(lctrConnCtx_t *pCtx) +{ + /* No need to reply to power change indications. */ + return; +} + +/*************************************************************************************************/ +/*! + * \brief Power monitoring action function + * + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +void lctrAutoPowerMonitorAct(lctrConnCtx_t *pCtx) +{ + if (!(pCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST)) + { + 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++; + + 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) + { + pCtx->pclMonitorParam.autoMonitor.curTimeSpent++; + + if (pCtx->pclMonitorParam.autoMonitor.curTimeSpent >= pCtx->pclMonitorParam.autoMonitor.minTimeSpent) + { + 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; + } + } + else + { + pCtx->pclMonitorParam.autoMonitor.curTimeSpent = 0; + } + + if (sendReqDelta != 0) + { + 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; + if ((pMsg = (lctrMsgPwrCtrlReq_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->hdr.handle = LCTR_GET_CONN_HANDLE(pCtx); + pMsg->hdr.dispId = LCTR_DISP_CONN; + pMsg->hdr.event = LCTR_CONN_MSG_API_PWR_CTRL_REQ; + pMsg->delta = sendReqDelta; + pMsg->phy = reqPhy; + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } + } +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_phy.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_phy.c index 6a5f91e22a..7c5b60deec 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_phy.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_act_phy.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller PHY features action routines. + * \file + * + * \brief Link layer controller PHY features action routines. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -34,8 +35,6 @@ * \brief Store PHY update request. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStoreHostPhyUpdate(lctrConnCtx_t *pCtx) @@ -53,8 +52,6 @@ void lctrStoreHostPhyUpdate(lctrConnCtx_t *pCtx) * \brief Store PHY update request. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStorePeerPhyReq(lctrConnCtx_t *pCtx) @@ -67,8 +64,6 @@ void lctrStorePeerPhyReq(lctrConnCtx_t *pCtx) * \brief Store PHY update indication. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrStorePeerPhyUpdateInd(lctrConnCtx_t *pCtx) @@ -102,8 +97,6 @@ void lctrStorePeerPhyUpdateInd(lctrConnCtx_t *pCtx) * \param opcode Opcode to send in PDU. * \param txPhys Transmitter PHYs. * \param rxPhys Receiver PHYs. - * - * \return None. */ /*************************************************************************************************/ static void lctrSendPhyPdu(lctrConnCtx_t *pCtx, uint8_t opcode, uint8_t txPhys, uint8_t rxPhys) @@ -134,8 +127,6 @@ static void lctrSendPhyPdu(lctrConnCtx_t *pCtx, uint8_t opcode, uint8_t txPhys, * \param pCtx Connection context. * \param txPhys Transmitter PHYs. * \param rxPhys Receiver PHYs. - * - * \return None. */ /*************************************************************************************************/ void lctrSendPhyReqPdu(lctrConnCtx_t *pCtx, uint8_t txPhys, uint8_t rxPhys) @@ -157,8 +148,6 @@ void lctrSendPhyReqPdu(lctrConnCtx_t *pCtx, uint8_t txPhys, uint8_t rxPhys) * \param pCtx Connection context. * \param txPhys Transmitter PHYs. * \param rxPhys Receiver PHYs. - * - * \return None. */ /*************************************************************************************************/ void lctrSendPhyRspPdu(lctrConnCtx_t *pCtx, uint8_t txPhys, uint8_t rxPhys) @@ -173,8 +162,6 @@ void lctrSendPhyRspPdu(lctrConnCtx_t *pCtx, uint8_t txPhys, uint8_t rxPhys) * \param pCtx Connection context. * \param txPhys Transmitter PHYS. * \param rxPhys Receiver PHYS. - * - * \return None. */ /*************************************************************************************************/ void lctrSendPhyUpdateIndPdu(lctrConnCtx_t *pCtx, uint8_t txPhys, uint8_t rxPhys) @@ -233,8 +220,6 @@ void lctrSendPhyUpdateIndPdu(lctrConnCtx_t *pCtx, uint8_t txPhys, uint8_t rxPhys * * \param pCtx Connection context. * \param status Status. - * - * \return None. */ /*************************************************************************************************/ void lctrNotifyHostPhyUpdateInd(lctrConnCtx_t *pCtx, uint8_t status) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int.h index d93a55f00a..055322511e 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal link layer controller interface file. + * \file + * + * \brief Internal link layer controller interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -25,10 +26,11 @@ #define LCTR_INT_H #include "lctr_api.h" -#include "ll_defs.h" #include "lmgr_api.h" +#include "ll_defs.h" #include "ll_math.h" #include "util/crc32.h" +#include "pal_bb.h" #if (LL_ENABLE_TESTER) #include "ll_tester_api.h" @@ -44,73 +46,76 @@ extern "C" { **************************************************************************************************/ /*! \brief Minimum delay between connect indication and data channel in CONNECT_IND units. */ -#define LCTR_DATA_CHAN_DLY 1 /* 1.25 ms */ +#define LCTR_DATA_CHAN_DLY 1 /* 1.25 ms */ /*! \brief Minimum delay between auxiliary connect request and data channel using uncoded PHY in CONNECT_REQ units. */ -#define LCTR_DATA_CHAN_DLY_AUX_UNCODED 2 /* 2.5 ms */ +#define LCTR_DATA_CHAN_DLY_AUX_UNCODED 2 /* 2.5 ms */ /*! \brief Minimum delay between auxiliary connect request and data channel using coded PHY in CONNECT_REQ units. */ -#define LCTR_DATA_CHAN_DLY_AUX_CODED 3 /* 3.75 ms */ +#define LCTR_DATA_CHAN_DLY_AUX_CODED 3 /* 3.75 ms */ /*! \brief Convert connect indication ticks to scheduler ticks. */ -#define LCTR_CONN_IND_TICKS(x) ((x) * (1250 / LL_BLE_US_PER_TICK)) +#define LCTR_CONN_IND_TICKS(x) ((x) * (1250 / LL_BLE_US_PER_TICK)) /*! \brief Convert connect indication ticks to milliseconds (no divide, rounds up). */ -#define LCTR_CONN_IND_MS(x) ((x) + ((x) >> 2) + (((x) & 3) ? 1 : 0)) +#define LCTR_CONN_IND_MS(x) ((x) + ((x) >> 2) + (((x) & 3) ? 1 : 0)) /*! \brief Convert connect indication ticks to microseconds. */ -#define LCTR_CONN_IND_US(x) ((x) * 1250) +#define LCTR_CONN_IND_US(x) ((x) * 1250) /*! \brief Convert connect indication timeout ticks to milliseconds. */ -#define LCTR_CONN_IND_TO_MS(x) ((x) * 10) +#define LCTR_CONN_IND_TO_MS(x) ((x) * 10) /*! \brief Convert microseconds to connection indication ticks. */ -#define LCTR_US_TO_CONN_IND(x) LL_MATH_DIV_1250(x) +#define LCTR_US_TO_CONN_IND(x) LL_MATH_DIV_1250(x) /*! \brief Convert BLE protocol ticks to microseconds. */ -#define LCTR_BLE_TO_US(x) ((x) * LL_BLE_US_PER_TICK) +#define LCTR_BLE_TO_US(x) ((x) * LL_BLE_US_PER_TICK) -/*! \brief Convert periodic interval units to microseconds. */ -#define LCTR_PER_INTER_TO_US(x) ((x) * 1250) +/*! \brief Convert periodic interval milliseconds to microseconds. */ +#define LCTR_PER_INTER_TO_US(x) ((x) * 1250) /*! \brief Convert periodic interval microseconds to milliseconds. */ -#define LCTR_PER_INTER_TO_MS(x) LL_MATH_DIV_1250(x) +#define LCTR_PER_INTER_TO_MS(x) LL_MATH_DIV_1250(x) /*! \brief Convert periodic sync timeout unit to milliseconds. */ -#define LCTR_PER_SYNC_TIMEOUT_TO_MS(x) ((x) * 10) +#define LCTR_PER_SYNC_TIMEOUT_TO_MS(x) ((x) * 10) /*! \brief Convert isochronous interval to microseconds. */ -#define LCTR_ISO_INT_TO_US(x) ((x) * 1250) +#define LCTR_ISO_INT_TO_US(x) ((x) * 1250) /*! \brief Fast termination supervision multiplier. */ -#define LCTR_FAST_TERM_CNT 6 +#define LCTR_FAST_TERM_CNT 6 /*! \brief Duration of a advertising packet in microseconds. */ -#define LCTR_ADV_PKT_1M_US(len) ((LL_PREAMBLE_LEN_1M + LL_AA_LEN + LL_ADV_HDR_LEN + len + LL_CRC_LEN) << 3) +#define LCTR_ADV_PKT_1M_US(len) ((LL_PREAMBLE_LEN_1M + LL_AA_LEN + LL_ADV_HDR_LEN + len + LL_CRC_LEN) << 3) /*! \brief Duration of a connection indication packet in microseconds. */ -#define LCTR_CONN_IND_PKT_1M_US LCTR_ADV_PKT_1M_US(LL_CONN_IND_PDU_LEN) +#define LCTR_CONN_IND_PKT_1M_US LCTR_ADV_PKT_1M_US(LL_CONN_IND_PDU_LEN) /*! \brief Extra area in ADVB buffer. */ -#define LCTR_ADVB_BUF_EXTRA_SIZE 6 +#define LCTR_ADVB_BUF_EXTRA_SIZE 6 /*! \brief Size for ADVB buffer allocation. */ -#define LCTR_ADVB_BUF_SIZE (WSF_MAX(BB_FIXED_ADVB_PKT_LEN, LL_ADVB_MAX_LEN) + LCTR_ADVB_BUF_EXTRA_SIZE) +#define LCTR_ADVB_BUF_SIZE (WSF_MAX(BB_FIXED_ADVB_PKT_LEN, LL_ADVB_MAX_LEN) + LCTR_ADVB_BUF_EXTRA_SIZE) /*! \brief RSSI offset of extra data in ADVB buffer. */ -#define LCTR_ADVB_BUF_OFFSET_RSSI ((LCTR_ADVB_BUF_SIZE - LCTR_ADVB_BUF_EXTRA_SIZE) + 0) +#define LCTR_ADVB_BUF_OFFSET_RSSI ((LCTR_ADVB_BUF_SIZE - LCTR_ADVB_BUF_EXTRA_SIZE) + 0) /*! \brief RPA offset of extra data in ADVB buffer. */ -#define LCTR_ADVB_BUF_OFFSET_RX_RPA ((LCTR_ADVB_BUF_SIZE - LCTR_ADVB_BUF_EXTRA_SIZE) + 1) +#define LCTR_ADVB_BUF_OFFSET_RX_RPA ((LCTR_ADVB_BUF_SIZE - LCTR_ADVB_BUF_EXTRA_SIZE) + 1) /*! \brief CRC offset of extra data in ADVB buffer. */ -#define LCTR_ADVB_BUF_OFFSET_CRC ((LCTR_ADVB_BUF_SIZE - LCTR_ADVB_BUF_EXTRA_SIZE) + 2) +#define LCTR_ADVB_BUF_OFFSET_CRC ((LCTR_ADVB_BUF_SIZE - LCTR_ADVB_BUF_EXTRA_SIZE) + 2) /*! \brief LCTR Maximum span of scheduler elements. */ -#define LCTR_SCH_MAX_SPAN 0x80000000 +#define LCTR_SCH_MAX_SPAN ((BbGetBbTimerBoundaryUs() >> 1) + 1) /*! \brief LCTR Maximum value for sleep clock accuracy. */ -#define LCTR_MAX_SCA 7 +#define LCTR_MAX_SCA 7 + +/*! \brief Change supervision timeout value to us. */ +#define LCTR_SUP_TIMEOUT_VAL_TO_US(x) (x * 10000) /************************************************************************************************** Data Types @@ -128,6 +133,9 @@ typedef void (*LctrEvtHdlr_t)(void); /*! \brief Reservation manager callback signature. */ 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); + /************************************************************************************************** Globals **************************************************************************************************/ @@ -137,13 +145,18 @@ extern LctrMsgDisp_t lctrMsgDispTbl[LCTR_DISP_TOTAL]; extern LctrEvtHdlr_t lctrEventHdlrTbl[LCTR_EVENT_TOTAL]; extern lctrMsgHdr_t *pLctrMsg; extern const uint16_t scaPpmTbl[]; +extern bool_t lctrResetEnabled; /************************************************************************************************** Functions **************************************************************************************************/ +/* Initialization. */ +void lctrRegisterChClassHandler(lctrChClassHdlr_t cback); + /* Helper routines. */ uint32_t lctrComputeAccessAddr(void); +uint32_t lctrComputeSeedAccessAddr(void); uint8_t lctrComputeHopInc(void); uint8_t lctrPeriodicSelectNextChannel(lmgrChanParam_t *pChanParam, uint16_t eventCounter); void lctrPeriodicBuildRemapTable(lmgrChanParam_t *pChanParam); @@ -177,6 +190,52 @@ static inline uint16_t lctrCalcDID(const uint8_t *pBuf, uint16_t len) return CalcCrc32(LlMathRandNum(), len, pBuf); } +/*************************************************************************************************/ +/*! + * \brief Convert PHYS bit to PHY. + * + * \param physBit PHYS bit. + * + * \return PHY. + */ +/*************************************************************************************************/ +static inline PalBbPhy_t lctrPhysBitToPhy(uint8_t physBit) +{ + switch (physBit) + { + default: + case LL_PHYS_LE_1M_BIT: + return BB_PHY_BLE_1M; + case LL_PHYS_LE_2M_BIT: + return BB_PHY_BLE_2M; + case LL_PHYS_LE_CODED_BIT: + return BB_PHY_BLE_CODED; + } +} + +/*************************************************************************************************/ +/*! + * \brief Convert PHY to PHYS bit. + * + * \param phy PHY. + * + * \return PHYS bit. + */ +/*************************************************************************************************/ +static inline uint8_t lctrPhyToPhysBit(uint8_t phy) +{ + switch (phy) + { + default: + case BB_PHY_BLE_1M: + return LL_PHYS_LE_1M_BIT; + case BB_PHY_BLE_2M: + return LL_PHYS_LE_2M_BIT; + case BB_PHY_BLE_CODED: + return LL_PHYS_LE_CODED_BIT; + } +} + #ifdef __cplusplus }; #endif diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_ae.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_ae.h index 05708f3eb1..afa53fb477 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_ae.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_ae.h @@ -1,24 +1,26 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Extended advertising common header file */ + * \file + * + * \brief Extended advertising common header file + * + * Copyright (c) 2018-2019 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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 LCTR_INT_ADV_AE_H @@ -26,65 +28,49 @@ #include "ll_defs.h" #include "lctr_api.h" +#include "lctr_api_adv_acad.h" #include #ifdef __cplusplus extern "C" { #endif -/*! \brief Acad parameter indicies */ +/*! \brief ACAD parameter indices */ enum { LCTR_ACAD_ID_CHAN_MAP_UPDATE, + LCTR_ACAD_ID_BIG_INFO, - /* Total number of Acad IDs. */ + /* Total number of ACAD IDs. */ LCTR_ACAD_NUM_ID, /* Invalid ID type. */ LCTR_ACAD_INVALID_ID = 0xFF }; -/*! \brief Acad states */ +/*! \brief ACAD states */ enum { LCTR_ACAD_STATE_DISABLED = 0, LCTR_ACAD_STATE_ENABLED, - LCTR_ACAD_STATE_TOTAL }; -/*! \brief Acad Common events */ +/*! \brief ACAD Common events */ enum { LCTR_ACAD_COMM_MSG_START, LCTR_ACAD_COMM_MSG_FINISH, - LCTR_ACAD_COMM_MSG_TOTAL, - LCTR_ACAD_COMM_MSG_INVALID = 0xFF }; -/*! \brief Acad header */ -typedef struct -{ - uint8_t state; /* State of Acad. */ - uint8_t opcode; /* Opcode of Acad. */ - uint8_t len; /* Length of Acad data field. */ -} lctrAcadHdr_t; - -/*! \brief Acad data field for channel map update */ -typedef struct -{ - lctrAcadHdr_t hdr; /* Acad header. */ - uint64_t chanMask; /* Channel mask for the update. */ - uint16_t instant; /* Instant for the update. */ -} lctrAcadChanMapUpd_t; - -/*! \brief Generic Acad packet. */ +/*! \brief Generic ACAD packet. */ typedef union { - lctrAcadHdr_t hdr; /* Acad header. */ - lctrAcadChanMapUpd_t chanMapUpdate; /* Channel map update. */ + LctrAcadHdr_t hdr; /*!< ACAD header. */ + LctrAcadChanMapUpd_t chanMapUpdate; /*!< Channel map update. */ + LctrAcadBigInfo_t bigInfo; /*!< BIG info. */ } lctrAcadParam_t; #ifdef __cplusplus diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_master.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_master.h index 93782d1e60..ce5ef69cb5 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_master.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_master.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal link layer controller scanning master interface file. + * \file + * + * \brief Internal link layer controller scanning master interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ @@ -38,8 +39,8 @@ extern "C" { Macros **************************************************************************************************/ -/*! \brief Minimum amount of time required for scanning, to be same as minimum time in BB(1528us). */ -#define LCTR_MIN_SCAN_USEC BB_SCAN_GUARD_US +/*! \brief Minimum amount of time required for scanning, to cover ADV + SCAN REQ + SCAN RSP. */ +#define LCTR_MIN_SCAN_USEC BB_MIN_SCAN_US /************************************************************************************************** Constants @@ -80,7 +81,7 @@ typedef struct wsfQueue_t rxAdvbQ; /*!< Receive ADVB queue. */ wsfQueue_t rxDirectAdvbQ; /*!< Receive direct ADVB queue. */ - uint32_t scanWinStart; /*!< Scan window origin. */ + uint32_t scanWinStartUsec; /*!< Scan window origin in microseconds. */ lmgrScanParam_t scanParam; /*!< Scan parameters. */ @@ -100,7 +101,6 @@ typedef struct uint64_t localRpa; /*!< Local RPA. */ uint16_t connHandle; /*!< Connection handle. */ uint16_t connInterval; /*!< Connection interval. */ - uint32_t firstCeDue; /*!< First CE due time. */ bool_t connBodLoaded; /*!< Connection BOD loaded flag. */ uint8_t usedChSel; /*!< Used channel selection. */ } init; /*!< Initiation specific data. */ @@ -144,7 +144,7 @@ void lctrMstDiscoverAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pAd bool_t lctrMstScanReqTxCompHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf); bool_t lctrMstScanRspRxCompHandler(BbOpDesc_t *pOp, const uint8_t *pRspBuf); -/* Action routines. */ +/* Action routines */ void lctrScanActDiscover(void); void lctrScanActShutdown(void); void lctrScanActScanCnf(void); @@ -158,15 +158,15 @@ void lctrInitActInitiate(void); void lctrInitActConnect(void); void lctrInitActShutdown(void); -/* Helper routines. */ +/* Helper routines */ void lctrScanCleanup(lctrMstScanCtx_t *pCtx); void lctrScanNotifyHostInitiateError(uint8_t reason, uint8_t peerAddrType, uint64_t peerAddr); -/* Channel. */ +/* Channel */ uint8_t lctrScanChanSelectInit(uint8_t chanMap); uint8_t lctrScanChanSelectNext(uint8_t chanIdx, uint8_t chanMap); -/* Advertising report filtering. */ +/* Advertising report filtering */ void lctrAdvRptEnable(lctrAdvRptFilt_t *pAdvFilt, bool_t filtEna); void lctrAdvRptGenerateLegacyHash(uint64_t *pHash, uint8_t addrType, uint64_t addr, uint8_t eventType); void lctrAdvRptGenerateExtHash(uint64_t *pHash, uint8_t addrType, uint64_t addr, uint8_t eventType, diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_master_ae.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_master_ae.h index 91090a0992..a69af4b68b 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_master_ae.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_master_ae.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal link layer controller extended scanning master interface file. + * \file + * + * \brief Internal link layer controller extended scanning master interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -42,13 +43,22 @@ extern "C" { **************************************************************************************************/ /*! \brief Resolve the extended scan handle from the context pointer. */ -#define LCTR_GET_EXT_SCAN_HANDLE(pCtx) (pCtx - lctrMstExtScanTbl) +#define LCTR_GET_EXT_SCAN_HANDLE(pCtx) (pCtx->handle) + +/*! \brief Resolve the extended scan context from the handle. */ +#define LCTR_GET_EXT_SCAN_CTX(h) (lctrMstExtScanTbl[h]) /*! \brief Resolve the periodic scanning handle from the context pointer. */ #define LCTR_GET_PER_SCAN_HANDLE(pCtx) (pCtx - lctrMstPerScanTbl) +/*! \brief Get topology manager handle from the periodic scanning context pointer. */ +#define LCTR_GET_PER_SCAN_TM_HANDLE(pCtx) (LL_MAX_CONN + LCTR_GET_PER_SCAN_HANDLE(pCtx)) + /*! \brief Resolve the periodic scanning context from the handle. */ -#define LCTR_GET_PER_SCAN_CTX(h) &(lctrMstPerScanTbl[h]) +#define LCTR_GET_PER_SCAN_CTX(h) (&lctrMstPerScanTbl[h]) + +/*! \brief Valid active scan mask. */ +#define LCTR_VALID_ACTIVE_SCAN_MASK ((1 << LCTR_SCAN_PHY_1M) | (1 << LCTR_SCAN_PHY_CODED)) /************************************************************************************************** Constants @@ -121,9 +131,11 @@ typedef struct uint8_t state; /*!< Scan state. */ bool_t selfTerm; /*!< Self-termination flag. */ bool_t shutdown; /*!< Client initiated shutdown flag. */ - uint32_t scanWinStart; /*!< Scan window origin. */ + bool_t bodAborted; /*!< True if BOD was aborted by scheduler. */ + uint32_t scanWinStartUsec; /*!< Scan window origin in microseconds. */ LlScanParam_t scanParam; /*!< Scan parameters. */ /* N.B. Scan parameters must persist after initiate. */ + uint8_t handle; /*!< Scan handle. */ union { struct @@ -150,9 +162,7 @@ typedef struct uint64_t localRpa; /*!< Local RPA. */ uint16_t connHandle; /*!< Connection handle. */ uint16_t connInterval; /*!< Connection interval. */ - uint32_t firstCeDue; /*!< First CE due time. */ - uint32_t scanWinStart; /*!< Scan window origin. */ - bool_t connBodLoaded; /*!< Connection BOD loaded flag. */ + uint32_t scanWinStartUsec; /*!< Scan window origin in microseconds. */ bool_t isLegacy; /*!< TRUE if legacy advertising PDU is received. */ uint8_t usedChSel; /*!< Used channel selection. */ uint8_t filtPolicy; /*!< Initiate filter policy. */ @@ -188,7 +198,7 @@ typedef struct { /* State. */ uint8_t enaPhys; /*!< Enabled PHYs. */ - bool_t scanTermByHost; /*!< Host initiated scan disable. */ + uint8_t scanTermByHost; /*!< Times host initiated scan disable. */ uint32_t nextScanWinStart; /*!< Next scan window origin. */ /* Report */ @@ -203,6 +213,17 @@ typedef struct wsfTimer_t tmrScanPer; /*!< Scan period timer. */ } lctrExtScanCtrlBlk_t; +/*! \brief Active extended scanning context. */ +typedef struct +{ + uint8_t scanMask; /*!< Mask for active scan contexts. */ + uint8_t scanIndex; /*!< Index of the active scan context. */ + uint8_t bodSchMask; /*!< Mask for BOD scheduling for each phy. */ +} lctrActiveExtScan_t; + +/*! \brief Termination event handler call signature. */ +typedef void (*lctrTermHdlr_t)(uint16_t syncHandle); + /*! \brief Periodic scanning context. */ typedef struct { @@ -215,6 +236,7 @@ typedef struct bool_t repDisabled; /*!< Reporting disabled. */ 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. */ /* Report handling. */ LlPerAdvReportInd_t advRpt; /*!< Periodic advertising report. */ @@ -227,18 +249,17 @@ typedef struct /* Peer periodic advertising parameters */ uint16_t eventCounter; /*!< Connection event counter. */ - uint32_t perInter; /*!< Periodic scanning interval in BB ticks. */ + uint32_t perInterUsec; /*!< Periodic scanning interval in microseconds. */ uint8_t sca; /*!< Sleep clock accuracy. */ - uint32_t skipInter; /*!< Skip interval in BB ticks. */ + uint32_t skipInterUsec; /*!< Skip interval in microseconds. */ uint32_t minDurUsec; /*!< Minimum required duration in microseconds. */ uint32_t rxSyncDelayUsec; /*!< Receive timeout in microseconds. */ - uint32_t lastAnchorPoint; /*!< Last anchor point in BB tick. */ + 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. */ - /* Acad control block */ - /* Note: for now, the acad type only applies to the periodic context. */ - lctrAcadParam_t acadParams[LCTR_ACAD_NUM_ID]; /*!< Acad control block array. */ + /* ACAD */ + lctrAcadParam_t acadParams[LCTR_ACAD_NUM_ID]; /*!< ACAD control block array. */ /* Local periodic scanning parameters */ uint16_t skip; /*!< Skip. */ @@ -249,7 +270,6 @@ typedef struct /* RF parameters */ int8_t rssi; /*!< RSSI. */ - lmgrChanParam_t chanParam; /*!< Channel parameters. */ /* Supervision */ @@ -279,19 +299,19 @@ typedef struct lctrPerScanCtx_t *pPerScanCtx; /*!< Current synchronous context. */ } lctrPerCreateSyncCtrlBlk_t; -/*! \brief Acad message header. */ +/*! \brief ACAD message header. */ typedef struct { uint16_t eventCtr; /*!< Current event counter. */ uint16_t skip; /*!< Skip amount. */ - uint8_t acadId; /*!< Acad ID being processed. */ + uint8_t acadId; /*!< ACAD ID being processed. */ uint16_t handle; /*!< Active Handle. */ } lctrAcadMsgHdr_t; -/*! \brief Acad message generic type. */ +/*! \brief ACAD message generic type. */ typedef union { - lctrAcadMsgHdr_t hdr; /*!< Header of an Acad Msg. */ + lctrAcadMsgHdr_t hdr; /*!< Header of an ACAD message. */ } lctrAcadMsg_t; /*! \brief Periodic sync transfer state context. */ @@ -312,8 +332,9 @@ typedef struct Globals **************************************************************************************************/ -extern lctrExtScanCtx_t lctrMstExtScanTbl[LCTR_SCAN_PHY_TOTAL]; +extern lctrExtScanCtx_t * lctrMstExtScanTbl[LCTR_SCAN_PHY_TOTAL]; extern lctrExtScanCtrlBlk_t lctrMstExtScan; +extern lctrActiveExtScan_t lctrActiveExtScan; extern lctrPerCreateSyncCtrlBlk_t lctrPerCreateSync; extern lctrPerTransferSyncCtrlBlk_t lctrPerTransferSync; extern lctrPerScanCtx_t lctrMstPerScanTbl[LL_MAX_PER_SCAN]; @@ -333,7 +354,7 @@ void lctrMstPerScanTransferOpCommit(uint16_t connHandle); /* ISR: Discovery packet handlers */ bool_t lctrMstDiscoverRxExtAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf); -void lctrMstDiscoverRxExtAdvPktPostProcessHandler(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); bool_t lctrMstDiscoverRxAuxScanRspHandler(BbOpDesc_t *pOp, const uint8_t *pRspBuf); uint32_t lctrMstDiscoverRxAuxChainHandler(BbOpDesc_t *pOp, const uint8_t *pChainBuf); @@ -343,6 +364,7 @@ bool_t lctrMstDiscoverTxLegacyScanReqHandler(BbOpDesc_t *pOp, const uint8_t *pRe bool_t lctrMstDiscoverRxLegacyScanRspHandler(BbOpDesc_t *pOp, const uint8_t *pRspBuf); /* ISR: Discovery BOD handlers */ void lctrMstExtDiscoverEndOp(BbOpDesc_t *pOp); +void lctrMstExtDiscoverAbortOp(BbOpDesc_t *pOp); void lctrMstAuxDiscoverEndOp(BbOpDesc_t *pOp); void lctrMstPerScanEndOp(BbOpDesc_t *pOp); void lctrMstPerScanAbortOp(BbOpDesc_t *pOp); @@ -353,7 +375,9 @@ bool_t lctrMstPerScanRxPerAdvPktPostHandler(BbOpDesc_t *pOp, const uint8_t *pAdv void lctrExtScanActDiscover(lctrExtScanCtx_t *pExtScanCtx); void lctrExtScanActShutdown(lctrExtScanCtx_t *pExtScanCtx); void lctrExtScanActScanCnf(lctrExtScanCtx_t *pExtScanCtx); +void lctrExtScanHostDisable(lctrExtScanCtx_t *pExtScanCtx); void lctrExtScanActDisallowScan(lctrExtScanCtx_t *pExtScanCtx); +void lctrExtScanActHostEnable(lctrExtScanCtx_t *pExtScanCtx); void lctrExtScanActScanTerm(lctrExtScanCtx_t *pExtScanCtx); void lctrExtScanActSelfTerm(lctrExtScanCtx_t *pExtScanCtx); void lctrExtScanActUpdateDiscover(lctrExtScanCtx_t *pExtScanCtx); @@ -444,8 +468,6 @@ static inline uint8_t lctrConvertAuxPtrPhyToBbPhy(uint8_t auxPtrPhy) * \param pAuxPtr Auxiliary Pointer. * \param pOffsetUsec Return auxiliary offset in microseconds. * \param pSyncDelayUsec Return synchronization delay in microseconds. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrMstComputeAuxOffset(lctrAuxPtr_t *pAuxPtr, uint32_t *pOffsetUsec, uint32_t *pSyncDelayUsec) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_slave.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_slave.h index 179af533f4..87cc8c1806 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_slave.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_slave.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal link layer controller advertising slave interface file. + * \file + * + * \brief Internal link layer controller advertising slave interface file. + * + * Copyright (c) 2013-2017 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ @@ -79,7 +80,7 @@ typedef struct uint8_t usedChSel; /*!< Used channel selection. */ BbOpDesc_t advBod; /*!< Advertising BOD. */ BbBleData_t bleData; /*!< BLE BB operation data. */ - uint32_t reqEndTs; /*!< Last received request end of packet timestamp. */ + uint32_t reqEndTsUsec; /*!< Last received request end of packet timestamp in microseconds. */ /* Scan buffer (placed here to 32-bit align) */ uint8_t scanRspBuf[LL_ADVB_MAX_LEN]; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_slave_ae.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_slave_ae.h index 82124a47ea..1dd7f971b1 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_slave_ae.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_adv_slave_ae.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal link layer controller slave extended advertising interface file. + * \file + * + * \brief Internal link layer controller slave extended advertising interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -65,6 +66,12 @@ extern "C" { /*! \brief Get reservation manager handle for periodic ADV from the context pointer. */ #define LCTR_GET_PER_RM_HANDLE(pAdvSet) (LL_MAX_CONN + LCTR_GET_EXT_ADV_INDEX(pAdvSet)) +/*! \brief Call signature for slave ACAD BIG related function. */ +typedef void (*lctrAcadBigHdlr_t)(uint8_t advHandle); + +/*! \brief Call signature for AdvSet Remove event handler. */ +typedef void (*lctrRemoveHdlr_t)(uint8_t advHandle); + /************************************************************************************************** Constants **************************************************************************************************/ @@ -96,22 +103,22 @@ enum /*! \brief Extended advertising parameters. */ typedef struct { - uint16_t advEventProp; /*!< Advertising Event Properties. */ - uint32_t priAdvInterMin; /*!< Primary Advertising Interval Minimum. */ - uint32_t priAdvInterMax; /*!< Primary Advertising Interval Maximum. */ - uint32_t priAdvTermCntDown; /*!< Primary Advertising termination count down. */ - uint64_t peerAddr; /*!< Peer Address. */ - uint8_t priAdvChanMap; /*!< Primary Advertising Channel Map. */ - uint8_t ownAddrType; /*!< Own Address Type. */ - uint8_t peerAddrType; /*!< Peer Address Type. */ - uint8_t advFiltPolicy; /*!< Advertising Filter Policy. */ - int8_t advTxPwr; /*!< Advertising Tx Power. */ - uint8_t priAdvPhy; /*!< Primary Advertising PHY. */ - uint8_t secAdvMaxSkip; /*!< Secondary Advertising Maximum Skip. */ - uint8_t secAdvPhy; /*!< Secondary Advertising PHY. */ - uint16_t advDID; /*!< Advertising Data ID. */ - uint8_t advSID; /*!< Advertising SID. */ - uint8_t scanReqNotifEna; /*!< Scan Request Notification Enable. */ + uint16_t advEventProp; /*!< Advertising Event Properties. */ + uint32_t priAdvInterMinUsec; /*!< Primary Advertising Interval Minimum in microseconds. */ + uint32_t priAdvInterMaxUsec; /*!< Primary Advertising Interval Maximum in microseconds. */ + uint32_t priAdvTermCntDownUsec; /*!< Primary Advertising termination count down in microseconds. */ + uint64_t peerAddr; /*!< Peer Address. */ + uint8_t priAdvChanMap; /*!< Primary Advertising Channel Map. */ + uint8_t ownAddrType; /*!< Own Address Type. */ + uint8_t peerAddrType; /*!< Peer Address Type. */ + uint8_t advFiltPolicy; /*!< Advertising Filter Policy. */ + int8_t advTxPwr; /*!< Advertising Tx Power. */ + uint8_t priAdvPhy; /*!< Primary Advertising PHY. */ + uint8_t secAdvMaxSkip; /*!< Secondary Advertising Maximum Skip. */ + uint8_t secAdvPhy; /*!< Secondary Advertising PHY. */ + uint16_t advDID; /*!< Advertising Data ID. */ + uint8_t advSID; /*!< Advertising SID. */ + uint8_t scanReqNotifEna; /*!< Scan Request Notification Enable. */ } lctrExtAdvParam_t; /*! \brief Periodic advertising parameters. */ @@ -129,10 +136,10 @@ typedef struct uint8_t perChHopInc; /*!< Periodic channel hop increment value. */ uint8_t perChIdx; /*!< Periodic LL Channel. */ bool_t shutdown; /*!< Client initiated shutdown flag. */ - uint32_t perAdvInter; /*!< Periodic advertising interval in BB ticks. */ + uint32_t perAdvInterUsec; /*!< Periodic advertising interval in microseconds. */ - uint32_t advInterMin; /*!< Periodic Advertising Interval Minimum in BB ticks. */ - uint32_t advInterMax; /*!< Periodic Advertising Interval Maximum in BB ticks. */ + 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. */ bool_t advParamReady; /*!< Periodic Advertising Parameter is ready or not. */ @@ -190,8 +197,8 @@ typedef struct uint32_t auxDelayUsec; /*!< Auxiliary advertising event delay. */ uint8_t advDataFragLen; /*!< Advertising data fragmentation length. */ - /* Acad control block */ - lctrAcadParam_t acadParams[LCTR_ACAD_NUM_ID]; /*!< Acad parameters. */ + /* ACAD control block */ + lctrAcadParam_t acadParams[LCTR_ACAD_NUM_ID]; /*!< ACAD parameters. */ /* Periodic advertising parameters */ lctrPerAdvParam_t perParam; /*!< Periodic advertising parameters. */ @@ -206,7 +213,7 @@ typedef struct uint8_t extHdrFlags; /*!< Extended header flags. */ uint8_t *pExtAdvAuxPtr; /*!< Extended advertising PDU buffer location of AuxPtr field. */ uint8_t auxChHopInc; /*!< Auxiliary channel hop increment value. */ - uint32_t auxSkipInter; /*!< Total skip time in BB ticks. */ + uint32_t auxSkipInterUsec; /*!< Total skip time in microseconds. */ /* Buffers */ uint8_t advHdrBuf[LCTR_EXT_ADVB_LEN(LL_EXT_ADV_HDR_MAX_LEN, 0)]; @@ -225,7 +232,7 @@ typedef struct /* Connection context. */ bool_t isAuxConnReq; /*!< True if AUX_CONN_REQ is received, False if CONN_IND is received. */ - uint32_t connIndEndTs; /*!< Connection indication end timestamp. */ + uint32_t connIndEndTsUsec; /*!< Connection indication end timestamp in microseconds. */ bool_t connIndRcvd; /*!< Connection request received flag. */ uint8_t usedChSel; /*!< Used channel selection. */ @@ -242,6 +249,11 @@ typedef struct bool_t didPerUpdate; /*!< Data ID update due to periodic enable or disable. */ bool_t advBodAbort; /*!< TRUE if extended advertising BOD is aborted. */ lctrAdvbPduHdr_t rspPduHdr; /*!< Response PDU header. */ + + /* BIG */ + lctrAcadBigHdlr_t bigCreated; /*!< Function pointer to the BIG created action function. */ + lctrAcadBigHdlr_t bigTerminated; /*!< Function pointer to the BIG terminated action function. */ + lctrRemoveHdlr_t removeCback; /*!< Function pointer to the AdvSet remove action function. */ } lctrAdvSet_t; /*! \brief Slave extended advertising state context. */ @@ -258,6 +270,7 @@ extern lctrAdvSet_t *pLctrAdvSetTbl; extern LctrExtAdvMsg_t *pLctrSlvExtAdvMsg; extern lctrSlvExtAdvCtx_t lctrSlvExtAdv; extern LctrPerAdvMsg_t *pLctrSlvPerAdvMsg; +extern lctrAcadSlvMsg_t *pLctrAcadSlvMsg; /************************************************************************************************** Function Declarations @@ -284,17 +297,18 @@ void lctrSelectNextAuxChannel(lctrAdvSet_t *pAdvSet); void lctrSelectNextPerChannel(lctrAdvSet_t *pAdvSet); /* ISR: Packet handlers */ -void lctrSlvTxSetupExtAdvHandler(BbOpDesc_t *pOp, uint32_t txTime); +void lctrSlvTxSetupExtAdvHandler(BbOpDesc_t *pOp, uint32_t txTime); uint32_t lctrSlvTxSetupAuxAdvDataHandler(BbOpDesc_t *pOp, bool_t isChainInd); uint32_t lctrSlvTxSetupAuxScanRspDataHandler(BbOpDesc_t *pOp, bool_t isChainInd); bool_t lctrSlvRxAuxScanReqHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf); -void lctrSlvRxAuxScanReqPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf); -void lctrSlvRxLegacyScanReqPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf); +void lctrSlvRxAuxScanReqPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf); +void lctrSlvRxLegacyScanReqPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf); bool_t lctrSlvRxAuxConnReqHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf); bool_t lctrSlvRxLegacyReqHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf); -void lctrSlvRxLegacyReqPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf); +void lctrSlvRxLegacyReqPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf); uint32_t lctrSlvTxSetupPeriodicAdvDataHandler(BbOpDesc_t *pOp, bool_t isChainInd); -void lctrSlvAcadHandler(lctrAdvSet_t *pAdvSet); +void lctrSlvAcadHandler(lctrAdvSet_t *pAdvSet); +void lctrSlvAcadDisable(lctrAcadParam_t *pAcadParam); /* ISR: BOD handlers */ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp); @@ -324,6 +338,8 @@ void lctrPeriodicAdvActResetTerm(lctrAdvSet_t *pAdvSet); void lctrPeriodicAdvActAdvTerm(lctrAdvSet_t *pAdvSet); void lctrSlvAcadActChanMapUpdateStart(lctrAdvSet_t *pAdvSet); void lctrSlvAcadActChanMapUpdateFinish(lctrAdvSet_t *pAdvSet); +void lctrSlvAcadActBigCreated(lctrAdvSet_t *pAdvSet); +void lctrSlvAcadActBigTerminated(lctrAdvSet_t *pAdvSet); /* Reservation */ uint32_t lctrGetPerRefTime(uint8_t perHandle, uint32_t *pDurUsec); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis.h new file mode 100644 index 0000000000..c2541366d6 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis.h @@ -0,0 +1,292 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Internal link layer controller connected isochronous interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 LCTR_INT_BIS_H +#define LCTR_INT_BIS_H + +#include "lctr_int_adv_slave_ae.h" +#include "lctr_int_adv_master_ae.h" +#include "lctr_int.h" +#include "lctr_int_iso.h" +#include "lctr_pdu_iso.h" +#include "bb_ble_api.h" +#include "pal_codec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief Get encryption ID from BIG context. */ +#define LCTR_BIG_CTRL_ENC_ID(pBigCtx) (LL_MAX_CONN + LL_MAX_CIG + LL_MAX_BIG + (pBigCtx - &pLctrBigTbl[0])) + +/*! \brief ISO Data PDU start offset in a buffer. */ +#define LCTR_ISO_SDU_START_OFFSET (HCI_ISO_HDR_LEN + HCI_ISO_DL_MAX_LEN - LL_ISO_DATA_HDR_LEN) + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +struct lctrBigCtx_tag; + +/*! \brief Broadcast Isochronous Stream (BIS) context. */ +typedef struct +{ + bool_t enabled; /*!< Enable flag. */ + uint8_t bisNum; /*!< BIS positional sequence number. */ + uint16_t handle; /*!< BIS handle. */ + struct lctrBigCtx_tag *pBigCtx; /*!< BIG context. */ + + union + { + 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. */ + + 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. */ + + /* ISO test */ + LlIsoTestCtrs_t stats; /*!< Rx statistics. */ + } mst; /*!< BIS master specific data. */ + } roleData; /*!< Role specific data. */ + + /* ISO test */ + struct + { + bool_t enabled; /*!< TRUE ISO test enabled, FALSE otherwise. */ + bool_t term; /*!< Flag for ISO test termination. */ + bool_t pendInit; /*!< Receive pending init. */ + union + { + struct + { + uint32_t payloadCtr; /*!< Payload counter for framed transmissions. */ + } framed; /*!< Framed context. */ + 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. */ + + /* 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; + +/*! \brief Broadcast Isochronous Group (BIG) context. */ +typedef struct lctrBigCtx_tag +{ + bool_t enabled; /*!< Context enabled. */ + uint8_t state; /*!< Current state. */ + uint8_t handle; /*!< BIG handle. */ + LlRole_t role:8; /*!< Role. */ + + /* Data */ + uint16_t maxPdu; /*!< Maximum size of BIS Data PDU. */ + uint16_t maxSdu; /*!< Maximum size of ISO SDU. */ + + /* Host */ + uint32_t sduInterUsec; /*!< SDU interval in microseconds. */ + uint32_t bisSpaceUsec; /*!< BIS space in microseconds. */ + uint32_t isoInterUsec; /*!< Isochronous PDU interval in microseconds. */ + uint8_t bn; /*!< Burst number. */ + uint8_t nse; /*!< Maximum number of subevent in each interval on BIS. */ + uint8_t pto; /*!< Pre-transmission offset. */ + uint8_t irc; /*!< Immediate repetition count. */ + LlFraming_t framing:8; /*!< BIS Data PDU format. */ + LlPacking_t packing:8; /*!< Packing sequence scheme. */ + + /* ISO Event */ + uint64_t eventCounter; /*!< Event counter. */ + uint32_t syncDelayUsec; /*!< Synchronization delay in microseconds. */ + uint32_t transLatUsec; /*!< The maximum transmission latency, in microseconds. */ + uint32_t subInterUsec; /*!< Subevent interval in microseconds. */ + + /* BIS */ + uint8_t numBis; /*!< Number of BISs. */ + lctrBisCtx_t *pBisCtx[LL_MAX_BIS]; /*!< BIS contexts. */ + + union + { + struct + { + lctrAdvSet_t *pAdvSet; /*!< Advertising Set parent. */ + wsfQueue_t txCtrlQ; /*!< Transmit BIG control queue. */ + bool_t notifyHostEst; /*!< Notify host event sent flag. */ + } slv; /*!< BIG slave specific data. */ + + struct + { + /* BIG Create Sync */ + lctrPerScanCtx_t *pPerScanCtx; /*!< Periodic Scan parent. */ + bool_t syncLostReason; /*!< BIG synchronization lost. */ + uint8_t mse; /*!< Maximum number of subevents. */ + uint8_t numBisIdx; /*!< Total number of BISes in the BIG. */ + 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. */ + + /* Encryption */ + uint8_t bcstCode[LL_BC_LEN]; /*!< Broadcast Code. */ + } mst; /*!< BIG master specific data. */ + } roleData; /*!< Role-specific data. */ + + /* Control */ + struct + { + uint8_t actMsk; /*!< Active control procedure bitmask. */ + uint8_t pendMsk; /*!< Pending control procedure bitmask. */ + uint8_t cssn; /*!< Control Subevent Sequence Number */ + struct + { + uint16_t inst; /*!< Instant. */ + uint64_t chanMap; /*!< Channel map. */ + } chanMapUpd; /*!< Channel Map Update data. */ + struct + { + uint16_t inst; /*!< Instant. */ + uint8_t reason; /*!< Termination reason. */ + } term; /*!< Terminate data. */ + } bcp; /*!< BIG Control Procedure data. */ + + /* BB */ + PalBbPhy_t phy:8; /*!< PHY used for the BIG. */ + BbOpDesc_t bod; /*!< BIG BOD. */ + BbBleData_t bleData; /*!< BLE BB operation data. */ + uint32_t seedAccAddr; /*!< Seed access address. */ + uint16_t baseCrcInit; /*!< Base CRC Init. */ + lmgrChanParam_t ctrChSelInfo; /*!< Control channel selection state. */ + PalBbBleChan_t ctrChan; /*!< BIG Control channelization parameters. */ + + /* Encryption */ + /* Note: located at end of structure for non-encryption optimization */ + 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. */ +typedef struct +{ + uint8_t bisEvtIdx; /*!< BIS event index within an event. */ + uint8_t burstIdx; /*!< Burst index within a subevent. */ + uint8_t repIdx; /*!< Repeat index within a subevent. */ + uint8_t ptIdx; /*!< Pre-transmission index within a subevent. */ +} lctrSeCtx_t; + +/************************************************************************************************** + Globals +**************************************************************************************************/ + +extern lctrBisCtx_t *pLctrBisTbl; +extern lctrBigCtx_t *pLctrBigTbl; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/* BIG Context */ +lctrBigCtx_t *lctrAllocBigCtx(uint8_t bigHandle); +void lctrFreeBigCtx(lctrBigCtx_t *pBigCtx); +uint8_t lctrBigIsPerAdvUsed(uint8_t handle); +lctrBigCtx_t *lctrFindBigByHandle(uint8_t bigHandle); +lctrBigCtx_t *lctrFindBigBySyncHandle(uint16_t syncHandle); +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); +uint32_t lctrComputeBisAccessAddr(uint32_t seedAccAddr, uint8_t bisNum); +void lctrSetupBisContext(lctrBisCtx_t *pBisCtx, uint32_t seedAccAddr, uint16_t baseCrcInit, uint64_t chMap, LlPhy_t phy); +void lctrSelectBigChannels(lctrBigCtx_t *pBigCtx); +void lctrRemapBigChannels(lctrBigCtx_t *pBigCtx, uint64_t chanMap); + +/* BIS Tx Data Path */ +void lctrBisTxIsoPduQueue(lctrBisCtx_t *pBisCtx, lctrIsoHdr_t *pIsoHdr, uint8_t *pIsoSdu); +uint8_t lctrBisTxQueuePeek(lctrBisCtx_t *pBisCtx, uint8_t burstIdx, PalBbBleTxBufDesc_t *descs); +void lctrBisTxQueuePopCleanup(lctrBisCtx_t *pBisCtx, uint8_t numFrag); +uint8_t *lctrBigTxCtrlAlloc(uint8_t pduLen); +void lctrBigTxCtrlQueue(lctrBigCtx_t *pBigCtx, uint8_t *pBuf, uint8_t numReTx); +uint8_t *lctrBigTxCtrlQueuePeek(lctrBigCtx_t *pBigCtx); +void lctrBigTxCtrlQueuePop(lctrBigCtx_t *pBigCtx); +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); + +/* ISO Test mode */ +uint8_t lctrBisTxTest(lctrBisCtx_t *pBisCtx, uint8_t pldType); +uint8_t lctrBisRxTest(lctrBisCtx_t *pBisCtx, uint8_t pldType); +uint8_t LctrBisReadTestCounters(lctrBisCtx_t *pBisCtx, LlIsoTestCtrs_t *pStats); + +/* BIS helper functions */ +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); + +#ifdef __cplusplus +}; +#endif + +#endif /* LCTR_INT_BIS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis_master.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis_master.h new file mode 100644 index 0000000000..54b72e3adb --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis_master.h @@ -0,0 +1,99 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Internal link layer controller isochronous master interface file. + * + * Copyright (c) 2019 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 LCTR_INT_BIS_MASTER_H +#define LCTR_INT_BIS_MASTER_H + +#include "lctr_api_bis_master.h" +#include "lctr_int_bis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief Get reservation manager handle for BIG from the context pointer. */ +#define LCTR_GET_BIG_RM_HANDLE(pBigCtx) (LL_MAX_CONN + LL_MAX_ADV_SETS + LL_MAX_BIG + (pBigCtx - &pLctrBigTbl[0])) + +/*! \brief Resolve BIG context pointer from the reservation manager handle. */ +#define LCTR_GET_BIG_RM_CTX(rmHandle) &(pLctrBigTbl[rmHandle - (LL_MAX_CONN + LL_MAX_ADV_SETS + LL_MAX_BIG)]) + +/************************************************************************************************** + Constants +**************************************************************************************************/ + +/*! \brief Slave BIG broadcasting states. */ +typedef enum +{ + LCTR_MST_BIG_STATE_DISABLED, /*!< BIG master disabled state. */ + LCTR_MST_BIG_STATE_SYNCING, /*!< BIG master synchronizing state. */ + LCTR_MST_BIG_STATE_SYNCED, /*!< BIG master synchronized state. */ + LCTR_MST_BIG_STATE_SHUTDOWN, /*!< BIG master shutdown in progress. */ + LCTR_MST_BIG_STATE_RESET, /*!< BIG master reset in progress. */ + LCTR_MST_BIG_STATE_TOTAL /*!< Total number of BIG master states. */ +} lctrMstBigState_t; + +/************************************************************************************************** + Globals +**************************************************************************************************/ + +extern lctrMstBigMsg_t *pLctrMstBigMsg; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/* Host Events */ +void lctrNotifyHostBigTerminateComplete(LlStatus_t status, uint8_t bigHandle); +void lctrNotifyHostSyncLost(uint8_t bigHandle, LlStatus_t reason); + +/* State machine for BIG master */ +void lctrMstBigSendMsg(lctrBigCtx_t *pBigCtx, LctrMstBigMsg_t event); +void lctrMstBigExecuteSm(lctrBigCtx_t *pBigCtx, LctrMstBigMsg_t event); + +/* Action routines */ +void lctrMstBigActStart(lctrBigCtx_t *pBigCtx); +void lctrMstBigActBigSync(lctrBigCtx_t *pBigCtx); +void lctrMstBigActTerm(lctrBigCtx_t *pBigCtx); +void lctrMstBigActShutdown(lctrBigCtx_t *pBigCtx); +void lctrMstBigActSyncLost(lctrBigCtx_t *pBigCtx); +void lctrMstBigActMicFailed(lctrBigCtx_t *pBigCtx); +void lctrMstBigActCleanup(lctrBigCtx_t *pBigCtx); + +/* Builder */ +void lctrMstBigBuildOp(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo); +void lctrMstSetupBigContext(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo); +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 lctrMstBigEndOp(BbOpDesc_t *pOp); + +#ifdef __cplusplus +}; +#endif + +#endif /* LCTR_INT_BIS_MASTER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis_slave.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis_slave.h new file mode 100644 index 0000000000..d5824f4dc2 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_bis_slave.h @@ -0,0 +1,95 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Internal link layer controller isochronous slave interface file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 LCTR_INT_BIS_SLAVE_H +#define LCTR_INT_BIS_SLAVE_H + +#include "lctr_api_bis_slave.h" +#include "lctr_int_bis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief Get reservation manager handle from BIG context. */ +#define LCTR_BIG_TO_RM_HANDLE(pBigCtx) (LL_MAX_CONN + LL_MAX_ADV_SETS + LL_MAX_CIG + (pBigCtx - &pLctrBigTbl[0])) + +/*! \brief Get BIG context from reservation manager handle. */ +#define LCTR_RM_HANDLE_TO_BIG(rmHandle) (&pLctrBigTbl[(rmHandle) - LL_MAX_CONN - LL_MAX_ADV_SETS - LL_MAX_CIG]) + +/************************************************************************************************** + Constants +**************************************************************************************************/ + +/*! \brief Slave BIS broadcasting states. */ +enum +{ + LCTR_SLV_BIG_STATE_DISABLED, /*!< BIS slave broadcasting disabled state. */ + LCTR_SLV_BIG_STATE_ENABLED, /*!< BIS slave broadcasting enabled state. */ + LCTR_SLV_BIG_STATE_SHUTDOWN, /*!< BIS slave broadcasting shutdown in progress. */ + LCTR_SLV_BIG_STATE_RESET, /*!< BIS slave broadcasting reset in progress. */ + LCTR_SLV_BIG_STATE_TOTAL /*!< Total number of extended advertising states. */ +}; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/* Host events */ +void lctrNotifyHostCreateBigComplete(lctrBigCtx_t *pBigCtx, uint8_t status); +void lctrNotifyHostTerminateBigComplete(lctrBigCtx_t *pBigCtx); + +/* State machine for BIS slave */ +void lctrSlvBigSendMsg(lctrBigCtx_t *pBigCtx, uint8_t event); +void lctrSlvBigSendAcadMsg(lctrBigCtx_t *pBigCtx, uint8_t event); +void lctrSlvBigExecuteSm(lctrBigCtx_t *pBigCtx, uint8_t event); + +/* Action routines */ +void lctrSlvBigActStart(lctrBigCtx_t *pBigCtx); +void lctrSlvBigActSendChMapUpd(lctrBigCtx_t *pBigCtx); +void lctrSlvBigActSendTerm(lctrBigCtx_t *pBigCtx); +void lctrSlvBigActShutdown(lctrBigCtx_t *pBigCtx); +void lctrSlvBigActCleanup(lctrBigCtx_t *pBigCtx); + +/* Builder */ +uint8_t lctrSlvBigBuildOp(lctrBigCtx_t *pBigCtx); + +/* ISR: Packet handlers */ +void lctrSlvBisTxCompletionSequential(BbOpDesc_t *pOp, uint8_t status); +void lctrSlvBisTxCompletionInterleaved(BbOpDesc_t *pOp, uint8_t status); + +/* ISR: BOD handlers */ +void lctrSlvBigBeginOp(BbOpDesc_t *pOp); +void lctrSlvBigEndOp(BbOpDesc_t *pOp); +void lctrSlvBigAbortOp(BbOpDesc_t *pOp); + +#ifdef __cplusplus +}; +#endif + +#endif /* LCTR_INT_BIS_SLAVE_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis.h new file mode 100644 index 0000000000..02d678254f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis.h @@ -0,0 +1,535 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Internal link layer controller connected isochronous stream interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 LCTR_INT_CIS_H +#define LCTR_INT_CIS_H + +#include "lmgr_api_iso.h" +#include "lctr_int.h" +#include "lctr_int_iso.h" +#include "lctr_int_conn.h" +#include "lctr_api_cis.h" +#include "lctr_pdu_conn.h" +#include "bb_ble_api.h" +#include "bb_ble_api_op.h" +#include "lctr_pdu_iso.h" +#include "wsf_timer.h" +#include "pal_codec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief Maximum number of burst number. */ +#define LCTR_MAX_BN 0x0F + +/*! \brief Get reservation manager handle for CIG from the context pointer. */ +#define LCTR_GET_CIG_RM_HANDLE(pCigCtx) (LL_MAX_CONN + LL_MAX_ADV_SETS + (pCigCtx - &pLctrCigTbl[0])) + +/*! \brief Get topology manager handle for CIG from the context pointer. */ +#define LCTR_GET_CIG_TM_HANDLE(pCigCtx) (LL_MAX_CONN + LL_MAX_PER_SCAN + (pCigCtx - &pLctrCigTbl[0])) + +/*! \brief Resolve CIG context pointer from the reservation manager handle. */ +#define LCTR_GET_CIG_RM_CTX(rmHandle) &(pLctrCigTbl[rmHandle - (LL_MAX_CONN + LL_MAX_ADV_SETS)]) + +/*! \brief Resolve CIG context pointer from the topology manager handle. */ +#define LCTR_GET_CIG_TM_CTX(rmHandle) &(pLctrCigTbl[rmHandle - (LL_MAX_CONN + LL_MAX_PER_SCAN)]) + +/*! \brief ISO Data PDU start offset in a buffer. */ +#define LCTR_CIS_DATA_PDU_START_OFFSET 3 + +/*! \brief Data PDU start offset in a buffer. */ +#define LCTR_CIS_DATA_TX_PDU_START_OFFSET 0 + +/************************************************************************************************** + Constants +**************************************************************************************************/ + +/*! \brief CIS main states. */ +enum +{ + LCTR_CIS_STATE_IDLE, /*!< CIS idle state. */ + LCTR_CIS_STATE_EST, /*!< CIS established state. */ + LCTR_CIS_STATE_SHUTDOWN, /*!< CIS terminating state. */ + LCTR_CIS_STATE_TOTAL /*!< Total number of CIS slave states. */ +}; + +/*! \brief CIS termination states. */ +enum +{ + LCTR_CIS_TERM_STATE_IDLE, /*!< Idle state. */ + LCTR_CIS_TERM_STATE_TERMINATING, /*!< Wait for LL_CIS_RSP state. */ + LCTR_CIS_TERM_STATE_TOTAL /*!< Total CIS states. */ +}; + +/*! \brief CIS termination procedure events. */ +enum +{ + LCTR_CIS_TERM_EVENT_HOST_DISC, /*!< Received host disconnect CIS. */ + LCTR_CIS_TERM_EVENT_PEER_DISC, /*!< Received peer disconnect CIS. */ + LCTR_CIS_TERM_EVENT_INT_START_DISC, /*!< Start pending host disconnect CIS procedure. */ + LCTR_CIS_TERM_EVENT_INT_START_PEER_DISC, /*!< Start pending peer disconnect CIS procedure. */ + LCTR_CIS_TERM_EVENT_CIS_TERM, /*!< Received CIS terminated event. */ + LCTR_CIS_TERM_EVENT_TOTAL, /*!< Total CIS events. */ + LCTR_CIS_TERM_EVENT_INVALID = 0xFF /*!< Invalid event. */ +}; + +/*! \brief CIS PDU type. */ +enum +{ + LCTR_CIS_PDU_DEFAULT, /*!< Default PDU. */ + LCTR_CIS_PDU_NULL, /*!< NULL PDU. */ + LCTR_CIS_PDU_EMPTY, /*!< Empty PDU. */ + LCTR_CIS_PDU_NON_EMPTY /*!< Non-empty PDU. */ +}; + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief Parameters related to Tx flush timeout. */ +typedef struct +{ + bool_t pduAcked; /*!< TRUE if current PDU is acked, for Tx only. */ + bool_t pduRcved; /*!< TRUE if current PDU is received, for Rx only. */ + uint8_t bn; /*!< Burst number for the flush timeout. */ + uint8_t pduCounter; /*!< Current PDU counter in term of BN. */ + uint8_t subEvtCounter; /*!< Current subevent counter before flush timeout. */ + uint8_t intervalTotal; /*!< Total number interval before flush timeout. */ + uint8_t intervalCounter; /*!< Current interval counter. */ + + uint8_t lastSubEvtFt[LCTR_MAX_BN]; /*!< Last subevent the PDU could be transmitted before flush timeout for each PDU(in the last interval). */ + uint8_t pduType[LCTR_MAX_BN]; /*!< PDU type, whether NULL, empty or non-empty. */ + bool_t isPduDone[LCTR_MAX_BN]; /*!< TRUE if the PDU is either acked or flushed. */ +} lctrFtParam_t; + +/*! \brief Flush timeout parameter node. */ +typedef struct ftNode +{ + lctrFtParam_t ftParam; /*!< Flush time parameter. */ + struct ftNode *pNext; /*!< Pointer to the next node. */ +} lctrFtParamNode_t; + +/*! \brief Flush timeout parameter list. */ +typedef struct ftList +{ + lctrFtParamNode_t *pHead; /*!< Pointer to the head of the CIS linked list. */ + lctrFtParamNode_t *pTail; /*!< Pointer to the tail of the CIS linked list. */ + uint8_t numNodes; /*!< Number of nodes in the CIS linked list. */ +} lctrFtParamList_t; + +/*! \brief Connected isochronous stream context. */ +typedef struct +{ + bool_t enabled; /*!< Enable flag. */ + uint8_t state; /*!< main state. */ + uint8_t estState; /*!< Establishment procedure state. */ + uint8_t termState; /*!< Termination procedure state. */ + uint16_t aclHandle; /*!< ACL handle. */ + uint16_t cisHandle; /*!< CIS handle. */ + uint8_t role; /*!< Role. */ + uint8_t cigId; /*!< Used to identify the connected isochronous group. */ + uint8_t cisId; /*!< Used to identify a connected isochronous stream. */ + uint16_t cisEvtCounter; /*!< Event counter. */ + uint32_t cisSyncDelayUsec; /*!< CIS synchronous delay in microsecond. */ + 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. */ + + uint8_t subEvtCounter; /*!< Sub event counter. */ + bool_t isTxDone; /*!< TRUE if all the Tx are done, start sending NULL packet. */ + bool_t pduFlushed; /*!< TRUE if the PDU is flushed, for Tx only. */ + + uint8_t reason; /*!< Disconnect reason. */ + lctrCisTermInd_t cisTerm; /*!< Peer CIS Disconnect reason. */ + + uint64_t txPktCounter; /*!< Transmit packet counter. */ + uint64_t rxPktCounter; /*!< Receive packet counter. */ + + /* Buffers */ + uint8_t dataHdrBuf[LL_DATA_HDR_LEN]; /*!< Data header buffer */ + uint8_t dataBuf[10]; /*!< Data header buffer */ + uint16_t dataCounter; /*!< Data counter. */ + + /* LLCP */ + bool_t isCisReqPend; /*!< True if CIS_REQ is sent and response is not received yet. */ + uint16_t ceRef; /*!< ACL connection event where the offset referenced. */ + uint16_t cisCeRef; /*!< Number of CIS event before CIS is started. */ + uint32_t offsetUsec; /*!< Time in microsecond between the start of the referenced CE to the start of first CIS event. */ + wsfTimer_t tmrProcRsp; /*!< Procedure response timer. */ + + union + { + struct + { + uint32_t anchorOffsetUsec; /*!< Offset to the stream anchor point. */ + lctrCisReq_t cisReq; /*!< CIS request parameters. */ + bool_t syncWithMaster; /*!< Flag indicating synchronize packet received from master. */ + bool_t rxFromMaster; /*!< At least one successful packet received from master. */ + bool_t firstRxFromMaster; /*!< TRUE if the first Rx from master. */ + uint32_t offsetUsec; /*!< Offset to the next Rx. */ + 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. */ + } slv; /*!< Slave connection specific data. */ + + struct + { + bool_t txPduIsAcked; /*!< TRUE if the PDU is acked. */ + bool_t rxFromSlave; /*!< At least one packet received from slave. */ + } mst; /*!< CIS master specific data. */ + } data; /*!< role-specific data. */ + + /* Channel parameters */ + lmgrChanParam_t chanParam; /*!< Channel parameter. */ + uint8_t chIdx; /*!< LL channel index. */ + uint8_t nextSubEvtChanIdx; /*!< Next subevent channel index. */ + uint32_t accessAddr; /*!< Access address. */ + uint32_t crcInit; /*!< CRC initialization value. */ + + /* Flow control */ + lctrCisDataPduHdr_t txHdr; /*!< Transmit data PDU header. */ + lctrCisDataPduHdr_t rxHdr; /*!< Receive data PDU header. */ + wsfQueue_t txIsoQ; /*!< Transmit ISO queue. */ + wsfQueue_t txArqQ; /*!< Transmit ARQ queue. */ + 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. */ + + /* Flush timeout Tx/Rx list */ + lctrFtParamList_t txFtParamList; /*!< Tx flush timeout parameters list. */ + lctrFtParamList_t rxFtParamList; /*!< Rx flush timeout parameters list. */ + + /* Data length */ + lctrDataLen_t localDataPdu; /*!< Local Data PDU parameters. */ + + /* BB data */ + BbBleData_t bleData; /*!< BLE BB operation data. */ + + /* Supervision */ + uint16_t supTimeoutMs; /*!< Supervision timeout in milliseconds. */ + wsfTimer_t tmrSupTimeout; /*!< Supervision timer. */ + bool_t connEst; /*!< Connection established. */ + bool_t powerIndReq; /*!< Power control indication required when established conn. */ + + /* Encryption */ + uint8_t iv[LL_IV_LEN]; /*!< Initialization vector. */ + + /* PHY */ + uint8_t phyMToS; /*!< Master to slave PHY. */ + uint8_t phySToM; /*!< Slave to master PHY. */ + + /* Data */ + uint8_t sca; /*!< Sleep clock accuracy. */ + uint8_t packing; /*!< Packing scheme. */ + uint8_t framing; /*!< Indicates the format of CIS Data PDUs. */ + 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 in microseconds */ + uint32_t sduIntervalSToM; /*!< Time interval between the start of consecutive SDUs from the master Host in microseconds */ + uint16_t isoInterval; /*!< Isochronous PDU interval in 1.25ms unit. */ + uint8_t ftMToS; /*!< Master to slave flush time. */ + uint8_t ftSToM; /*!< Slave to master flush time. */ + uint8_t nse; /*!< Maximum number of subevent in each interval on CIS. */ + uint32_t subIntervUsec; /*!< Subevent duration in microsecond. */ + uint8_t bnMToS; /*!< Master to slave burst number. */ + uint8_t bnSToM; /*!< Slave to master burst number. */ + uint32_t transLatUsec; /*!< The maximum time, in microseconds, for transmission of SDUs of all CISes. */ + uint32_t nextCisOffsetUsec; /*!< For slave sequential packing only, from the start of this CIS to the start of the next CIS. */ + + /* BB/ISR context */ + bool_t firstFromPeer; /*!< TRUE if received once from peer, used for fast supervision timeout. */ + uint8_t txDataCounter; /*!< Tx data counter in each ISO interval, used to determine whether continue operation for the BOD or not. */ + uint8_t rxDataCounter; /*!< Rx data counter in each ISO interval, used to determine whether continue operation for the BOD or not. */ + + /* Datapath configuration */ + lctrInDataPathCtx_t dataPathInCtx; /*!< Input data path config. */ + lctrOutDataPathCtx_t dataPathOutCtx; /*!< Output data path context. */ + + /* ISO test */ + bool_t txTestEnabled; /*!< TRUE ISO test enabled, FALSE otherwise. */ + bool_t rxTestEnabled; /*!< TRUE if ISO RX test enabled, FALSE otherwise. */ + uint32_t testSduTs; /*!< Timestamp of last tx sdu. */ + LlIsoPldType_t testPldType:8; /*!< Test payload type. */ + + uint32_t expectedPkt; /*!< Next expected packet for Rx test. */ + uint32_t testTxPktCtr; /*!< Packet counter for TX test. */ + uint32_t numRxSuccess; /*!< ISO Rx received payload counter. */ + uint32_t numRxMissed; /*!< ISO Rx missed payload counter. */ + uint32_t numRxFailed; /*!< ISO Rx failed payload counter. */ + uint8_t isoRxPldType; /*!< ISO RX payload length type. */ + bool_t rxPendInit; /*!< ISO test pending initialization flag. */ + + LlIsoLinkQual_t isoLinkQualStats; /*!< ISO Link quality statistics. */ + + lctrIsoalTxCtx_t isoalTxCtx; /*!< ISOAL transmit context. */ + lctrIsoalRxCtx_t isoalRxCtx; /*!< Partial receive context. */ +} lctrCisCtx_t; + +/*! \brief Connected isochronous stream node. */ +typedef struct node +{ + lctrCisCtx_t *pCisCtx; /*!< CIS context. */ + struct node *pNext; /*!< Next node. */ +} lctrCisNode_t; + +/*! \brief Connected isochronous stream linked list. */ +typedef struct list +{ + lctrCisNode_t *pHead; /*!< Pointer to the head of the CIS linked list. */ + lctrCisNode_t *pTail; /*!< Pointer to the tail of the CIS linked list. */ + uint8_t numNodes; /*!< Number of nodes in the CIS linked list. */ +} lctrCisList_t; + +/*! \brief Connected isochronous group context. */ +typedef struct +{ + bool_t enabled; /*!< Context enabled. */ + uint8_t packing; /*!< Packing scheme. */ + bool_t isBodBuilt; /*!< TRUE if BOD is built. */ + bool_t isBodStarted; /*!< TRUE if BOD is started. */ + bool_t isRmAdded; /*!< TRUE if reservation is added. */ + uint8_t cigId; /*!< Used to identify the connected isochronous group. */ + uint16_t cigHandle; /*!< CIG handle. */ + uint32_t cigSyncDelayUsec; /*!< CIG synchronous delay in microsecond. */ + uint16_t isoInterval; /*!< Isochronous PDU interval in 1.25ms unit. */ + bool_t isValid; /*!< TRUE if CIS parameters are valid and is able to be scheduled. */ + uint8_t numCisEsted; /*!< Number of CISs that are established. */ + bool_t isLoopBack; /*!< TRUE if all the CIS streams have been traversed once. */ + bool_t headCisRmved; /*!< TRUE if the head CIS in the CIG is removed. */ + uint32_t offsetUsec; /*!< Only valid when headCisRmved is TRUE, duration between the old anchor point and new anchor point. */ + uint32_t firstRxStartTsUsec; /*!< Only valid when headCisRmved is TRUE, timestamp of the first received frame regardless of CRC error. */ + + /* BB data */ + BbOpDesc_t cigBod; /*!< CIG BOD. */ + + /* Linked list of CIS context. */ + lctrCisCtx_t *pCisCtx; /*!< Pointer to the current CIS context. */ + lctrCisList_t list; /*!< CIS linked list. */ + + /* BOD data. */ + union + { + struct + { + uint16_t cigEvtCounter; /*!< Event counter. */ + uint32_t anchorPointUsec; /*!< Anchor point in microseconds. */ + uint16_t lastActiveEvent; /*!< Last active event counter. */ + uint16_t totalAcc; /*!< Combined sleep clock inaccuracy. */ + } slv; /*!< Slave BOD data. */ + + struct + { + uint8_t numCis; /*!< Number of CIS. */ + } mst; /*!< Master BOD data. */ + } roleData; /*!< Role-specific BOD Data. */ + + PalBbBleTxBufDesc_t dataPdu[3]; /*!< Data PDU descriptor. */ +} lctrCigCtx_t; + +/************************************************************************************************** + Globals +**************************************************************************************************/ + +extern lctrCisCtx_t *pLctrCisTbl; +extern lctrCigCtx_t *pLctrCigTbl; +extern lctrCisMsg_t *pLctrCisMsg; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ +/* State machine */ +void lctrCisExecuteSm(lctrCisCtx_t *pCisCtx, uint8_t event); +bool_t lctrLlcpExecuteCisTermSm(lctrConnCtx_t *pCtx, uint8_t event); +void lctrCisDisp(lctrCisMsg_t *pMsg); + +/* Action routines for main state machine */ +void lctrCisActCisEst(lctrCisCtx_t *pCtx); +void lctrCisActCisEstFail(lctrCisCtx_t *pCtx); +void lctrCisActDisc(lctrCisCtx_t *pCtx); +void lctrCisActClosed(lctrCisCtx_t *pCisCtx); +void lctrCisActFail(lctrCisCtx_t *pCisCtx); + +/* Action routines for LLCP termination state machine */ +void lctrCisLlcpActHostDisc(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); +void lctrCisLlcpActPeerDisc(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); +void lctrCisLlcpActCisTerm(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); +void lctrCisLlcpActIntHostDisc(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); +void lctrCisLlcpActIntPeerDisc(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); + +/* CIS Context */ +lctrCisCtx_t *lctrAllocCisCtx(lctrCigCtx_t *pCigCtx); +void lctrCleanupCtx(lctrCisCtx_t *pCisCtx); +void lctrFreeCisCtx(lctrCisCtx_t *pCisCtx); +lctrCisCtx_t *lctrFindCisByHandle(uint16_t cisHandle); +lctrCisCtx_t *lctrFindCisById(uint8_t cigId, uint8_t cisId); +uint8_t lctrGetNumAvailCisCtx(); +uint8_t lctrGetNumEnabledCisCtx(LlCisCigParams_t *pSetCigParam); +uint8_t lctrGetNumEnabledCisCtxTest(LlCisCigParamsTest_t *pSetCigParam); +uint8_t lctrGetNumEstCisCtx(LlCisCigParams_t *pSetCigParam); +uint8_t lctrGetNumEstCisCtxTest(LlCisCigParamsTest_t *pSetCigParam); +uint8_t lctrGetNumEstCisCtxByCigCtx(lctrCigCtx_t *pCigCtx); + +/* CIS list utility functions */ +bool_t lctrCisInsertHead(lctrCisList_t *pList, lctrCisCtx_t *pCisCtx); +bool_t lctrCisInsertTail(lctrCisList_t *pList, lctrCisCtx_t *pCisCtx); +bool_t lctrCisRemoveHead(lctrCisList_t *pList); +bool_t lctrCisRemoveTail(lctrCisList_t *pList); +bool_t lctrCisRemoveMiddle(lctrCisList_t *pList, lctrCisCtx_t *pCisCtx); +bool_t lctrCisRemove(lctrCisList_t *pList, lctrCisCtx_t *pCisCtx); +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); +lctrCisCtx_t * lctrCisGetNextCis(lctrCisList_t *pList, lctrCisCtx_t *pCurCis); +lctrCisCtx_t * lctrCisGetPreCis(lctrCisList_t *pList, lctrCisCtx_t *pCurCis); +bool_t lctrCisAreCisCtxDone(lctrCisList_t *pList); +void lctrCisClearCisDone(lctrCisList_t *pList); +void lctrCisSetCisDone(lctrCisList_t *pList, lctrCisCtx_t *pCurCisCtx); + +/* CIS flush timeout list utility functions */ +lctrFtParamNode_t * lctrCisFtCreateFtParamNode(lctrFtParam_t *pFtParam); +bool_t lctrCisFtInsertHead(lctrFtParamList_t *pList, lctrFtParam_t *pFtParam); +bool_t lctrCisFtInsertTail(lctrFtParamList_t *pList, lctrFtParam_t *pFtParam); +bool_t lctrCisFtRemoveHead(lctrFtParamList_t *pList); +bool_t lctrCisFtRemoveTail(lctrFtParamList_t *pList); +bool_t lctrCisFtIsListEmpty(lctrFtParamList_t *pList); +void lctrCisFtListClear(lctrFtParamList_t *pList); + +/* CIG Context */ +lctrCigCtx_t *lctrAllocCigCtx(uint8_t cigId); +void lctrFreeCigCtx(lctrCigCtx_t *pCigCtx); +lctrCigCtx_t *lctrFindCigById(uint8_t cigId); +uint8_t lctrGetNumAvailCigCtx(); + +/* Helper */ +void lctrCisDefaults(void); +bool_t lctrIsCisEst(lctrCisCtx_t *pCtx); +void lctrCisSetupChanParam(lctrCisCtx_t *pCisCtx, uint64_t chanMask); +void lctrCisSetupEncrypt(lctrCisCtx_t *pCisCtx); +void lctrCisStoreTerminateReason(lctrCisCtx_t *pCisCtx); +void lctrCisStoreDisconnectReason(lctrCisCtx_t *pCisCtx); +void lctrCisStoreConnFailEstablishTerminateReason(lctrCisCtx_t *pCisCtx); +void lctrCisStoreLlcpTimeoutTerminateReason(lctrCisCtx_t *pCisCtx); +void lctrCisStoreLocalLowResourceTerminateReason(lctrCisCtx_t *pCisCtx); +void lctrCisStoreMicFailedTerminateReason(lctrCisCtx_t *pCisCtx); +void lctrCisStoreConnTimeoutTerminateReason(lctrCisCtx_t *pCisCtx); +void lctrCisStoreLlcpPeerRejTerminateReason(lctrCisCtx_t *pCisCtx); +void lctrCisStartLlcpTimer(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); +void lctrCisStopLlcpTimer(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); +void lctrCisInitFtParam(lctrFtParam_t *pTxFtParam, uint8_t bn, uint8_t ft, uint8_t nse); +uint32_t lctrCisCalcSubEvtDurationUsecSeq(uint8_t phyMToS, uint8_t phySToM, uint8_t plMToS, uint8_t plSToM); +uint32_t lctrCisCalcSubEvtDurationUsecInter(LlCisCigParams_t *pSetCigParam); +void LctrCisUpdateChanMap(uint16_t aclHandle); +void lctrCleanupCigCtx(); + +/* Function used by connection context */ +bool_t lctrCheckForCisLinkTerm(uint16_t aclHandle); +bool_t lctrCheckIsCisEstAcl(uint16_t aclHandle); +bool_t lctrCheckIsCisEstCis(uint16_t cisHandle); + +/* CIS Tx data path */ +uint16_t lctrIsoTxInitMem(uint8_t *pFreeMem, uint32_t freeMemSize); +void lctrCisTxDataPduQueue(lctrCisCtx_t *pCtx, lctrIsoHdr_t *pIsoHdr, uint8_t *pIsoBuf); +uint8_t lctrCisTxQueuePeek(lctrCisCtx_t *pCisCtx, PalBbBleTxBufDesc_t *bbDescs); +bool_t lctrCisTxQueuePop(lctrCisCtx_t *pCisCtx); +void lctrCisTxQueuePopCleanup(lctrCisCtx_t *pCisCtx); +uint8_t lctrCisTxQueueClear(lctrCisCtx_t *pCisCtx); + +/* CIS Rx data path */ +uint8_t *lctrCisRxPduAlloc(uint16_t maxRxLen); +void lctrCisRxPduFree(uint8_t *pBuf); +void lctrCisRxEnq(uint8_t *pBuf, uint16_t eventCounter, uint16_t cisHandle); +uint8_t *lctrCisRxDeq(uint16_t *pConnHandle); + +/* Message */ +void lctrSendCisMsg(lctrCisCtx_t *pCisCtx, uint8_t event); +void lctrSendCisLlcpMsg(lctrCisCtx_t *pCisCtx, uint8_t event); + +/* Notification */ +void lctrNotifyHostCisEst(lctrCisCtx_t *pCisCtx, uint8_t status, uint32_t cigSyncDelayUsec); +void lctrNotifyHostCisTerm(lctrCisCtx_t *pCisCtx); + +/* ISR */ +uint16_t lctrCisSetupForTx(lctrCigCtx_t *pCigCtx, uint8_t rxStatus, bool_t reqTx); +bool_t lctrCisProcessRxAck(lctrCisCtx_t *pCisCtx); +bool_t lctrCisProcessTxAck(lctrCisCtx_t *pCisCtx); +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); + +/* Scheduler */ +BbOpDesc_t *lctrCisResolveConflict(BbOpDesc_t *pNewOp, BbOpDesc_t *pExistOp); + +/*************************************************************************************************/ +/*! + * \brief Increment the Tx/encrypt packet counter. + * + * \param pCisCtx Connection context. + */ +/*************************************************************************************************/ +static inline void lctrCisIncPacketCounterTx(lctrCisCtx_t *pCisCtx) +{ + pCisCtx->txPktCounter++; + + /* Set the new packet counter for inline encryption. */ + if (lctrSetEncryptPktCountHdlr) + { + lctrSetEncryptPktCountHdlr(&pCisCtx->bleData.chan.enc, pCisCtx->txPktCounter); + } +} + +/*************************************************************************************************/ +/*! + * \brief Increment the Rx/decrypt packet counter. + * + * \param pCisCtx Connection context. + */ +/*************************************************************************************************/ +static inline void lctrCisIncPacketCounterRx(lctrCisCtx_t *pCisCtx) +{ + pCisCtx->rxPktCounter++; + + /* Set the new packet counter for inline encryption. */ + if (lctrSetDecryptPktCountHdlr) + { + /* lctrSetDecryptPktCountHdlr(&pCisCtx->bleData.chan.enc, pCisCtx->rxPktCounter); */ /* Not necessary. */ + } +} + +#ifdef __cplusplus +}; +#endif + +#endif /* LCTR_INT_CIS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis_master.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis_master.h new file mode 100644 index 0000000000..92263d06ea --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis_master.h @@ -0,0 +1,115 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Internal link layer controller master connected isochronous stream interface file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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 LCTR_INT_CIS_MASTER_H +#define LCTR_INT_CIS_MASTER_H + +#include "lctr_int.h" +#include "lctr_int_conn.h" +#include "lctr_int_cis.h" +#include "lctr_api_cis_master.h" +#include "lmgr_api_cis_master.h" +#include "bb_ble_api.h" +#include "bb_ble_api_op.h" +#include "wsf_timer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/************************************************************************************************** + Constants +**************************************************************************************************/ + +/*! \brief CIS master establishment states. */ +enum +{ + LCTR_CIS_MST_EST_STATE_IDLE, /*!< Idle state. */ + LCTR_CIS_MST_EST_STATE_CIS_RSP, /*!< Wait for LL_CIS_RSP state. */ + LCTR_CIS_MST_EST_STATE_TOTAL /*!< Total CIS master establishment states. */ +}; + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief Create CIS pending. */ +typedef struct +{ + uint8_t numCis; /*!< Number of CISs to create. */ + uint16_t cisHandle[LL_MAX_CIS]; /*!< CIS handle array. */ + uint16_t aclHandle[LL_MAX_CIS]; /*!< ACL handle array. */ + uint8_t isCreateCisDone[LL_MAX_CIS]; /*!< TRUE if create CIS is done, either succeed or fail. */ +} lctrCreateCisPend_t; + +/************************************************************************************************** + Globals +**************************************************************************************************/ + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ +/* State machine for CIS LLCP */ +bool_t lctrMstLlcpExecuteCisEstSm(lctrConnCtx_t *pCtx, uint8_t event); + +/* Builder */ +void lctrMstCisBuildCigOp(lctrCigCtx_t *pCigCtx); +void lctrMstCisCigOpCommit(lctrCigCtx_t *pCigCtx, lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); +void lctrMstCisBuildCisData(lctrCisCtx_t *pCisCtx); + +/* ISR: Packet handlers */ +void lctrMstCisCigTxCompletion(BbOpDesc_t *pOp, uint8_t status); +void lctrMstCisCigRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status); + +/* ISR: BOD handlers */ +uint32_t lctrMstCisCheckContOp(BbOpDesc_t *pOp, bool_t *pNewCisCtx); +void lctrMstCisCigBeginOp(BbOpDesc_t *pOp); +void lctrMstCisCigContOp(BbOpDesc_t *pOp); +void lctrMstCisCigPostSubEvt(BbOpDesc_t *pOp, uint8_t status); +void lctrMstCisCigEndOp(BbOpDesc_t *pOp); +void lctrMstCisCigCleanupOp(BbOpDesc_t *pOp); +void lctrMstCisCigAbortOp(BbOpDesc_t *pOp); + +/* Action routines for CIS master LLCP state machine */ +void lctrMstCisLlcpActHostCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); +void lctrMstCisLlcpActPeerRej(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); +void lctrMstCisLlcpActPeerCisRsp(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); +void lctrMstCisLlcpActRspTimeout(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); +void lctrMstCisLlcpActLocalReject(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); + +/* Reservation */ +uint32_t lctrGetCigRefTime(uint8_t connHandle, uint32_t *pDurUsec); + +/* Utility function */ +void lctrMstCreateCisDone(lctrCisCtx_t *pCisCtx); + +#ifdef __cplusplus +}; +#endif + +#endif /* LCTR_INT_CIS_MASTER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis_slave.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis_slave.h new file mode 100644 index 0000000000..344c528ff2 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_cis_slave.h @@ -0,0 +1,107 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Internal link layer controller connected isochronous stream slave interface file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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 LCTR_INT_CIS_SLAVE_H +#define LCTR_INT_CIS_SLAVE_H + +#include "lctr_int.h" +#include "lctr_api_cis.h" +#include "lctr_int_conn.h" +#include "lctr_int_cis.h" +#include "lctr_api_cis_slave.h" +#include "lmgr_api_cis_slave.h" +#include "bb_ble_api.h" +#include "bb_ble_api_op.h" +#include "wsf_timer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/************************************************************************************************** + Constants +**************************************************************************************************/ +/*! \brief CIS slave establishment states. */ +enum +{ + LCTR_CIS_SLV_EST_STATE_IDLE, /*!< Idle state. */ + LCTR_CIS_SLV_EST_STATE_HOST_REPLY, /*!< Wait for host reply state. */ + LCTR_CIS_SLV_EST_STATE_CIS_IND, /*!< Wait for LL_CIS_IND state. */ + LCTR_CIS_SLV_EST_STATE_TOTAL /*!< Total CIS slave establishment states. */ +}; + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/************************************************************************************************** + Globals +**************************************************************************************************/ + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ +/* State machine for CIS LLCP */ +bool_t lctrSlvLlcpExecuteCisEstSm(lctrConnCtx_t *pCtx, uint8_t event); + +/* Builder */ +void lctrSlvCisBuildCigOp(lctrCigCtx_t *pCigCtx); +void lctrSlvCisCigOpCommit(lctrCigCtx_t *pCigCtx, lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); +void lctrSlvCisBuildCisData(lctrCisCtx_t *pCisCtx); + +/* ISR: Packet handlers */ +void lctrSlvCisCigTxCompletion(BbOpDesc_t *pOp, uint8_t status); +void lctrSlvCisCigRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status); + +/* ISR: BOD handlers */ +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); +void lctrSlvCisCigEndOp(BbOpDesc_t *pOp); +void lctrSlvCisCigCleanupOp(BbOpDesc_t *pOp); +void lctrSlvCisCigAbortOp(BbOpDesc_t *pOp); + +/* Action routines for CIS slave LLCP state machine */ +void lctrSlvCisLlcpActPeerCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); +void lctrSlvCisLlcpActRejCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); +void lctrSlvCisLlcpActAcpCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); +void lctrSlvCisLlcpActPeerCisInd(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); +void lctrSlvCisLlcpActPeerCisRej(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); +void lctrSlvCisLlcpActIntPeerCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); + +/* Reservation */ + +/* Helper */ +void lctrCisStorePeerCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); + +#ifdef __cplusplus +}; +#endif + +#endif /* LCTR_INT_CIS_SLAVE_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_conn.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_conn.h index 12b61aee47..dce8cd882e 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_conn.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_conn.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal link layer controller connection interface file. + * \file + * + * \brief Internal link layer controller connection interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -47,9 +48,7 @@ extern "C" { #define LCTR_MAX_CONS_CRC 2 /*!< Maximum number of consecutive CRC failures. */ -#ifndef LCTR_DATA_PDU_START_OFFSET #define LCTR_DATA_PDU_START_OFFSET 2 /*!< Data PDU start offset in a buffer (match ACL header size). */ -#endif #define LCTR_DATA_PDU_FC_OFFSET 0 /*!< Flow control fields data PDU offset. */ #define LCTR_DATA_PDU_LEN_OFFSET 1 /*!< Length field data PDU offset. */ @@ -68,6 +67,28 @@ extern "C" { /*! \brief Resolve connection context from the handle. */ #define LCTR_GET_CONN_CTX(h) &(pLctrConnTbl[h]) +/*! \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 + /************************************************************************************************** Data Types **************************************************************************************************/ @@ -139,12 +160,31 @@ enum LCTR_PROC_CIS_EST_PEER, /*!< Peer-initiated CIS establishment procedure. */ LCTR_PROC_CIS_TERM, /*!< CIS termination procedure. */ 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_INVALID = 0xFF /*!< Invalid ID. */ /* Note: additional procedures without instants can be overridden. */ }; +/*! \brief Power control monitor schemes. */ +enum +{ + LCTR_PC_MONITOR_AUTO, /*!< Automatic monitoring scheme. */ + LCTR_PC_MONITOR_PATH_LOSS, /*!< Path loss monitoring scheme. */ + + LCTR_PC_MONITOR_SCHEME_TOTAL /*!< Total number of monitoring schemes. */ +}; + +/*! \brief Power control scheme states. */ +enum +{ + LCTR_PC_MONITOR_DISABLED, /*!< Disabled monitoring. */ + LCTR_PC_MONITOR_ENABLED, /*!< Monitoring enabled. */ + LCTR_PC_MONITOR_READY /*!< Monitoring ready for enable. */ +}; + /*! \brief Check if CIS is enabled by the CIS handle signature. */ typedef bool_t (*lctrCheckCisEstCisFn_t)(uint16_t cisHandle); /*! \brief Check for CIS termination signature. */ @@ -175,7 +215,7 @@ typedef struct uint16_t totalAcc; /*!< Combined sleep clock inaccuracy. */ uint16_t lastActiveEvent; /*!< Last active event counter. */ uint32_t txWinSizeUsec; /*!< Tx window size. */ - uint32_t anchorPoint; /*!< Anchor point. */ + uint32_t anchorPointUsec; /*!< Anchor point in microseconds. */ uint32_t unsyncedTime; /*!< Unsynced time in BB tick before connection update. */ bool_t initAckRcvd; /*!< Ack received from master. */ bool_t abortSlvLatency; /*!< If TRUE abort slave latency. */ @@ -183,7 +223,7 @@ typedef struct uint8_t consCrcFailed; /*!< Number of consecutive CRC failures. */ bool_t syncWithMaster; /*!< Flag indicating synchronize packet received from master. */ bool_t rxFromMaster; /*!< At least one successful packet received from master. */ - uint32_t firstRxStartTs; /*!< Timestamp of the first received frame regardless of CRC error. */ + uint32_t firstRxStartTsUsec; /*!< Timestamp of the first received frame regardless of CRC error in microseconds. */ } slv; /*!< Slave connection specific data. */ @@ -200,6 +240,7 @@ typedef struct /* RF parameters */ int8_t rssi; /*!< RSSI. */ + uint8_t lastRxStatus; /*!< Status code of last rx. */ /* Channel parameters */ uint8_t lastChanIdx; /*!< Current channel index. */ @@ -212,6 +253,8 @@ typedef struct uint16_t chIdentifier; /*!< Channel identifier. */ uint32_t crcInit; /*!< CRC initialization value. */ uint32_t accessAddr; /*!< Connection access address. */ + int8_t phyTxPower[LL_PC_PHY_TOTAL]; + /*!< Saved txPower configuration for PHYs. */ /* Flow control */ lctrDataPduHdr_t txHdr; /*!< Transmit data PDU header. */ @@ -262,6 +305,11 @@ typedef struct uint64_t usedFeatSet; /*!< Used feature set. */ uint8_t peerSca; /*!< Peer SCA. */ + int8_t peerTxPower; /*!< Peer reported txPower. */ + uint8_t peerPwrLimits; /*!< Peer power limits field. */ + uint8_t peerApr[LL_PC_PHY_TOTAL]; + /*!< Acceptable reduction of power as calculated by the peer. */ + /* Data length */ lctrDataLen_t localDataPdu; /*!< Local Data PDU parameters. */ lctrDataLen_t effDataPdu; /*!< Effective Data PDU parameters. */ @@ -316,12 +364,49 @@ typedef struct lctrPhyUpdInd_t phyUpd; /*!< PHY update parameters. */ wsfTimer_t tmrProcRsp; /*!< Procedure response timer. */ uint8_t scaUpdAction; /*!< Sca update action variable. */ + bool_t readRemoteTxPower; /*!< Currently reading remote txPower. */ int8_t scaMod; /*!< Local sca override modifier. */ + uint8_t reqErrCode; /*!< LLCP error code. */ + + /* Power Control */ + int8_t delta; /*!< Power control delta storage. */ + bool_t peerReqRecvd; /*!< Peer request received. */ + uint8_t reqPhy; /*!< PHY of most recent power control request. */ + bool_t powerRptLocal; /*!< Currently reporting local power changes. */ + bool_t powerRptRemote; /*!< Currently reporting remote power changes. */ + uint8_t powerMonitorScheme; /*!< Active power monitoring scheme. */ + uint8_t monitoringState; /*!< Current state of active power monitoring scheme. */ + bool_t controllerInitRead; /*!< A controller initiated read command. */ + union + { + 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. */ + uint8_t requestVal; /*!< Value of increase/decrease in power to request. */ + } autoMonitor; /*!< Autonomous RSSI monitoring specific data. */ + + struct + { + uint8_t highThreshold; /*!< Path loss high threshold. */ + uint8_t highHysteresis; /*!< Path loss high hysteresis. */ + uint8_t lowThreshold; /*!< Path loss low threshold. */ + uint8_t lowHysteresis; /*!< Path loss low hysteresis. */ + uint8_t minTimeSpent; /*!< Minimum time spent to trigger an event. */ + uint8_t curTimeSpent; /*!< Current time spent in a new path loss zone. */ + uint8_t curZone; /*!< Current path loss zone. */ + uint8_t newZone; /*!< New zone. */ + bool_t initialPathLossRead; /*!< A power control request is required to start path loss monitoring. */ + } pathLoss; /*!< Path loss parameters. */ + } 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. */ + 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. */ } lctrConnCtx_t; /*! \brief Call signature of a cipher block handler. */ @@ -348,6 +433,18 @@ typedef uint8_t (*LctrChSelHdlr_t)(lctrConnCtx_t *pCtx, uint16_t numSkip); /*! \brief Call signature of an action handler. */ typedef void (*lctrLlcpEh_t)(lctrConnCtx_t *pCtx); +/*! \brief Call signature of a power monitor function. */ +typedef void (*lctrPcMonAct_t)(lctrConnCtx_t *pCtx); + +/*! \brief Call signature of power change indication handler. */ +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); + +/*! \brief Call signature of CIS pend disconnect function. */ +typedef bool_t (*lctrPendCisDisc_t)(lctrConnCtx_t *pCtx); + /*! \brief LLCP state machine handlers. */ enum { @@ -357,6 +454,7 @@ enum 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_CMN, /*!< Common LLCP state machine. */ LCTR_LLCP_SM_TOTAL /*!< Total number of LLCP state machine. */ }; @@ -382,6 +480,9 @@ 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 lctrPcPowInd_t lctrSendPowerChangeIndCback; +extern lctrPcNotifyPwr_t lctrNotifyPowerReportIndCback; /************************************************************************************************** Function Declarations @@ -465,7 +566,7 @@ void lctrReceivePeriodicSyncInd(lctrConnCtx_t *pCtx); void lctrSendPerSyncFromScan(lctrConnCtx_t *pCtx); void lctrSendPerSyncFromBcst(lctrConnCtx_t *pCtx); -/* Request peer SCA actions */ +/* Request peer SCA actions. */ void lctrStoreScaAction(lctrConnCtx_t *pCtx); void lctrSendPeerScaReq(lctrConnCtx_t *pCtx); void lctrSendPeerScaRsp(lctrConnCtx_t *pCtx); @@ -530,6 +631,8 @@ bool_t lctrExceededMaxDur(lctrConnCtx_t *pCtx, uint32_t ceStart, uint32_t pendDu uint32_t lctrCalcPingPeriodMs(lctrConnCtx_t *pCtx, uint32_t authTimeoutMs); uint8_t lctrComputeSca(void); uint32_t lctrConnGetAnchorPoint(lctrConnCtx_t *pCtx, uint16_t ceCounter); +void lctrInitPhyTxPower(lctrConnCtx_t *pCtx); +uint8_t lctrGetPowerLimits(int8_t txPower); /* Reservation */ uint32_t lctrGetConnRefTime(uint8_t connHandle, uint32_t *pDurUsec); @@ -539,8 +642,6 @@ uint32_t lctrGetConnRefTime(uint8_t connHandle, uint32_t *pDurUsec); * \brief Set flags for link termination. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrFlagLinkTerm(lctrConnCtx_t *pCtx) @@ -561,8 +662,6 @@ static inline void lctrFlagLinkTerm(lctrConnCtx_t *pCtx) * \brief Service the Control PDU ACK state after a successful reception. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrCheckControlPduAck(lctrConnCtx_t *pCtx) @@ -579,8 +678,6 @@ static inline void lctrCheckControlPduAck(lctrConnCtx_t *pCtx) * \brief Service the Control PDU ACK state after a successful transmission. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrSetControlPduAck(lctrConnCtx_t *pCtx) @@ -627,8 +724,6 @@ static inline bool_t lctrCheckForLinkTerm(lctrConnCtx_t *pCtx) * \brief Increment the Tx/encrypt packet counter. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrIncPacketCounterTx(lctrConnCtx_t *pCtx) @@ -650,8 +745,6 @@ static inline void lctrIncPacketCounterTx(lctrConnCtx_t *pCtx) * \brief Increment the Rx/decrypt packet counter. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrIncPacketCounterRx(lctrConnCtx_t *pCtx) @@ -673,8 +766,6 @@ static inline void lctrIncPacketCounterRx(lctrConnCtx_t *pCtx) * \brief Set the transmit packet counter value in the BB. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrSetBbPacketCounterTx(lctrConnCtx_t *pCtx) @@ -693,7 +784,7 @@ static inline void lctrSetBbPacketCounterTx(lctrConnCtx_t *pCtx) case PAL_BB_NONCE_MODE_PKT_CNTR: lctrSetEncryptPktCountHdlr(pEnc, pCtx->txPktCounter); break; - case PAL_BB_NONCE_MODE_EVT_CNTR: + case PAL_BB_NONCE_MODE_EXT16_CNTR: lctrSetEncryptPktCountHdlr(pEnc, pCtx->eventCounter); break; default: @@ -707,8 +798,6 @@ static inline void lctrSetBbPacketCounterTx(lctrConnCtx_t *pCtx) * \brief Set the receive packet counter value in the BB. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrSetBbPacketCounterRx(lctrConnCtx_t *pCtx) @@ -727,7 +816,7 @@ static inline void lctrSetBbPacketCounterRx(lctrConnCtx_t *pCtx) case PAL_BB_NONCE_MODE_PKT_CNTR: lctrSetDecryptPktCountHdlr(pEnc, pCtx->rxPktCounter); break; - case PAL_BB_NONCE_MODE_EVT_CNTR: + case PAL_BB_NONCE_MODE_EXT16_CNTR: lctrSetDecryptPktCountHdlr(pEnc, pCtx->eventCounter); break; default: @@ -764,8 +853,6 @@ static inline bool_t lctrCheckActiveOrPend(lctrConnCtx_t *pCtx, uint8_t proc) * \brief Store connection timeout termination reason. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrStoreConnTimeoutTerminateReason(lctrConnCtx_t *pCtx) @@ -779,8 +866,6 @@ static inline void lctrStoreConnTimeoutTerminateReason(lctrConnCtx_t *pCtx) /*************************************************************************************************/ /*! * \brief Increment available Tx data buffers. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrDataTxIncAvailBuf(void) @@ -795,8 +880,6 @@ static inline void lctrDataTxIncAvailBuf(void) /*************************************************************************************************/ /*! * \brief Decrement available Tx data buffers. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrDataTxDecAvailBuf(void) @@ -813,9 +896,7 @@ static inline void lctrDataTxDecAvailBuf(void) * \brief Increment available Rx data buffers. * * \param numBufs Number of completed packets. - * - * \return None. - */ + */ /*************************************************************************************************/ static inline void lctrDataRxIncAvailBuf(uint8_t numBufs) { @@ -843,52 +924,6 @@ static inline bool_t lctrGetConnOpFlag(lctrConnCtx_t *pCtx, uint32_t flag) return (pCtx->opModeFlags & flag) ? TRUE : FALSE; } -/*************************************************************************************************/ -/*! - * \brief Convert PHYS bit to PHY. - * - * \param physBit PHYS bit. - * - * \return PHY. - */ -/*************************************************************************************************/ -static inline uint8_t lctrPhysBitToPhy(uint8_t physBit) -{ - switch (physBit) - { - default: - case LL_PHYS_LE_1M_BIT: - return BB_PHY_BLE_1M; - case LL_PHYS_LE_2M_BIT: - return BB_PHY_BLE_2M; - case LL_PHYS_LE_CODED_BIT: - return BB_PHY_BLE_CODED; - } -} - -/*************************************************************************************************/ -/*! - * \brief Convert PHY to PHYS bit. - * - * \param phy PHY. - * - * \return PHYS bit. - */ -/*************************************************************************************************/ -static inline uint8_t lctrPhyToPhysBit(uint8_t phy) -{ - switch (phy) - { - default: - case BB_PHY_BLE_1M: - return LL_PHYS_LE_1M_BIT; - case BB_PHY_BLE_2M: - return LL_PHYS_LE_2M_BIT; - case BB_PHY_BLE_CODED: - return LL_PHYS_LE_CODED_BIT; - } -} - /*************************************************************************************************/ /*! * \brief Get LLCP procedure ID. diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_conn_master.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_conn_master.h index 9351604021..9bd5fc2666 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_conn_master.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_conn_master.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal link layer controller master connection interface file. + * \file + * + * \brief Internal link layer controller master connection interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ @@ -75,7 +76,6 @@ void lctrMstSetEstablishConn(lctrConnCtx_t *pCtx); void lctrMstReloadDataPdu(lctrConnCtx_t *pCtx); /* Helper */ -uint32_t lctrMstConnAdjustOpStart(lctrConnCtx_t *pCtx, uint32_t scanRefTime, uint32_t scanMinDurUsec, lctrConnInd_t *pConnInd); #ifdef __cplusplus }; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_conn_slave.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_conn_slave.h index b130cc7d04..d971314c0f 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_conn_slave.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_conn_slave.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal link layer controller slave connection interface file. + * \file + * + * \brief Internal link layer controller slave connection interface file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_enc_master.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_enc_master.h index b79b9e5c4e..5a11a37dc7 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_enc_master.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_enc_master.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal link layer controller master connection interface file. + * \file + * + * \brief Internal link layer controller master connection interface file. + * + * Copyright (c) 2013-2017 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_enc_slave.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_enc_slave.h index 95f66d273f..94c464fb19 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_enc_slave.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_enc_slave.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal link layer controller slave connection interface file. + * \file + * + * \brief Internal link layer controller slave connection interface file. + * + * Copyright (c) 2013-2017 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_init_master.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_init_master.h index c2756bbdee..562b532384 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_init_master.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_init_master.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal link layer controller scanning master interface file. + * \file + * + * \brief Internal link layer controller scanning master interface file. + * + * Copyright (c) 2013-2017 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_init_master_ae.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_init_master_ae.h index dc429b89be..b01010a549 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_init_master_ae.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_init_master_ae.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal link layer controller scanning master interface file. + * \file + * + * \brief Internal link layer controller scanning master interface file. + * + * Copyright (c) 2013-2019 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ @@ -90,7 +91,6 @@ uint8_t lctrMstAuxInitiateBuildOp(lctrExtScanCtx_t *pExtInitCtx, LlConnSpec_t *p void lctrMstExtInitiateOpCommit(lctrExtScanCtx_t *pExtInitCtx); /* ISR: Initiate packet handlers */ -void lctrMstExtPreInitiateExecHandler(BbOpDesc_t *pOp); bool_t lctrMstInitiateRxExtAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf); void lctrMstInitiateRxExtAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf); bool_t lctrMstInitiateRxAuxAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_iso.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_iso.h new file mode 100644 index 0000000000..47ff93cb7c --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_iso.h @@ -0,0 +1,263 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Internal link layer controller connection interface file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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 LCTR_INT_ISO_H +#define LCTR_INT_ISO_H + +#include "lctr_api_iso.h" +#include "lctr_int.h" +#include "lctr_int_conn.h" +#include "lctr_pdu_iso.h" +#include "lmgr_api_iso.h" +#include "ll_defs.h" +#include "wsf_cs.h" +#include "pal_codec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +#define LCTR_ISO_DATA_PDU_FC_OFFSET 0 /*!< Flow control fields data PDU offset. */ +#define LCTR_ISO_DATA_PDU_LEN_OFFSET 1 /*!< Length field CIS or BIS Data PDU offset. */ + +/*! \brief First CIS handle (follows ACL handles). */ +#define LCTR_FIRST_CIS_HANDLE (pLctrRtCfg->maxConn) + +/*! \brief First BIS handle (follows CIS handles). */ +#define LCTR_FIRST_BIS_HANDLE (pLctrRtCfg->maxConn + pLctrRtCfg->maxCis) + +/*! \brief Fragment header maximum length. */ +#define LCTR_ISO_FRAG_HDR_MAX_LEN (LL_ISO_DATA_HDR_LEN + LL_ISO_SEG_HDR_LEN + LL_ISO_SEG_TO_LEN) + +/*! \brief Fragment trailer maximum length. */ +#define LCTR_ISO_FRAG_TRL_MAX_LEN LL_DATA_MIC_LEN + +/*! \brief SDU offset to start of the SDU data buffer. */ +#define LCTR_ISO_SDU_DATA_START_OFFSET HCI_ISO_HDR_LEN + HCI_ISO_DL_MAX_LEN + +/************************************************************************************************** + Type Definitions +**************************************************************************************************/ + +/*! \brief Transmit buffer descriptor. */ +typedef struct +{ + uint8_t *pIsoSdu; /*!< ISO buffer. */ + uint8_t *pPduBuf; /*!< PDU data buffer. */ + uint16_t isoLen; /*!< ISO SDU length. */ + uint8_t fragLen; /*!< Fragmentation length. */ + uint8_t fragCnt; /*!< Current fragmentation Tx count. */ + struct + { + uint8_t hdrLen; /*!< Data PDU header length. */ + uint8_t trlLen; /*!< Data PDU trailer length. */ + uint8_t hdr[LCTR_ISO_FRAG_HDR_MAX_LEN]; /*!< Data PDU header. */ + uint8_t trl[LCTR_ISO_FRAG_TRL_MAX_LEN]; /*!< Data PDU trailer (i.e., MIC). */ + } frag[]; /*!< Fragmented Data PDU packet data. */ +} lctrIsoTxBufDesc_t; + +/*! \brief Start stream call signature. */ +typedef bool_t (*lctrCodecStartStream)(uint16_t id, PalCodecSreamParam_t *pParam); + +/*! \brief Stop stream call signature. */ +typedef void (*lctrCodecStopStream)(uint16_t id); + +/*! \brief Stream in data call signature. */ +typedef uint16_t (*lctrCodecStreamIn)(uint16_t id, uint8_t *pBuf, uint16_t len, uint32_t *pPktCtr); + +/*! \brief Stream out data call signature. */ +typedef void (*lctrCodecStreamOut)(uint16_t id, const uint8_t *pBuf, uint16_t len, uint32_t pktCtr); + +/*! \brief Codec event handlers. */ +typedef struct +{ + lctrCodecStartStream start; /*!< Start stream. */ + lctrCodecStopStream stop; /*!< Stop stream. */ + lctrCodecStreamIn in; /*!< Stream data input. */ + lctrCodecStreamOut out; /*!< Stream data output. */ +} lctrCodecHandlers_t; + +/*! \brief Codec event handlers. */ +extern lctrCodecHandlers_t lctrCodecHdlr; + +/*! \brief Transmit ISOAL Context. */ +typedef struct +{ + wsfQueue_t pendingSduQ; /*!< ISO pending SDU queue. */ + uint8_t pendQueueSize; /*!< Pending queue size. */ + uint16_t sduOffset; /*!< Offset of incomplete SDU. */ + uint8_t compSdu; /*!< Number of completed SDUs for current ISO event. */ +} lctrIsoalTxCtx_t; + +/*! \brief Receive ISOAL Context. */ +typedef struct +{ + uint8_t *pPendSduBuf; /*!< Pointer to incomplete SDU buffer. */ + uint16_t rxSduOffset; /*!< Offset of SDU currently being assembled. */ + bool_t pduFlushed; /*!< Most recent PDU was flushed due to failed RXs. */ + uint8_t rxState; /*!< RX state. */ + uint16_t packetSequence; /*!< Packet sequence number. */ + + union + { + struct + { + uint32_t timeOffset; /*!< Time offset of an SDU. */ + } framed; /*!< Framed specific data. */ + + struct + { + wsfQueue_t pendSduQ; /*!< Pending PDU fragments. */ + uint16_t curLen; /*!< Current length of SDU being received. */ + uint8_t ps; /*!< Packet status. */ + } unframed; /*!< Unframed specific data. */ + } data; /*!< Framing-specific data. */ +} lctrIsoalRxCtx_t; + +/*! \brief Input datapath context. */ +typedef struct +{ + LlIsoDataPath_t id; /*!< Input data path ID. */ +} lctrInDataPathCtx_t; /*!< Input datapath configuration. */ + +/*! \brief Output datapath context. */ +typedef struct +{ + LlIsoDataPath_t id; /*!< Output data path ID. */ + + union + { + struct + { + wsfQueue_t rxDataQ; /*!< Receive data pending 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. */ +typedef union +{ + lctrInDataPathCtx_t in; /*!< Input context. */ + lctrOutDataPathCtx_t out; /*!< Output context. */ +} lctrDataPathCtx_t; /*!< Datapath context collection. */ + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/* Task event handler */ +void lctrIsoTxCompletedHandler(void); +void lctrCisRxPendingHandler(void); +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); +void lctrIsoalRxDataPathClear(lctrIsoalRxCtx_t *pRxCtx, uint8_t framing); +void lctrIsoOutDataPathSetup(lctrOutDataPathCtx_t *pOutCtx); +uint8_t *lctrIsoRxConnDeq(lctrOutDataPathCtx_t *pOutCtx); +bool_t lctrIsoUnframedRxSduPendQueue(lctrIsoalRxCtx_t *pRxCtx, uint8_t *pSdu, uint16_t handle, + uint16_t dataLen, uint8_t llid); + +/* ISO Test mode. */ +uint8_t *lctrGenerateIsoTestData(uint16_t handle, LlIsoPldType_t pldType, uint16_t maxSdu, uint32_t pktCtr); +void lctrValidateIsoTestData(uint8_t *pPld, uint8_t actLen, LlIsoTestCtrs_t *pRxStats, uint8_t pldType, uint16_t expMaxSdu, uint32_t expPldCtr); +/* ISOAL Utility. */ +uint8_t lctrAssembleTxFramedPdu(lctrIsoalTxCtx_t *pIsoalTxCtx, uint8_t *pPduBuf, uint16_t maxPduLen); +uint8_t lctrAssembleRxFramedSdu(lctrIsoalRxCtx_t *pIsoalRxCtx, wsfQueue_t *pRxQueue, + uint16_t handle, uint8_t *pIsoBuf, uint8_t len); +uint8_t *lctrTxIsoDataPduAlloc(void); + +/*************************************************************************************************/ +/*! + * \brief Increment available Tx data buffers. + */ +/*************************************************************************************************/ +static inline void lctrIsoSduTxIncAvailBuf(void) +{ + WSF_CS_INIT(); + + WSF_CS_ENTER(); + lmgrIsoCb.availTxBuf++; + WSF_CS_EXIT(); +} + +/*************************************************************************************************/ +/*! + * \brief Decrement available Tx data buffers. + */ +/*************************************************************************************************/ +static inline void lctrIsoSduTxDecAvailBuf(void) +{ + WSF_CS_INIT(); + + WSF_CS_ENTER(); + lmgrIsoCb.availTxBuf--; + WSF_CS_EXIT(); +} + +/*************************************************************************************************/ +/*! + * \brief Increment available Rx data buffers. + * + * \param numBufs Number of additional buffers available. + */ +/*************************************************************************************************/ +static inline void lctrIsoDataRxIncAvailBuf(uint8_t numBufs) +{ + WSF_CS_INIT(); + + WSF_CS_ENTER(); + lmgrIsoCb.availRxBuf += numBufs; + WSF_CS_EXIT(); +} + +/*************************************************************************************************/ +/*! + * \brief Decrement available Rx data buffers. + */ +/*************************************************************************************************/ +static inline void lctrIsoDataRxDecAvailBuf(void) +{ + WSF_CS_INIT(); + + WSF_CS_ENTER(); + lmgrIsoCb.availRxBuf--; + WSF_CS_EXIT(); +} + +#ifdef __cplusplus +}; +#endif + +#endif /* LCTR_INT_ISO_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_master_phy.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_master_phy.h index 7436d860cb..21520b9336 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_master_phy.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_master_phy.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal link layer controller PHY features (master) interface file. + * \file + * + * \brief Internal link layer controller PHY features (master) interface file. + * + * Copyright (c) 2016-2017 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_pc.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_pc.h new file mode 100644 index 0000000000..8127ddc50b --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_pc.h @@ -0,0 +1,76 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Internal link layer controller power control interface file. + * + * Copyright (c) 2019 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 LCTR_INT_PC_H +#define LCTR_INT_PC_H + +#include "lctr_api.h" +#include "lctr_int_conn.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); + +/* Power indication actions. */ +void lctrStorePeerPowerInd(lctrConnCtx_t *pCtx); +void lctrSendPeerPowerRsp(lctrConnCtx_t *pCtx); + +/* Power control actions. */ +void lctrStorePowerControlAction(lctrConnCtx_t *pCtx); +void lctrSendPeerPowerControlReq(lctrConnCtx_t *pCtx); +void lctrStorePeerPowerControlReq(lctrConnCtx_t *pCtx); +void lctrSendPeerPowerControlRsp(lctrConnCtx_t *pCtx); +void lctrStorePeerPowerControlRsp(lctrConnCtx_t *pCtx); + +/* Power monitoring actions. */ +void lctrAutoPowerMonitorAct(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); +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); + +/* State machine */ +bool_t lctrLlcpExecutePclSm(lctrConnCtx_t *pCtx, uint8_t event); + +#ifdef __cplusplus +}; +#endif + +#endif /* LCTR_INT_PC_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_priv.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_priv.h index 488a72fde1..d948eabeee 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_priv.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_priv.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal link layer controller privacy interface file. + * \file + * + * \brief Internal link layer controller privacy interface file. + * + * Copyright (c) 2013-2017 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_slave_phy.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_slave_phy.h index 12762e9fe6..73a86c037c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_slave_phy.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_int_slave_phy.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal link layer controller PHY features (slave) interface file. + * \file + * + * \brief Internal link layer controller PHY features (slave) interface file. + * + * Copyright (c) 2016-2017 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_master.c index 21f48e7dfe..be3b7a73b0 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master advertising event ISR callbacks. + * \file + * + * \brief Link layer controller master advertising event ISR callbacks. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -44,8 +45,6 @@ extern bool_t bbTxAccAddrShiftMask; * \brief End a discovery scan operation in the master role. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrMstDiscoverEndOp(BbOpDesc_t *pOp) @@ -102,18 +101,18 @@ void lctrMstDiscoverEndOp(BbOpDesc_t *pOp) /*** Reschedule operation ***/ /* Reset due time to start of scan window. */ - pOp->due = pCtx->scanWinStart; + pOp->dueUsec = pCtx->scanWinStartUsec; if ((pCtx->scanParam.scanInterval != pCtx->scanParam.scanWindow) && ((pScan->elapsedUsec + pOp->minDurUsec) < LCTR_BLE_TO_US(pCtx->scanParam.scanWindow))) { - const uint32_t min = BB_US_TO_BB_TICKS(pScan->elapsedUsec); - const uint32_t max = BB_BLE_TO_BB_TICKS(pCtx->scanParam.scanWindow); + const uint32_t min = pScan->elapsedUsec; + const uint32_t max = BB_BLE_TO_US(pCtx->scanParam.scanWindow); if (SchInsertEarlyAsPossible(pOp, min, max)) { /* Continue interrupted operation. */ - pScan->elapsedUsec = BB_TICKS_TO_US(pOp->due - pCtx->scanWinStart); + pScan->elapsedUsec = BbGetTargetTimeDelta(pOp->dueUsec, pCtx->scanWinStartUsec); WSF_ASSERT(pScan->elapsedUsec < pOp->maxDurUsec); return; } @@ -128,33 +127,33 @@ void lctrMstDiscoverEndOp(BbOpDesc_t *pOp) if (pCtx->scanParam.scanInterval == pCtx->scanParam.scanWindow) { - /* Continuous scan. */ + /* Continuous scan, move to the next scan window. */ SchInsertNextAvailable(pOp); - pCtx->scanWinStart = pOp->due; + pCtx->scanWinStartUsec = pOp->dueUsec; } else { /* Next scan interval. */ - const uint32_t min = BB_BLE_TO_BB_TICKS(pCtx->scanParam.scanInterval); - const uint32_t max = min + BB_BLE_TO_BB_TICKS(pCtx->scanParam.scanWindow); + const uint32_t min = BB_BLE_TO_US(pCtx->scanParam.scanInterval); + const uint32_t max = min + BB_BLE_TO_US(pCtx->scanParam.scanWindow); while (TRUE) { /* Store start of next scan window. */ - pCtx->scanWinStart = pOp->due + min; + pCtx->scanWinStartUsec = pOp->dueUsec + min; if (SchInsertEarlyAsPossible(pOp, min, max)) { - pScan->elapsedUsec = BB_TICKS_TO_US(pOp->due - pCtx->scanWinStart); + pScan->elapsedUsec = BbGetTargetTimeDelta(pOp->dueUsec, pCtx->scanWinStartUsec); WSF_ASSERT(pScan->elapsedUsec < pOp->maxDurUsec); break; } else { /* Advance to next scan window. */ - pOp->due = pCtx->scanWinStart; + pOp->dueUsec = pCtx->scanWinStartUsec; - LL_TRACE_WARN1("!!! Scan schedule conflict at due=%u", pOp->due + min); + LL_TRACE_WARN1("!!! Scan schedule conflict at dueUsec=%u", pOp->dueUsec + min); LL_TRACE_WARN1("!!! scanWindowUsec=%u", LCTR_BLE_TO_US(pCtx->scanParam.scanWindow)); } } @@ -259,8 +258,6 @@ bool_t lctrMstDiscoverAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf) * * \param pOp Originating operation. * \param pAdvBuf Received advertising buffer. - * - * \return None. */ /*************************************************************************************************/ void lctrMstDiscoverAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf) @@ -372,7 +369,7 @@ bool_t lctrMstScanRspRxCompHandler(BbOpDesc_t *pOp, const uint8_t *pRspBuf) /* scanReqAdvAddr is assigned when LL_PDU_ADV_SCAN_IND is received. */ if (lctrMstScan.data.disc.scanReqAdvAddr != pScan->filtResults.peerAddr) { - LL_TRACE_WARN0("Ignore scan_rsp since advAddr doesn't match the one sent in the scan_req."); + LL_TRACE_WARN0("Ignore SCAN_RSP due to mismatched advAddr in SCAN_REQ"); break; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_master_ae.c index 2869ae5904..1be7be1d3c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_master_ae.c @@ -1,28 +1,30 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master advertising event ISR callbacks. + * \file + * + * \brief Link layer controller master advertising event ISR callbacks. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_adv_master_ae.h" #include "lctr_int_conn_master.h" +#include "lctr_api_bis_master.h" #include "sch_api.h" #include "sch_api_ble.h" #include "bb_ble_api_reslist.h" @@ -78,13 +80,51 @@ struct { bool_t filtResult; /*!< PDU filter result, filter out if TRUE, FAlSE otherwise. */ bool_t syncWithSlave; /*!< Flag indicating synchronize packet received from slave. */ - uint32_t firstRxStartTs; /*!< Timestamp of the first received frame regardless of CRC error. */ + uint32_t firstRxStartTsUsec; /*!< Timestamp in microseconds of the first received frame regardless of CRC error. */ } lctrMstPerScanIsr; /************************************************************************************************** Functions: Utility functions **************************************************************************************************/ +/*************************************************************************************************/ +/*! + * \brief Notify host of BIG Info + * + * \param syncHandle Sync handle. + * \param pBigInfo BIG info. + */ +/*************************************************************************************************/ +static void lctrNotifyHostBigInfoAdvReport(uint16_t syncHandle, LctrAcadBigInfo_t *pBigInfo) +{ + LlBigInfoAdvRptInd_t evt; + + /* Clear not required; all values are written. */ + /* memset(&evt, 0, sizeof(LlBigInfoAdvRptInd_t)); */ + + evt.hdr.param = syncHandle; + evt.hdr.event = LL_BIG_INFO_ADV_REPORT_IND; + evt.hdr.status = LL_SUCCESS; + + evt.syncHandle = syncHandle; + evt.numBis = pBigInfo->numBis; + evt.nse = pBigInfo->nse; + evt.isoInterv = pBigInfo->isoInter; + evt.bn = pBigInfo->bn; + evt.pto = pBigInfo->pto; + evt.irc = pBigInfo->irc; + evt.maxPdu = pBigInfo->maxPdu; + evt.sduInterv = pBigInfo->sduInterUsec; + evt.maxSdu = pBigInfo->maxSdu; + evt.phy = pBigInfo->phy; + evt.framing = pBigInfo->framing; + evt.encrypt = pBigInfo->encrypt; + + LL_TRACE_INFO1("### LlEvent ### LL_BIG_INFO_ADV_REPORT_IND, syncHandle=%u", syncHandle); + + LmgrSendEvent((LlEvt_t *)&evt); +} + /*************************************************************************************************/ /*! * \brief Get the local ID address. @@ -95,8 +135,6 @@ struct * \param pLocalIdAddrType Storage for local ID address type; * \param peerIdAddr Peer ID address. * \param peerIdAddrType Peer ID address type. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrGetLocalIdAddr(lctrExtScanCtx_t *pExtScanCtx, uint64_t targetAddr, @@ -144,50 +182,157 @@ static inline void lctrGetLocalIdAddr(lctrExtScanCtx_t *pExtScanCtx, uint64_t ta /*************************************************************************************************/ /*! - * \brief Master Acad handler. + * \brief Check if the received BIG Info are valid. * - * \param pPerScanCtx Periodic scan context. + * \param pBigInfo BIG Info. * - * \return None + * \return TRUE if parameter is valid, FALSE otherwise. */ /*************************************************************************************************/ -void lctrMstAcadHandler(lctrPerScanCtx_t * const pPerScanCtx) +static bool_t lctrIsBigInfoParamsValid(LctrAcadBigInfo_t *pBigInfo) { - if (pPerScanCtx->extAdvHdr.acadLen == 0) + const uint8_t MIN_NUM_BIS = 0x01; + const uint8_t MAX_NUM_BIS = 0x1F; + const uint32_t MIN_SDU_INTERVAL = 0x00100; + const uint32_t MAX_SDU_INTERVAL = 0xFFFFF; + const uint16_t MIN_ISO_INTERVAL = 0x0004; + const uint16_t MAX_ISO_INTERVAL = 0x0C80; + const uint8_t MIN_NUM_NSE = 0x01; + const uint8_t MAX_NUM_NSE = 0x1F; + const uint16_t MAX_SDU = 0x0FFF; + const uint8_t MIN_PDU = 0x01; + const uint8_t MAX_PDU = 0xFB; + const uint8_t MAX_PHY = 0x02; + const uint8_t MAX_FRAMING = 0x01; + const uint8_t MIN_BN = 0x01; + const uint8_t MAX_BN = 0x07; + const uint8_t MIN_IRC = 0x01; + const uint8_t MAX_IRC = 0x0F; + const uint8_t MAX_PTO = 0x0F; + + if ((pBigInfo->numBis < MIN_NUM_BIS) || (pBigInfo->numBis > MAX_NUM_BIS)) { - return; + LL_TRACE_WARN1("numBis=%u out of range", pBigInfo->numBis); + return FALSE; + } + if ((pBigInfo->sduInterUsec < MIN_SDU_INTERVAL) || (pBigInfo->sduInterUsec > MAX_SDU_INTERVAL)) + { + LL_TRACE_WARN1("sduInterval=%u out of range", pBigInfo->sduInterUsec); + return FALSE; + } + if ((pBigInfo->isoInter < MIN_ISO_INTERVAL) || (pBigInfo->isoInter > MAX_ISO_INTERVAL)) + { + LL_TRACE_WARN1("isoInterval=%u out of range", pBigInfo->isoInter); + return FALSE; + } + if ((pBigInfo->nse < MIN_NUM_NSE) || (pBigInfo->nse > MAX_NUM_NSE)) + { + LL_TRACE_WARN1("NSE=%u out of range", pBigInfo->nse); + return FALSE; + } + if (pBigInfo->maxSdu > MAX_SDU) + { + LL_TRACE_WARN1("maxSdu=%u out of range", pBigInfo->maxSdu); + return FALSE; + } + if ((pBigInfo->maxPdu < MIN_PDU) || (pBigInfo->maxPdu > MAX_PDU)) + { + LL_TRACE_WARN1("maxPdu=%u out of range", pBigInfo->maxPdu); + return FALSE; + } + if ((pBigInfo->phy - 1) > MAX_PHY) + { + LL_TRACE_WARN1("phy=%u out of range", (pBigInfo->phy - 1)); + return FALSE; + } + if (pBigInfo->framing > MAX_FRAMING) + { + LL_TRACE_WARN1("framing=%u out of range", pBigInfo->framing); + return FALSE; + } + if ((pBigInfo->bn < MIN_BN) || (pBigInfo->bn > MAX_BN)) + { + LL_TRACE_WARN1("BN=%u out of range", pBigInfo->bn); + return FALSE; + } + if ((pBigInfo->irc < MIN_IRC) || (pBigInfo->irc > MAX_IRC)) + { + LL_TRACE_WARN1("IRC=%u out of range", pBigInfo->irc); + return FALSE; + } + if (pBigInfo->pto > MAX_PTO) + { + LL_TRACE_WARN1("PTO=%u out of range", pBigInfo->pto); + return FALSE; } - /* Enable any new Acad if necessary */ + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Master ACAD handler. + * + * \param pPerScanCtx Periodic scan context. + */ +/*************************************************************************************************/ +static void lctrMstAcadHandler(lctrPerScanCtx_t * const pPerScanCtx) +{ uint8_t len = pPerScanCtx->extAdvHdr.acadLen; - uint8_t *pBuf = (uint8_t *) pPerScanCtx->extAdvHdr.pAcad; - while(len > 0) + const uint8_t *pBuf = pPerScanCtx->extAdvHdr.pAcad; + + while (len > 0) { - uint8_t acadLen = 0; + uint8_t acadLen; BSTREAM_TO_UINT8(acadLen, pBuf); - uint8_t opcode = 0; + uint8_t opcode; BSTREAM_TO_UINT8(opcode, pBuf); - switch (opcode) { - case LL_ACAD_OPCODE_CHANNEL_MAP_UPDATE: + switch (opcode) + { + case LL_ACAD_OPCODE_CHAN_MAP_UPD: { lctrAcadParam_t *pAcadParam = &pPerScanCtx->acadParams[LCTR_ACAD_ID_CHAN_MAP_UPDATE]; + pAcadParam->hdr.len = acadLen; + pAcadParam->hdr.opcode = opcode; if (pAcadParam->hdr.state == LCTR_ACAD_STATE_DISABLED) { pAcadParam->hdr.state = LCTR_ACAD_STATE_ENABLED; - - BSTREAM_TO_UINT40(pAcadParam->chanMapUpdate.chanMask, pBuf); - BSTREAM_TO_UINT16(pAcadParam->chanMapUpdate.instant, pBuf); + lctrUnpackAcadChanMapUpd(&pAcadParam->chanMapUpdate, pBuf); } break; } + case LL_ACAD_OPCODE_BIG_INFO: + { + lctrAcadParam_t *pAcadParam = &pPerScanCtx->acadParams[LCTR_ACAD_ID_BIG_INFO]; + pAcadParam->hdr.len = acadLen; + pAcadParam->hdr.opcode = opcode; + if (pAcadParam->hdr.state == LCTR_ACAD_STATE_DISABLED) + { + lctrUnpackAcadBigInfo(&pAcadParam->bigInfo, pBuf, acadLen); + if (lctrIsBigInfoParamsValid(&pAcadParam->bigInfo)) + { + pAcadParam->hdr.state = LCTR_ACAD_STATE_ENABLED; + + lctrNotifyHostBigInfoAdvReport(LCTR_GET_PER_SCAN_HANDLE(pPerScanCtx), &pAcadParam->bigInfo); + } + else + { + pAcadParam->hdr.state = LCTR_ACAD_STATE_DISABLED; + } + } + break; + } default: + LL_TRACE_WARN2("Unknown ACAD received: opcode=%u acadLen=%u", opcode, len); + break; } - len -= (acadLen + 1); /* Minus the Acad plus the acadLen field. */ + + len -= acadLen + LL_ACAD_LEN_FIELD_LEN; } } @@ -609,8 +754,6 @@ static inline bool_t lctrPerAdvRptPackTruncate(BbOpDesc_t *pOp, const uint8_t *p * \brief Scan backoff maintenance when response reception is successful. * * \param pExtScanCtx Extended scan context. - * - * \return None. */ /*************************************************************************************************/ void lctrScanBackoffRspSuccess(lctrExtScanCtx_t *pExtScanCtx) @@ -638,8 +781,6 @@ void lctrScanBackoffRspSuccess(lctrExtScanCtx_t *pExtScanCtx) * \brief Scan backoff maintenance when response reception failed. * * \param pExtScanCtx Extended scan context. - * - * \return None. */ /*************************************************************************************************/ static void lctrScanBackoffRspFailed(lctrExtScanCtx_t *pExtScanCtx) @@ -727,7 +868,7 @@ bool_t lctrMstDiscoverRxExtAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf switch (advHdr.pduType) { case LL_PDU_ADV_EXT_IND: - /* FIXME Check if secondary PHY is supported. */ + /* TODO Check if secondary PHY is supported. */ break; default: /* Legacy advertising. */ @@ -745,8 +886,6 @@ bool_t lctrMstDiscoverRxExtAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf * * \param pOp Originating operation. * \param pAdvBuf Received advertising buffer. - * - * \return None. */ /*************************************************************************************************/ void lctrMstDiscoverRxExtAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf) @@ -783,7 +922,7 @@ void lctrMstDiscoverRxExtAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t { if ((extAdvHdrFlags & LL_EXT_HDR_ADV_ADDR_BIT) == 0) { - LL_TRACE_WARN0("Ignoring LL_PDU_ADV_EXT_IND due to missing mandatory advA when there is no auxiliary packet."); + LL_TRACE_WARN0("Ignoring LL_PDU_ADV_EXT_IND due to missing mandatory advA when there is no auxiliary packet"); lctrMstExtScanIsr.filtResult = TRUE; break; } @@ -800,7 +939,7 @@ void lctrMstDiscoverRxExtAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t if (BbBleExtPduFiltCheck(¶ms, &pOp->prot.pBle->pduFilt, FALSE, &pScan->filtResults) == FALSE) { - LL_TRACE_WARN0("Ignoring LL_PDU_ADV_EXT_IND due to PDU filtering."); + LL_TRACE_WARN0("EXT_ADV_IND failed BbBleExtPduFiltCheck"); lctrMstExtScanIsr.filtResult = TRUE; break; } @@ -904,16 +1043,16 @@ void lctrMstDiscoverRxExtAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t pOp->minDurUsec = 0; /* Update primary scan BOD min duration so that secondary scan can be scheduled. */ lctrUnpackAuxPtr(&pExtScanCtx->priChAuxPtr, pExtScanCtx->extAdvHdr.pAuxPtr); - uint32_t endTs = pScan->advStartTs + - BB_US_TO_BB_TICKS(SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, pScan->advRxPhyOptions, LL_ADV_HDR_LEN + pScan->filtResults.pduLen)); - lctrMstAuxDiscoverOpCommit(pExtScanCtx, &pExtScanCtx->priChAuxPtr, pScan->advStartTs, endTs); + uint32_t endTs = pScan->advStartTsUsec + + SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, pScan->advRxPhyOptions, LL_ADV_HDR_LEN + pScan->filtResults.pduLen); + lctrMstAuxDiscoverOpCommit(pExtScanCtx, &pExtScanCtx->priChAuxPtr, pScan->advStartTsUsec, endTs); if ((pExtScanCtx->auxOpPending == FALSE) && (lctrPerCreateSync.state == LCTR_CREATE_SYNC_STATE_DISCOVER) && (lctrMstPerScanIsr.filtResult == FALSE)) { /* Reset the flag if cannot schedule the auxiliary operation. */ - LL_TRACE_WARN0("Reset filter flag due to auxiliary operation scheduling conflict."); + LL_TRACE_WARN0("Reset filter flag due to auxiliary operation scheduling conflict"); lctrMstPerScanIsr.filtResult = TRUE; } @@ -953,6 +1092,8 @@ void lctrMstDiscoverRxExtAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t uint64_t peerIdAddr = 0; uint8_t peerIdAddrType = 0; + memset(&pExtScanCtx->extAdvHdr, 0, sizeof(pExtScanCtx->extAdvHdr)); + BbBlePduFiltResultsGetPeerIdAddr(&pScan->filtResults, &peerIdAddr, &peerIdAddrType); LlExtAdvReportInd_t * const pRpt = &pExtScanCtx->data.scan.advRpt; @@ -1038,7 +1179,7 @@ bool_t lctrMstDiscoverRxAuxAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf /* AdvA is mandatory. */ if ((lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_ADV_ADDR_BIT) == 0) { - LL_TRACE_WARN0("Ignoring LL_PDU_AUX_ADV_IND due to missing mandatory advA."); + LL_TRACE_WARN0("Ignoring LL_PDU_AUX_ADV_IND due to missing mandatory AdvA"); lctrMstExtScanIsr.filtResult = TRUE; break; } @@ -1055,7 +1196,7 @@ bool_t lctrMstDiscoverRxAuxAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf if (BbBleExtPduFiltCheck(¶ms, &pOp->prot.pBle->pduFilt, FALSE, &pAuxScan->filtResults) == FALSE) { - LL_TRACE_INFO1("Ignoring LL_PDU_AUX_ADV_IND due to PDU filtering, SID=%u", pExtScanCtx->extAdvHdr.sid); + LL_TRACE_WARN0("EXT_ADV_IND failed BbBleExtPduFiltCheck"); lctrMstExtScanIsr.filtResult = TRUE; /* Continue processing for sync establishment filter even when scan filtering failed. */ } @@ -1129,10 +1270,10 @@ bool_t lctrMstDiscoverRxAuxAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf /*** Save peer periodic advertising parameters. ***/ pPerScanCtx->eventCounter = pExtScanCtx->secSyncInfo.eventCounter; pPerScanCtx->initEventCounter = pExtScanCtx->secSyncInfo.eventCounter; - pPerScanCtx->perInter = BB_US_TO_BB_TICKS(LCTR_PER_INTER_TO_US(pExtScanCtx->secSyncInfo.syncInter)); + pPerScanCtx->perInterUsec = LCTR_PER_INTER_TO_US(pExtScanCtx->secSyncInfo.syncInter); pPerScanCtx->sca = pExtScanCtx->secSyncInfo.sca; pPerScanCtx->rxPhys = lctrConvertAuxPtrPhyToBbPhy(pExtScanCtx->priChAuxPtr.auxPhy); - pPerScanCtx->skipInter = pPerScanCtx->perInter * pPerScanCtx->skip; + pPerScanCtx->skipInterUsec = pPerScanCtx->perInterUsec * pPerScanCtx->skip; if (advAMatch == TRUE) { @@ -1146,9 +1287,9 @@ bool_t lctrMstDiscoverRxAuxAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf pPerScanCtx->trsfAddrType = lctrMstExtScanIsr.advHdr.txAddrRnd; } - uint32_t endTs = pAuxScan->auxStartTs + - BB_US_TO_BB_TICKS(SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, pAuxScan->auxRxPhyOptions, pAuxScan->txAuxReqLen)); - lctrMstPerScanOpCommit(pExtScanCtx, &pExtScanCtx->priChAuxPtr, &pExtScanCtx->secSyncInfo, pAuxScan->auxStartTs, endTs); + 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; @@ -1179,7 +1320,7 @@ bool_t lctrMstDiscoverRxAuxAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf { if (!pAuxScan->filtResults.peerMatch) { - /* Require peer match. */ + LL_TRACE_WARN0("AUX_ADV_IND failed peer match"); lctrMstExtScanIsr.filtResult = TRUE; return FALSE; } @@ -1299,7 +1440,7 @@ bool_t lctrMstDiscoverRxAuxScanRspHandler(BbOpDesc_t *pOp, const uint8_t *pRspBu if (BbBleExtPduFiltCheck(¶ms, &pOp->prot.pBle->pduFilt, FALSE, &pAuxScan->filtResults) == FALSE) { - LL_TRACE_WARN0("LL_PDU_AUX_SCAN_RSP failed PDU filtering."); + LL_TRACE_WARN0("LL_PDU_AUX_SCAN_RSP failed PDU filtering"); lctrMstExtScanIsr.filtResult = TRUE; return FALSE; } @@ -1314,7 +1455,7 @@ bool_t lctrMstDiscoverRxAuxScanRspHandler(BbOpDesc_t *pOp, const uint8_t *pRspBu /* scanReqAdvAddr is assigned when LL_PDU_ADV_SCAN_IND is received. */ if (pExtScanCtx->data.scan.scanReqAdvAddr != pAuxScan->filtResults.peerAddr) { - LL_TRACE_WARN0("Ignore AUX_SCAN_RSP since advAddr doesn't match the one sent in the AUX_SCAN_REQ."); + LL_TRACE_WARN0("Ignore AUX_SCAN_RSP since advAddr doesn't match the one sent in the AUX_SCAN_REQ"); lctrMstExtScanIsr.filtResult = TRUE; return FALSE; } @@ -1431,6 +1572,7 @@ bool_t lctrMstDiscoverRxAuxChainPostProcessHandler(BbOpDesc_t *pOp, const uint8_ bool_t result = TRUE; /*** Report generation. ***/ + if (lctrMstExtScanIsr.filtResult) { /* No further processing for filtered PDUs. */ @@ -1654,7 +1796,7 @@ bool_t lctrMstDiscoverRxLegacyScanRspHandler(BbOpDesc_t *pOp, const uint8_t *pRs /* scanReqAdvAddr is assigned when LL_PDU_ADV_SCAN_IND is received. */ if (pExtScanCtx->data.scan.scanReqAdvAddr != pScan->filtResults.peerAddr) { - LL_TRACE_WARN0("Ignore scan_rsp since advAddr doesn't match the one sent in the scan_req."); + LL_TRACE_WARN0("Ignore scan_rsp since advAddr doesn't match the one sent in the scan_req"); break; } @@ -1700,79 +1842,106 @@ bool_t lctrMstDiscoverRxLegacyScanRspHandler(BbOpDesc_t *pOp, const uint8_t *pRs * \brief Reschedule primary scan operation. * * \param pExtScanCtx Extended scan context. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstExtDiscoverReschedule(lctrExtScanCtx_t *pExtScanCtx) { + lctrExtScanCtx_t *pNextScanCtx = pExtScanCtx; BbOpDesc_t *pOp = &pExtScanCtx->scanBod; - BbBleData_t * const pBle = pOp->prot.pBle; - BbBleMstAdvEvent_t * const pScan = &pBle->op.mstAdv; + BbBleData_t *pBle = pOp->prot.pBle; + BbBleMstAdvEvent_t *pScan = &pBle->op.mstAdv; + uint8_t scanPhyIndex = (LCTR_GET_EXT_SCAN_HANDLE(pExtScanCtx) == LCTR_SCAN_PHY_CODED) ? LCTR_SCAN_PHY_CODED : LCTR_SCAN_PHY_1M; /*** Reschedule primary operation ***/ - /* Recover primary scan BOD min duration so that its run will be guaranteed in BB. */ - pOp->minDurUsec = LCTR_MIN_SCAN_USEC; - /* Reset due time to start of scan window. */ - pOp->due = pExtScanCtx->scanWinStart; + pOp->dueUsec = pExtScanCtx->scanWinStartUsec; + + /* Recover primary scan BOD min duration if it was set to 0 to yield to aux BOD. */ + pOp->minDurUsec = LCTR_MIN_SCAN_USEC; if ((pExtScanCtx->scanParam.scanInterval != pExtScanCtx->scanParam.scanWindow) && ((pScan->elapsedUsec + pOp->minDurUsec) < LCTR_BLE_TO_US(pExtScanCtx->scanParam.scanWindow))) { - const uint32_t min = BB_US_TO_BB_TICKS(pScan->elapsedUsec); - const uint32_t max = BB_BLE_TO_BB_TICKS(pExtScanCtx->scanParam.scanWindow); + const uint32_t min = pScan->elapsedUsec; + const uint32_t max = LCTR_BLE_TO_US(pExtScanCtx->scanParam.scanWindow) - LCTR_MIN_SCAN_USEC; - if (SchInsertEarlyAsPossible(pOp, min, max)) + if (min <= max) { - /* Continue interrupted operation. */ - pScan->elapsedUsec = BB_TICKS_TO_US(pOp->due - pExtScanCtx->scanWinStart); - WSF_ASSERT(pScan->elapsedUsec < pOp->maxDurUsec); - return; + if (SchInsertEarlyAsPossible(pOp, min, max)) + { + /* Continue interrupted operation. */ + pScan->elapsedUsec = pOp->dueUsec - pExtScanCtx->scanWinStartUsec; + WSF_ASSERT(pScan->elapsedUsec < pOp->maxDurUsec); + return; + } } } /* Advance to next scanInterval. */ + /* Decide which scan context BOD will run next. */ + /* If aborted, continue running the aborted BOD. */ + if (pExtScanCtx->bodAborted == FALSE) + { + uint8_t index; + + WSF_ASSERT((lctrActiveExtScan.scanMask & LCTR_VALID_ACTIVE_SCAN_MASK) != 0); + + for (index = 0; index < LCTR_SCAN_PHY_TOTAL; index++) + { + scanPhyIndex++; + if (scanPhyIndex >= LCTR_SCAN_PHY_TOTAL) + { + scanPhyIndex = LCTR_SCAN_PHY_1M; + } + + if (lctrActiveExtScan.scanMask & (1 << scanPhyIndex)) + { + lctrActiveExtScan.scanIndex = scanPhyIndex; + + pNextScanCtx = LCTR_GET_EXT_SCAN_CTX(scanPhyIndex); + pOp = &pNextScanCtx->scanBod; + pBle = pOp->prot.pBle; + pScan = &pBle->op.mstAdv; + break; + } + } + + /* Compute next channel. */ + pBle->chan.chanIdx = lctrScanChanSelectNext(pBle->chan.chanIdx, pScan->scanChMap); + } + pScan->elapsedUsec = 0; - /* Compute next channel. */ - pBle->chan.chanIdx = lctrScanChanSelectNext(pBle->chan.chanIdx, pScan->scanChMap); - - if (pExtScanCtx->scanParam.scanInterval == pExtScanCtx->scanParam.scanWindow) + if (pNextScanCtx->scanParam.scanInterval == pNextScanCtx->scanParam.scanWindow) { - /* Continuous scan. */ + /* Continuous scan, move to the next scan window. */ SchInsertNextAvailable(pOp); - pExtScanCtx->scanWinStart = pOp->due; + pNextScanCtx->scanWinStartUsec = pOp->dueUsec; } else { - /* Next scan interval. */ - const uint32_t min = BB_BLE_TO_BB_TICKS(pExtScanCtx->scanParam.scanInterval); - const uint32_t max = min + BB_BLE_TO_BB_TICKS(pExtScanCtx->scanParam.scanWindow); - - while (TRUE) + if (!(lctrActiveExtScan.bodSchMask & (1 << scanPhyIndex))) { - /* Store start of next scan window. */ - pExtScanCtx->scanWinStart = pOp->due + min; + /* Due time is not initialized for this BOD yet. */ + SchInsertNextAvailable(pOp); + pNextScanCtx->scanWinStartUsec = pOp->dueUsec; + lctrActiveExtScan.bodSchMask |= (1 << scanPhyIndex); + } + else + { + /* Move to next scan interval. */ + pOp->dueUsec += LCTR_BLE_TO_US(pNextScanCtx->scanParam.scanInterval); + pNextScanCtx->scanWinStartUsec = pOp->dueUsec; + (void)SchInsertEarlyAsPossible(pOp, 0, LCTR_SCH_MAX_SPAN); - if (SchInsertEarlyAsPossible(pOp, min, max)) - { - pScan->elapsedUsec = BB_TICKS_TO_US(pOp->due - pExtScanCtx->scanWinStart); - WSF_ASSERT(pScan->elapsedUsec < pOp->maxDurUsec); - break; - } - else - { - /* Advance to next scan window. */ - pOp->due = pExtScanCtx->scanWinStart; - - LL_TRACE_WARN1("!!! Scan schedule conflict at due=%u", pOp->due + min); - LL_TRACE_WARN1("!!! scanWindowUsec=%u", LCTR_BLE_TO_US(pExtScanCtx->scanParam.scanWindow)); - } + /* Align the scan interval. If elapsedUsec is over the window size, BB will not execute the BOD. */ + pScan->elapsedUsec = pOp->dueUsec - pNextScanCtx->scanWinStartUsec; } } + + pNextScanCtx->bodAborted = FALSE; } /*************************************************************************************************/ @@ -1780,13 +1949,12 @@ static void lctrMstExtDiscoverReschedule(lctrExtScanCtx_t *pExtScanCtx) * \brief End a discovery scan operation in the master role. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrMstExtDiscoverEndOp(BbOpDesc_t *pOp) { lctrExtScanCtx_t * const pExtScanCtx = pOp->pCtx; + const uint8_t scanPhyIndex = (LCTR_GET_EXT_SCAN_HANDLE(pExtScanCtx) == LCTR_SCAN_PHY_CODED) ? LCTR_SCAN_PHY_CODED : LCTR_SCAN_PHY_1M; if (pExtScanCtx->shutdown || pExtScanCtx->selfTerm) { @@ -1794,6 +1962,7 @@ void lctrMstExtDiscoverEndOp(BbOpDesc_t *pOp) if (( pExtScanCtx->auxOpPending && (pExtScanCtx->bodTermCnt >= 2)) || /* Wait for both ExtScan and AuxScan operations. */ (!pExtScanCtx->auxOpPending && (pExtScanCtx->bodTermCnt >= 1))) /* Wait only for ExtScan operation. */ { + lctrActiveExtScan.scanMask &= ~(1 << scanPhyIndex); lctrSendExtScanMsg(pExtScanCtx, LCTR_EXT_SCAN_MSG_TERMINATE); } return; @@ -1811,21 +1980,39 @@ void lctrMstExtDiscoverEndOp(BbOpDesc_t *pOp) /* else postpone until lctrMstAuxDiscoverEndOp(). */ } +/*************************************************************************************************/ +/*! + * \brief Abort a discovery scan operation in the master role. + * + * \param pOp Aborted operation. + */ +/*************************************************************************************************/ +void lctrMstExtDiscoverAbortOp(BbOpDesc_t *pOp) +{ + lctrExtScanCtx_t * const pExtScanCtx = pOp->pCtx; + + WSF_ASSERT(pOp->protId == BB_PROT_BLE); + WSF_ASSERT(pOp->prot.pBle->chan.opType == BB_BLE_OP_MST_ADV_EVENT); + + pExtScanCtx->bodAborted = TRUE; + lctrMstExtDiscoverEndOp(pOp); +} + /*************************************************************************************************/ /*! * \brief End an auxiliary discovery scan operation in the master role. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrMstAuxDiscoverEndOp(BbOpDesc_t *pOp) { lctrExtScanCtx_t * const pExtScanCtx = pOp->pCtx; + const uint8_t scanPhyIndex = (LCTR_GET_EXT_SCAN_HANDLE(pExtScanCtx) == LCTR_SCAN_PHY_CODED) ? LCTR_SCAN_PHY_CODED : LCTR_SCAN_PHY_1M; if (pExtScanCtx->shutdown || pExtScanCtx->selfTerm) { + lctrActiveExtScan.scanMask &= ~(1 << scanPhyIndex); lctrSendExtScanMsg(pExtScanCtx, LCTR_EXT_SCAN_MSG_TERMINATE); return; } @@ -1845,8 +2032,6 @@ void lctrMstAuxDiscoverEndOp(BbOpDesc_t *pOp) * \brief End an periodic scan operation in the master role. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrMstPerScanEndOp(BbOpDesc_t *pOp) @@ -1880,7 +2065,7 @@ void lctrMstPerScanEndOp(BbOpDesc_t *pOp) if ((pPerScanCtx->eventCounter - pPerScanCtx->initEventCounter) == (fastTermCnt - 1)) { - LL_TRACE_ERR0("!!! lctrMstPerScanEndOp: Failed to receive AUX_SYNC_IND within first 6 intervals."); + LL_TRACE_ERR0("!!! lctrMstPerScanEndOp: Failed to receive AUX_SYNC_IND within first 6 intervals"); /* Notify create sync state machine with sync failed. */ lctrSendCreateSyncMsg(pPerScanCtx, LCTR_CREATE_SYNC_MSG_FAILED); } @@ -1893,14 +2078,14 @@ void lctrMstPerScanEndOp(BbOpDesc_t *pOp) if (lctrMstPerScanIsr.syncWithSlave) { /* Re-sync with advertiser */ - pPerScanCtx->lastAnchorPoint = lctrMstPerScanIsr.firstRxStartTs; + pPerScanCtx->lastAnchorPointUsec = lctrMstPerScanIsr.firstRxStartTsUsec; lctrMstPerScanIsr.syncWithSlave = FALSE; pPerScanCtx->lastActiveEvent = pPerScanCtx->eventCounter; /* Reset supervision timer. */ WsfTimerStartMs(&pPerScanCtx->tmrSupTimeout, pPerScanCtx->syncTimeOutMs); - if (pPerScanCtx->skipInter && - pPerScanCtx->skipInter < BB_US_TO_BB_TICKS(pPerScanCtx->syncTimeOutMs * 1000)) + if (pPerScanCtx->skipInterUsec && + pPerScanCtx->skipInterUsec < pPerScanCtx->syncTimeOutMs * 1000) { /* Skip is set and shorter than the sync timeout. */ skip = pPerScanCtx->skip; @@ -1920,13 +2105,13 @@ void lctrMstPerScanEndOp(BbOpDesc_t *pOp) while (TRUE) { - /* Handle Acad if any pending actions are waiting. */ + /* Handle ACAD if any pending actions are waiting. */ lctrAcadMsg_t acadMsg; acadMsg.hdr.eventCtr = pPerScanCtx->eventCounter; acadMsg.hdr.skip = skip; acadMsg.hdr.handle = LCTR_GET_PER_SCAN_HANDLE(pPerScanCtx); - for (uint8_t acadId = 0; acadId < LCTR_ACAD_NUM_ID; acadId++) + for (unsigned int acadId = 0; acadId < LCTR_ACAD_NUM_ID; acadId++) { if (pPerScanCtx->acadParams[acadId].hdr.state != LCTR_ACAD_STATE_DISABLED) { @@ -1938,17 +2123,14 @@ void lctrMstPerScanEndOp(BbOpDesc_t *pOp) pPerScanCtx->eventCounter += skip; numUnsyncIntervals += skip; - uint32_t unsyncTimeUsec = BB_TICKS_TO_US(pPerScanCtx->perInter * numUnsyncIntervals); + uint32_t unsyncTimeUsec = pPerScanCtx->perInterUsec * numUnsyncIntervals; uint32_t caPpm = lctrCalcTotalAccuracy(pPerScanCtx->sca); uint32_t wwTotalUsec = lctrCalcWindowWideningUsec(unsyncTimeUsec, caPpm); - uint32_t wwTotal = BB_US_TO_BB_TICKS(wwTotalUsec); - uint32_t connInterUsec = BB_TICKS_TO_US(numUnsyncIntervals * pPerScanCtx->perInter); - uint32_t connInter = BB_US_TO_BB_TICKS(connInterUsec); - int16_t dueOffsetUsec = (connInterUsec - wwTotalUsec) - BB_TICKS_TO_US(connInter - wwTotal); + uint32_t connInterUsec = numUnsyncIntervals * pPerScanCtx->perInterUsec; /* Advance to next interval. */ - pOp->due = pPerScanCtx->lastAnchorPoint + connInter - wwTotal; - pOp->dueOffsetUsec = WSF_MAX(dueOffsetUsec, 0); + pOp->dueUsec = pPerScanCtx->lastAnchorPointUsec + connInterUsec - wwTotalUsec; + pOp->minDurUsec = pPerScanCtx->minDurUsec + wwTotalUsec; pBle->op.mstPerScan.rxSyncDelayUsec = pPerScanCtx->rxSyncDelayUsec + (wwTotalUsec << 1); @@ -1967,8 +2149,6 @@ void lctrMstPerScanEndOp(BbOpDesc_t *pOp) * \brief Abort an periodic scan operation in the master role. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrMstPerScanAbortOp(BbOpDesc_t *pOp) @@ -2022,7 +2202,7 @@ uint32_t lctrMstPerScanRxPerAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBu if (lctrPerTransferSync.state == LCTR_TRANSFER_SYNC_STATE_DISCOVER) { - pPerScanCtx->skipInter = pPerScanCtx->perInter * pPerScanCtx->skip; + pPerScanCtx->skipInterUsec = pPerScanCtx->perInterUsec * pPerScanCtx->skip; } } @@ -2031,14 +2211,38 @@ uint32_t lctrMstPerScanRxPerAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBu (pMstPerScan->perIsFirstTs == TRUE) && (status == BB_STATUS_SUCCESS)) { - lctrMstPerScanIsr.firstRxStartTs = pMstPerScan->perStartTs; + lctrMstPerScanIsr.firstRxStartTsUsec = pMstPerScan->perStartTsUsec; lctrMstPerScanIsr.syncWithSlave = TRUE; } /*** ACAD processing. ***/ + lctrMstAcadHandler(pPerScanCtx); + LctrAcadBigInfo_t *pBigInfo = &pPerScanCtx->acadParams[LCTR_ACAD_ID_BIG_INFO].bigInfo; + + if (pBigInfo->hdr.state == LCTR_ACAD_STATE_ENABLED) + { + pBigInfo->bigAnchorPoint = pMstPerScan->perStartTsUsec + + (pBigInfo->bigOffs * ((pBigInfo->bigOffsUnits == 0) ? 30 : 300)); + + /* TODO: Use ACAD state machine instead of direct message to BIG. + * Periodic Master should not know about BIG contexts. */ + LctrBigInfoMsg_t *pMsg; + if ((pMsg = WsfMsgAlloc(sizeof(LctrBigInfoMsg_t))) != NULL) + { + pMsg->hdr.handle = 0; + pMsg->hdr.dispId = LCTR_DISP_BIG_SYNC; + pMsg->hdr.event = 3; /* LCTR_MST_BIG_ACAD_BIG_INFO */ + + memcpy(&pMsg->data, pBigInfo, sizeof(pMsg->data)); + + WsfMsgSend(lmgrPersistCb.handlerId, &pMsg->hdr); + } + } + /*** Periodic Advertising Data processing. ***/ + uint32_t auxOffsetUsec = 0; if (lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_AUX_PTR_BIT) { @@ -2060,7 +2264,7 @@ uint32_t lctrMstPerScanRxPerAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBu * \param pOp Originating operation. * \param pAdvBuf Advertising buffer. * - * \return None + * \return TRUE if report generated, FALSE if not. */ /*************************************************************************************************/ bool_t lctrMstPerScanRxPerAdvPktPostHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf) @@ -2143,8 +2347,6 @@ bool_t lctrMstPerScanRxPerAdvPktPostHandler(BbOpDesc_t *pOp, const uint8_t *pAdv /*************************************************************************************************/ /*! * \brief Initialize periodic scan ISR context. - * - * \return None */ /*************************************************************************************************/ void lctrMstPerScanIsrInit(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_slave.c index 185e31b9da..979cdefa25 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave advertising ISR callbacks. + * \file + * + * \brief Link layer controller slave advertising ISR callbacks. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -67,8 +68,6 @@ bool_t lctrScanReqHandler(BbOpDesc_t *pOp, uint8_t reqLen) * \param pOp Originating operation. * \param reqLen Request packet length. * \param pReqBuf Received request buffer. - * - * \return None. */ /*************************************************************************************************/ void lctrConnIndHandler(BbOpDesc_t *pOp, uint8_t reqLen, const uint8_t *pReqBuf) @@ -129,8 +128,8 @@ bool_t lctrSlvAdvHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf) case LL_PDU_CONNECT_IND: /* BOD must be terminated before setting up the next operation. */ lctrConnIndHandler(pOp, pduLen, pReqBuf); - lctrSlvAdv.reqEndTs = pAdv->reqStartTs + - BB_US_TO_BB_TICKS(LCTR_CONN_IND_PKT_1M_US); /* N.B.: may round to an earlier time */ + lctrSlvAdv.reqEndTsUsec = pAdv->reqStartTsUsec + + LCTR_CONN_IND_PKT_1M_US; /* Requirement for peer address match will be enforced in action handler. */ break; @@ -147,8 +146,6 @@ bool_t lctrSlvAdvHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf) * * \param pOp Originating operation. * \param pReqBuf Received request buffer. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvAdvPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf) @@ -196,8 +193,6 @@ void lctrSlvAdvPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf) * \brief End an advertising operation. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvAdvEndOp(BbOpDesc_t *pOp) @@ -330,28 +325,28 @@ void lctrSlvAdvEndOp(BbOpDesc_t *pOp) { /* maxDelay is 16, it times 625 still fits in uint32_t. */ /* coverity[overflow_before_widen] */ - pOp->due += BB_BLE_TO_BB_TICKS(lctrCalcAdvDelay()); + pOp->dueUsec += BB_BLE_TO_US(lctrCalcAdvDelay()); } - if (lmgrSlvAdvCb.advParam.advInterMin == lmgrSlvAdvCb.advParam.advInterMax) + if (lmgrSlvAdvCb.advParam.advInterMinUsec == lmgrSlvAdvCb.advParam.advInterMaxUsec) { - pOp->due += lmgrSlvAdvCb.advParam.advInterMin; + pOp->dueUsec += lmgrSlvAdvCb.advParam.advInterMinUsec; result = SchInsertAtDueTime(pOp, NULL); } else { result = SchInsertEarlyAsPossible(pOp, - lmgrSlvAdvCb.advParam.advInterMin, - lmgrSlvAdvCb.advParam.advInterMax); + lmgrSlvAdvCb.advParam.advInterMinUsec, + lmgrSlvAdvCb.advParam.advInterMaxUsec); if (!result) { - pOp->due += lmgrSlvAdvCb.advParam.advInterMax; + pOp->dueUsec += lmgrSlvAdvCb.advParam.advInterMaxUsec; } } if (!result) { - LL_TRACE_WARN1("!!! Adv schedule conflict at due=%u", pOp->due); + LL_TRACE_WARN1("!!! Adv schedule conflict at dueUsec=%u", pOp->dueUsec); LL_TRACE_WARN1("!!! minDurUsec=%u", pOp->minDurUsec); } @@ -361,32 +356,32 @@ void lctrSlvAdvEndOp(BbOpDesc_t *pOp) } case LL_ADV_CONN_DIRECT_HIGH_DUTY: { - uint32_t advEventStart = pOp->due; - uint32_t advTermCntDown = lmgrSlvAdvCb.advTermCntDown; + uint32_t advEventStart = pOp->dueUsec; + uint32_t advTermCntDown = lmgrSlvAdvCb.advTermCntDownUsec; bool_t result = FALSE; - while (!result && lmgrSlvAdvCb.advTermCntDown) + while (!result && lmgrSlvAdvCb.advTermCntDownUsec) { - result = SchInsertLateAsPossible(pOp, lmgrSlvAdvCb.advParam.advInterMin, lmgrSlvAdvCb.advParam.advInterMax); + result = SchInsertLateAsPossible(pOp, lmgrSlvAdvCb.advParam.advInterMinUsec, lmgrSlvAdvCb.advParam.advInterMaxUsec); if (!result) { - pOp->due += lmgrSlvAdvCb.advParam.advInterMax; + pOp->dueUsec += lmgrSlvAdvCb.advParam.advInterMaxUsec; } - uint32_t advEventDur = pOp->due - advEventStart; + uint32_t advEventDur = BbGetTargetTimeDelta(pOp->dueUsec, advEventStart); - if ((advEventDur + lmgrSlvAdvCb.advParam.advInterMax) < advTermCntDown) + if ((advEventDur + lmgrSlvAdvCb.advParam.advInterMaxUsec) < advTermCntDown) { - lmgrSlvAdvCb.advTermCntDown = advTermCntDown - advEventDur; + lmgrSlvAdvCb.advTermCntDownUsec = advTermCntDown - advEventDur; } else { /* Terminate at end of next advertising event. */ - lmgrSlvAdvCb.advTermCntDown = 0; + lmgrSlvAdvCb.advTermCntDownUsec = 0; } } - if (!result && !lmgrSlvAdvCb.advTermCntDown) + if (!result && !lmgrSlvAdvCb.advTermCntDownUsec) { lctrMsgHdr_t *pMsg; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_slave_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_slave_ae.c index 5dd5ab9eb0..69db9834b3 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_slave_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_adv_slave_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave extended advertising ISR callbacks. + * \file + * + * \brief Link layer controller slave extended advertising ISR callbacks. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -56,19 +57,17 @@ static lctrScanReq_t lctrAdvIsrScanReq; /*! * \brief Transmit setup complete for an extended advertising primary channel operation. * - * \param pOp Completed operation. - * \param advTxTime Start time of advertising packet. - * - * \return None. + * \param pOp Completed operation. + * \param advTxTimeUsec Start time of advertising packet in microseconds. */ /*************************************************************************************************/ -void lctrSlvTxSetupExtAdvHandler(BbOpDesc_t *pOp, uint32_t advTxTime) +void lctrSlvTxSetupExtAdvHandler(BbOpDesc_t *pOp, uint32_t advTxTimeUsec) { lctrAdvSet_t * const pAdvSet = pOp->pCtx; if (pAdvSet->pExtAdvAuxPtr && pAdvSet->auxBodUsed) { - uint32_t auxOffsetUsec = BB_TICKS_TO_US(pAdvSet->auxAdvBod.due - advTxTime); + uint32_t auxOffsetUsec = BbGetTargetTimeDelta(pAdvSet->auxAdvBod.dueUsec, advTxTimeUsec); /* Compute EXT_ADV_IND PDU OTA time. */ uint32_t txAdvUsec; @@ -176,6 +175,32 @@ uint32_t lctrSlvTxSetupPeriodicAdvDataHandler(BbOpDesc_t *pOp, bool_t isChainInd /* Compute new chanIdx for next chain packet. */ lctrSelectNextPerChannel(pAdvSet); + /* Update BIG Info timing values. */ + LctrAcadBigInfo_t * const pBigInfo = &pAdvSet->acadParams[LCTR_ACAD_ID_BIG_INFO].bigInfo; + if (pBigInfo->hdr.state == LCTR_ACAD_STATE_ENABLED) + { + uint32_t bigOffsUsec = pBigInfo->bigAnchorPoint - pOp->dueUsec; + + if (bigOffsUsec < 600) + { + bigOffsUsec += pBigInfo->isoInter * 1250; + pBigInfo->bisPldCtr += pBigInfo->nse; + } + + if (bigOffsUsec < 491460) + { + /* use 30us units */ + pBigInfo->bigOffsUnits = 0; + pBigInfo->bigOffs = LL_MATH_DIV_30(bigOffsUsec); + } + else + { + /* use 300us units */ + pBigInfo->bigOffsUnits = 1; + pBigInfo->bigOffs = LL_MATH_DIV_300(bigOffsUsec); + } + } + pPerAdv->txAuxAdvPdu[0].len = lctrPackSyncIndPdu(pAdvSet, pAdvSet->perAdvHdrBuf, &pAdvSet->perAdvData, TRUE); /* Set initial fragment. */ @@ -187,7 +212,7 @@ uint32_t lctrSlvTxSetupPeriodicAdvDataHandler(BbOpDesc_t *pOp, bool_t isChainInd /* Store/use current AuxPtr values. */ uint16_t advDataOffs = pAdvSet->perAdvData.txOffs; - /* Compute new chanIdx for next chainpacket if there is any. */ + /* Compute new chanIdx for next chain packet if there is any. */ if (pAdvSet->perAdvData.txOffs < pAdvSet->perAdvData.len) { lctrSelectNextPerChannel(pAdvSet); @@ -302,7 +327,6 @@ bool_t lctrSlvRxAuxScanReqHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf) if (BbBleExtPduFiltCheck(¶ms, &pOp->prot.pBle->pduFilt, FALSE, &pAuxAdv->filtResults) == FALSE) { - LL_TRACE_WARN0("Ignoring LL_PDU_AUX_SCAN_REQ due to PDU filtering."); return FALSE; } @@ -315,8 +339,6 @@ bool_t lctrSlvRxAuxScanReqHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf) * * \param pOp Originating operation. * \param pReqBuf Received request buffer. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvRxAuxScanReqPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf) @@ -332,7 +354,7 @@ void lctrSlvRxAuxScanReqPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pReqB BbBlePduFiltResultsGetPeerIdAddr(&pAuxAdv->filtResults, &peerIdAddr, &peerIdAddrType); - // TODO Offload report to task context. + /* TODO Offload report to task context. */ LmgrSendScanReqReceivedInd(pAdvSet->handle, peerIdAddrType, peerIdAddr); @@ -345,8 +367,6 @@ void lctrSlvRxAuxScanReqPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pReqB * * \param pOp Originating operation. * \param pReqBuf Received request buffer. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvRxLegacyScanReqPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf) @@ -362,7 +382,7 @@ void lctrSlvRxLegacyScanReqPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pR BbBlePduFiltResultsGetPeerIdAddr(&pAdv->filtResults, &peerIdAddr, &peerIdAddrType); - // TODO Offload report to task context. + /* TODO Offload report to task context. */ LmgrSendScanReqReceivedInd(pAdvSet->handle, peerIdAddrType, peerIdAddr); @@ -412,7 +432,6 @@ bool_t lctrSlvRxAuxConnReqHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf) if (BbBleExtPduFiltCheck(¶ms, &pOp->prot.pBle->pduFilt, FALSE, &pAuxAdv->filtResults) == FALSE) { - LL_TRACE_WARN0("Ignoring LL_PDU_AUX_CON_REQ due to PDU filtering."); return sendRsp; } @@ -474,10 +493,9 @@ bool_t lctrSlvRxAuxConnReqHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf) /*** Received advertising PDU post-processing. ***/ pAdvSet->usedChSel = LL_CH_SEL_2; /* LL_PDU_AUX_CONNECT_REQ always uses Channel Selection #2. */ - pAdvSet->connIndEndTs = pAuxAdv->auxReqStartTs + - /* N.B.: May round to an earlier time. */ - BB_US_TO_BB_TICKS(SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, pAuxAdv->auxRxPhyOptions, - LL_ADV_HDR_LEN + LL_CONN_IND_PDU_LEN)); + pAdvSet->connIndEndTsUsec = pAuxAdv->auxReqStartTsUsec + + SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, pAuxAdv->auxRxPhyOptions, + LL_ADV_HDR_LEN + LL_CONN_IND_PDU_LEN); sendRsp = TRUE; } @@ -540,8 +558,6 @@ bool_t lctrSlvRxLegacyReqHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf) * * \param pOp Originating operation. * \param pReqBuf Received request buffer. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvRxLegacyReqPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf) @@ -571,8 +587,8 @@ void lctrSlvRxLegacyReqPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pReqBu pAdvSet->usedChSel = LL_CH_SEL_1; } - pAdvSet->connIndEndTs = pAdv->reqStartTs + - BB_US_TO_BB_TICKS(LCTR_CONN_IND_PKT_1M_US); /* N.B.: May round to an earlier time. */ + pAdvSet->connIndEndTsUsec = pAdv->reqStartTsUsec + + LCTR_CONN_IND_PKT_1M_US; break; default: break; @@ -581,39 +597,40 @@ void lctrSlvRxLegacyReqPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pReqBu /*************************************************************************************************/ /*! - * \brief Acad handler for post op. + * \brief ACAD handler for post op. * * \param pAdvSet Advertising Set. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvAcadHandler(lctrAdvSet_t *pAdvSet) { - for (uint8_t acadId = 0; acadId < LCTR_ACAD_NUM_ID; acadId++) + for (unsigned int acadId = 0; acadId < LCTR_ACAD_NUM_ID; acadId++) { - lctrAcadParam_t *pData = &pAdvSet->acadParams[acadId]; + lctrAcadParam_t *pAcad = &pAdvSet->acadParams[acadId]; - if (pData->hdr.state != LCTR_ACAD_STATE_ENABLED) + if (pAcad->hdr.state != LCTR_ACAD_STATE_ENABLED) { continue; } /* coverity[dead_error_condition] */ - switch(acadId) + switch (acadId) { case LCTR_ACAD_ID_CHAN_MAP_UPDATE: { - if (pData->chanMapUpdate.instant == pAdvSet->perParam.perEventCounter) + if (pAcad->chanMapUpdate.instant == pAdvSet->perParam.perEventCounter) { /* Update the channel map. */ - pAdvSet->perParam.perChanParam.chanMask = pData->chanMapUpdate.chanMask; + pAdvSet->perParam.perChanParam.chanMask = pAcad->chanMapUpdate.chanMask; LmgrBuildRemapTable(&pAdvSet->perParam.perChanParam); /* Disable the ACAD. */ lctrSlvAcadExecuteSm(pAdvSet, LCTR_ACAD_MSG_CHAN_UPDATE_FINISH); - /* If the most updated channel map does not match the current mask, start a new update. */ + /* Update Channel Map in BIG Info. */ + pAcad->bigInfo.chanMap = pAdvSet->perParam.perChanParam.chanMask; + + /* Check for updated Channel Map. */ if (pAdvSet->perParam.perChanParam.chanMask != pAdvSet->perParam.updChanMask) { lctrSlvAcadExecuteSm(pAdvSet, LCTR_ACAD_MSG_CHAN_UPDATE); @@ -622,6 +639,18 @@ void lctrSlvAcadHandler(lctrAdvSet_t *pAdvSet) break; } + case LCTR_ACAD_ID_BIG_INFO: + { + /* Updated in lctrSlvAcadHandler(), upon Channel Map changes. */ + /* pAcad->bigInfo.chanMap = pAdvSet->perParam.perChanParam.chanMask; */ + + /* Updated in lctrSlvBigEndOp(), upon timing changes. */ + /* pAcad->bigInfo.bigAnchorPoint = pOp->dueUsec; */ + /* pAcad->bigInfo.bisPldCtr = pBigCtx->eventCounter; */ + + break; + } + default: break; } @@ -637,8 +666,6 @@ void lctrSlvAcadHandler(lctrAdvSet_t *pAdvSet) * \brief End an extended advertising primary channel operation. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp) @@ -698,6 +725,7 @@ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp) } /*** Update advertising data ***/ + if ((pAdvSet->param.advEventProp & LL_ADV_EVT_PROP_LEGACY_ADV_BIT) == 0) { /* Update superior PDU including AdvA and TgtA. */ @@ -721,7 +749,7 @@ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp) } } - /* Schedule aux BOD if periodic advertisng is enabled. */ + /* Schedule auxiliary BOD if periodic advertising is enabled. */ if ((pAdvSet->perParam.perAuxStart == TRUE) && pAdvSet->perParam.perAdvEnabled && pAdvSet->pExtAdvAuxPtr && @@ -741,7 +769,6 @@ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp) } else /* (pAdvSet->param.advEventProp & LL_ADV_EVT_PROP_LEGACY_ADV_BIT) */ { - /* Update local private address. */ bool_t update = FALSE; uint64_t newAddr = 0; @@ -841,38 +868,39 @@ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp) SchBleCalcAdvOpDuration(pOp, 0); /*** Reschedule operation ***/ + const uint8_t LEGACY_HIGH_DUTY = (LL_ADV_EVT_PROP_LEGACY_ADV_BIT | LL_ADV_EVT_PROP_HIGH_DUTY_ADV_BIT | LL_ADV_EVT_PROP_DIRECT_ADV_BIT | LL_ADV_EVT_PROP_CONN_ADV_BIT); if ((pAdvSet->param.advEventProp & LEGACY_HIGH_DUTY) == LEGACY_HIGH_DUTY) { { - uint32_t advEventStart = pOp->due; - uint32_t advTermCntDown = pAdvSet->param.priAdvTermCntDown; + uint32_t advEventStartUsec = pOp->dueUsec; + uint32_t advTermCntDown = pAdvSet->param.priAdvTermCntDownUsec; bool_t result = FALSE; - while (!result && pAdvSet->param.priAdvTermCntDown) + while (!result && pAdvSet->param.priAdvTermCntDownUsec) { - result = SchInsertLateAsPossible(pOp, pAdvSet->param.priAdvInterMin, pAdvSet->param.priAdvInterMax); + result = SchInsertLateAsPossible(pOp, pAdvSet->param.priAdvInterMinUsec, pAdvSet->param.priAdvInterMaxUsec); if (!result) { - pOp->due += pAdvSet->param.priAdvInterMax; + pOp->dueUsec += pAdvSet->param.priAdvInterMaxUsec; } - uint32_t advEventDur = pOp->due - advEventStart; + uint32_t advEventDur = BbGetTargetTimeDelta(pOp->dueUsec, advEventStartUsec); - if ((advEventDur + pAdvSet->param.priAdvInterMax) < advTermCntDown) + if ((advEventDur + pAdvSet->param.priAdvInterMaxUsec) < advTermCntDown) { - pAdvSet->param.priAdvTermCntDown = advTermCntDown - advEventDur; + pAdvSet->param.priAdvTermCntDownUsec = advTermCntDown - advEventDur; } else { /* Terminate at end of next advertising event. */ - pAdvSet->param.priAdvTermCntDown = 0; + pAdvSet->param.priAdvTermCntDownUsec = 0; } } - if (!result && !pAdvSet->param.priAdvTermCntDown) + if (!result && !pAdvSet->param.priAdvTermCntDownUsec) { pAdvSet->termReason = LL_ERROR_CODE_ADV_TIMEOUT; lctrSendAdvSetMsg(pAdvSet, LCTR_EXT_ADV_MSG_TERMINATE); @@ -882,11 +910,11 @@ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp) else { uint32_t totalDuration = pOp->minDurUsec; - uint32_t prefInterval; + uint32_t prefIntervalUsec; if (lmgrGetOpFlag(LL_OP_MODE_FLAG_ENA_ADV_DLY)) { - pOp->due += BB_BLE_TO_BB_TICKS(lctrCalcAdvDelay()); + pOp->dueUsec += BB_BLE_TO_US(lctrCalcAdvDelay()); } if (pAdvSet->auxBodUsed) @@ -894,8 +922,8 @@ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp) totalDuration += pAdvSet->auxAdvBod.minDurUsec; } - /* Pick an interval so that advertising(primary + aux) BOD would take less than half of total bandwidth. */ - prefInterval = WSF_MAX(BB_US_TO_BB_TICKS(totalDuration * 2), pAdvSet->param.priAdvInterMin); + /* Pick an interval so that advertising (primary + aux) BOD would take less than half of total bandwidth. */ + prefIntervalUsec = WSF_MAX(totalDuration * 2, pAdvSet->param.priAdvInterMinUsec); if (pAdvSet->advBodAbort) { @@ -904,7 +932,7 @@ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp) } else { - (void)SchInsertEarlyAsPossible(pOp, prefInterval, LCTR_SCH_MAX_SPAN); + (void)SchInsertEarlyAsPossible(pOp, prefIntervalUsec, LCTR_SCH_MAX_SPAN); } } } @@ -914,8 +942,6 @@ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp) * \brief Abort an extended advertising primary channel operation. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvExtAdvAbortOp(BbOpDesc_t *pOp) @@ -931,8 +957,6 @@ void lctrSlvExtAdvAbortOp(BbOpDesc_t *pOp) * \brief End an extended advertising secondary channel operation. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvAuxAdvEndOp(BbOpDesc_t *pOp) @@ -1048,8 +1072,6 @@ void lctrSlvAuxAdvEndOp(BbOpDesc_t *pOp) * \brief End an periodic advertising channel operation. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvPeriodicAdvEndOp(BbOpDesc_t *pOp) @@ -1095,11 +1117,12 @@ void lctrSlvPeriodicAdvEndOp(BbOpDesc_t *pOp) while (TRUE) { - pOp->due += pAdvSet->perParam.perAdvInter; + pOp->dueUsec += pAdvSet->perParam.perAdvInterUsec; pAdvSet->perParam.perEventCounter++; - /*** Process ACAD fields if necessary ***/ + /*** Process ACAD fields ***/ + lctrSlvAcadHandler(pAdvSet); pAdvSet->perParam.perChIdx = lctrPeriodicSelectNextChannel(&pAdvSet->perParam.perChanParam, @@ -1109,6 +1132,7 @@ void lctrSlvPeriodicAdvEndOp(BbOpDesc_t *pOp) { break; } + LL_TRACE_WARN1("!!! Periodic advertising schedule conflict eventCounter=%u", pAdvSet->perParam.perEventCounter); } } @@ -1118,8 +1142,6 @@ void lctrSlvPeriodicAdvEndOp(BbOpDesc_t *pOp) * \brief Abort an periodic advertising channel operation. * * \param pOp Aborted operation. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvPeriodicAdvAbortOp(BbOpDesc_t *pOp) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_bis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_bis_master.c new file mode 100644 index 0000000000..d253b87311 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_bis_master.c @@ -0,0 +1,937 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller master BIG ISR callbacks. + * + * 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 "lctr_int_bis_master.h" +#include "lctr_int_iso.h" +#include "ll_defs.h" +#include "wsf_trace.h" +#include "util/bstream.h" + +/************************************************************************************************** + Globals +**************************************************************************************************/ + +/*! \brief BIS master ISR control block. */ +static struct +{ + lctrSeCtx_t se; /*!< Subevent context. */ + uint8_t numRcvdPkt; /*!< Number of successfully received packets. */ + bool_t firstRxComp; /*!< First Rx in ISO Event completion flag. */ + bool_t cstf; /*!< BIG Event's valid Control Subevent Transmission Flag. */ + uint8_t cssn; /*!< BIG Event's valid Control Subevent Sequence Number. */ + uint32_t nextSeOffs; /*!< Next subevent time. */ + PalBbBleChan_t *pNextChan;/*!< Next subevent channel. */ + uint8_t *pCtrlBuf; /*!< Received BIS Control PDU buffer. */ + uint8_t *pDataBuf[LL_MAX_BIS][LL_MAX_BN]; + /*!< Received data buffers. */ +} lctrMstBisIsr; + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Update loop counters for sequential packing. + * + * \param pBigCtx BIG context. + * + * \return TRUE if more Rx pending, FALSE otherwise. + */ +/*************************************************************************************************/ +static bool_t lctrMstBisLoopCounterSequential(lctrBigCtx_t *pBigCtx) +{ + size_t numSePkts = (pBigCtx->bn * pBigCtx->irc) + lctrMstBisIsr.se.ptIdx; + + /* BIG Event limit (beyond BIS Control SubEvent). */ + + if (lctrMstBisIsr.se.bisEvtIdx >= pBigCtx->numBis) + { + return FALSE; + } + + if (!lctrSlvBisCalcNextIdxSequential(pBigCtx, &lctrMstBisIsr.se, numSePkts)) + { + if (!lctrMstBisIsr.cstf) + { + 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; + } + + /* Compute next packet time. */ + lctrMstBisIsr.nextSeOffs += pBigCtx->subInterUsec; + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Update loop counters for interleaved packing. + * + * \param pBigCtx BIG context. + * + * \return TRUE if more Rx pending, FALSE otherwise. + */ +/*************************************************************************************************/ +static bool_t lctrMstBisLoopCounterInterleaved(lctrBigCtx_t *pBigCtx) +{ + size_t numSePkts = (pBigCtx->bn * pBigCtx->irc) + lctrMstBisIsr.se.ptIdx; + + /* BIG Event limit (beyond BIS Control SubEvent). */ + + if (numSePkts > pBigCtx->nse) + { + return FALSE; + } + + if (!lctrSlvBisCalcNextIdxInterleaved(pBigCtx, &lctrMstBisIsr.se, numSePkts)) + { + if (!lctrMstBisIsr.cstf) + { + 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; + } + + /* Compute next packet time. */ + lctrMstBisIsr.nextSeOffs += pBigCtx->bisSpaceUsec; + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Setup a receive PDU. + * + * \param pBigCtx BIG context. + * \param reAcqSync Re-acquisition of synchronization is needed. + * \param pBuf Unused buffer from last receive operation. + * + * \return TRUE if successful, FALSE if out of memory. + */ +/*************************************************************************************************/ +static bool_t lctrMstBisRxData(lctrBigCtx_t *pBigCtx, bool_t reAcqSync, uint8_t *pBuf) +{ + if ((pBuf == NULL) && + ((pBuf = lctrBisRxIsoDataPduAlloc()) == NULL)) + { + LL_TRACE_WARN2("BIG event flow controlled, bigHandle=%u, ec[15:0]=%u", pBigCtx->handle, pBigCtx->eventCounter); + + /* Flow control BIG Event. */ + return FALSE; + } + + /*** Commit transmission ***/ + + 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, + lctrMstBisIsr.pNextChan, + reAcqSync); + + /*** Post-commit calculation ***/ + + /* Now that channel data is set in BB, compute next channel information. */ + pBisCtx->chan.chanIdx = LmgrSelectNextSubEvtChannel(&pBisCtx->chSelInfo); + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief BIG Control PDU decrypt. + * + * \param pBigCtx BIG context. + * + * \return TRUE if successful, FALSE for MIC failure. + */ +/*************************************************************************************************/ +static bool_t lctrMstBigControlDecrypt(lctrBigCtx_t *pBigCtx) +{ + if (pBigCtx->encrypt && lctrPktDecryptHdlr) + { + uint64_t pktCtr = pBigCtx->eventCounter * pBigCtx->bn; + pBigCtx->ctrChan.enc.pRxPktCounter = &pktCtr; + + if (!lctrPktDecryptHdlr(&pBigCtx->ctrChan.enc, lctrMstBisIsr.pCtrlBuf)) + { + LL_TRACE_ERR0("!!! MIC verification failed on BIS Control PDU"); + lctrBisRxIsoDataPduFree(lctrMstBisIsr.pCtrlBuf); + lctrMstBisIsr.pCtrlBuf = NULL; + lctrMstBigSendMsg(pBigCtx, LCTR_MST_BIG_INT_MIC_FAILED); + return FALSE; + } + } + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief BIG Control PDU post processing. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +static void lctrMstBigControlPostProcess(lctrBigCtx_t *pBigCtx) +{ + uint8_t opcode = lctrMstBisIsr.pCtrlBuf[LL_DATA_HDR_LEN]; + + if (!pBigCtx->bcp.actMsk) + { + if (opcode < LL_BIG_OPCODE_MAX) + { + switch (opcode) + { + case LL_BIG_OPCODE_CHAN_MAP_IND: + lctrBisUnpackBigChannelMapInd(&pBigCtx->bcp.chanMapUpd.chanMap, + &pBigCtx->bcp.chanMapUpd.inst, + lctrMstBisIsr.pCtrlBuf + LL_DATA_HDR_LEN); + + if (((uint16_t)(pBigCtx->bcp.chanMapUpd.inst - (uint16_t)pBigCtx->eventCounter)) < 0x8000) + { + pBigCtx->bcp.actMsk |= 1 << opcode; + LL_TRACE_INFO2("BIG Channel Map Procedure, bigHandle=%u, instant=%u", pBigCtx->handle, pBigCtx->bcp.chanMapUpd.inst); + } + else + { + /* Ignore error attempt to remain connected as long as possible. */ + LL_TRACE_WARN1("Invalid BIG Channel Map parameters, bigHandle=%u", pBigCtx->handle); + } + + break; + + case LL_BIG_OPCODE_BIG_TERM_IND: + lctrBisUnpackBigTerminateInd(&pBigCtx->bcp.term.reason, + &pBigCtx->bcp.term.inst, + lctrMstBisIsr.pCtrlBuf + LL_DATA_HDR_LEN); + + if (((uint16_t)(pBigCtx->bcp.term.inst - (uint16_t)pBigCtx->eventCounter)) < 0x8000) + { + pBigCtx->bcp.actMsk |= 1 << opcode; + LL_TRACE_INFO2("BIG Terminate Procedure, bigHandle=%u, instant=%u", pBigCtx->handle, pBigCtx->bcp.term.inst); + } + else + { + /* Terminate regardless of error. */ + pBigCtx->bcp.term.reason = LL_ERROR_CODE_INVALID_LMP_PARAMS; + lctrMstBigSendMsg(pBigCtx, LCTR_MST_BIG_PDU_TERM); + LL_TRACE_WARN1("Invalid BIG Terminate parameters, bigHandle=%u", pBigCtx->handle); + } + + break; + + default: + break; + } + } + } + else + { + LL_TRACE_WARN2("Unexpected overlapped BIS Control Procedure, bigHandle=%u, opcode=%u", pBigCtx->handle, opcode); + } + + lctrBisRxIsoDataPduFree(lctrMstBisIsr.pCtrlBuf); +} + +/*************************************************************************************************/ +/*! + * \brief BIG Control Procedure handler. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +static void lctrMstBigControlProcedureHandler(lctrBigCtx_t *pBigCtx) +{ + if (pBigCtx->bcp.actMsk) + { + uint16_t inst = (pBigCtx->eventCounter + 1) & 0xFFFF; + + if ((pBigCtx->bcp.actMsk & (1 << LL_BIG_OPCODE_CHAN_MAP_IND)) && + (inst == pBigCtx->bcp.chanMapUpd.inst)) + { + pBigCtx->bcp.actMsk &= ~(1 << LL_BIG_OPCODE_CHAN_MAP_IND); + + lctrRemapBigChannels(pBigCtx, pBigCtx->bcp.chanMapUpd.chanMap); + + LL_TRACE_INFO2("Updated channel map: bigHandle=%u inst=%u", pBigCtx->handle, inst); + } + + if (pBigCtx->bcp.actMsk & (1 << LL_BIG_OPCODE_BIG_TERM_IND)) + /* Does not need to wait for instant. */ + { + /* pBigCtx->bcp.actMsk &= ~(1 << LL_BIG_OPCODE_BIG_TERM_IND); */ /* Not needed. */ + lctrMstBigSendMsg(pBigCtx, LCTR_MST_BIG_PDU_TERM); + } + } +} + +/*************************************************************************************************/ +/*! + * \brief BIS Rx Data PDU consumer. + * + * \param pBigCtx BIG context. + * \param rxEvtCtr Received event counter. + */ +/*************************************************************************************************/ +static void lctrMstBisRxDataPduHandler(lctrBigCtx_t *pBigCtx, uint32_t rxEvtCtr) +{ + uint8_t numHandles = 0; + uint16_t handles[LL_MAX_BIS] = { 0 }; + uint16_t numSdu[LL_MAX_BIS] = { 0 }; + uint64_t pktCtrBase = rxEvtCtr * pBigCtx->bn; + lctrIsoalRxCtx_t *pRxCtx; + + for (unsigned int i = 0; i < pBigCtx->numBis; i++) + { + lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[i]; + pRxCtx = &pBisCtx->roleData.mst.isoalRxCtx; + + uint8_t *pDataPdu; + uint8_t pldCtrOffs; + + while ((pDataPdu = lctrBisDequeueRxDataPdu(pBisCtx, &pldCtrOffs)) != NULL) + { + uint64_t pktCtr = pktCtrBase + pldCtrOffs; + pBisCtx->chan.enc.pRxPktCounter = &pktCtr; + + if (lctrPktDecryptHdlr) + { + if (!lctrPktDecryptHdlr(&pBisCtx->chan.enc, pDataPdu)) + { + LL_TRACE_ERR1("!!! MIC verification failed on bisHandle=%u", pBisCtx->handle); + lctrBisRxIsoDataPduFree(pDataPdu); + lctrMstBigSendMsg(pBigCtx, LCTR_MST_BIG_INT_MIC_FAILED); + return; + } + } + + 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) + { + case LL_ISO_DATA_PATH_HCI: + { + lctrIsoHdr_t isoHdr = + { + /* 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 + }; + + if (pBigCtx->lastPduMissed) + { + pRxCtx->data.unframed.ps = LCTR_PS_INVALID; + } + + switch (pBisCtx->lastLlid) + { + 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)) + { + 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) + { + lctrBisRxIsoSduEnq(pBisCtx, pSduFrag); + numSdu[numHandles]++; + } + break; + } + + case LL_ISO_DATA_PATH_VS: + { + 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; + } + + default: + { + LL_TRACE_WARN2("Data path disabled; dropping Rx ISO PDU, bigHandle=%u, pktCtr[15:0]=%u", pBigCtx->handle, pktCtr); + WsfMsgFree(pIsoSdu); + break; + } + } + } + else /* LL_ISO_PDU_TYPE_FRAMED */ + { + switch (pBisCtx->path) + { + case LL_ISO_DATA_PATH_HCI: + { + 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) + { + lctrIsoHdr_t isoHdr; + lctrIsoUnpackHdr(&isoHdr, pIsoBuf); + + lctrCodecHdlr.out(pBisCtx->handle, isoHdr.pSdu, isoHdr.sduLen, pktCtr); + WsfMsgFree(pIsoBuf); /* TODO Resolve PDU free in Audio layer */ + } + break; + } + default: + { + LL_TRACE_WARN2("Data path disabled; dropping Rx ISO PDU, bigHandle=%u, pktCtr[15:0]=%u", pBigCtx->handle, pktCtr); + break; + } + } + lctrBisRxIsoDataPduFree(pDataPdu); + } + } + + if (numSdu[numHandles]) + { + if (!pBisCtx->test.enabled) + { + handles[numHandles] = pBisCtx->handle; + numHandles++; + } + else + { + numSdu[numHandles] = 0; + } + } + } + + if (numHandles) + { + /* Notify host received SDUs. */ + lmgrPersistCb.recvIsoPendCback(numHandles, handles, numSdu); + } +} + +/*************************************************************************************************/ +/*! + * \brief BIS Rx Test payload consumer. + * + * \param pBigCtx BIG context. + * \param rxEvtCtr Received event counter. + */ +/*************************************************************************************************/ +static void lctrMstBisRxTestPduHandler(lctrBigCtx_t *pBigCtx, uint32_t rxEvtCtr) +{ + for (unsigned int i = 0; i < pBigCtx->numBis; i++) + { + lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[i]; + + /* Consume data for RX test. */ + if (pBisCtx->test.enabled) + { + if (!pBisCtx->test.term) + { + uint8_t *pTestBuf; + uint32_t expPayloadCtr; + + lctrIsoHdr_t isoHdr; + while ((pTestBuf = lctrBisRxIsoSduDeq(pBisCtx)) != NULL) + { + lctrIsoUnpackHdr(&isoHdr, pTestBuf); + + if (pBigCtx->framing == LL_ISO_PDU_TYPE_FRAMED) + { + if (pBisCtx->test.pendInit) + { + uint8_t *pTestDataBuf = (uint8_t *) isoHdr.pSdu; + BSTREAM_TO_UINT32(pBisCtx->test.util.framed.payloadCtr, pTestDataBuf); + LL_TRACE_INFO1("BIS Framed payload counter initialized to %d", pBisCtx->test.util.framed.payloadCtr); + 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; + } + + lctrValidateIsoTestData((uint8_t *)isoHdr.pSdu, isoHdr.sduLen, &pBisCtx->roleData.mst.stats, + pBisCtx->test.pldType, pBigCtx->maxSdu, expPayloadCtr); + WsfMsgFree(pTestBuf); + lctrIsoDataRxIncAvailBuf(1); + } + } + + else + { + /* Terminate ISO Test mode operation. */ + pBisCtx->test.enabled = FALSE; + pBisCtx->test.term = FALSE; + pBisCtx->test.pendInit = FALSE; + pBisCtx->test.util.framed.payloadCtr = 0; + } + } + } +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Complete a received BIS data buffer. + * + * \param pOp Operation context. + * \param pBuf Receive buffer. + * \param status Receive status. + */ +/*************************************************************************************************/ +void lctrMstBisRxCompletion(BbOpDesc_t *pOp, uint8_t *pBuf, uint8_t status) +{ + lctrBigCtx_t * const pBigCtx = pOp->pCtx; + BbBleData_t * const pBle = &pBigCtx->bleData; + BbBleMstBisEvent_t * const pBis = &pBle->op.mstBis; + + bool_t reAcqTrain = FALSE; + + if (status == BB_STATUS_SUCCESS) + { + lctrMstBisIsr.numRcvdPkt++; + } + + if (pBigCtx->state != LCTR_MST_BIG_STATE_SYNCED) + { + BbSetBodTerminateFlag(); + goto RxPostProcess; + } + + switch (status) + { + case BB_STATUS_FAILED: + case BB_STATUS_CANCELED: + /* Continue to next BIG Event. */ + BbSetBodTerminateFlag(); + goto RxPostProcess; + + default: + break; + } + + /* Synchronize BIS Event timing. */ + + if (!lctrMstBisIsr.firstRxComp) + { + lctrMstBisIsr.firstRxComp = TRUE; + + switch (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; + break; + + default: + break; + } + } + + /* Handle subevent flags. */ + + lctrBisDataPduHdr_t hdr; + lctrBisUnpackDataPduHdr(&hdr, pBuf); + + switch (status) + { + case BB_STATUS_SUCCESS: + lctrMstBisIsr.cstf = hdr.cstf; + lctrMstBisIsr.cssn = hdr.cssn; + break; + + default: + break; + } + + /* Pend BIS PDU. */ + + if ((status == BB_STATUS_SUCCESS) && + !(hdr.llid == LL_LLID_BIG_CTRL_PDU) && + !((hdr.llid == LL_LLID_ISO_EMPTY_PDU) && (hdr.len == 0)) && /* Ignore Empty PDU */ + (lctrMstBisIsr.pDataBuf[lctrMstBisIsr.se.bisEvtIdx][lctrMstBisIsr.se.burstIdx] == NULL)) /* Ignore duplicate */ + { + /* Pend unique BIS PDU reception. */ + lctrMstBisIsr.pDataBuf[lctrMstBisIsr.se.bisEvtIdx][lctrMstBisIsr.se.burstIdx] = pBuf; + pBuf = NULL; + } + + /* Handle failures. */ + + switch (status) + { + case BB_STATUS_RX_TIMEOUT: + /* Re-acquire the receive train. */ + BbBleBisRxDataReAcq(pBigCtx->roleData.mst.anchorPoint + lctrMstBisIsr.nextSeOffs, + lctrMstBisIsr.pNextChan); + reAcqTrain = TRUE; + pBigCtx->lastPduMissed = TRUE; + break; + + default: + break; + } + + /* Adjust loop counters. */ + + switch (pBigCtx->packing) + { + case LL_PACKING_INTERLEAVED: + if (!lctrMstBisLoopCounterInterleaved(pBigCtx)) + { + /* Continue to next BIG Event. */ + BbSetBodTerminateFlag(); + goto RxPostProcess; + } + break; + + case LL_PACKING_SEQUENTIAL: + default: + if (!lctrMstBisLoopCounterSequential(pBigCtx)) + { + /* Continue to next BIG Event. */ + BbSetBodTerminateFlag(); + goto RxPostProcess; + } + break; + } + + /* Receive next SubEvent. */ + + if (lctrMstBisRxData(pBigCtx, reAcqTrain, pBuf)) + { + pBuf = NULL; + } + else + { + BbSetBodTerminateFlag(); + } + + /* Now that next Rx is setup, process the received packet. */ +RxPostProcess: + + switch (status) + { + case BB_STATUS_SUCCESS: + switch (hdr.llid) + { + case LL_LLID_BIG_CTRL_PDU: + if (lctrMstBisIsr.pCtrlBuf != NULL) + { + LL_TRACE_WARN1("Unexpected multiple BIS Control PDU received in a single BIG Event, bigHandle=%u", pBigCtx->handle); + } + else if (hdr.cssn == pBigCtx->bcp.cssn) + { + LL_TRACE_WARN1("Unexpected duplicate BIS Control PDU recieved, bigHandle=%u", pBigCtx->handle); + } + else + { + /* Do not receive future duplicate PDUs. */ + pBigCtx->bcp.cssn = hdr.cssn; + + lctrMstBisIsr.pCtrlBuf = pBuf; + pBuf = NULL; + /* Buffer freed in lctrMstBigEndOp(). */ + } + break; + default: + break; + } + break; + + default: + break; + } + + if (pBuf) + { + /* Free unconsumed Data PDU. */ + lctrBisRxIsoDataPduFree(pBuf); + } +} + +/*************************************************************************************************/ +/*! + * \brief Begin a BIG operation. + * + * \param pOp Begin operation. + */ +/*************************************************************************************************/ +void lctrMstBigBeginOp(BbOpDesc_t *pOp) +{ + lctrBigCtx_t * const pBigCtx = pOp->pCtx; + + if (pBigCtx->state != LCTR_MST_BIG_STATE_SYNCED) + { + BbSetBodTerminateFlag(); + return; + } + + memset(&lctrMstBisIsr, 0, sizeof(lctrMstBisIsr)); + + /* Compute next packet time. */ + switch (pBigCtx->packing) + { + case LL_PACKING_INTERLEAVED: + if (pBigCtx->numBis > 1) + { + lctrMstBisIsr.pNextChan = &pBigCtx->pBisCtx[1]->chan; + } + else if (pBigCtx->nse > 1) + { + lctrMstBisIsr.pNextChan = &pBigCtx->pBisCtx[0]->chan; + } + else + { + lctrMstBisIsr.pNextChan = &pBigCtx->ctrChan; + } + + lctrMstBisIsr.nextSeOffs = pBigCtx->bisSpaceUsec; + break; + + case LL_PACKING_SEQUENTIAL: + default: + if (pBigCtx->nse > 1) + { + lctrMstBisIsr.pNextChan = &pBigCtx->pBisCtx[0]->chan; + } + else if (pBigCtx->numBis > 1) + { + lctrMstBisIsr.pNextChan = &pBigCtx->pBisCtx[1]->chan; + } + else + { + lctrMstBisIsr.pNextChan = &pBigCtx->ctrChan; + } + + lctrMstBisIsr.nextSeOffs = pBigCtx->subInterUsec; + break; + } + + lctrMstBisIsr.cstf = TRUE; /* receive Control PDU by default */ + lctrMstBisIsr.cssn = 0xFF; + + if (!lctrMstBisRxData(pBigCtx, FALSE, NULL)) + { + BbSetBodTerminateFlag(); + return; + } +} + +/*************************************************************************************************/ +/*! + * \brief End a BIS operation. + * + * \param pOp Completed operation. + */ +/*************************************************************************************************/ +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; + } + + /* Enqueue BIS Data PDUs. */ + + uint32_t rxEventCounter = pBigCtx->eventCounter; + + for (unsigned int bisIdx = 0; bisIdx < pBigCtx->numBis; bisIdx++) + { + for (unsigned int bnIdx = 0; bnIdx < pBigCtx->bn; bnIdx++) + { + if (lctrMstBisIsr.pDataBuf[bisIdx][bnIdx]) + { + lctrBisEnqueueRxDataPdu(pBigCtx->pBisCtx[bisIdx], + lctrMstBisIsr.pDataBuf[bisIdx][bnIdx], + bnIdx); /* payload counter offset from rxEventCounter */ + } + } + } + + /* BIG Control procedure. */ + + if (lctrMstBisIsr.pCtrlBuf) + { + if (lctrMstBigControlDecrypt(pBigCtx)) + { + lctrMstBigControlPostProcess(pBigCtx); + } + else + { + goto RxPostProcess; + } + } + + /* Reset synchronization timeout timer. */ + + if (lctrMstBisIsr.numRcvdPkt) + { + WsfTimerStartMs(&pBigCtx->roleData.mst.bigSyncTmr, pBigCtx->roleData.mst.bigSyncTimeoutMs); + } + + /* Setup for next BIG Event. */ + + uint32_t unsyncTimeUsec = pBigCtx->roleData.mst.anchorPoint - pBigCtx->roleData.mst.rxSyncTime; + + while (TRUE) + { + /* Advance to next interval. */ + pBigCtx->eventCounter += 1; + pBigCtx->roleData.mst.anchorPoint += pBigCtx->isoInterUsec; + unsyncTimeUsec += pBigCtx->isoInterUsec; + + uint32_t wwTotalUsec = lctrCalcWindowWideningUsec(unsyncTimeUsec, pBigCtx->roleData.mst.totalAcc) + + pBigCtx->roleData.mst.extraWwUsec; + /* TODO Limit to half the ISO Interval size */ + + pOp->dueUsec = pBigCtx->roleData.mst.anchorPoint - wwTotalUsec; + pBis->rxSyncDelayUsec = wwTotalUsec << 1; /* multiply 2 for before and after BIG Anchor Point */ + + lctrSelectBigChannels(pBigCtx); + lctrMstBigControlProcedureHandler(pBigCtx); + + if (SchInsertAtDueTime(pOp, NULL)) + { + break; + } + + LL_TRACE_WARN2("!!! BIG schedule conflict handle=%u, ec[15:0]=%u", pBigCtx->handle, pBigCtx->eventCounter); + } + +RxPostProcess: + /* Consume ISO Data PDU. */ + + lctrMstBisRxDataPduHandler(pBigCtx, rxEventCounter); + lctrMstBisRxTestPduHandler(pBigCtx, rxEventCounter); + + if (lmgrCb.sendIsoCmplEvt) + { + lctrNotifyHostIsoEventComplete(pBigCtx->handle, (uint32_t) pBigCtx->eventCounter); + } +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_bis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_bis_slave.c new file mode 100644 index 0000000000..fc86e93ebc --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_bis_slave.c @@ -0,0 +1,771 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller slave BIG ISR callbacks. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_bis_slave.h" +#include "lctr_int_bis.h" +#include "lctr_int_iso.h" +#include "ll_defs.h" +#include "wsf_trace.h" + +#if (LL_ENABLE_TESTER) +#include "pal_bb_ble_tester.h" +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief Write CSSN value. */ +#define LCTR_BIS_WR_CSSN(v, cssn) (v) = ((v) & 0xE3) | (((cssn) & 0x7) << 2) + +/*! \brief Set CSTF flag. */ +#define LCTR_BIS_SET_CSTF(v) (v) |= (1 << 5) + +/*! \brief Clear CSTF flag. */ +#define LCTR_BIS_CLR_CSTF(v) (v) &= ~(1 << 5) + +/************************************************************************************************** + Globals +**************************************************************************************************/ + +/*! \brief BIS slave ISR control block. */ +static struct +{ + lctrSeCtx_t se; /*!< Subevent context. */ + uint8_t csFlags; /*!< CSSN and CSTF flags. */ + uint8_t emptyPdu[LL_EMPTY_PDU_LEN]; + /*!< Empty PDU buffer. */ + uint8_t numTxFrags[LL_MAX_BIS]; + /*!< Number of fragments transmitted. */ + uint32_t nextSeOffs; /*!< Next subevent time. */ + PalBbBleChan_t *pNextChan;/*!< Next subevent channel. */ + uint8_t *pCtrlBuf; /*!< Transmit BIS Control PDU buffer. */ +} lctrSlvBisIsr; + +/*! \brief Transmit descriptor. */ +PalBbBleTxBufDesc_t lctrSlvBisTxDesc[LL_MAX_BIS][LL_MAX_BN][3]; /* Place outside of lctrSlvBisIsr to reduce memclr(). */ + +/*! \brief Encrypted BIS Control PDU buffer. */ +static uint8_t lctrEncCtrlBuf[32]; /* Place outside of lctrSlvBisIsr to reduce memclr(). */ + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Setup BIS Data PDU for an BIS ISO Event. + * + * \param pBigCtx BIG context. + * \param bisIdx BIS index. + * \param burstIdx Burst index. + */ +/*************************************************************************************************/ +static void lctrSlvBisSetupTxData(lctrBigCtx_t *pBigCtx, uint8_t bisIdx, uint8_t burstIdx) +{ + if (lctrBisTxQueuePeek(pBigCtx->pBisCtx[bisIdx], burstIdx, &lctrSlvBisTxDesc[bisIdx][burstIdx][0]) > 0) + { + lctrSlvBisIsr.numTxFrags[bisIdx]++; + + /* Update Control PDU flags. */ + LCTR_BIS_WR_CSSN(lctrSlvBisTxDesc[bisIdx][burstIdx][0].pBuf[LCTR_ISO_DATA_PDU_FC_OFFSET], pBigCtx->bcp.cssn); + if (lctrSlvBisIsr.pCtrlBuf) + { + LCTR_BIS_SET_CSTF(lctrSlvBisTxDesc[bisIdx][burstIdx][0].pBuf[LCTR_ISO_DATA_PDU_FC_OFFSET]); + } + else + { + LCTR_BIS_CLR_CSTF(lctrSlvBisTxDesc[bisIdx][burstIdx][0].pBuf[LCTR_ISO_DATA_PDU_FC_OFFSET]); + } + } + else + { + /* BIS Empty PDU. */ + lctrSlvBisTxDesc[bisIdx][burstIdx][0].pBuf = lctrSlvBisIsr.emptyPdu; + lctrSlvBisTxDesc[bisIdx][burstIdx][0].len = sizeof(lctrSlvBisIsr.emptyPdu); + lctrSlvBisTxDesc[bisIdx][burstIdx][1].pBuf = NULL; + } +} + +/*************************************************************************************************/ +/*! + * \brief BIG Control PDU decrypt. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +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]; + + /* Ensure encryption shadow buffer can hold the contents of the data. */ + WSF_ASSERT((size_t)(LL_DATA_HDR_LEN + len + LL_DATA_MIC_LEN) <= sizeof(lctrEncCtrlBuf)); + + memcpy(lctrEncCtrlBuf, lctrSlvBisIsr.pCtrlBuf, LL_DATA_HDR_LEN + len); + uint8_t *pPld = lctrEncCtrlBuf + LL_DATA_HDR_LEN; + uint8_t *pTrl = pPld + len; + + if (lctrPktEncryptHdlr(&pBigCtx->ctrChan.enc, lctrEncCtrlBuf, pPld, pTrl)) + { + #if (LL_ENABLE_TESTER) + pTrl[0] ^= (llTesterCb.pktMic >> 0) & 0xFF; + pTrl[1] ^= (llTesterCb.pktMic >> 8) & 0xFF; + pTrl[2] ^= (llTesterCb.pktMic >> 16) & 0xFF; + pTrl[3] ^= (llTesterCb.pktMic >> 24) & 0xFF; + #endif + } + } +} + +/*************************************************************************************************/ +/*! + * \brief Transmit a BIS Control PDU. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +static void lctrSlvBisTxControl(lctrBigCtx_t *pBigCtx) +{ + PalBbBleTxBufDesc_t desc; + + if (pBigCtx->encrypt && lctrPktEncryptHdlr) + { + desc.pBuf = lctrEncCtrlBuf; + } + else + { + desc.pBuf = lctrSlvBisIsr.pCtrlBuf; + } + desc.len = LL_DATA_HDR_LEN + desc.pBuf[LCTR_ISO_DATA_PDU_LEN_OFFSET]; + + /* Update Control PDU flags. */ + 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]); + + BbBleBisTxData(&desc, 1, 0, NULL); +} + +/*************************************************************************************************/ +/*! + * \brief Transmit a BIS Data PDU. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +static void lctrSlvBisTxData(lctrBigCtx_t *pBigCtx) +{ + lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[lctrSlvBisIsr.se.bisEvtIdx]; + uint8_t descCnt; + PalBbBleTxBufDesc_t *pTxDesc; + + /* Get BIS Data PDU. */ + + PalBbBleTxBufDesc_t ptoTxDesc; + if (lctrSlvBisIsr.se.ptIdx == 0) + { + pTxDesc = &lctrSlvBisTxDesc[lctrSlvBisIsr.se.bisEvtIdx][lctrSlvBisIsr.se.burstIdx][0]; + + if (pTxDesc[1].pBuf) + { + if (pTxDesc[2].pBuf) + { + descCnt = 3; + } + else + { + descCnt = 2; + } + } + else + { + descCnt = 1; + } + } + else + { + ptoTxDesc.pBuf = lctrSlvBisIsr.emptyPdu; + ptoTxDesc.len = sizeof(lctrSlvBisIsr.emptyPdu); + + pTxDesc = &ptoTxDesc; + descCnt = 1; + } + + /* Commit transmission. */ + +#if (LL_ENABLE_TESTER) + /* Check subevent trigger for access address invalidation. */ + if ((llTesterCb.isoAccAddrSeTrigMask & (1 << lctrSlvBisIsr.se.burstIdx)) && + !llTesterCb.isoAccAddrInvForRx) + { + PalBbTesterInvalidateNextAccAddr(FALSE); + + if (llTesterCb.isoAccAddrInvNumTrig) + { + llTesterCb.isoAccAddrInvNumTrig--; + if (llTesterCb.isoAccAddrInvNumTrig == 0) + { + llTesterCb.isoAccAddrSeTrigMask = 0; + } + } + } +#endif + + BbBleBisTxData(pTxDesc, descCnt, + pBigCtx->bod.dueUsec + lctrSlvBisIsr.nextSeOffs, + lctrSlvBisIsr.pNextChan); + + /* Post-commit calculation. */ + + /* Now that channel data is set in BB, compute next channel information. */ + pBisCtx->chan.chanIdx = LmgrSelectNextSubEvtChannel(&pBisCtx->chSelInfo); +} + +/*************************************************************************************************/ +/*! + * \brief BIS Tx Test payload generator. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +static void lctrSlvBisTxTestPayloadHandler(lctrBigCtx_t *pBigCtx) +{ + for (unsigned int i = 0; i < pBigCtx->numBis; i++) + { + lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[i]; + + if (pBisCtx->test.enabled) + { + if (!pBisCtx->test.term) + { + uint8_t *pIsoBuf; + uint32_t pldCtr; + + if (pBigCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED) + { + for (unsigned int j = 0; j < pBigCtx->bn; j++) + { + pldCtr = (pBigCtx->eventCounter * pBigCtx->bn) + j; + if ((pIsoBuf = lctrGenerateIsoTestData(pBisCtx->handle, pBisCtx->test.pldType, + pBigCtx->maxSdu, pldCtr)) != NULL) + { + LctrTxIso(pIsoBuf); + } + else + { + /* Out of memory; gracefully continue execution. */ + return; + } + } + } + + else /* LL_ISO_PDU_TYPE_FRAMED */ + { + pldCtr = pBisCtx->test.util.framed.payloadCtr++; + if ((pIsoBuf = lctrGenerateIsoTestData(pBisCtx->handle, pBisCtx->test.pldType, + pBigCtx->maxSdu, pldCtr)) != NULL) + { + LctrTxIso(pIsoBuf); + } + else + { + /* Out of memory; gracefully continue execution. */ + return; + } + } + } + else + { + /* Terminate ISO Test mode operation. */ + pBisCtx->test.enabled = FALSE; + pBisCtx->test.term = FALSE; + pBisCtx->test.util.framed.payloadCtr = 0; + } + } + } +} + +/*************************************************************************************************/ +/*! + * \brief Check for pending SDU fragments. + * + * \param pBigCtx BIG context. + * + * SDU fragments may be pending waiting on a missed SDU event. Call the ISOAL PDU assembler to + * obtain any pending data. + */ +/*************************************************************************************************/ +static void lctrSlvCheckPendingSdu(lctrBigCtx_t *pBigCtx) +{ + for (unsigned int i = 0; i < pBigCtx->numBis; i++) + { + lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[i]; + + uint8_t *pDataBuf; + + if (pBisCtx->roleData.slv.isoalTxCtx.pendQueueSize == 0) + { + /* No pending SDUs. */ + continue; + } + + if ((pDataBuf = lctrTxIsoDataPduAlloc()) != NULL) + { + lctrIsoHdr_t isoHdr = + { + .handle = pBisCtx->handle, + .tsFlag = FALSE + }; + + if ((isoHdr.sduLen = lctrAssembleTxFramedPdu(&pBisCtx->roleData.slv.isoalTxCtx, pDataBuf, pBisCtx->pBigCtx->maxPdu)) > 0) + { + lctrBisTxIsoPduQueue(pBisCtx, &isoHdr, pDataBuf); + } + else + { + /* Release unused buffer. */ + WsfMsgFree(pDataBuf); + } + } + else + { + LL_TRACE_WARN0("Tx path flow controlled; flush pending SDU queue"); + + uint8_t *pSduBuf; + wsfHandlerId_t temp; + + while ((pSduBuf = WsfMsgDeq(&pBisCtx->roleData.slv.isoalTxCtx.pendingSduQ, &temp)) != NULL) + { + WsfMsgFree(pSduBuf); + lctrIsoSduTxIncAvailBuf(); + } + } + } +} + +/*************************************************************************************************/ +/*! + * \brief BIG Control Procedure handler. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +static void lctrSlvBigControlProcedureHandler(lctrBigCtx_t *pBigCtx) +{ + if (pBigCtx->bcp.actMsk) + { + uint16_t inst = (pBigCtx->eventCounter + 1) & 0xFFFF; + + if ((pBigCtx->bcp.actMsk & (1 << LL_BIG_OPCODE_CHAN_MAP_IND)) && + (inst == pBigCtx->bcp.chanMapUpd.inst)) + { + pBigCtx->bcp.actMsk &= ~(1 << LL_BIG_OPCODE_CHAN_MAP_IND); + + lctrRemapBigChannels(pBigCtx, pBigCtx->bcp.chanMapUpd.chanMap); + + LL_TRACE_INFO2("Updated channel map: bigHandle=%u inst=%u", pBigCtx->handle, inst); + + if (pBigCtx->roleData.slv.pAdvSet) + { + /* Re-enable BIG Info transmissions. */ + LctrAcadBigInfo_t *pBigInfo = &pBigCtx->roleData.slv.pAdvSet->acadParams[LCTR_ACAD_ID_BIG_INFO].bigInfo; + pBigInfo->chanMap = pBigCtx->bcp.chanMapUpd.chanMap; + pBigInfo->hdr.state = LCTR_ACAD_STATE_ENABLED; + } + } + + /* Resume pending BIG Control Procedure. */ + if (pBigCtx->bcp.actMsk == 0) + { + if (pBigCtx->bcp.pendMsk & (1 << LL_BIG_OPCODE_CHAN_MAP_IND)) + { + pBigCtx->bcp.pendMsk &= ~(1 << LL_BIG_OPCODE_CHAN_MAP_IND); + lctrSlvBigSendMsg(pBigCtx, LCTR_SLV_BIG_MSG_CH_MAP_UPD); + } + else if (pBigCtx->bcp.pendMsk & (1 << LL_BIG_OPCODE_BIG_TERM_IND)) + { + pBigCtx->bcp.pendMsk &= ~(1 << LL_BIG_OPCODE_BIG_TERM_IND); + lctrSlvBigSendMsg(pBigCtx, LCTR_SLV_BIG_MSG_TERMINATE_BIG); + } + } + } +} + +/*************************************************************************************************/ +/*! + * \brief BIS Tx Data PDU complete handler. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +static void lctrSlvBisTxDataPduHandler(lctrBigCtx_t *pBigCtx) +{ + /*** Tx completion ***/ + + for (unsigned int i = 0; i < pBigCtx->numBis; i++) + { + lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[i]; + + if (lctrSlvBisIsr.numTxFrags[i]) + { + lctrBisTxQueuePopCleanup(pBisCtx, lctrSlvBisIsr.numTxFrags[i]); + } + } + + lctrNotifyIsoTxComplete(pBigCtx); +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Complete a transmitted BIS data buffer using sequential packing. + * + * \param pOp Operation context. + * \param status Transmit status. + */ +/*************************************************************************************************/ +void lctrSlvBisTxCompletionSequential(BbOpDesc_t *pOp, uint8_t status) +{ + lctrBigCtx_t * const pBigCtx = pOp->pCtx; + + if (status != BB_STATUS_SUCCESS) + { + LL_TRACE_WARN2("!!! Failed BIG transmission handle=%u ec[15:0]=%u", pBigCtx->handle, pBigCtx->eventCounter); + + BbSetBodTerminateFlag(); + return; + } + + /* BIG Event limit (beyond BIS Control SubEvent). */ + + if (lctrSlvBisIsr.se.bisEvtIdx >= pBigCtx->numBis) + { + BbSetBodTerminateFlag(); + return; + } + + size_t numSePkts = (pBigCtx->bn * pBigCtx->irc) + lctrSlvBisIsr.se.ptIdx; + + if (!lctrSlvBisCalcNextIdxSequential(pBigCtx, &lctrSlvBisIsr.se, numSePkts)) + { + if (lctrSlvBisIsr.pCtrlBuf) + { + lctrSlvBisTxControl(pBigCtx); + } + else + { + BbSetBodTerminateFlag(); + } + return; + } + + /* Compute next channel. */ + lctrSeCtx_t nextSe = lctrSlvBisIsr.se; + if (lctrSlvBisCalcNextIdxSequential(pBigCtx, &nextSe, numSePkts)) + { + lctrSlvBisIsr.pNextChan = &pBigCtx->pBisCtx[nextSe.bisEvtIdx]->chan; + } + else + { + lctrSlvBisIsr.pNextChan = &pBigCtx->ctrChan; + } + + /* Compute next packet time. */ + lctrSlvBisIsr.nextSeOffs += pBigCtx->subInterUsec; + + lctrSlvBisTxData(pBigCtx); +} + +/*************************************************************************************************/ +/*! + * \brief Complete a transmitted BIS data buffer using interleaved packing. + * + * \param pOp Operation context. + * \param status Transmit status. + */ +/*************************************************************************************************/ +void lctrSlvBisTxCompletionInterleaved(BbOpDesc_t *pOp, uint8_t status) +{ + lctrBigCtx_t * const pBigCtx = pOp->pCtx; + + if (status != BB_STATUS_SUCCESS) + { + LL_TRACE_WARN2("!!! Failed BIG transmission handle=%u ec[15:0]=%u", pBigCtx->handle, pBigCtx->eventCounter); + + BbSetBodTerminateFlag(); + return; + } + + size_t numSePkts = (pBigCtx->bn * pBigCtx->irc) + lctrSlvBisIsr.se.ptIdx; + + /* BIG Event limit (beyond BIS Control SubEvent). */ + + if (numSePkts > pBigCtx->nse) + { + BbSetBodTerminateFlag(); + return; + } + + /* BIS loop. */ + + if (!lctrSlvBisCalcNextIdxInterleaved(pBigCtx, &lctrSlvBisIsr.se, numSePkts)) + { + if (lctrSlvBisIsr.pCtrlBuf) + { + lctrSlvBisTxControl(pBigCtx); + } + else + { + BbSetBodTerminateFlag(); + } + + return; + } + + /* Compute next channel. */ + lctrSeCtx_t nextSe = lctrSlvBisIsr.se; + if (lctrSlvBisCalcNextIdxInterleaved(pBigCtx, &nextSe, numSePkts)) + { + lctrSlvBisIsr.pNextChan = &pBigCtx->pBisCtx[nextSe.bisEvtIdx]->chan; + } + else + { + lctrSlvBisIsr.pNextChan = &pBigCtx->ctrChan; + } + + /* Compute next packet time. */ + lctrSlvBisIsr.nextSeOffs += pBigCtx->bisSpaceUsec; + + lctrSlvBisTxData(pBigCtx); +} + +/*************************************************************************************************/ +/*! + * \brief Begin a BIG operation. + * + * \param pOp Begin operation. + */ +/*************************************************************************************************/ +void lctrSlvBigBeginOp(BbOpDesc_t *pOp) +{ + lctrBigCtx_t * const pBigCtx = pOp->pCtx; + + memset(&lctrSlvBisIsr, 0, sizeof(lctrSlvBisIsr)); + + switch (pBigCtx->packing) + { + case LL_PACKING_INTERLEAVED: + if (pBigCtx->numBis > 1) + { + lctrSlvBisIsr.pNextChan = &pBigCtx->pBisCtx[1]->chan; + } + else if (pBigCtx->nse > 1) + { + lctrSlvBisIsr.pNextChan = &pBigCtx->pBisCtx[0]->chan; + } + else + { + lctrSlvBisIsr.pNextChan = &pBigCtx->ctrChan; + } + + lctrSlvBisIsr.nextSeOffs = pBigCtx->bisSpaceUsec; + break; + + case LL_PACKING_SEQUENTIAL: + default: + if (pBigCtx->nse > 1) + { + lctrSlvBisIsr.pNextChan = &pBigCtx->pBisCtx[0]->chan; + } + else if (pBigCtx->numBis > 1) + { + lctrSlvBisIsr.pNextChan = &pBigCtx->pBisCtx[1]->chan; + } + else + { + lctrSlvBisIsr.pNextChan = &pBigCtx->ctrChan; + } + + lctrSlvBisIsr.nextSeOffs = pBigCtx->subInterUsec; + break; + } + + /* Setup Control PDU */ + lctrSlvBisIsr.pCtrlBuf = lctrBigTxCtrlQueuePeek(pBigCtx); + + /* Pre-pack BIS Empty PDU. */ + lctrBisDataPduHdr_t hdr = + { + .llid = LL_LLID_ISO_EMPTY_PDU, + .cssn = pBigCtx->bcp.cssn, + .cstf = lctrSlvBisIsr.pCtrlBuf != NULL, + .len = 0 + }; + uint8_t *pEmptyPdu = lctrSlvBisIsr.emptyPdu; + lctrBisPackDataPduHdr(pEmptyPdu, &hdr); + + /* Commit first Data PDU. */ + lctrSlvBisSetupTxData(pBigCtx, 0, 0); + lctrSlvBisTxData(pBigCtx); + + /* Now that the first Data PDU is committed, setup remaining Data PDUs. */ + for (unsigned int i = 0; i < pBigCtx->numBis; i++) + { + for (unsigned int j = 0; j < pBigCtx->bn; j++) + { + if (!((i == 0) && (j == 0))) /* skip first Data PDU */ + { + lctrSlvBisSetupTxData(pBigCtx, i, j); + } + } + } + + /* Post setup processing. */ + + if (!pBigCtx->roleData.slv.notifyHostEst) + { + pBigCtx->roleData.slv.notifyHostEst = TRUE; + lctrNotifyHostCreateBigComplete(pBigCtx, LL_SUCCESS); + } + + if (lctrSlvBisIsr.pCtrlBuf) + { + lctrMstBigControlEncrypt(pBigCtx); + } +} + +/*************************************************************************************************/ +/*! + * \brief End a BIS operation. + * + * \param pOp Completed operation. + */ +/*************************************************************************************************/ +void lctrSlvBigEndOp(BbOpDesc_t *pOp) +{ + lctrBigCtx_t * const pBigCtx = pOp->pCtx; + + /* Setup for next BIG Event. */ + + while (TRUE) + { + /* Complete BIS Data PDU processing. */ + lctrSlvBisTxDataPduHandler(pBigCtx); + /* TODO Incoming data payloadCounter should match scheduled eventCounter */ + + /* BIS Control PDU accounting. */ + lctrBigTxCtrlQueuePop(pBigCtx); + + if (pBigCtx->state != LCTR_SLV_BIG_STATE_ENABLED) + { + if (pBigCtx->bcp.actMsk & (1 << LL_BIG_OPCODE_BIG_TERM_IND)) + { + /* Ensure delivery of BIG_TERMINATE_IND is complete. */ + if (WsfQueueEmpty(&pBigCtx->roleData.slv.txCtrlQ)) + { + lctrSlvBigSendMsg(pBigCtx, LCTR_SLV_BIG_MSG_TERMINATED); + return; + } + } + else /* Reset */ + { + lctrSlvBigSendMsg(pBigCtx, LCTR_SLV_BIG_MSG_TERMINATED); + return; + } + } + + /* Advance to next interval. */ + pBigCtx->eventCounter += 1; + pOp->dueUsec += pBigCtx->isoInterUsec; + + /* Select next BIS Event channels. */ + lctrSelectBigChannels(pBigCtx); + lctrSlvBigControlProcedureHandler(pBigCtx); + + if (SchInsertAtDueTime(pOp, NULL)) + { + break; + } + + LL_TRACE_WARN2("!!! BIG schedule conflict handle=%u, ec[15:0]=%u", pBigCtx->handle, pBigCtx->eventCounter); + } + + /* SDU generator. */ + + lctrSlvBisTxTestPayloadHandler(pBigCtx); + + /* Update BIG Info. */ + + lctrAdvSet_t * const pAdvSet = pBigCtx->roleData.slv.pAdvSet; + if (pAdvSet) + { + lctrAcadParam_t * const pAcad = &pAdvSet->acadParams[LCTR_ACAD_ID_BIG_INFO]; + pAcad->bigInfo.bigAnchorPoint = pOp->dueUsec; + pAcad->bigInfo.bisPldCtr = pBigCtx->eventCounter * pBigCtx->bn; + } + + /* SDU queue maintenance. */ + + if (pBigCtx->framing == LL_ISO_PDU_TYPE_FRAMED) + { + lctrSlvCheckPendingSdu(pBigCtx); + } + + /* Notifications. */ + + if (lmgrCb.sendIsoCmplEvt) + { + lctrNotifyHostIsoEventComplete(pBigCtx->handle, (uint32_t) pBigCtx->eventCounter); + } +} + +/*************************************************************************************************/ +/*! + * \brief Abort a BIS operation. + * + * \param pOp Completed operation. + */ +/*************************************************************************************************/ +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); + + lctrSlvBigEndOp(pOp); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis.c new file mode 100644 index 0000000000..4cec77a5df --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis.c @@ -0,0 +1,358 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller connected isochronous stream ISR callbacks. + * + * Copyright (c) 2013-2019 ARM Ltd. All Rights Reserved. + * + * 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 "lctr_int_iso.h" +#include "lctr_int_cis.h" +#include "bb_ble_api.h" +#include "pal_bb.h" +#include "wsf_assert.h" +#include "wsf_math.h" +#include "wsf_msg.h" +#include "wsf_os.h" +#include "util/bstream.h" +#include + +#if (LL_ENABLE_TESTER) +#include "pal_bb_ble_tester.h" +#endif + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*! \brief CIS ISR control block. */ +static union +{ + /* Added at top of structure for 32-bit alignment. */ + uint8_t emptyPdu[LL_EMPTY_PDU_LEN]; + /*!< Empty PDU buffer. Used only by active operation. */ + uint32_t align32; /*!< Not used, declared for alignment of emptyPdu. */ +} lctrCisIsr; + +/*************************************************************************************************/ +/*! + * \brief Build empty CIS PDU. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static inline void lctrCisBuildEmptyPdu(lctrCisCtx_t *pCisCtx) +{ + pCisCtx->txHdr.llid = LL_LLID_ISO_EMPTY_PDU; + /* pCisCtx->txHdr.nesn = 0; */ /* FC bits already valid */ + /* pCisCtx->txHdr.sn = 0; */ /* FC bits already valid */ + /* pCisCtx->txHdr.cie = 0; */ /* already set */ + pCisCtx->txHdr.len = 0; + + lctrCisPackDataPduHdr(lctrCisIsr.emptyPdu, &pCisCtx->txHdr); +} + +/*************************************************************************************************/ +/*! + * \brief Build NULL CIS PDU. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static inline void lctrCisBuildNullPdu(lctrCisCtx_t *pCisCtx) +{ + pCisCtx->txHdr.llid = LL_LLID_ISO_UNF_END_PDU; + /* pCisCtx->txHdr.nesn = 0; */ /* FC bits already valid */ + pCisCtx->txHdr.sn = 0; + /* pCisCtx->txHdr.cie = 0; */ /* already set */ + pCisCtx->txHdr.np = 1; + pCisCtx->txHdr.len = 0; + + lctrCisPackDataPduHdr(lctrCisIsr.emptyPdu, &pCisCtx->txHdr); +} + +/*************************************************************************************************/ +/*! + * \brief Set flow control bits in PDU. + * + * \param pHdr Unpacked PDU header. + * \param pBuf Packed packet buffer. + */ +/*************************************************************************************************/ +static inline void lctrCisUpdateFlowCtrlBits(const lctrCisDataPduHdr_t *pHdr, uint8_t *pBuf) +{ + const uint8_t FC_BITMASK = 0xC; + + pBuf[LCTR_ISO_DATA_PDU_FC_OFFSET] &= ~FC_BITMASK; + + pBuf[LCTR_ISO_DATA_PDU_FC_OFFSET] |= (pHdr->nesn & 1) << 2; + pBuf[LCTR_ISO_DATA_PDU_FC_OFFSET] |= (pHdr->sn & 1) << 3; + pBuf[LCTR_ISO_DATA_PDU_FC_OFFSET] |= (pHdr->cie & 1) << 4; + pBuf[LCTR_ISO_DATA_PDU_FC_OFFSET] |= (pHdr->np & 1) << 6; +} + +/*************************************************************************************************/ +/*! + * \brief Process Rx acknowledgment. + * + * \param pCisCtx CIS context. + * + * \return TRUE if peer ACK last Tx PDU, FALSE if peer NACK'ed last PDU. + */ +/*************************************************************************************************/ +bool_t lctrCisProcessRxAck(lctrCisCtx_t *pCisCtx) +{ + bool_t result = FALSE; + + if (pCisCtx->rxHdr.np == 1) + { + /* NULL PDU doesn't need to be acked or processed.*/ + return result; + } + + /* Acknowledgment of received PDU (new data PDU). */ + if (((pCisCtx->rxHdr.sn ^ pCisCtx->txHdr.nesn) & 1) == 0) /* bits are same */ + { + /* Accept packets up to the maximum length because peer may queue packets before length change. */ + if (pCisCtx->rxHdr.len > (pCisCtx->localDataPdu.maxRxLen + LL_DATA_MIC_LEN)) + { + /* Invalid length value; ack PDU but drop it (don't process it). */ + lctrCisIncPacketCounterRx(pCisCtx); + pCisCtx->txHdr.nesn++; + return result; + } + + if ((pCisCtx->rxHdr.len) || + ((pCisCtx->rxHdr.len == 0) && (pCisCtx->rxHdr.llid == LL_LLID_ISO_UNF_END_PDU))) + { + /* lctrCisIncPacketCounterRx(pCisCtx) */ /* done after decryption in lctrCisRxPendingHandler */ + result = TRUE; + } + else /* Empty PDU. */ + { + lctrCisIncPacketCounterRx(pCisCtx); + } + /* Invalid LLID value; ack PDU but drop it (don't process it). */ + /* length of 0 and LLID of LL_LLID_EMPTY_PDU implies padding/empty PDU. */ + + pCisCtx->txHdr.nesn++; + pCisCtx->rxFtParamList.pHead->ftParam.pduRcved = TRUE; + return result; + } + + return FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Last Data PDU acknowledged by peer. + * + * \param pCisCtx Connection context. + */ +/*************************************************************************************************/ +void lctrCisTxPduAck(lctrCisCtx_t *pCisCtx) +{ + pCisCtx->txHdr.len = 0; + pCisCtx->txBufPendAck = FALSE; + + /* Remove last transmitted PDU. */ + if (lctrCisTxQueuePop(pCisCtx)) + { + pCisCtx->txDataCounter++; + } +} + +/*************************************************************************************************/ +/*! + * \brief Process Tx acknowledgment. + * + * \param pCisCtx Connection context. + * + * \return TRUE if peer ACK last Tx PDU, FALSE if peer NACK'ed last PDU. + * + * Free ARQ element on peer acknowledgment. + */ +/*************************************************************************************************/ +bool_t lctrCisProcessTxAck(lctrCisCtx_t *pCisCtx) +{ + if (((pCisCtx->rxHdr.nesn ^ pCisCtx->txHdr.sn) & 1) == 1) /* bits are different */ + { + pCisCtx->txHdr.sn++; + + + if (pCisCtx->txBufPendAck) + { + /*** Peer ACK'ed a data PDU ***/ + + lctrCisTxPduAck(pCisCtx); + } + else + { + /*** Peer ACK'ed an Empty PDU ***/ + + pCisCtx->txDataCounter++; + } + + pCisCtx->txFtParamList.pHead->ftParam.pduAcked = TRUE; + + return TRUE; + } + /* Peer NACK'ed PDU. */ + return FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Post-process Tx acknowledgment. + * + * \param pCisCtx Connection context. + * + * Cleanup from Tx acknowledgment processing. + */ +/*************************************************************************************************/ +void lctrCisProcessTxAckCleanup(lctrCisCtx_t *pCisCtx) +{ + /* Complete buffer cleanup. */ + if (pCisCtx->txPduIsAcked || pCisCtx->pduFlushed) + { + lctrCisTxQueuePopCleanup(pCisCtx); + } +} + +/*************************************************************************************************/ +/*! + * \brief Setup for CIS data PDU transmission. + * + * \param pCigCtx Connection context. + * \param rxStatus Status of last receive. + * \param reqTx Require Tx. + * + * \return Number of bytes transmitted, 0 if no packet transmitted. + */ +/*************************************************************************************************/ +uint16_t lctrCisSetupForTx(lctrCigCtx_t *pCigCtx, uint8_t rxStatus, bool_t reqTx) +{ + uint16_t numTxBytes = 0; + lctrCisCtx_t *pCisCtx = pCigCtx->pCisCtx; + +#if (LL_ENABLE_TESTER) + /* Invalidate access address if trigger is set. */ + if (llTesterCb.isoAccAddrSeTrigMask && + (llTesterCb.isoAccAddrSeTrigMask & (1 << pCisCtx->subEvtCounter)) && + !llTesterCb.isoAccAddrInvForRx) + { + PalBbTesterInvalidateNextAccAddr(FALSE); + + if (llTesterCb.isoAccAddrInvNumTrig) + { + llTesterCb.isoAccAddrInvNumTrig--; + if (llTesterCb.isoAccAddrInvNumTrig == 0) + { + llTesterCb.isoAccAddrSeTrigMask = 0; + } + } + } +#endif + + /*** Setup for transmit ***/ + + /* pCisCtx->txHdr.cie = 0; CIE bit is initialized in the lctrMstCisInitIsr or lctrSlvCisInitIsr and shall be set once for the event. */ + pCisCtx->txHdr.np = 0; + pCisCtx->txHdr.len = 0; + pCisCtx->txHdr.llid = LL_LLID_ISO_UNF_END_PDU; + + if ((rxStatus != BB_STATUS_SUCCESS) || + reqTx) + { + PalBbBleTxBufDesc_t bbDesc[3]; + uint8_t bbDescCnt; + + if (pCisCtx->isTxDone == TRUE) + { + /*** Send NULL PDU ***/ + + lctrCisBuildNullPdu(pCisCtx); + + PalBbBleTxBufDesc_t desc = {.pBuf = lctrCisIsr.emptyPdu, .len = sizeof(lctrCisIsr.emptyPdu)}; + BbBleCisTxData(&desc, 1); + numTxBytes = desc.len; + + return numTxBytes; + } + + /* Do not remove from ARQ until acknowledged by peer. */ + bbDescCnt = lctrCisTxQueuePeek(pCisCtx, &bbDesc[0]); + lctrFtParam_t *pFtParam = &pCisCtx->txFtParamList.pHead->ftParam; + + if (bbDescCnt > 0) + { + /* Set flow control bits. */ + pCisCtx->txHdr.len = bbDesc[0].pBuf[LCTR_ISO_DATA_PDU_LEN_OFFSET]; + pFtParam->pduType[pFtParam->pduCounter] = LCTR_CIS_PDU_NON_EMPTY; + pCisCtx->txBufPendAck = TRUE; + lctrCisUpdateFlowCtrlBits(&pCisCtx->txHdr, bbDesc[0].pBuf); + +#if (LL_ENABLE_TESTER) + bbDesc[0].pBuf[0] ^= llTesterCb.pktLlId & 0x03; +#endif + + BbBleCisTxData(&bbDesc[0], bbDescCnt); + numTxBytes = LL_DATA_HDR_LEN + bbDesc[0].pBuf[LCTR_ISO_DATA_PDU_LEN_OFFSET]; + + if (pCisCtx->subEvtCounter == pCisCtx->nse) + { + pCisCtx->isoLinkQualStats.txLastSubEventPkt++; + } + } + else + { + /*** Send Empty PDU ***/ + + lctrCisBuildEmptyPdu(pCisCtx); + pFtParam->pduType[pFtParam->pduCounter] = LCTR_CIS_PDU_EMPTY; + + PalBbBleTxBufDesc_t desc = {.pBuf = lctrCisIsr.emptyPdu, .len = sizeof(lctrCisIsr.emptyPdu)}; + BbBleCisTxData(&desc, 1); + numTxBytes = desc.len; + } + } + /* else nothing to transmit */ + + return numTxBytes; +} + +/*************************************************************************************************/ +/*! + * \brief Rx post processing. + * + * \param pCisCtx CIS context. + * \param pRxBuf Rx buffer. + */ +/*************************************************************************************************/ +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 + { + lctrCisRxPduFree(pRxBuf); + } +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis_master.c new file mode 100644 index 0000000000..d970825935 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis_master.c @@ -0,0 +1,1205 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller master connected isochronous stream ISR callbacks. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int.h" +#include "lctr_int_cis.h" +#include "lctr_int_cis_master.h" +#include "lctr_int_iso.h" +#include "lmgr_api_conn.h" +#include "sch_api.h" +#include "sch_api_ble.h" +#include "bb_ble_api.h" +#include "wsf_assert.h" +#include "wsf_math.h" +#include "wsf_msg.h" +#include "wsf_os.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include "pal_codec.h" + +#if (LL_ENABLE_TESTER) +#include "pal_bb_ble_tester.h" +#endif + +#include + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +#if (LL_ENABLE_TESTER) +void LctrCisProcessRxTxAck(lctrCisCtx_t *pCtx, bool_t *pValidRx, bool_t *pTxPduIsAcked); +#endif + +/*************************************************************************************************/ +/*! + * \brief Initialize master CIS event resources. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static void lctrMstCisInitIsr(lctrCisCtx_t *pCisCtx) +{ + pCisCtx->subEvtCounter = 0; + pCisCtx->data.mst.rxFromSlave = FALSE; + 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) + { + pCisCtx->isTxDone = TRUE; + } + else + { + pCisCtx->isTxDone = FALSE; + } + + /*** Setup for transmit ***/ + + pCisCtx->txHdr.cie = 0; + pCisCtx->txHdr.np = 0; + + /*** Setup for receive ***/ + + pCisCtx->rxHdr.cie = 0; + pCisCtx->rxHdr.np = 0; + pCisCtx->rxHdr.len = 0; + pCisCtx->rxHdr.llid = LL_LLID_ISO_UNF_END_PDU; +} + +/*************************************************************************************************/ +/*! + * \brief Setup the resource for the Rx. + * + * \param pCigCtx CIG context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static void lctrMstCisSetupRx(lctrCigCtx_t *pCigCtx, lctrCisCtx_t *pCisCtx) +{ + uint8_t *pBuf; + + if (!lmgrIsoCb.availRxBuf) + { + LL_TRACE_ERR1("!!! lctrMstCisSetupRx, RX buffer not available, cisHandle=%u", pCisCtx->cisHandle); + return; /* flow control Rx */ + } + + /*** Setup for receive ***/ + + if ((pBuf = lctrCisRxPduAlloc(pCisCtx->localDataPdu.maxRxLen)) != NULL) + { +#if (LL_ENABLE_TESTER) + /* Invalidate access address if trigger is set. */ + if (llTesterCb.isoAccAddrSeTrigMask && + (llTesterCb.isoAccAddrSeTrigMask & (1 << pCisCtx->subEvtCounter)) && + llTesterCb.isoAccAddrInvForRx) + { + PalBbTesterInvalidateNextAccAddr(TRUE); + + if (llTesterCb.isoAccAddrInvNumTrig) + { + llTesterCb.isoAccAddrInvNumTrig--; + if (llTesterCb.isoAccAddrInvNumTrig == 0) + { + llTesterCb.isoAccAddrSeTrigMask = 0; + } + } + } +#endif + + 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); + BbSetBodTerminateFlag(); + } +} + +/*************************************************************************************************/ +/*! + * \brief Setup the resource for the Tx. + * + * \param pCigCtx CIG context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static void lctrMstCisSetupTx(lctrCigCtx_t *pCigCtx, lctrCisCtx_t *pCisCtx) +{ + (void)lctrCisSetupForTx(pCigCtx, BB_STATUS_SUCCESS /* does not matter */, TRUE); +} + +/*************************************************************************************************/ +/*! + * \brief Check Tx flush timeout and flush PDU if necessary after RX. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static void lctrCisCheckTxFtAfterRx(lctrCisCtx_t *pCisCtx) +{ + if (lctrCisFtIsListEmpty(&pCisCtx->txFtParamList)) + { + /* List is empty. */ + return; + } + + if (pCisCtx->txHdr.np) + { + /* NULL PDU doesn't need to be acked or flushed. */ + return; + } + + lctrFtParam_t *pFtParam = &pCisCtx->txFtParamList.pHead->ftParam; + + if (pFtParam->pduAcked) + { + pFtParam->isPduDone[pFtParam->pduCounter] = TRUE; /* The PDU is done. */ + pFtParam->pduCounter++; + lctrCisIncPacketCounterTx(pCisCtx); + } + else + { + /* Check if this is the last interval before FT. */ + if ((pFtParam->intervalCounter + 1) == pFtParam->intervalTotal) + { + if (pFtParam->subEvtCounter == pFtParam->lastSubEvtFt[pFtParam->pduCounter]) + { + /* PDU needs to be flushed. */ + pCisCtx->txHdr.sn++; + pFtParam->isPduDone[pFtParam->pduCounter] = TRUE; /* The PDU is done. */ + + 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. */ + } + pFtParam->pduCounter++; + lctrCisIncPacketCounterTx(pCisCtx); + pCisCtx->isoLinkQualStats.txUnAckPkt++; + } + } + else /* Implies that a retransmit will happen. */ + { + pCisCtx->isoLinkQualStats.retransmitPkt++; + } + } + + /* Set the flag to send NULL packet. */ + bool_t removeFromList = TRUE; + for (unsigned int i = 0; i < WSF_MIN(pFtParam->bn, LCTR_MAX_BN); i++) + { + if (pFtParam->isPduDone[i] == FALSE) + { + removeFromList = FALSE; + break; + } + } + if (removeFromList == TRUE) + { + lctrCisFtRemoveHead(&pCisCtx->txFtParamList); + } + + /* No more data to send, send NULL packet. */ + if (lctrCisFtIsListEmpty(&pCisCtx->txFtParamList)) + { + pCisCtx->isTxDone = TRUE; + } +} + +/*************************************************************************************************/ +/*! + * \brief Check Rx flush timeout and flush PDU if necessary after RX. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static void lctrCisCheckRxFtAfterRx(lctrCisCtx_t *pCisCtx) +{ + if (lctrCisFtIsListEmpty(&pCisCtx->rxFtParamList)) + { + /* List is empty. */ + 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) + { + pFtParam->isPduDone[pFtParam->pduCounter] = TRUE; /* The PDU is done. */ + pFtParam->pduCounter++; + } + else + { + /* Check if this is the last interval before FT. */ + if ((pFtParam->intervalCounter + 1) == pFtParam->intervalTotal) + { + if (pFtParam->subEvtCounter == pFtParam->lastSubEvtFt[pFtParam->pduCounter]) + { + /* PDU needs to be flushed. */ + pCisCtx->txHdr.nesn++; + lctrCisIncPacketCounterRx(pCisCtx); + pFtParam->isPduDone[pFtParam->pduCounter] = TRUE; /* The PDU is done. */ + pFtParam->pduCounter++; + pCisCtx->isoLinkQualStats.rxUnreceivedPkt++; + pCisCtx->isoalRxCtx.pduFlushed = TRUE; + pCisCtx->isoalRxCtx.packetSequence++; + pCisCtx->numRxMissed++; + } + } + } + + /* Remove the node if all the items are done. */ + bool_t removeFromList = TRUE; + for (unsigned int i = 0; i < WSF_MIN(pFtParam->bn, LCTR_MAX_BN); i++) + { + if (pFtParam->isPduDone[i] == FALSE) + { + removeFromList = FALSE; + break; + } + } + if (removeFromList == TRUE) + { + lctrCisFtRemoveHead(&pCisCtx->rxFtParamList); + } +} + +/*************************************************************************************************/ +/*! + * \brief Check flush timeout and flush PDU if necessary after end of BOD. + * + * \param pCisCtx CIS Context. + */ +/*************************************************************************************************/ +static void lctrCisCheckTxFtAfterBod(lctrCisCtx_t *pCisCtx) +{ + if (lctrCisFtIsListEmpty(&pCisCtx->txFtParamList)) + { + /* List is empty. */ + 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. */ + while (pNode) + { + pNode->ftParam.intervalCounter++; + pNode = pNode->pNext; + } + + /* Only check the head node. */ + lctrFtParam_t *pFtParam = &pCisCtx->txFtParamList.pHead->ftParam; + for (unsigned int i = 0; i < WSF_MIN(pFtParam->bn, LCTR_MAX_BN); i++) + { + if (pFtParam->isPduDone[i] == FALSE && /* If the PDU is not done. */ + pFtParam->intervalCounter == pFtParam->intervalTotal) /* Check if the PDU needs to be flush in this interval. */ + { + pFtParam->isPduDone[i] = TRUE; + pCisCtx->txHdr.sn++; + + 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++; + } + } + + /* Remove the node if all the items are done. */ + bool_t removeFromList = TRUE; + for (unsigned int i = 0; i < WSF_MIN(pFtParam->bn, LCTR_MAX_BN); i++) + { + if (pFtParam->isPduDone[i] == FALSE) + { + removeFromList = FALSE; + break; + } + } + if (removeFromList == TRUE) + { + /* pCisCtx->isTxDone = TRUE; No need since BOD is done. */ + lctrCisFtRemoveHead(&pCisCtx->txFtParamList); + } +} + +/*************************************************************************************************/ +/*! + * \brief Check flush timeout and flush PDU if necessary after end of BOD. + * + * \param pCisCtx CIS context. + * + */ +/*************************************************************************************************/ +static void lctrCisCheckRxFtAfterBod(lctrCisCtx_t *pCisCtx) +{ + if (lctrCisFtIsListEmpty(&pCisCtx->rxFtParamList)) + { + /* List is empty. */ + return; + } + + lctrFtParamNode_t *pNode = pCisCtx->rxFtParamList.pHead; + + /* Increment interval counter for all the node in the list. */ + while (pNode) + { + pNode->ftParam.intervalCounter++; + pNode = pNode->pNext; + } + + /* Only check the head node */ + lctrFtParam_t *pFtParam = &pCisCtx->rxFtParamList.pHead->ftParam; + for (unsigned int i = 0; i < WSF_MIN(pFtParam->bn, LCTR_MAX_BN); i++) + { + if (pFtParam->isPduDone[i] == FALSE && /* If the PDU is not done. */ + pFtParam->intervalCounter == pFtParam->intervalTotal) /* Check if the PDU needs to be flush in this interval. */ + { + pFtParam->isPduDone[i] = TRUE; + pCisCtx->txHdr.nesn++; + pFtParam->pduCounter++; + } + } + + /* Remove the node if all the items are done. */ + bool_t removeFromList = TRUE; + for (unsigned int i = 0; i < WSF_MIN(pFtParam->bn, LCTR_MAX_BN); i++) + { + if (pFtParam->isPduDone[i] == FALSE) + { + removeFromList = FALSE; + break; + } + } + if (removeFromList == TRUE) + { + lctrCisFtRemoveHead(&pCisCtx->rxFtParamList); + } +} + +/*************************************************************************************************/ +/*! + * \brief Check flush timeout and flush PDU if necessary after RX. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static void lctrCisCheckFtAfterRx(lctrCisCtx_t *pCisCtx) +{ + lctrCisCheckTxFtAfterRx(pCisCtx); + lctrCisCheckRxFtAfterRx(pCisCtx); +} + +/*************************************************************************************************/ +/*! + * \brief Check flush timeout and flush PDU if necessary after end of BOD. + * + * \param pCisCtx CIS Context. + */ +/*************************************************************************************************/ +static void lctrCisCheckFtAfterBod(lctrCisCtx_t *pCisCtx) +{ + lctrCisCheckTxFtAfterBod(pCisCtx); + lctrCisCheckRxFtAfterBod(pCisCtx); +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Check whether continue the current operation. + * + * \param pOp Operation. + * \param pNewCisCtx A new CIS operation. + * + * \return Offset of the next operation, zero discontinue next operation, otherwise continue. + */ +/*************************************************************************************************/ +uint32_t lctrMstCisCheckContOp(BbOpDesc_t *pOp, bool_t *pNewCisCtx) +{ + lctrCigCtx_t * const pCigCtx = pOp->pCtx; + lctrCisCtx_t *pCisCtx = pCigCtx->pCisCtx; + uint32_t delayUsec = pCisCtx->delayUsec; + uint32_t subIntervUsec = pCisCtx->subIntervUsec; + + WSF_ASSERT(pCisCtx); + + BbBleData_t *pBle = &pCisCtx->bleData; + + if (pCigCtx->packing == LL_PACKING_SEQUENTIAL) + { + if (pCisCtx->rxHdr.cie || pCisCtx->txHdr.cie) + { + /* Skip additional sub-events if receive CIE before reaching the NSE */ + if ((pCisCtx->subEvtCounter + 1) < pCisCtx->nse) /* Plus one since subEvtCounter has not been updated yet. */ + { + delayUsec += delayUsec * (pCisCtx->nse - (pCisCtx->subEvtCounter + 1)); + } + + goto SwitchSeq; + } + + /* Check whether the CIS shall start or not. */ + if (pCisCtx->cisCeRef != 0) + { + goto SwitchSeq; + } + + if (pCisCtx->txDataCounter >= pCisCtx->bnMToS && pCisCtx->rxDataCounter >= pCisCtx->bnSToM && pCisCtx->isTxDone == TRUE) + { + /* There is no more data to send. */ + pCisCtx->txHdr.cie = 1; + + if (lmgrGetOpFlag(LL_OP_MODE_FLAG_ENA_MST_CIS_NULL_PDU) == FALSE) + { + goto SwitchSeq; + } + } + + pCisCtx->subEvtCounter++; + + if (pCisCtx->subEvtCounter == pCisCtx->nse) + { + /* There is no more subevent. */ + pCisCtx->txHdr.cie = 1; + pCisCtx->cisDone = TRUE; + goto SwitchSeq; + } + + /*** Continue current CIS ***/ + + /* Set next channel index. */ + pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */ + return delayUsec; + +SwitchSeq: + if ((pCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCisCtx)) == NULL) + { + goto Done; + } + else + { + /* Check whether the CIS shall start or not. */ + if (pCisCtx->cisCeRef != 0) + { + goto Done; + } + + 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; + + /* Move the current CIS to the next CIS. */ + pOp->prot.pBle = pBle; + pCigCtx->pCisCtx = pCisCtx; + memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan)); + pBle->chan.chanIdx = pCigCtx->pCisCtx->chIdx; /* Set the next channel to the first channel in the next CIS. */ + + return delayUsec; /* Return the offset from the old CIS */ + } + } + else /* LL_PACKING_INTERLEAVED */ + { + uint8_t oriNextSubEvtChanIdx = pCisCtx->nextSubEvtChanIdx; + + if (pCisCtx->rxHdr.cie || pCisCtx->txHdr.cie) + { + pCisCtx->cisDone = TRUE; + goto SwitchInt; + } + + /* Check whether the CIS shall start or not. */ + if (pCisCtx->cisCeRef != 0) + { + lctrCisSetCisDone(&pCigCtx->list, pCisCtx); + goto SwitchInt; + } + + if (pCisCtx->txDataCounter >= pCisCtx->bnMToS && pCisCtx->rxDataCounter >= pCisCtx->bnSToM && pCisCtx->isTxDone == TRUE) + { + /* There is no more data to send. */ + pCisCtx->txHdr.cie = 1; + + if (lmgrGetOpFlag(LL_OP_MODE_FLAG_ENA_MST_CIS_NULL_PDU) == FALSE) + { + pCisCtx->cisDone = TRUE; + goto SwitchInt; + } + } + + pCisCtx->subEvtCounter++; + + if (pCisCtx->subEvtCounter == pCisCtx->nse) + { + /* There is no more subevent. */ + pCisCtx->txHdr.cie = 1; + pCisCtx->cisDone = TRUE; + goto SwitchInt; + } + +SwitchInt: + if (lctrCisGetListCount(&pCigCtx->list) == 1) + { + if (lctrCisAreCisCtxDone(&pCigCtx->list)) + { + goto Done; + } + + /*** Continue current CIS ***/ + + /* Set next channel index. */ + pBle->chan.chanIdx = oriNextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */ + return subIntervUsec; + } + + if ((pCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCisCtx)) == NULL) + { + if (lctrCisAreCisCtxDone(&pCigCtx->list)) + { + 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. */ + + return delayUsec; /* Return the offset from the old CIS */ + } + else + { + if (lctrCisAreCisCtxDone(&pCigCtx->list)) + { + goto Done; + } + + /* Check whether the CIS shall start or not. */ + if (pCisCtx->cisCeRef != 0) + { + /*** Continue head CIS ***/ + + /* Set next channel index. */ + lctrCisSetCisDone(&pCigCtx->list, pCisCtx); + + lctrCisCtx_t *pNextCtx, *pTempCtx; + uint32_t addDelayUsec = 0; + + pTempCtx = lctrCisGetHeadCis(&pCigCtx->list); + pCigCtx->pCisCtx = pTempCtx; + pBle = &pTempCtx->bleData; + memcpy(&pBle->chan, &pTempCtx->bleData.chan, sizeof(pBle->chan)); + pBle->chan.chanIdx = pTempCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */ + pOp->prot.pBle = pBle; + pCigCtx->isLoopBack = TRUE; + + while (pTempCtx) + { + pNextCtx = lctrCisGetNextCis(&pCigCtx->list, pTempCtx); + + if (pNextCtx == NULL) + { + break; + } + + if (pNextCtx == pCisCtx) + { + break; + } + + addDelayUsec += pTempCtx->delayUsec; + pTempCtx = pNextCtx; + } + + 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. */ + } + + return delayUsec; /* Return the offset from the old CIS */ + } + } + +Done: + /* All CISs are done. Set next CIS to the head of the list. */ + pCigCtx->pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + pOp->prot.pBle = &pCigCtx->pCisCtx->bleData; + *pNewCisCtx = TRUE; + lctrCisClearCisDone(&pCigCtx->list); + return 0; +} + +/*************************************************************************************************/ +/*! + * \brief Start the CIG operation. + * + * \param pOp Begin operation. + */ +/*************************************************************************************************/ +void lctrMstCisCigBeginOp(BbOpDesc_t *pOp) +{ + lctrCigCtx_t *pCigCtx = pOp->pCtx; + lctrCisCtx_t *pCisCtx; + + pCisCtx = pCigCtx->pCisCtx; + pCigCtx->isLoopBack = FALSE; + + /* Need to setup Tx/Rx flush timeout parameter first since some field will be used in the lctrSlvCisInitIsr. */ + 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); + + lctrMstCisSetupTx(pCigCtx, pCisCtx); + + /* Setup Tx could fail which leads to terminate BOD. */ + if (!BbGetBodTerminateFlag()) + { + lctrMstCisSetupRx(pCigCtx, pCisCtx); + } +} + +/*************************************************************************************************/ +/*! + * \brief Continue the CIG operation. + * + * \param pOp Begin operation. + */ +/*************************************************************************************************/ +void lctrMstCisCigContOp(BbOpDesc_t *pOp) +{ + lctrCigCtx_t *pCigCtx = pOp->pCtx; + lctrCisCtx_t *pCisCtx; + + pCisCtx = pCigCtx->pCisCtx; + + lctrMstCisSetupTx(pCigCtx, pCisCtx); + + /* Setup Tx could fail which leads to terminate BOD. */ + if (!BbGetBodTerminateFlag()) + { + lctrMstCisSetupRx(pCigCtx, pCisCtx); + } +} + +/*************************************************************************************************/ +/*! + * \brief Post subevent callback, setup for the next subevent channel index. + * + * \param pOp Current operation. + * \param status Status. + */ +/*************************************************************************************************/ +void lctrMstCisCigPostSubEvt(BbOpDesc_t *pOp, uint8_t status) +{ + lctrCigCtx_t *pCigCtx = pOp->pCtx; + lctrCisCtx_t *pCisCtx; + + WSF_ASSERT(pCigCtx); + pCisCtx = pCigCtx->pCisCtx; + + WSF_ASSERT(pCisCtx); + + /* Pre-calculate the next subevent channel. */ + pCisCtx->nextSubEvtChanIdx = LmgrSelectNextSubEvtChannel(&pCisCtx->chanParam); +} + +/*************************************************************************************************/ +/*! + * \brief Cleanup a connection operation. + * + * \param pOp Completed operation. + */ +/*************************************************************************************************/ +void lctrMstCisCigCleanupOp(BbOpDesc_t *pOp) +{ + +} + +/*************************************************************************************************/ +/*! + * \brief End a CIG operation. + * + * \param pOp Completed operation. + */ +/*************************************************************************************************/ +void lctrMstCisCigEndOp(BbOpDesc_t *pOp) +{ + /* Pre-resolve common structures for efficient access. */ + lctrCigCtx_t * const pCigCtx = pOp->pCtx; + lctrCisCtx_t *pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + lctrConnCtx_t * pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); + WSF_ASSERT(pCisCtx); /* At least one CIS in the CIG. */ + + while (pCisCtx) + { + pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); + + /* 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) + { + /* This was a host-initiated termination of the CIS. */ + lctrNotifyHostCisTerm(pCisCtx); + } + + pCisCtx->isClosing = FALSE; + pCigCtx->numCisEsted--; + lctrCleanupCtx(pCisCtx); + } + + pCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCisCtx); + } + + if (pCigCtx->numCisEsted == 0) + { + return; + } + + pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + + while (pCisCtx) + { + pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); + + lctrCisCheckFtAfterBod(pCisCtx); + + /* Process event completion */ + + if (!pCisCtx->connEst && pCisCtx->data.mst.rxFromSlave) + { + WsfTimerStartMs(&pCisCtx->tmrSupTimeout, pCisCtx->supTimeoutMs); + + pCisCtx->connEst = TRUE; + + /* Now that the first CIS has been established, + * notify host of connection establish and + * start the next CIS creation, if needed. + */ + if (lmgrCisMstCb.createCisPend) + { + lctrMstCreateCisDone(pCisCtx); + lctrNotifyHostCisEst(pCisCtx, LL_SUCCESS, pCisCtx->cigSyncDelayUsec); + } + + if (pCisCtx->powerIndReq && lctrSendPowerChangeIndCback) + { + uint8_t txPhy = (pCisCtx->role == LL_ROLE_MASTER) ? pCisCtx->phyMToS : pCisCtx->phySToM; + lctrSendPowerChangeIndCback(pConnCtx, txPhy, 0, pLctrRtCfg->defTxPwrLvl, TRUE); + } + } + else if (pCisCtx->data.mst.rxFromSlave) + { + /* Reset supervision timer. */ + WsfTimerStartMs(&pCisCtx->tmrSupTimeout, pCisCtx->supTimeoutMs); + } + + /* Failed to receive packet within the first 6 intervals. */ + if ((pCisCtx->firstFromPeer == FALSE) && (pCisCtx->cisEvtCounter == LCTR_FAST_TERM_CNT)) + { + LL_TRACE_WARN1("CIS terminated due to fast termination timeout, handle=%d", pCisCtx->cisHandle); + lctrCisStoreConnFailEstablishTerminateReason(pCisCtx); + lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_CLOSED); + + if (pCigCtx->numCisEsted == 1) + { + /* If the last CIS to close, schedule no more operation. */ + return; + } + } + + /* Terminate connection */ + if (lctrCheckForCisLinkTerm(pCisCtx->aclHandle)) + { + lctrSendCisLlcpMsg(pCisCtx, LCTR_CIS_TERM_EVENT_CIS_TERM); + } + pCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCisCtx); + } + + pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + + /*** Adjust the anchor point if the head CIS is removed ***/ + + if (pCigCtx->headCisRmved == TRUE) + { + pCigCtx->headCisRmved = FALSE; + + pOp->dueUsec += pCigCtx->offsetUsec; + pCigCtx->offsetUsec = 0; + + BbBleData_t *pBle = &pCisCtx->bleData; + /* Move the current CIS to the head CIS. */ + pOp->prot.pBle = pBle; + pCigCtx->pCisCtx = pCisCtx; + memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan)); + pBle->chan.chanIdx = pCigCtx->pCisCtx->chIdx; /* Set the next channel to the first channel in the next CIS. */ + } + + /*** Update txPower ***/ + + pCisCtx->bleData.chan.txPower = LCTR_GET_TXPOWER(pConnCtx, pCisCtx->phyMToS, pCisCtx->bleData.chan.initTxPhyOptions); +#if(LL_ENABLE_TESTER) + pCisCtx->bleData.chan.txPower += pConnCtx->bleData.chan.txPwrOffset; +#endif + + /*** Reschedule operation ***/ + + while (TRUE) + { + /* Advance to next interval. */ + pOp->dueUsec += LCTR_ISO_INT_TO_US(pCigCtx->isoInterval); + + pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + WSF_ASSERT(pCisCtx); /* At least one CIS in the CIG. */ + + while (pCisCtx) + { + if (pCisCtx->cisCeRef == 0) + { + BbBleData_t * const pBle = &pCisCtx->bleData; + pCisCtx->cisEvtCounter++; + pCisCtx->chIdx = pBle->chan.chanIdx = LmgrSelectNextChannel(&pCisCtx->chanParam, pCisCtx->cisEvtCounter, 0, TRUE); + pCisCtx->nextSubEvtChanIdx = LmgrSelectNextSubEvtChannel(&pCisCtx->chanParam); + + if (pCisCtx->txTestEnabled) + { + uint32_t sduInt = pCisCtx->sduIntervalMToS; + + while ((pOp->dueUsec - pCisCtx->testSduTs) >= sduInt) + { + lctrCisTxTestPayloadHandler(pCisCtx); + pCisCtx->testSduTs += sduInt; + } + } + + /* Assemble framed data. */ + if ((pCisCtx->framing == LL_ISO_PDU_TYPE_FRAMED) && + pCisCtx->isoalTxCtx.pendQueueSize) + { + uint8_t *pDataBuf = lctrTxIsoDataPduAlloc(); + + if (pDataBuf == NULL) + { + /* TODO optimize statement as the call to WsfMsgFree() has no effect and should not continue to following statement. */ + LL_TRACE_WARN0("LctrTxIso, Unable to allocate PDU for transmit"); + WsfMsgFree(pDataBuf); + } + + lctrIsoHdr_t isoHdr; + + isoHdr.sduLen = lctrAssembleTxFramedPdu(&pCisCtx->isoalTxCtx, pDataBuf, pCisCtx->localDataPdu.maxTxLen); + isoHdr.tsFlag = 0; + + lctrIsoSduTxDecAvailBuf(); + lctrCisTxDataPduQueue(pCisCtx, &isoHdr, pDataBuf); + } + } + else + { + pCisCtx->cisCeRef--; + } + pCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCisCtx); + } + + if (SchInsertAtDueTime(pOp, NULL)) + { + break; + } + + pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + LL_TRACE_WARN1("!!! CIS master schedule conflict eventCounter=%u", pCisCtx->cisEvtCounter); + } + + if (lmgrCb.sendIsoCmplEvt) + { + lctrNotifyHostIsoEventComplete(pCigCtx->cigHandle, (uint32_t) pCisCtx->cisEvtCounter); + } +} + +/*************************************************************************************************/ +/*! + * \brief Abort a connection operation. + * + * \param pOp Completed operation. + */ +/*************************************************************************************************/ +void lctrMstCisCigAbortOp(BbOpDesc_t *pOp) +{ + lctrCigCtx_t * const pCigCtx = pOp->pCtx; + + /* Need to setup Tx/Rx flush timeout parameter first since some field will be used in the lctrSlvCisInitIsr. */ + + if (pCigCtx->numCisEsted > 0) + { + lctrCisCtx_t *pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + /* It is possible there is no CIS since it is aborting. */ + + while (pCisCtx) + { + 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); + + pCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCisCtx); + } + } + + lctrMstCisCigEndOp(pOp); +} + +/*************************************************************************************************/ +/*! + * \brief Complete a transmitted data buffer. + * + * \param pOp Operation context. + * \param status Transmit status. + */ +/*************************************************************************************************/ +void lctrMstCisCigTxCompletion(BbOpDesc_t *pOp, uint8_t status) +{ + lctrCigCtx_t * const pCigCtx = pOp->pCtx; + lctrCisCtx_t *pCisCtx = pCigCtx->pCisCtx; + + pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter++; +} + +/*************************************************************************************************/ +/*! + * \brief Complete a received data buffer. + * + * \param pOp Operation context. + * \param pRxBuf Next receive buffer or NULL to flow control. + * \param status Receive status. + */ +/*************************************************************************************************/ +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; + pCisCtx->validRx = FALSE; + pCisCtx->txPduIsAcked = FALSE; + pCisCtx->pduFlushed = FALSE; + + if (status == BB_STATUS_CRC_FAILED) + { + pCisCtx->isoLinkQualStats.crcErrPkt++; + } + + /*** Cancellation processing ***/ + + if (status == BB_STATUS_CANCELED) + { + lctrCisRxPduFree(pRxBuf); + goto Done; + } + + /*** Receive packet pre-processing ***/ + + if (status == 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); + goto PostProcessing; + } + + lctrCisUnpackDataPduHdr(&pCisCtx->rxHdr, pRxBuf); + +#if (LL_ENABLE_TESTER) + if ((llTesterCb.cisAckMode != LL_TESTER_ACK_MODE_NORMAL) || + (llTesterCb.cisFwdPkt == TRUE)) + { + LctrCisProcessRxTxAck(pCisCtx, &pCisCtx->validRx, &pCisCtx->txPduIsAcked); + + /* Don't report the empty packet. */ + if (pCisCtx->rxHdr.len == 0) + { + pCisCtx->validRx = FALSE; + } + } + else +#endif + { + pCisCtx->validRx = lctrCisProcessRxAck(pCisCtx); + pCisCtx->txPduIsAcked = lctrCisProcessTxAck(pCisCtx); + } + + /*** 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); + } + + /*** 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; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis_slave.c new file mode 100644 index 0000000000..269c90468b --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_cis_slave.c @@ -0,0 +1,1295 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller slave connected isochronous stream ISR callbacks. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int.h" +#include "lctr_int_cis.h" +#include "lctr_int_cis_slave.h" +#include "lctr_int_iso.h" +#include "lmgr_api_conn.h" +#include "sch_api.h" +#include "sch_api_ble.h" +#include "bb_ble_api.h" +#include "wsf_assert.h" +#include "wsf_math.h" +#include "wsf_msg.h" +#include "wsf_os.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include +#include "pal_codec.h" + +#if (LL_ENABLE_TESTER) +#include "pal_bb_ble_tester.h" +#endif + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +#if (LL_ENABLE_TESTER) +void LctrCisProcessRxTxAck(lctrCisCtx_t *pCtx, bool_t *pValidRx, bool_t *pTxPduIsAcked); +#endif + +/*************************************************************************************************/ +/*! + * \brief Initialize slave CIS ISR resources. + * + * \param pCisCtx CIS Context. + */ +/*************************************************************************************************/ +static void lctrSlvCisInitIsr(lctrCisCtx_t *pCisCtx) +{ + pCisCtx->data.slv.syncWithMaster = FALSE; + pCisCtx->data.slv.rxFromMaster = FALSE; + pCisCtx->data.slv.firstRxFromMaster = TRUE; + pCisCtx->data.slv.rxStatus = BB_STATUS_RX_TIMEOUT; + pCisCtx->subEvtCounter = 0; + 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) + { + pCisCtx->isTxDone = TRUE; + } + else + { + pCisCtx->isTxDone = FALSE; + } + + /*** Setup for transmit ***/ + + pCisCtx->txHdr.cie = 0; + pCisCtx->txHdr.np = 0; + + /*** Setup for receive ***/ + + pCisCtx->rxHdr.cie = 0; + pCisCtx->rxHdr.np = 0; + pCisCtx->rxHdr.len = 0; + pCisCtx->rxHdr.llid = LL_LLID_ISO_UNF_END_PDU; +} + +/*************************************************************************************************/ +/*! + * \brief Execution CIG operation + * + * \param pCisCtx CIS Context. + */ +/*************************************************************************************************/ +static void lctrSlvCisCigExecOp(lctrCisCtx_t *pCisCtx) +{ + uint8_t *pBuf; + + if (!lmgrIsoCb.availRxBuf) + { + LL_TRACE_ERR1("!!! lctrSlvCisCigExecOp, RX buffer not available, cisHandle=%u", pCisCtx->cisHandle); + return; /* flow control Rx */ + } + + /*** Setup receiver ***/ + + if ((pBuf = lctrCisRxPduAlloc(pCisCtx->localDataPdu.maxRxLen)) != NULL) + { +#if (LL_ENABLE_TESTER) + if (llTesterCb.isoAccAddrSeTrigMask && + (llTesterCb.isoAccAddrSeTrigMask & (1 << pCisCtx->subEvtCounter)) && + llTesterCb.isoAccAddrInvForRx) + { + PalBbTesterInvalidateNextAccAddr(TRUE); + + if (llTesterCb.isoAccAddrInvNumTrig) + { + llTesterCb.isoAccAddrInvNumTrig--; + if (llTesterCb.isoAccAddrInvNumTrig == 0) + { + llTesterCb.isoAccAddrSeTrigMask = 0; + } + } + } +#endif + + 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 CIS, cisHandle=%u", pCisCtx->cisHandle); + BbSetBodTerminateFlag(); + } +} + +/*************************************************************************************************/ +/*! + * \brief Check Tx flush timeout and flush PDU if necessary after RX. + * +* \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static void lctrCisCheckTxFtAfterRx(lctrCisCtx_t *pCisCtx) +{ + if (lctrCisFtIsListEmpty(&pCisCtx->txFtParamList)) + { + /* List is empty. */ + return; + } + + if (pCisCtx->txHdr.np) + { + /* NULL PDU doesn't need to be acked or flushed. */ + return; + } + + lctrFtParam_t *pFtParam = &pCisCtx->txFtParamList.pHead->ftParam; + + if (pFtParam->pduAcked) + { + pFtParam->isPduDone[pFtParam->pduCounter] = TRUE; /* The PDU is done. */ + lctrCisIncPacketCounterTx(pCisCtx); + pFtParam->pduCounter++; + } + else + { + /* Check if this is the last FT interval. */ + if ((pFtParam->intervalCounter + 1) == pFtParam->intervalTotal) + { + if (pFtParam->subEvtCounter == pFtParam->lastSubEvtFt[pFtParam->pduCounter]) + { + /* PDU needs to be flushed. */ + pCisCtx->txHdr.sn++; + + lctrCisIncPacketCounterTx(pCisCtx); + pFtParam->isPduDone[pFtParam->pduCounter] = TRUE; /* The PDU is done. */ + + 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. */ + } + pFtParam->pduCounter++; + pCisCtx->isoLinkQualStats.txUnAckPkt++; + } + } + else /* Implies that a retransmit will happen. */ + { + pCisCtx->isoLinkQualStats.retransmitPkt++; + } + } + + /* Remove the node if all the items are done. */ + bool_t removeFromList = TRUE; + for (unsigned int i = 0; i < WSF_MIN(pFtParam->bn, LCTR_MAX_BN); i++) + { + if (pFtParam->isPduDone[i] == FALSE) + { + removeFromList = FALSE; + break; + } + } + if (removeFromList == TRUE) + { + lctrCisFtRemoveHead(&pCisCtx->txFtParamList); + } + + /* No more data to send, send NULL packet. */ + if (lctrCisFtIsListEmpty(&pCisCtx->txFtParamList)) + { + pCisCtx->isTxDone = TRUE; + } +} + +/*************************************************************************************************/ +/*! + * \brief Check Rx flush timeout and flush PDU if necessary after RX. + * +* \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static void lctrCisCheckRxFtAfterRx(lctrCisCtx_t *pCisCtx) +{ + if (lctrCisFtIsListEmpty(&pCisCtx->rxFtParamList)) + { + /* List is empty. */ + 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) + { + pFtParam->isPduDone[pFtParam->pduCounter] = TRUE; /* The PDU is done. */ + pFtParam->pduCounter++; + } + else + { + /* Check if this is the last interval before FT. */ + if ((pFtParam->intervalCounter + 1) == pFtParam->intervalTotal) + { + if (pFtParam->subEvtCounter == pFtParam->lastSubEvtFt[pFtParam->pduCounter]) + { + /* PDU needs to be flushed. */ + pCisCtx->txHdr.nesn++; + lctrCisIncPacketCounterRx(pCisCtx); + pFtParam->isPduDone[pFtParam->pduCounter] = TRUE; /* The PDU is done. */ + pFtParam->pduCounter++; + pCisCtx->isoLinkQualStats.rxUnreceivedPkt++; + pCisCtx->isoalRxCtx.pduFlushed = TRUE; + pCisCtx->isoalRxCtx.packetSequence++; + pCisCtx->numRxMissed++; + } + } + } + + /* Remove the node if all the items are done. */ + bool_t removeFromList = TRUE; + for (unsigned int i = 0; i < WSF_MIN(pFtParam->bn, LCTR_MAX_BN); i++) + { + if (pFtParam->isPduDone[i] == FALSE) + { + removeFromList = FALSE; + break; + } + } + if (removeFromList == TRUE) + { + lctrCisFtRemoveHead(&pCisCtx->rxFtParamList); + } +} + +/*************************************************************************************************/ +/*! + * \brief Check flush timeout and flush PDU if necessary after end of BOD. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static void lctrCisCheckTxFtAfterBod(lctrCisCtx_t *pCisCtx) +{ + if (lctrCisFtIsListEmpty(&pCisCtx->txFtParamList)) + { + /* List is empty. */ + 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. */ + while (pNode) + { + pNode->ftParam.intervalCounter++; + pNode = pNode->pNext; + } + + /* Only check the head node */ + lctrFtParam_t *pFtParam = &pCisCtx->txFtParamList.pHead->ftParam; + for (unsigned int i = 0; i < WSF_MIN(pFtParam->bn, LCTR_MAX_BN); i++) + { + if (pFtParam->isPduDone[i] == FALSE && /* If the PDU is not done. */ + pFtParam->intervalCounter == pFtParam->intervalTotal) /* Check if the PDU needs to be flush in this interval. */ + { + pFtParam->isPduDone[i] = TRUE; + pCisCtx->txHdr.sn++; + + PalBbBleTxBufDesc_t bbDesc[3]; + if (lctrCisTxQueuePeek(pCisCtx, &bbDesc[0])) + { + /* Need to remove from ack queue if non-empty PDU. */ + lctrCisTxPduAck(pCisCtx); + lctrCisTxQueuePopCleanup(pCisCtx); + } + pFtParam->pduCounter++; + } + } + + /* Remove the node if all the items are done. */ + bool_t removeFromList = TRUE; + for (unsigned int i = 0; i < WSF_MIN(pFtParam->bn, LCTR_MAX_BN); i++) + { + if (pFtParam->isPduDone[i] == FALSE) + { + removeFromList = FALSE; + break; + } + } + if (removeFromList == TRUE) + { + /* pCisCtx->isTxDone = TRUE; No need since BOD is done. */ + lctrCisFtRemoveHead(&pCisCtx->txFtParamList); + } +} + +/*************************************************************************************************/ +/*! + * \brief Check flush timeout and flush PDU if necessary after end of BOD. + * + * \param pCisCtx CIS Context. + */ +/*************************************************************************************************/ +static void lctrCisCheckRxFtAfterBod(lctrCisCtx_t *pCisCtx) +{ + if (lctrCisFtIsListEmpty(&pCisCtx->rxFtParamList)) + { + /* List is empty. */ + return; + } + + lctrFtParamNode_t *pNode = pCisCtx->rxFtParamList.pHead; + + /* Increment interval counter for all the node in the list. */ + while (pNode) + { + pNode->ftParam.intervalCounter++; + pNode = pNode->pNext; + } + + /* Only check the head node */ + lctrFtParam_t *pFtParam = &pCisCtx->rxFtParamList.pHead->ftParam; + for (unsigned int i = 0; i < WSF_MIN(pFtParam->bn, LCTR_MAX_BN); i++) + { + if (pFtParam->isPduDone[i] == FALSE && /* If the PDU is not done. */ + pFtParam->intervalCounter == pFtParam->intervalTotal) /* Check if the PDU needs to be flush in this interval. */ + { + pFtParam->isPduDone[i] = TRUE; + pCisCtx->txHdr.nesn++; + lctrCisIncPacketCounterRx(pCisCtx); + pFtParam->pduCounter++; + } + } + + /* Remove the node if all the items are done. */ + bool_t removeFromList = TRUE; + for (unsigned int i = 0; i < WSF_MIN(pFtParam->bn, LCTR_MAX_BN); i++) + { + if (pFtParam->isPduDone[i] == FALSE) + { + removeFromList = FALSE; + break; + } + } + if (removeFromList == TRUE) + { + lctrCisFtRemoveHead(&pCisCtx->rxFtParamList); + } +} + +/*************************************************************************************************/ +/*! + * \brief Check flush timeout and flush PDU if necessary after RX. + * +* \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static void lctrCisCheckFtAfterRx(lctrCisCtx_t *pCisCtx) +{ + lctrCisCheckTxFtAfterRx(pCisCtx); + lctrCisCheckRxFtAfterRx(pCisCtx); +} + +/*************************************************************************************************/ +/*! + * \brief Check flush timeout and flush PDU if necessary after end of BOD. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static void lctrCisCheckFtAfterBod(lctrCisCtx_t *pCisCtx) +{ + lctrCisCheckTxFtAfterBod(pCisCtx); + lctrCisCheckRxFtAfterBod(pCisCtx); +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Setup for the next current operation. + * + * \param pOp Begin operation. + * \param pNewCisCtx New CIS context to begin. + * + * \return Offset in usec. + */ +/*************************************************************************************************/ +uint32_t lctrSlvCisCheckContOp(BbOpDesc_t *pOp, bool_t *pNewCisCtx) +{ + lctrCigCtx_t * const pCigCtx = pOp->pCtx; + lctrCisCtx_t *pCisCtx = pCigCtx->pCisCtx; + uint32_t wwTotalUsec; + uint32_t offsetUsec; + uint32_t delayUsec = pCisCtx->delayUsec; + bool_t isSuccess = (pCisCtx->data.slv.rxStatus == BB_STATUS_SUCCESS ? TRUE : FALSE); + + WSF_ASSERT(pCisCtx); + + BbBleData_t *pBle = &pCisCtx->bleData; + BbBleSlvCisEvent_t * const pCis = &pBle->op.slvCis; + + if (pCigCtx->packing == LL_PACKING_SEQUENTIAL) + { + uint32_t subIntervUsec = pCisCtx->subIntervUsec; + + pCisCtx->subEvtCounter++; + + if (pCisCtx->rxHdr.cie || pCisCtx->txHdr.cie) + { + goto SwitchSeq; + } + + /* Check whether the CIS shall start or not. */ + if (pCisCtx->cisCeRef != 0) + { + goto SwitchSeq; + } + + if (pCisCtx->subEvtCounter == pCisCtx->nse) + { + pCisCtx->txHdr.cie = 1; + /* There is no more subevent. */ + goto SwitchSeq; + } + + /*** Continue current CIS ***/ + + /* Set next channel index. */ + pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */ + + /* Only apply WW when rx success. */ + if (isSuccess) + { + wwTotalUsec = lctrCalcWindowWideningUsec(subIntervUsec, pCigCtx->roleData.slv.totalAcc); + offsetUsec = subIntervUsec - wwTotalUsec; + pCis->rxSyncDelayUsec = (wwTotalUsec << 1); + } + else + { + offsetUsec = subIntervUsec; + } + return offsetUsec; + +SwitchSeq: + /* Skip additional sub-events if switching CIS, might not be used if next CIS is NULL */ + subIntervUsec = pCisCtx->nextCisOffsetUsec - subIntervUsec * (pCisCtx->subEvtCounter - 1); /* pCisCtx->subEvtCounter is already incremented */ + + if ((pCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCisCtx)) == NULL) + { + goto Done; + } + else + { + /* Check whether the CIS shall start or not. */ + if (pCisCtx->cisCeRef != 0) + { + goto Done; + } + + 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; + + /* Continue on the next subevent. */ + pBle->op.slvCis.rxTsUsec = pCis->rxTsUsec; + + /* Move the current CIS to the next CIS. */ + pOp->prot.pBle = pBle; + pCigCtx->pCisCtx = pCisCtx; + memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan)); + pBle->chan.chanIdx = pCigCtx->pCisCtx->chIdx; /* Set the next channel to the first channel in the next CIS. */ + + /* Only apply WW when rx success. */ + if (isSuccess) + { + wwTotalUsec = lctrCalcWindowWideningUsec(subIntervUsec, pCigCtx->roleData.slv.totalAcc); + offsetUsec = subIntervUsec - wwTotalUsec; + pCis->rxSyncDelayUsec = (wwTotalUsec << 1); + } + else + { + offsetUsec = subIntervUsec; + } + + return offsetUsec; + } + } + else + { + uint32_t subIntervUsec = pCisCtx->subIntervUsec; + uint8_t oriNextSubEvtChanIdx = pCisCtx->nextSubEvtChanIdx; + + if (pCisCtx->rxHdr.cie || pCisCtx->txHdr.cie) + { + pCisCtx->cisDone = TRUE; + goto SwitchInt; + } + + /* Check whether the CIS shall start or not. */ + if (pCisCtx->cisCeRef != 0) + { + lctrCisSetCisDone(&pCigCtx->list, pCisCtx); + goto SwitchInt; + } + + pCisCtx->subEvtCounter++; + + if (pCisCtx->subEvtCounter == pCisCtx->nse) + { + pCisCtx->txHdr.cie = 1; + pCisCtx->cisDone = TRUE; + /* There is no more subevent. */ + goto SwitchInt; + } + +SwitchInt: + if (lctrCisGetListCount(&pCigCtx->list) == 1) + { + if (lctrCisAreCisCtxDone(&pCigCtx->list)) + { + goto Done; + } + + /*** Continue current CIS ***/ + + /* Set next channel index. */ + pBle->chan.chanIdx = oriNextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */ + /* Only apply WW when rx success. */ + if (isSuccess) + { + wwTotalUsec = lctrCalcWindowWideningUsec(subIntervUsec, pCigCtx->roleData.slv.totalAcc); + offsetUsec = subIntervUsec - wwTotalUsec; + pCis->rxSyncDelayUsec = (wwTotalUsec << 1); + } + else + { + offsetUsec = subIntervUsec; + } + + return offsetUsec; + } + + if ((pCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCisCtx)) == NULL) + { + if (lctrCisAreCisCtxDone(&pCigCtx->list)) + { + 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. */ + + /* Only apply WW when rx success. */ + if (isSuccess) + { + wwTotalUsec = lctrCalcWindowWideningUsec(delayUsec, pCigCtx->roleData.slv.totalAcc); + offsetUsec = delayUsec - wwTotalUsec; + pCis->rxSyncDelayUsec = (wwTotalUsec << 1); + } + else + { + offsetUsec = delayUsec; + } + + return offsetUsec; + } + else + { + /* Get the next CIS in the list. */ + if (lctrCisAreCisCtxDone(&pCigCtx->list)) + { + goto Done; + } + + /* Check whether the CIS shall start or not. */ + if (pCisCtx->cisCeRef != 0) + { + /*** Continue head CIS ***/ + + lctrCisSetCisDone(&pCigCtx->list, pCisCtx); + + lctrCisCtx_t *pNextCtx, *pTempCtx; + uint32_t addDelayUsec = 0; + + pTempCtx = lctrCisGetHeadCis(&pCigCtx->list); + pCigCtx->pCisCtx = pTempCtx; + pBle = &pTempCtx->bleData; + memcpy(&pBle->chan, &pTempCtx->bleData.chan, sizeof(pBle->chan)); + pBle->chan.chanIdx = pTempCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */ + pOp->prot.pBle = pBle; + pCigCtx->isLoopBack = TRUE; + + while (pTempCtx) + { + pNextCtx = lctrCisGetNextCis(&pCigCtx->list, pTempCtx); + + if (pNextCtx == NULL) + { + break; + } + + if (pNextCtx == pCisCtx) + { + break; + } + + addDelayUsec += pTempCtx->delayUsec; + pTempCtx = pNextCtx; + } + + /* Only apply WW when Rx success. */ + if (isSuccess) + { + wwTotalUsec = lctrCalcWindowWideningUsec(subIntervUsec, pCigCtx->roleData.slv.totalAcc); + offsetUsec = subIntervUsec - wwTotalUsec; + pCis->rxSyncDelayUsec = (wwTotalUsec << 1); + } + else + { + offsetUsec = subIntervUsec; + } + + 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. */ + } + + /* Only apply WW when rx success. */ + if (isSuccess) + { + wwTotalUsec = lctrCalcWindowWideningUsec(delayUsec, pCigCtx->roleData.slv.totalAcc); + offsetUsec = delayUsec - wwTotalUsec; + pCis->rxSyncDelayUsec = (wwTotalUsec << 1); + } + else + { + offsetUsec = delayUsec; + } + return offsetUsec; + } + } + +Done: + /* All CISs are done. Set next CIS to the head of the list. */ + pCigCtx->pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + pOp->prot.pBle = &pCigCtx->pCisCtx->bleData; + *pNewCisCtx = TRUE; + lctrCisClearCisDone(&pCigCtx->list); + return 0; +} + +/*************************************************************************************************/ +/*! + * \brief Cleanup a connection operation. + * + * \param pOp Completed operation. + */ +/*************************************************************************************************/ +void lctrSlvCisCigCleanupOp(BbOpDesc_t *pOp) +{ + +} + +/*************************************************************************************************/ +/*! + * \brief End a connection operation. + * + * \param pOp Completed operation. + */ +/*************************************************************************************************/ +void lctrSlvCisCigEndOp(BbOpDesc_t *pOp) +{ + lctrCigCtx_t * const pCigCtx = pOp->pCtx; + lctrCisCtx_t *pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + lctrConnCtx_t *pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); + WSF_ASSERT(pCisCtx); /* At least one CIS in the CIG. */ + + if (pCisCtx->data.slv.syncWithMaster) + { + /* Re-sync to master's clock. */ + pCigCtx->roleData.slv.anchorPointUsec = pCisCtx->data.slv.firstRxStartTsUsec; + pCigCtx->roleData.slv.lastActiveEvent = pCigCtx->roleData.slv.cigEvtCounter; + } + + while (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) + { + /* This was a host-initiated termination of the CIS. */ + lctrNotifyHostCisTerm(pCisCtx); + } + + pCigCtx->numCisEsted--; + pCisCtx->isClosing = FALSE; + lctrCleanupCtx(pCisCtx); + } + + pCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCisCtx); + } + + if (pCigCtx->numCisEsted == 0) + { + return; + } + + pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + + while (pCisCtx) + { + lctrCisCheckFtAfterBod(pCisCtx); + + if (!pCisCtx->connEst && pCisCtx->data.slv.rxFromMaster) + { + WsfTimerStartMs(&pCisCtx->tmrSupTimeout, pCisCtx->supTimeoutMs); + pCisCtx->connEst = TRUE; + + if (pCisCtx->powerIndReq && lctrSendPowerChangeIndCback) + { + uint8_t txPhy = (pCisCtx->role == LL_ROLE_MASTER) ? pCisCtx->phyMToS : pCisCtx->phySToM; + lctrSendPowerChangeIndCback(pConnCtx, txPhy, 0, pLctrRtCfg->defTxPwrLvl, TRUE); + } + + lctrNotifyHostCisEst(pCisCtx, LL_SUCCESS, pCisCtx->cigSyncDelayUsec); + } + else if (pCisCtx->data.slv.rxFromMaster) + { + /* Reset supervision timer. */ + WsfTimerStartMs(&pCisCtx->tmrSupTimeout, pCisCtx->supTimeoutMs); + } + + /* Failed to receive packet within the first 6 intervals. */ + if ((pCisCtx->firstFromPeer == FALSE) && (pCisCtx->cisEvtCounter == LCTR_FAST_TERM_CNT)) + { + LL_TRACE_WARN0("CIS terminated due to fast termination timeout"); + lctrCisStoreConnFailEstablishTerminateReason(pCisCtx); + lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_CLOSED); + + if (pCigCtx->numCisEsted == 1) + { + /* If the last CIS to close, schedule no more operation. */ + return; + } + } + + /* Terminate connection */ + if (lctrCheckForCisLinkTerm(pCisCtx->aclHandle)) + { + lctrSendCisLlcpMsg(pCisCtx, LCTR_CIS_TERM_EVENT_CIS_TERM); + } + + pCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCisCtx); + } + + pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + + if (pCigCtx->headCisRmved == TRUE) + { + BbBleData_t *pBle = &pCisCtx->bleData; + /* Move the current CIS to the head CIS. */ + pOp->prot.pBle = pBle; + pCigCtx->pCisCtx = pCisCtx; + memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan)); + pBle->chan.chanIdx = pCigCtx->pCisCtx->chIdx; /* Set the next channel to the first channel in the next CIS. */ + } + + uint16_t numUnsyncIntervals = pCigCtx->roleData.slv.cigEvtCounter - pCigCtx->roleData.slv.lastActiveEvent; + + /* Update txPower. */ + pCisCtx->bleData.chan.txPower = LCTR_GET_TXPOWER(pConnCtx, pCisCtx->phySToM, pCisCtx->bleData.chan.initTxPhyOptions); +#if(LL_ENABLE_TESTER) + pCisCtx->bleData.chan.txPower += pConnCtx->bleData.chan.txPwrOffset; +#endif + + while (TRUE) + { + pCigCtx->roleData.slv.cigEvtCounter++; + numUnsyncIntervals += 1; + + uint32_t cigInterUsec = LCTR_ISO_INT_TO_US(pCigCtx->isoInterval); + uint32_t unsyncTimeUsec = cigInterUsec * numUnsyncIntervals; + uint32_t wwTotalUsec = lctrCalcWindowWideningUsec(unsyncTimeUsec, pCigCtx->roleData.slv.totalAcc); + + pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + WSF_ASSERT(pCisCtx); /* At least one CIS in the CIG. */ + + while (pCisCtx) + { + if (pCisCtx->cisCeRef == 0) + { + BbBleData_t * const pBle = &pCisCtx->bleData; + pCisCtx->cisEvtCounter++; + pCisCtx->chIdx = pBle->chan.chanIdx = LmgrSelectNextChannel(&pCisCtx->chanParam, pCisCtx->cisEvtCounter, 0, TRUE); + pCisCtx->nextSubEvtChanIdx = LmgrSelectNextSubEvtChannel(&pCisCtx->chanParam); + + if (pCisCtx->txTestEnabled) + { + uint32_t sduInt = pCisCtx->sduIntervalSToM; + + while ((pOp->dueUsec - pCisCtx->testSduTs) >= sduInt) + { + lctrCisTxTestPayloadHandler(pCisCtx); + pCisCtx->testSduTs += sduInt; + } + } + + /* Assemble framed data. */ + if ((pCisCtx->framing == LL_ISO_PDU_TYPE_FRAMED) && + pCisCtx->isoalTxCtx.pendQueueSize) + { + uint8_t *pDataBuf = lctrTxIsoDataPduAlloc(); + + if (pDataBuf == NULL) + { + /* TODO optimize statement as the call to WsfMsgFree() has no effect and should not continue to following statement. */ + LL_TRACE_WARN0("LctrTxIso, Unable to allocate PDU for transmit"); + WsfMsgFree(pDataBuf); + } + + lctrIsoHdr_t isoHdr; + + isoHdr.sduLen = lctrAssembleTxFramedPdu(&pCisCtx->isoalTxCtx, pDataBuf, pCisCtx->localDataPdu.maxTxLen); + isoHdr.tsFlag = 0; + + lctrIsoSduTxDecAvailBuf(); + lctrCisTxDataPduQueue(pCisCtx, &isoHdr, pDataBuf); + } + + /* TODO: resolve magic number */ + if (pCisCtx->nse < 3) + { + if (wwTotalUsec >= ((cigInterUsec >> 1) - WSF_MAX(LL_BLE_TIFS_US, BbGetSchSetupDelayUs()))) + { + LL_TRACE_WARN2("!!! Terminating CIG due to excessive WW handle=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->cisEvtCounter); + lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_CLOSED); + + if (pCigCtx->numCisEsted == 1) + { + /* If the last CIS to close, schedule no more operation. */ + return; + } + } + } + else + { + if (wwTotalUsec >= pCisCtx->subIntervUsec) + { + LL_TRACE_WARN2("!!! Terminating CIG due to excessive WW handle=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->cisEvtCounter); + lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_CLOSED); + + if (pCigCtx->numCisEsted == 1) + { + /* If the last CIS to close, schedule no more operation. */ + return; + } + } + } + } + else + { + pCisCtx->cisCeRef--; + } + + pCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCisCtx); + } + + /* 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); + + if (pCigCtx->headCisRmved == TRUE) + { + pCigCtx->headCisRmved = FALSE; + pOp->dueUsec += pCigCtx->offsetUsec; + pCigCtx->offsetUsec = 0; + } + + if (SchInsertAtDueTime(pOp, lctrCisResolveConflict)) + { + break; + } + + pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + LL_TRACE_WARN1("!!! CIG slave schedule conflict eventCounter=%u", pCisCtx->cisEvtCounter); + } + + + if (lmgrCb.sendIsoCmplEvt) + { + lctrNotifyHostIsoEventComplete(pCigCtx->cigHandle, (uint32_t) pCisCtx->cisEvtCounter); + } +} + +/*************************************************************************************************/ +/*! + * \brief Abort a connection operation. + * + * \param pOp Completed operation. + */ +/*************************************************************************************************/ +void lctrSlvCisCigAbortOp(BbOpDesc_t *pOp) +{ + lctrCigCtx_t * const pCigCtx = pOp->pCtx; + + if (pCigCtx->numCisEsted > 0) + { + lctrCisCtx_t *pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + /* It is possible there is no CIS since it is aborting. */ + + while (pCisCtx) + { + lctrFtParam_t txFtParam, rxFtParam; + + /* Need to setup Tx/Rx flush timeout parameter first since some field will be used in the lctrSlvCisInitIsr. */ + if (pCisCtx->bnMToS) + { + lctrCisInitFtParam(&txFtParam, pCisCtx->bnSToM, pCisCtx->ftSToM, pCisCtx->nse); + (void)lctrCisFtInsertTail(&pCisCtx->txFtParamList, &txFtParam); /* Assume there is memory. */ + } + + if (pCisCtx->bnSToM) + { + lctrCisInitFtParam(&rxFtParam, pCisCtx->bnMToS, pCisCtx->ftMToS, pCisCtx->nse); + (void)lctrCisFtInsertTail(&pCisCtx->rxFtParamList, &rxFtParam); /* Assume there is memory. */ + } + + lctrSlvCisInitIsr(pCisCtx); + + pCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCisCtx); + } + } + + lctrSlvCisCigEndOp(pOp); +} + +/*************************************************************************************************/ +/*! + * \brief Complete a transmitted data buffer. + * + * \param pOp Operation context. + * \param status Transmit status. + */ +/*************************************************************************************************/ +void lctrSlvCisCigTxCompletion(BbOpDesc_t *pOp, uint8_t status) +{ + lctrCigCtx_t * const pCigCtx = pOp->pCtx; + lctrCisCtx_t *pCisCtx = pCigCtx->pCisCtx; + + pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter++; +} + +/*************************************************************************************************/ +/*! + * \brief Complete a received data buffer. + * + * \param pOp Operation context. + * \param pRxBuf Next receive buffer or NULL to flow control. + * \param status Receive status. + */ +/*************************************************************************************************/ +void lctrSlvCisCigRxCompletion(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; + BbBleSlvCisEvent_t * const pCis = &pBle->op.slvCis; + + pCisCtx->data.slv.rxStatus = status; + + pCisCtx->rxFtParamList.pHead->ftParam.subEvtCounter++; + pCisCtx->txFtParamList.pHead->ftParam.pduAcked = FALSE; + pCisCtx->rxFtParamList.pHead->ftParam.pduRcved = FALSE; + pCisCtx->validRx = FALSE; + pCisCtx->txPduIsAcked = FALSE; + pCisCtx->pduFlushed = FALSE; + + /*** Cancellation processing ***/ + + if (status == BB_STATUS_CANCELED) + { + lctrCisRxPduFree(pRxBuf); + + goto Done; + } + + /*** CIS event pre-processing ***/ + + /* Save time stamp for the first Rx. */ + if (pCisCtx->data.slv.firstRxFromMaster == TRUE) + { + pCisCtx->data.slv.firstRxFromMaster = FALSE; + pCisCtx->data.slv.firstRxStartTsUsec = pCis->startTsUsec; + } + + if ((!pCisCtx->data.slv.syncWithMaster) && + (status == BB_STATUS_SUCCESS)) + { + /* Receive successful packet, update anchor point later. */ + pCisCtx->firstFromPeer = TRUE; + pCisCtx->data.slv.syncWithMaster = TRUE; + } + + /*** Receive packet pre-processing ***/ + + switch (status) + { + case BB_STATUS_SUCCESS: + 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); + + pCisCtx->validRx = FALSE; + pCisCtx->txPduIsAcked = FALSE; + + goto SetupTx; + + default: + break; + } + + lctrCisUnpackDataPduHdr(&pCisCtx->rxHdr, pRxBuf); + +#if (LL_ENABLE_TESTER) + if ((llTesterCb.cisAckMode != LL_TESTER_ACK_MODE_NORMAL) || + (llTesterCb.cisFwdPkt == TRUE)) + { + LctrCisProcessRxTxAck(pCisCtx, &pCisCtx->validRx, &pCisCtx->txPduIsAcked); + + /* Don't report the empty packet. */ + if (pCisCtx->rxHdr.len == 0) + { + pCisCtx->validRx = FALSE; + } + } + else +#endif + { + pCisCtx->validRx = lctrCisProcessRxAck(pCisCtx); + pCisCtx->txPduIsAcked = lctrCisProcessTxAck(pCisCtx); /* Always Tx after Rx. */ + } + + /*** Setup for transmit ***/ + +SetupTx: + + lctrCisCheckFtAfterRx(pCisCtx); + + /* Slave always transmits after receiving. */ + lctrCisSetupForTx(pCigCtx, status, TRUE); + + /* Tx post-processing. */ + lctrCisProcessTxAckCleanup(pCisCtx); + + /* 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); + + return; +} + +/*************************************************************************************************/ +/*! + * \brief Begin a connection operation. + * + * \param pOp Begin operation. + * + * \note Scheduler may call this routine multiple times in the following situation: + * this BOD is pending and a BOD is inserted before. + */ +/*************************************************************************************************/ +void lctrSlvCisCigBeginOp(BbOpDesc_t *pOp) +{ + lctrCigCtx_t * const pCigCtx = pOp->pCtx; + lctrCisCtx_t *pCisCtx; + pCisCtx = pCigCtx->pCisCtx; + pCigCtx->isLoopBack = FALSE; + + /* Need to setup Tx/Rx flush timeout parameter first since some field will be used in the lctrSlvCisInitIsr. */ + 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); + + lctrSlvCisCigExecOp(pCisCtx); +} + +/************************************************* ************************************************/ +/*! + * \brief Begin a connection operation. + * + * \param pOp Begin operation. + * + * \note Scheduler may call this routine multiple times in the following situation: + * this BOD is pending and a BOD is inserted before. + */ +/*************************************************************************************************/ +void lctrSlvCisCigContOp(BbOpDesc_t *pOp) +{ + lctrCigCtx_t * const pCigCtx = pOp->pCtx; + lctrCisCtx_t *pCisCtx; + pCisCtx = pCigCtx->pCisCtx; + + lctrSlvCisCigExecOp(pCisCtx); +} + +/*************************************************************************************************/ +/*! + * \brief Post subevent callback, setup for the next subevent channel index. + * + * \param pOp Current operation. + * \param status Status. + */ +/*************************************************************************************************/ +void lctrSlvCisCigPostSubEvt(BbOpDesc_t *pOp, uint8_t status) +{ + lctrCigCtx_t *pCigCtx = pOp->pCtx; + lctrCisCtx_t *pCisCtx; + + WSF_ASSERT(pCigCtx); + pCisCtx = pCigCtx->pCisCtx; + + WSF_ASSERT(pCisCtx); + pCisCtx->nextSubEvtChanIdx = LmgrSelectNextSubEvtChannel(&pCisCtx->chanParam); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn.c index 3868d3d9bc..9493c0d377 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave connection ISR callbacks. + * \file + * + * \brief Link layer controller slave connection ISR callbacks. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -50,8 +51,6 @@ static union * \brief Setup next transmit data buffer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrBuildEmptyPdu(lctrConnCtx_t *pCtx) @@ -71,8 +70,6 @@ static inline void lctrBuildEmptyPdu(lctrConnCtx_t *pCtx) * * \param pHdr Unpacked PDU header. * \param pBuf Packed packet buffer. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrUpdateFlowCtrlBits(const lctrDataPduHdr_t *pHdr, uint8_t *pBuf) @@ -182,8 +179,6 @@ uint8_t *lctrProcessRxAck(lctrConnCtx_t *pCtx) * \brief Last Data PDU acknowledged by peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrTxPduAck(lctrConnCtx_t *pCtx) @@ -240,8 +235,6 @@ bool_t lctrProcessTxAck(lctrConnCtx_t *pCtx) * * \param pCtx Connection context. * - * \return None. - * * Cleanup from Tx acknowledgment processing. */ /*************************************************************************************************/ @@ -383,13 +376,13 @@ void lctrRxPostProcessing(lctrConnCtx_t *pCtx, uint8_t *pRxBuf, uint8_t *pNextRx * \brief Check for maximum CE duration. * * \param pCtx Connection context. - * \param ceStart CE start time. + * \param ceStartUsec CE start time in microseconds. * \param pendDurUsec Pending operation duration in microseconds. * * \return FALSE if within duration period, TRUE if exceeds period. */ /*************************************************************************************************/ -bool_t lctrExceededMaxDur(lctrConnCtx_t *pCtx, uint32_t ceStart, uint32_t pendDurUsec) +bool_t lctrExceededMaxDur(lctrConnCtx_t *pCtx, uint32_t ceStartUsec, uint32_t pendDurUsec) { BbOpDesc_t *pOp = &pCtx->connBod; @@ -398,7 +391,7 @@ bool_t lctrExceededMaxDur(lctrConnCtx_t *pCtx, uint32_t ceStart, uint32_t pendDu return FALSE; } - const uint32_t curTime = PalBbGetCurrentTime(USE_RTC_BB_CLK); + const uint32_t curTime = PalBbGetCurrentTime(); const uint32_t setupDelayUsec = BbGetSchSetupDelayUs(); uint32_t availCeUsec = LCTR_CONN_IND_US(pCtx->connInterval); @@ -406,10 +399,10 @@ bool_t lctrExceededMaxDur(lctrConnCtx_t *pCtx, uint32_t ceStart, uint32_t pendDu if (pOp->pNext) { /* Limit CE duration to the edge of neighboring BOD. */ - availCeUsec = WSF_MIN(availCeUsec, BB_TICKS_TO_US(pOp->pNext->due - ceStart)); + availCeUsec = WSF_MIN(availCeUsec, BbGetTargetTimeDelta(pOp->pNext->dueUsec, ceStartUsec)); } - if ((BB_TICKS_TO_US(curTime - ceStart) + LL_BLE_TIFS_US + pendDurUsec + setupDelayUsec) > availCeUsec) + if ((BbGetTargetTimeDelta(curTime, ceStartUsec) + LL_BLE_TIFS_US + pendDurUsec + setupDelayUsec) > availCeUsec) { return TRUE; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn_master.c index 91d127316a..d6ef7af539 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master connection ISR callbacks. + * \file + * + * \brief Link layer controller master connection ISR callbacks. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -65,8 +66,6 @@ extern void LctrProcessRxTxAck(lctrConnCtx_t *pCtx, uint8_t *pRxBuf, uint8_t **p * \brief Update a connection operation. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstConnUpdateOp(lctrConnCtx_t *pCtx) @@ -89,9 +88,7 @@ static void lctrMstConnUpdateOp(lctrConnCtx_t *pCtx) /*** General setup ***/ - const uint32_t txWinOffset = BB_BLE_TO_BB_TICKS(LCTR_CONN_IND_TICKS(pConnUpdInd->txWinOffset)); - - pOp->due += txWinOffset; + pOp->dueUsec += BB_BLE_TO_US(LCTR_CONN_IND_TICKS(pConnUpdInd->txWinOffset)); pOp->maxDurUsec = LCTR_CONN_IND_US(pCtx->connInterval); /* Unconditionally reset supervision timer with transitional value. @@ -120,8 +117,6 @@ static void lctrMstConnUpdateOp(lctrConnCtx_t *pCtx) * \brief Update the channel map. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstChanMapUpdateOp(lctrConnCtx_t *pCtx) @@ -132,6 +127,12 @@ static void lctrMstChanMapUpdateOp(lctrConnCtx_t *pCtx) /* Delay notification until CE starts. */ pCtx->llcpInstantComp = TRUE; + /* Update the channel map for CIS master as well. */ + if (LctrUpdateCisChanMapFn) + { + LctrUpdateCisChanMapFn(LCTR_GET_CONN_HANDLE(pCtx)); + } + LL_TRACE_INFO2(" >>> Channel map updated, handle=%u, eventCounter=%u <<<", LCTR_GET_CONN_HANDLE(pCtx), pCtx->eventCounter); } @@ -140,26 +141,41 @@ static void lctrMstChanMapUpdateOp(lctrConnCtx_t *pCtx) * \brief Update the selected PHY. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstPhyUpdateOp(lctrConnCtx_t *pCtx) { - uint8_t txPhyOld = lctrPhyToPhysBit(pCtx->bleData.chan.txPhy); - uint8_t rxPhyOld = lctrPhyToPhysBit(pCtx->bleData.chan.rxPhy); + BbBleData_t * pBle = &pCtx->bleData; + uint8_t txPhyOld = lctrPhyToPhysBit(pBle->chan.txPhy); + uint8_t rxPhyOld = lctrPhyToPhysBit(pBle->chan.rxPhy); /* Notify host only if PHY changed. */ if ((pCtx->phyUpd.masterToSlavePhy != LL_PHYS_NONE) && (pCtx->phyUpd.masterToSlavePhy != txPhyOld)) { - pCtx->bleData.chan.txPhy = lctrPhysBitToPhy(pCtx->phyUpd.masterToSlavePhy); + pBle->chan.txPhy = lctrPhysBitToPhy(pCtx->phyUpd.masterToSlavePhy); + pBle->chan.txPower = LCTR_GET_TXPOWER(pCtx, pCtx->bleData.chan.txPhy, pBle->chan.initTxPhyOptions); pCtx->llcpNotifyMask |= 1 << LCTR_PROC_PHY_UPD; + + if (pBle->chan.txPower == LL_PWR_CTRL_TXPOWER_UNMANAGED) + { + pBle->chan.txPower = pLctrRtCfg->defTxPwrLvl; + LCTR_SET_TXPOWER(pCtx, pBle->chan.txPhy, pLctrRtCfg->defTxPwrLvl); + if (pBle->chan.txPhy == BB_PHY_BLE_CODED) + { + LCTR_SET_TXPOWER(pCtx, LL_PC_PHY_CODED_S2, pLctrRtCfg->defTxPwrLvl); + } + + if ((pCtx->usedFeatSet & LL_FEAT_POWER_CHANGE_IND) && lctrSendPowerChangeIndCback) + { + lctrSendPowerChangeIndCback(pCtx, pBle->chan.txPhy, 0, pLctrRtCfg->defTxPwrLvl, TRUE); + } + } } if ((pCtx->phyUpd.slaveToMasterPhy != LL_PHYS_NONE) && (pCtx->phyUpd.slaveToMasterPhy != rxPhyOld)) { - pCtx->bleData.chan.rxPhy = lctrPhysBitToPhy(pCtx->phyUpd.slaveToMasterPhy); + pBle->chan.rxPhy = lctrPhysBitToPhy(pCtx->phyUpd.slaveToMasterPhy); pCtx->llcpNotifyMask |= 1 << LCTR_PROC_PHY_UPD; } @@ -179,8 +195,6 @@ static void lctrMstPhyUpdateOp(lctrConnCtx_t *pCtx) * * \param pOp Begin operation. * - * \return None. - * * \note Scheduler may call this routine multiple times in the following situations: * (1) this BOD is pending and a BOD is inserted before, or (2) a Data PDU is queued * into an empty list. @@ -243,8 +257,6 @@ void lctrMstConnBeginOp(BbOpDesc_t *pOp) * \brief Cleanup a connection operation. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrMstConnCleanupOp(BbOpDesc_t *pOp) @@ -265,8 +277,6 @@ void lctrMstConnCleanupOp(BbOpDesc_t *pOp) * \brief End a connection operation. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrMstConnEndOp(BbOpDesc_t *pOp) @@ -275,9 +285,11 @@ void lctrMstConnEndOp(BbOpDesc_t *pOp) BbBleData_t * const pBle = pOp->prot.pBle; BbBleMstConnEvent_t * const pConn = &pBle->op.mstConn; lctrConnCtx_t * const pCtx = pOp->pCtx; - /* Process event completion */ +#if (LL_ENABLE_TESTER == TRUE) + pBle->chan.txPower = LCTR_GET_TXPOWER(pCtx, pCtx->bleData.chan.txPhy, pCtx->bleData.chan.initTxPhyOptions); +#endif if (!pCtx->connEst && (lctrMstConnIsr.rxFromSlave || (lctrMstConnIsr.consCrcFailed > 0))) { lctrStoreConnTimeoutTerminateReason(pCtx); @@ -293,7 +305,14 @@ void lctrMstConnEndOp(BbOpDesc_t *pOp) pCtx->rssi = pConn->rssi; - SchRmSetReference(LCTR_GET_CONN_HANDLE(pCtx)); + if ((pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) && + (pCtx->lastRxStatus == BB_STATUS_SUCCESS)) + { + if (lctrPcActTbl[pCtx->powerMonitorScheme]) + { + lctrPcActTbl[pCtx->powerMonitorScheme](pCtx); + } + } if (pCtx->checkCisTerm) { @@ -333,7 +352,7 @@ void lctrMstConnEndOp(BbOpDesc_t *pOp) pCtx->connUpd.instant = pCtx->eventCounter + ceOffset; /* Use smallest txWindowOffset (i.e. 0) to minimize data loss. */ - uint32_t txWinOffsetUsec = SchRmGetOffsetUsec(0, LCTR_GET_CONN_HANDLE(pCtx), pOp->due); + uint32_t txWinOffsetUsec = SchRmGetOffsetUsec(0, LCTR_GET_CONN_HANDLE(pCtx), pOp->dueUsec); pCtx->connUpd.txWinOffset = LCTR_US_TO_CONN_IND(txWinOffsetUsec); lctrPackConnUpdInd(pPdu, &pCtx->connUpd); @@ -363,8 +382,7 @@ void lctrMstConnEndOp(BbOpDesc_t *pOp) /*** Update for next operation ***/ - uint32_t anchorPoint = pOp->due; - uint16_t anchorPointOffsetUsec = pOp->dueOffsetUsec; + uint32_t anchorPointUsec = pOp->dueUsec; uint16_t numIntervals = 0; if (pBle->chan.tifsTxPhyOptions != BB_PHY_OPTIONS_DEFAULT) @@ -378,26 +396,26 @@ void lctrMstConnEndOp(BbOpDesc_t *pOp) pBle->chan.initTxPhyOptions = pConn->rxPhyOptions; } + if (pBle->chan.txPhy == BB_PHY_BLE_CODED) + { + pBle->chan.txPower = LCTR_GET_TXPOWER(pCtx, pBle->chan.txPhy, pBle->chan.initTxPhyOptions); + } + while (TRUE) { numIntervals += 1; pCtx->eventCounter += 1; - uint32_t connInterUsec = LCTR_CONN_IND_US(numIntervals * pCtx->connInterval) + anchorPointOffsetUsec; - uint32_t connInter = BB_US_TO_BB_TICKS(connInterUsec); - int16_t dueOffsetUsec = connInterUsec - BB_TICKS_TO_US(connInter); + uint32_t connInterUsec = LCTR_CONN_IND_US(numIntervals * pCtx->connInterval); #if (LL_ENABLE_TESTER) if (llTesterCb.connIntervalUs) { - connInterUsec = (numIntervals * llTesterCb.connIntervalUs) + anchorPointOffsetUsec; - connInter = BB_US_TO_BB_TICKS(connInterUsec); - dueOffsetUsec = 0; + connInterUsec = (numIntervals * llTesterCb.connIntervalUs); } #endif /* Advance to next interval. */ - pOp->due = anchorPoint + connInter; - pOp->dueOffsetUsec = WSF_MAX(dueOffsetUsec, 0); + pOp->dueUsec = anchorPointUsec + connInterUsec; if ((pCtx->llcpActiveProc == LCTR_PROC_CONN_UPD) && (pCtx->eventCounter == pCtx->connUpd.instant)) @@ -431,14 +449,14 @@ void lctrMstConnEndOp(BbOpDesc_t *pOp) * \brief Abort a connection operation. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ 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); + /* Reset operation to state before BOD began */ if (pCtx->emptyPduPend && pCtx->emptyPduFirstAtt) @@ -461,8 +479,6 @@ void lctrMstConnAbortOp(BbOpDesc_t *pOp) * * \param pOp Operation context. * \param status Transmit status. - * - * \return None. */ /*************************************************************************************************/ void lctrMstConnTxCompletion(BbOpDesc_t *pOp, uint8_t status) @@ -482,13 +498,12 @@ void lctrMstConnTxCompletion(BbOpDesc_t *pOp, uint8_t status) * \param pOp Operation context. * \param pRxBuf Next receive buffer or NULL to flow control. * \param status Receive status. - * - * \return None. */ /*************************************************************************************************/ void lctrMstConnRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status) { lctrConnCtx_t * const pCtx = pOp->pCtx; + pCtx->lastRxStatus = status; /* Local state */ uint8_t *pNextRxBuf = NULL; @@ -570,7 +585,7 @@ void lctrMstConnRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status) /*** Scheduler termination ***/ - if (lctrExceededMaxDur(pCtx, pOp->due, pCtx->effConnDurUsec)) + if (lctrExceededMaxDur(pCtx, pOp->dueUsec, pCtx->effConnDurUsec)) { BbSetBodTerminateFlag(); goto PostProcessing; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn_slave.c index 913b662ef1..7358c1f79f 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_conn_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave connection ISR callbacks. + * \file + * + * \brief Link layer controller slave connection ISR callbacks. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -58,26 +59,24 @@ extern void LctrProcessRxTxAck(lctrConnCtx_t *pCtx, uint8_t *pRxBuf, uint8_t **p * \brief Abort the slave latency and recover connection BOD due time and event counter. * * \param pOp Connection operation. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvAbortSlvLatency(BbOpDesc_t *pOp) { lctrConnCtx_t * const pCtx = pOp->pCtx; - const uint32_t curTime = PalBbGetCurrentTime(USE_RTC_BB_CLK); - uint32_t connInterval = BB_US_TO_BB_TICKS(LCTR_CONN_IND_US(pCtx->connInterval)); + const uint32_t curTime = PalBbGetCurrentTime(); + uint32_t connIntervalUsec = LCTR_CONN_IND_US(pCtx->connInterval); uint32_t count = 0; - if ((pOp->due - curTime) >= LCTR_SCH_MAX_SPAN) + if (BbGetTargetTimeDelta(pOp->dueUsec, curTime) == 0) { /* Slave tries to exit latency while the current BoD is executing, do nothing. */ } - else if (pOp->due - curTime > connInterval) /* Imply (pOp->due - curTime) < LCTR_SCH_MAX_SPAN */ + else if (BbGetTargetTimeDelta(pOp->dueUsec, curTime) > connIntervalUsec) { /* If the connection BOD is due in the future and after the next immediate anchor point, * adjust the event counter. */ - count = LlMathDivideUint32((pOp->due - curTime), connInterval); + count = LlMathDivideUint32(BbGetTargetTimeDelta(pOp->dueUsec, curTime), connIntervalUsec); pCtx->eventCounter -= count; /* Need to adjust the lastChanIdx for channel selection algorithm 1. */ @@ -111,8 +110,6 @@ static void lctrSlvAbortSlvLatency(BbOpDesc_t *pOp) * * \param pCtx Connection context. * \param ignoreOffset txWinOffset will be ignored if TRUE. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvConnUpdateOp(lctrConnCtx_t *pCtx, bool_t ignoreOffset) @@ -132,13 +129,12 @@ static void lctrSlvConnUpdateOp(lctrConnCtx_t *pCtx, bool_t ignoreOffset) /* Make sure set the anchor point to the instant in the connection update indication. */ const uint16_t numIntervals = pCtx->eventCounter - pCtx->data.slv.lastActiveEvent + 1; const uint32_t timeUsec = LCTR_CONN_IND_US(connIntervalOld * numIntervals); - const uint32_t time = BB_US_TO_BB_TICKS(timeUsec); - pCtx->data.slv.anchorPoint += time; + pCtx->data.slv.anchorPointUsec = pCtx->data.slv.anchorPointUsec + timeUsec; if (pCtx->connUpd.instant != pCtx->data.slv.lastActiveEvent) { /* Save the unsynced time before the connection update. */ - pCtx->data.slv.unsyncedTime = time; + pCtx->data.slv.unsyncedTime = timeUsec; } pCtx->data.slv.lastActiveEvent = pCtx->eventCounter + 1; /* guarantee execution of first connection event. */ @@ -148,19 +144,18 @@ static void lctrSlvConnUpdateOp(lctrConnCtx_t *pCtx, bool_t ignoreOffset) pCtx->supTimeoutMs = LCTR_CONN_IND_TO_MS(pConnUpdInd->timeout); /*** General setup ***/ + if (ignoreOffset == FALSE) { const uint32_t txWinOffsetUsec = LCTR_CONN_IND_US(pConnUpdInd->txWinOffset); - const uint32_t txWinOffset = BB_US_TO_BB_TICKS(txWinOffsetUsec); const uint32_t txWinSizeUsec = LCTR_CONN_IND_US(pConnUpdInd->txWinSize); const uint32_t wwTxWinOffsetUsec = lctrCalcWindowWideningUsec((txWinOffsetUsec + txWinSizeUsec), pCtx->data.slv.totalAcc); - const uint32_t wwTxWinOffset = BB_US_TO_BB_TICKS(wwTxWinOffsetUsec); /* txWinOffset is relative to anchorPoint. */ - pCtx->data.slv.anchorPoint += txWinOffset; + pCtx->data.slv.anchorPointUsec += txWinOffsetUsec; /* Add additional time due to Tx window offset and subtract WW due to Tx window offset. */ - pOp->due += txWinOffset - wwTxWinOffset; + pOp->dueUsec += txWinOffsetUsec - wwTxWinOffsetUsec; pCtx->data.slv.txWinSizeUsec = txWinSizeUsec; @@ -200,8 +195,6 @@ static void lctrSlvConnUpdateOp(lctrConnCtx_t *pCtx, bool_t ignoreOffset) * \brief Update the channel map. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvChanMapUpdateOp(lctrConnCtx_t *pCtx) @@ -212,6 +205,12 @@ static void lctrSlvChanMapUpdateOp(lctrConnCtx_t *pCtx) /* Delay notification until CE starts. */ pCtx->llcpInstantComp = TRUE; + /* Update the channel map for CIS master as well. */ + if (LctrUpdateCisChanMapFn) + { + LctrUpdateCisChanMapFn(LCTR_GET_CONN_HANDLE(pCtx)); + } + LL_TRACE_INFO2(" >>> Channel map updated, handle=%u, eventCounter=%u <<<", LCTR_GET_CONN_HANDLE(pCtx), pCtx->eventCounter); } @@ -220,26 +219,41 @@ static void lctrSlvChanMapUpdateOp(lctrConnCtx_t *pCtx) * \brief Update the selected PHY. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvPhyUpdateOp(lctrConnCtx_t *pCtx) { - uint8_t txPhyOld = lctrPhyToPhysBit(pCtx->bleData.chan.txPhy); - uint8_t rxPhyOld = lctrPhyToPhysBit(pCtx->bleData.chan.rxPhy); + BbBleData_t * pBle = &pCtx->bleData; + uint8_t txPhyOld = lctrPhyToPhysBit(pBle->chan.txPhy); + uint8_t rxPhyOld = lctrPhyToPhysBit(pBle->chan.rxPhy); /* Notify host only if PHY changed. */ if ((pCtx->phyUpd.slaveToMasterPhy != LL_PHYS_NONE) && (pCtx->phyUpd.slaveToMasterPhy != txPhyOld)) { - pCtx->bleData.chan.txPhy = lctrPhysBitToPhy(pCtx->phyUpd.slaveToMasterPhy); + pBle->chan.txPhy = lctrPhysBitToPhy(pCtx->phyUpd.slaveToMasterPhy); + pBle->chan.txPower = LCTR_GET_TXPOWER(pCtx, pCtx->bleData.chan.txPhy, pBle->chan.initTxPhyOptions); pCtx->llcpNotifyMask |= 1 << LCTR_PROC_PHY_UPD; + + if (pBle->chan.txPower == LL_PWR_CTRL_TXPOWER_UNMANAGED) + { + pBle->chan.txPower = pLctrRtCfg->defTxPwrLvl; + LCTR_SET_TXPOWER(pCtx, pBle->chan.txPhy, pLctrRtCfg->defTxPwrLvl); + if (pBle->chan.txPhy == BB_PHY_BLE_CODED) + { + LCTR_SET_TXPOWER(pCtx, LL_PC_PHY_CODED_S2, pLctrRtCfg->defTxPwrLvl); + } + + if ((pCtx->usedFeatSet & LL_FEAT_POWER_CHANGE_IND) && lctrSendPowerChangeIndCback) + { + lctrSendPowerChangeIndCback(pCtx, pBle->chan.txPhy, 0, pBle->chan.txPower, TRUE); + } + } } if ((pCtx->phyUpd.masterToSlavePhy != LL_PHYS_NONE) && (pCtx->phyUpd.masterToSlavePhy != rxPhyOld)) { - pCtx->bleData.chan.rxPhy = lctrPhysBitToPhy(pCtx->phyUpd.masterToSlavePhy); + pBle->chan.rxPhy = lctrPhysBitToPhy(pCtx->phyUpd.masterToSlavePhy); pCtx->llcpNotifyMask |= 1 << LCTR_PROC_PHY_UPD; } @@ -258,8 +272,6 @@ static void lctrSlvPhyUpdateOp(lctrConnCtx_t *pCtx) * \brief Initialize connection event resources. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvInitConnIsr(lctrConnCtx_t *pCtx) @@ -267,7 +279,7 @@ static void lctrSlvInitConnIsr(lctrConnCtx_t *pCtx) pCtx->data.slv.consCrcFailed = 0; pCtx->data.slv.syncWithMaster = FALSE; pCtx->data.slv.rxFromMaster = FALSE; - pCtx->data.slv.firstRxStartTs = 0; + pCtx->data.slv.firstRxStartTsUsec = 0; } /*************************************************************************************************/ @@ -276,8 +288,6 @@ static void lctrSlvInitConnIsr(lctrConnCtx_t *pCtx) * * \param pOp Begin operation. * - * \return None. - * * \note Scheduler may call this routine multiple times in the following situation: * this BOD is pending and a BOD is inserted before. */ @@ -322,13 +332,10 @@ void lctrSlvConnBeginOp(BbOpDesc_t *pOp) * \brief Cleanup a connection operation. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvConnCleanupOp(BbOpDesc_t *pOp) { - } /*************************************************************************************************/ @@ -336,8 +343,6 @@ void lctrSlvConnCleanupOp(BbOpDesc_t *pOp) * \brief End a connection operation. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvConnEndOp(BbOpDesc_t *pOp) @@ -347,6 +352,10 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp) BbBleSlvConnEvent_t * const pConn = &pBle->op.slvConn; lctrConnCtx_t * const pCtx = pOp->pCtx; +#if (LL_ENABLE_TESTER == TRUE) + pBle->chan.txPower = LCTR_GET_TXPOWER(pCtx, pCtx->bleData.chan.txPhy, pCtx->bleData.chan.initTxPhyOptions); +#endif + /* Process event completion */ if (pCtx->data.slv.abortSlvLatency) { @@ -356,10 +365,19 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp) pCtx->rssi = pConn->rssi; + if ((pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) && + (pCtx->lastRxStatus == BB_STATUS_SUCCESS)) + { + if (lctrPcActTbl[pCtx->powerMonitorScheme]) + { + lctrPcActTbl[pCtx->powerMonitorScheme](pCtx); + } + } + if (pCtx->data.slv.syncWithMaster) { /* Re-sync to master's clock. */ - pCtx->data.slv.anchorPoint = pCtx->data.slv.firstRxStartTs; + pCtx->data.slv.anchorPointUsec = pCtx->data.slv.firstRxStartTsUsec; pCtx->data.slv.lastActiveEvent = pCtx->eventCounter + 1; pCtx->svtState = LCTR_SVT_STATE_IDLE; @@ -520,10 +538,7 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp) unsyncTimeUsec += pCtx->data.slv.unsyncedTime; uint32_t wwTotalUsec = lctrCalcWindowWideningUsec(unsyncTimeUsec, pCtx->data.slv.totalAcc); - uint32_t wwTotal = BB_US_TO_BB_TICKS(wwTotalUsec); uint32_t connInterUsec = LCTR_CONN_IND_US(numUnsyncIntervals * pCtx->connInterval); - uint32_t connInter = BB_US_TO_BB_TICKS(connInterUsec); - int16_t dueOffsetUsec = (connInterUsec - wwTotalUsec) - BB_TICKS_TO_US(connInter - wwTotal); if (wwTotalUsec >= ((connInterUsec >> 1) - WSF_MAX(LL_BLE_TIFS_US, BbGetSchSetupDelayUs()))) { @@ -534,9 +549,9 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp) } /* Advance to next interval. */ - pOp->due = pCtx->data.slv.anchorPoint + connInter - wwTotal; - pOp->dueOffsetUsec = WSF_MAX(dueOffsetUsec, 0); - pOp->minDurUsec = pCtx->data.slv.txWinSizeUsec + pCtx->localConnDurUsec + wwTotalUsec; + pOp->dueUsec = pCtx->data.slv.anchorPointUsec + connInterUsec - wwTotalUsec; + + pOp->minDurUsec = pCtx->data.slv.txWinSizeUsec + pCtx->effConnDurUsec + wwTotalUsec; pConn->rxSyncDelayUsec = pCtx->data.slv.txWinSizeUsec + (wwTotalUsec << 1); if ((pCtx->llcpActiveProc == LCTR_PROC_CONN_UPD) && @@ -599,8 +614,6 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp) * \brief Abort a connection operation. * * \param pOp Aborted operation. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvConnAbortOp(BbOpDesc_t *pOp) @@ -617,8 +630,6 @@ void lctrSlvConnAbortOp(BbOpDesc_t *pOp) * * \param pOp Operation context. * \param status Transmit status. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvConnTxCompletion(BbOpDesc_t *pOp, uint8_t status) @@ -639,8 +650,6 @@ void lctrSlvConnTxCompletion(BbOpDesc_t *pOp, uint8_t status) * \param pRxBuf Receive buffer. * \param status Receive status. * - * \return None. - * * \note 1. pRxBuf must be freed or placed into a queue by this function. * 2. If the BOD is terminated during this function, no further receive buffer should * remain allocated for the caller to clean up. @@ -652,6 +661,7 @@ void lctrSlvConnRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status) BbBleData_t * const pBle = &pCtx->bleData; BbBleSlvConnEvent_t * const pConn = &pBle->op.slvConn; + pCtx->lastRxStatus = status; /* Local state */ bool_t loadRxBuf = FALSE; @@ -701,7 +711,7 @@ void lctrSlvConnRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status) ((status == BB_STATUS_SUCCESS) || (!lctrGetConnOpFlag(pCtx, LL_OP_MODE_FLAG_IGNORE_CRC_ERR_TS) && (status == BB_STATUS_CRC_FAILED)))) { - pCtx->data.slv.firstRxStartTs = pConn->startTs; + pCtx->data.slv.firstRxStartTsUsec = pConn->startTsUsec; pCtx->data.slv.syncWithMaster = TRUE; } @@ -788,7 +798,7 @@ SetupTx: /*** Setup for receive ***/ loadRxBuf = ((status == BB_STATUS_CRC_FAILED) || pCtx->rxHdr.md || pCtx->txHdr.md) && - !lctrExceededMaxDur(pCtx, pConn->startTs, SchBleCalcDataPktDurationUsec(pCtx->bleData.chan.txPhy, txLen) + pCtx->effConnDurUsec); + !lctrExceededMaxDur(pCtx, pConn->startTsUsec, SchBleCalcDataPktDurationUsec(pCtx->bleData.chan.txPhy, txLen) + pCtx->effConnDurUsec); /*** Packet post-processing ***/ PostProcessing: diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_init_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_init_master.c index cb8faef4f8..0ed98891e6 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_init_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_init_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master advertising event ISR callbacks. + * \file + * + * \brief Link layer controller master advertising event ISR callbacks. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -41,27 +42,33 @@ * \brief End an initiate scan operation in the master role. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrMstInitiateEndOp(BbOpDesc_t *pOp) { - if (!lctrMstInit.selfTerm) /* implies not a LL_CONN_IND Tx completion */ + lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(lctrMstInit.data.init.connHandle); + BbOpDesc_t * pConnBod = &pCtx->connBod; + + if (lctrMstInit.selfTerm) /* implies a LL_CONN_IND Tx completion */ { - lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(lctrMstInit.data.init.connHandle); + uint16_t numIntervals = 0; + uint32_t anchorPointUsec = pConnBod->dueUsec; - /* Service RM. */ - SchRmSetReference(lctrMstInit.data.init.connHandle); - - /* Connection cleanup. */ - if (lctrMstInit.data.init.connBodLoaded) + while (TRUE) { - lctrMstInit.data.init.connBodLoaded = FALSE; + if (SchInsertAtDueTime(pConnBod, lctrConnResolveConflict)) + { + break; + } - bool_t result = SchRemove(&pCtx->connBod); - (void)result; - WSF_ASSERT(result); /* non-head BOD always remove-able */ + LL_TRACE_WARN1("!!! Establish CE schedule conflict handle=%u", LCTR_GET_CONN_HANDLE(pCtx)); + + numIntervals++; + pCtx->eventCounter++; + + uint32_t connInterUsec = LCTR_CONN_IND_US(numIntervals * pCtx->connInterval); + + pConnBod->dueUsec = anchorPointUsec + connInterUsec; } } @@ -86,10 +93,12 @@ bool_t lctrMstInitiateAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf) WSF_ASSERT(pOp->prot.pBle->chan.opType == BB_BLE_OP_MST_ADV_EVENT); lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(lctrMstInit.data.init.connHandle); + BbOpDesc_t * const pConnBod = &pCtx->connBod; BbBleData_t * const pBle = pOp->prot.pBle; BbBleMstAdvEvent_t * const pScan = &pBle->op.mstAdv; - uint32_t advEndTs = pScan->advStartTs + BB_US_TO_BB_TICKS(LCTR_ADV_PKT_1M_US(pScan->filtResults.pduLen)); + uint32_t advEndTs = pScan->advStartTsUsec + LCTR_ADV_PKT_1M_US(pScan->filtResults.pduLen); + uint32_t refTime = advEndTs; /*** Transmit response PDU processing. ***/ @@ -99,10 +108,6 @@ bool_t lctrMstInitiateAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf) { /* Require peer match. */ } - else if (!lctrMstInit.data.init.connBodLoaded) - { - BbSetBodTerminateFlag(); - } else if (pScan->pTxReqBuf) { /* Update connection indication header with advertiser's address. */ @@ -169,21 +174,30 @@ bool_t lctrMstInitiateAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf) lctrPackAdvbPduHdr(pScan->pTxReqBuf, &lctrMstInit.reqPduHdr); /* Update txWinOffset field in CONN_IND PDU. */ - uint32_t txWinOffsetUsec = BB_TICKS_TO_US(lctrMstInit.data.init.firstCeDue - advEndTs) - LL_BLE_TIFS_US - LCTR_CONN_IND_PKT_1M_US; - uint16_t txWinOffset = LCTR_US_TO_CONN_IND(txWinOffsetUsec) - LCTR_DATA_CHAN_DLY; + refTime += LL_BLE_TIFS_US; + refTime += LCTR_CONN_IND_PKT_1M_US; + refTime += LCTR_CONN_IND_US(LCTR_DATA_CHAN_DLY); + + /* Now reference time is the start of transmitWindowOffset. */ + uint32_t txWinOffsetUsec = SchRmGetOffsetUsec(LCTR_CONN_IND_US(pCtx->connInterval), LCTR_GET_CONN_HANDLE(pCtx), refTime); + uint16_t txWinOffset = LCTR_US_TO_CONN_IND(txWinOffsetUsec); + UINT16_TO_BUF(pScan->pTxReqBuf + LCTR_CONN_IND_TX_WIN_OFFSET, txWinOffset); lctrMstInit.data.init.connInd.txWinOffset = txWinOffset; + /*** Update due time of first CE. ***/ + pConnBod->dueUsec = refTime + txWinOffsetUsec; + #if (LL_ENABLE_TESTER) switch (llTesterCb.connFirstCePos) { case LL_TESTER_FIRST_CE_POS_BEGIN: /* BOD is not scheduled; force time adjustment here. */ - pCtx->connBod.due = advEndTs + BB_US_TO_BB_TICKS(txWinOffsetUsec + LL_BLE_TIFS_US + LCTR_CONN_IND_PKT_1M_US); + pCtx->connBod.dueUsec = advEndTs + LCTR_CONN_IND_US(LCTR_DATA_CHAN_DLY) + txWinOffsetUsec + LL_BLE_TIFS_US + LCTR_CONN_IND_PKT_1M_US; break; case LL_TESTER_FIRST_CE_POS_END: /* BOD is not scheduled; force time adjustment here. */ - pCtx->connBod.due = advEndTs + BB_US_TO_BB_TICKS(txWinOffsetUsec + LCTR_CONN_IND_US(lctrMstInit.data.init.connInd.txWinSize - 1) + LL_BLE_TIFS_US + LCTR_CONN_IND_PKT_1M_US); + pCtx->connBod.dueUsec = advEndTs + LCTR_CONN_IND_US(LCTR_DATA_CHAN_DLY) + txWinOffsetUsec + LCTR_CONN_IND_US(lctrMstInit.data.init.connInd.txWinSize - 1) + LL_BLE_TIFS_US + LCTR_CONN_IND_PKT_1M_US; break; case LL_TESTER_FIRST_CE_POS_NORMAL: default: @@ -192,35 +206,18 @@ bool_t lctrMstInitiateAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf) llTesterCb.connFirstCePos = LL_TESTER_FIRST_CE_POS_NORMAL; #endif - if (txWinOffsetUsec < LCTR_CONN_IND_US(LCTR_DATA_CHAN_DLY)) - { - LL_TRACE_WARN1("AE too close to initial CE deltaUsec=%u, suppressed LL_CONN_IND delivery", BB_TICKS_TO_US(lctrMstInit.data.init.firstCeDue - advEndTs)); + txConnInd = TRUE; - /* Restart scanning with better initial CE margin. */ - BbSetBodTerminateFlag(); - } - else if (txWinOffset > pCtx->connInterval) - { - LL_TRACE_WARN1("Scan period exceeded initial CE time by deltaUsec=%u, suppressed LL_CONN_IND delivery", BB_TICKS_TO_US(advEndTs - lctrMstInit.data.init.firstCeDue)); + /*** Received advertising PDU post-processing. ***/ - /* Restart scanning with CE in the future. */ - BbSetBodTerminateFlag(); + if ((lctrMstInit.reqPduHdr.chSel == LL_CH_SEL_2) && /* local initiator supports CS#2 */ + (pAdvBuf[0] & (1 << LCTR_ADV_HDR_CH_SEL_SHIFT))) /* peer advertiser supports CS#2 */ + { + lctrMstInit.data.init.usedChSel = LL_CH_SEL_2; } else { - txConnInd = TRUE; - - /*** Received advertising PDU post-processing. ***/ - - if ((lctrMstInit.reqPduHdr.chSel == LL_CH_SEL_2) && /* local initiator supports CS#2 */ - (pAdvBuf[0] & (1 << LCTR_ADV_HDR_CH_SEL_SHIFT))) /* peer advertiser supports CS#2 */ - { - lctrMstInit.data.init.usedChSel = LL_CH_SEL_2; - } - else - { - lctrMstInit.data.init.usedChSel = LL_CH_SEL_1; - } + lctrMstInit.data.init.usedChSel = LL_CH_SEL_1; } } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_init_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_init_master_ae.c index 3cd53b11af..16c61b1dbe 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_init_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_isr_init_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master advertising event ISR callbacks. + * \file + * + * \brief Link layer controller master advertising event ISR callbacks. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -44,8 +45,6 @@ * \brief Reschedule primary scan operation for initiation. * * \param pExtInitCtx Extended initiate context. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstExtInitiateScanReschedule(lctrExtScanCtx_t *pExtInitCtx) @@ -60,18 +59,18 @@ static void lctrMstExtInitiateScanReschedule(lctrExtScanCtx_t *pExtInitCtx) pOp->minDurUsec = LCTR_MIN_SCAN_USEC; /* Reset due time to start of scan window. */ - pOp->due = pExtInitCtx->data.init.scanWinStart; + pOp->dueUsec = pExtInitCtx->data.init.scanWinStartUsec; if ((pExtInitCtx->data.init.param.scanInterval != pExtInitCtx->data.init.param.scanWindow) && ((pScan->elapsedUsec + pOp->minDurUsec) < LCTR_BLE_TO_US(pExtInitCtx->data.init.param.scanWindow))) { - const uint32_t min = BB_US_TO_BB_TICKS(pScan->elapsedUsec); - const uint32_t max = BB_BLE_TO_BB_TICKS(pExtInitCtx->data.init.param.scanWindow); + const uint32_t min = pScan->elapsedUsec; + const uint32_t max = BB_BLE_TO_US(pExtInitCtx->data.init.param.scanWindow); if (SchInsertEarlyAsPossible(pOp, min, max)) { /* Continue interrupted operation. */ - pScan->elapsedUsec = BB_TICKS_TO_US(pOp->due - pExtInitCtx->data.init.scanWinStart); + pScan->elapsedUsec = BbGetTargetTimeDelta(pOp->dueUsec, pExtInitCtx->data.init.scanWinStartUsec); WSF_ASSERT(pScan->elapsedUsec < pOp->maxDurUsec); return; } @@ -88,69 +87,42 @@ static void lctrMstExtInitiateScanReschedule(lctrExtScanCtx_t *pExtInitCtx) { /* Continuous scan. */ SchInsertNextAvailable(pOp); - pExtInitCtx->data.init.scanWinStart = pOp->due; + pExtInitCtx->data.init.scanWinStartUsec = pOp->dueUsec; } else { /* Next scan interval. */ - const uint32_t min = BB_BLE_TO_BB_TICKS(pExtInitCtx->data.init.param.scanInterval); - const uint32_t max = min + BB_BLE_TO_BB_TICKS(pExtInitCtx->data.init.param.scanWindow); + const uint32_t min = BB_BLE_TO_US(pExtInitCtx->data.init.param.scanInterval); + const uint32_t max = min + BB_BLE_TO_US(pExtInitCtx->data.init.param.scanWindow); while (TRUE) { /* Store start of next scan window. */ - pExtInitCtx->data.init.scanWinStart = pOp->due + min; + pExtInitCtx->data.init.scanWinStartUsec = pOp->dueUsec + min; if (SchInsertEarlyAsPossible(pOp, min, max)) { - pScan->elapsedUsec = BB_TICKS_TO_US(pOp->due - pExtInitCtx->data.init.scanWinStart); + pScan->elapsedUsec = BbGetTargetTimeDelta(pOp->dueUsec, pExtInitCtx->data.init.scanWinStartUsec); WSF_ASSERT(pScan->elapsedUsec < pOp->maxDurUsec); break; } else { /* Advance to next scan window. */ - pOp->due = pExtInitCtx->data.init.scanWinStart; + pOp->dueUsec = pExtInitCtx->data.init.scanWinStartUsec; - LL_TRACE_WARN1("!!! Scan schedule conflict at due=%u", pOp->due + min); + LL_TRACE_WARN1("!!! Scan schedule conflict at dueUsec=%u", pOp->dueUsec + min); LL_TRACE_WARN1("!!! scanWindowUsec=%u", LCTR_BLE_TO_US(pExtInitCtx->data.init.param.scanWindow)); } } } } -/*************************************************************************************************/ -/*! - * \brief Handler for pre-initiate scan execution. - * - * \param pOp BB operation descriptor. - * - * \return None. - */ -/*************************************************************************************************/ -void lctrMstExtPreInitiateExecHandler(BbOpDesc_t *pOp) -{ - lctrExtScanCtx_t * const pExtInitCtx = pOp->pCtx; - - if (!pExtInitCtx->shutdown || !pExtInitCtx->selfTerm) - { - /* Setup connection's initial CE now that RM is synchronized BB. This step must be performed - * before initiate's scan operation sets up its executing duration (i.e. "pre-execute"). */ - pExtInitCtx->data.init.firstCeDue = lctrMstConnAdjustOpStart(LCTR_GET_CONN_CTX(pExtInitCtx->data.init.connHandle), - pOp->due, - pOp->minDurUsec, - &pExtInitCtx->data.init.connInd); - pExtInitCtx->data.init.connBodLoaded = TRUE; - } -} - /*************************************************************************************************/ /*! * \brief End a initiate scan operation in the master role. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrMstExtInitiateScanEndOp(BbOpDesc_t *pOp) @@ -185,8 +157,6 @@ void lctrMstExtInitiateScanEndOp(BbOpDesc_t *pOp) * \brief End an auxiliary initiate scan operation in the master role. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrMstAuxInitiateScanEndOp(BbOpDesc_t *pOp) @@ -210,52 +180,36 @@ void lctrMstAuxInitiateScanEndOp(BbOpDesc_t *pOp) * \brief End an initiate operation in the master role. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrMstExtInitiateEndOp(BbOpDesc_t *pOp) { lctrExtScanCtx_t * const pExtInitCtx = pOp->pCtx; + lctrConnCtx_t * pCtx = LCTR_GET_CONN_CTX(pExtInitCtx->data.init.connHandle); + BbOpDesc_t * pConnBod = &pCtx->connBod; - if (!pExtInitCtx->selfTerm && /* Implies not a LL_CONN_IND Tx completion. */ - !pExtInitCtx->auxOpPending) /* Auxiliary EndOp handles cleanup. */ + if (pExtInitCtx->selfTerm && /* LL_CONN_IND Tx Complete. */ + !pExtInitCtx->auxOpPending) /* No aux scan bod pending + * (means that the self termination was generated from a legacy advertisement connection). */ { - lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(pExtInitCtx->data.init.connHandle); + uint16_t numIntervals = 0; + uint32_t anchorPointUsec = pConnBod->dueUsec; - /* Service RM. */ - SchRmSetReference(pExtInitCtx->data.init.connHandle); - - /* Connection cleanup. */ - if (pExtInitCtx->data.init.connBodLoaded) + while (TRUE) { - pExtInitCtx->data.init.connBodLoaded = FALSE; + if (SchInsertAtDueTime(pConnBod, lctrConnResolveConflict)) + { + break; + } - bool_t result = SchRemove(&pCtx->connBod); - (void)result; - WSF_ASSERT(result); /* Non-head BOD always remove-able. */ - } - } - else if (!pExtInitCtx->selfTerm && /* Implies not a LL_CONN_IND Tx completion. */ - pExtInitCtx->auxOpPending) /* AuxBod is scheduled. */ - { - lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(pExtInitCtx->data.init.connHandle); + LL_TRACE_WARN2("!!!Establish CE Schedule conflict handle=%u, evtCtr=%u", LCTR_GET_CONN_HANDLE(pCtx), pCtx->eventCounter); - if (pExtInitCtx->data.init.connBodLoaded && - pCtx->connBod.due < pExtInitCtx->auxScanBod.due) - { - /* connBod is scheduled and due before auxScanBod, need to reschedule connBod. */ - pExtInitCtx->data.init.connBodLoaded = FALSE; + numIntervals++; + pCtx->eventCounter++; - bool_t result = SchRemove(&pCtx->connBod); - (void)result; - WSF_ASSERT(result); /* Non-head BOD always remove-able. */ + uint32_t connInterUsec = LCTR_CONN_IND_US(numIntervals * pCtx->connInterval); - pExtInitCtx->data.init.firstCeDue = lctrMstConnAdjustOpStart(LCTR_GET_CONN_CTX(pExtInitCtx->data.init.connHandle), - pExtInitCtx->auxScanBod.due, - pExtInitCtx->auxScanBod.minDurUsec, - &pExtInitCtx->data.init.connInd); - pExtInitCtx->data.init.connBodLoaded = TRUE; + pConnBod->dueUsec = anchorPointUsec + connInterUsec; } } @@ -267,29 +221,34 @@ void lctrMstExtInitiateEndOp(BbOpDesc_t *pOp) * \brief End an auxiliary initiate operation in the master role. * * \param pOp Completed operation. - * - * \return None. */ /*************************************************************************************************/ void lctrMstAuxInitiateEndOp(BbOpDesc_t *pOp) { lctrExtScanCtx_t * const pExtInitCtx = pOp->pCtx; + lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(pExtInitCtx->data.init.connHandle); + BbOpDesc_t * pConnBod = &pCtx->connBod; - if (!pExtInitCtx->selfTerm) /* Implies not a LL_CONN_IND Tx completion. */ + if (pExtInitCtx->selfTerm) /* Implies a LL_CONN_IND Tx completion. */ { - lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(pExtInitCtx->data.init.connHandle); + uint16_t numIntervals = 0; + uint32_t anchorPointUsec = pConnBod->dueUsec; - /* Service RM. */ - SchRmSetReference(pExtInitCtx->data.init.connHandle); - - /* Connection cleanup. */ - if (pExtInitCtx->data.init.connBodLoaded) + while (TRUE) { - pExtInitCtx->data.init.connBodLoaded = FALSE; + if (SchInsertAtDueTime(pConnBod, lctrConnResolveConflict)) + { + break; + } - bool_t result = SchRemove(&pCtx->connBod); - (void)result; - WSF_ASSERT(result); /* Non-head BOD always remove-able. */ + LL_TRACE_WARN2("!!!Establish CE Schedule conflict handle=%u, evtCtr=%u", LCTR_GET_CONN_HANDLE(pCtx), pCtx->eventCounter); + + numIntervals++; + pCtx->eventCounter++; + + uint32_t connInterUsec = LCTR_CONN_IND_US(numIntervals * pCtx->connInterval); + + pConnBod->dueUsec = anchorPointUsec + connInterUsec; } } @@ -347,12 +306,15 @@ bool_t lctrMstInitiateExtAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf) WSF_ASSERT(pOp->prot.pBle->chan.opType == BB_BLE_OP_MST_ADV_EVENT); lctrExtScanCtx_t *pCtx = pOp->pCtx; + lctrConnCtx_t *pConnCtx = LCTR_GET_CONN_CTX(pCtx->data.init.connHandle); + BbOpDesc_t * const pConnBod = &pConnCtx->connBod; BbBleData_t * const pBle = pOp->prot.pBle; BbBleMstAdvEvent_t * const pScan = &pBle->op.mstAdv; - uint32_t advEndTs = pScan->advStartTs + - BB_US_TO_BB_TICKS(SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, pScan->advRxPhyOptions, - LL_ADV_HDR_LEN + pScan->filtResults.pduLen)); + uint32_t advEndTs = pScan->advStartTsUsec + + SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, pScan->advRxPhyOptions, + LL_ADV_HDR_LEN + pScan->filtResults.pduLen); + uint32_t refTime = advEndTs; /*** Transmit response PDU processing. ***/ @@ -362,10 +324,6 @@ bool_t lctrMstInitiateExtAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf) { /* Require peer match. */ } - else if (!pCtx->data.init.connBodLoaded) - { - BbSetBodTerminateFlag(); - } else if (pScan->pTxReqBuf) { /* Update connection indication header with advertiser's address. */ @@ -427,46 +385,37 @@ bool_t lctrMstInitiateExtAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf) lctrPackAdvbPduHdr(pScan->pTxReqBuf, &pCtx->reqPduHdr); /* Update txWinOffset field in CONN_IND PDU. */ - uint32_t txWinOffsetUsec = BB_TICKS_TO_US(pCtx->data.init.firstCeDue - advEndTs) - LL_BLE_TIFS_US - - SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, pScan->advRxPhyOptions, LL_ADV_HDR_LEN + LL_CONN_IND_PDU_LEN); /* Assume conn_ind uses the same PHY as adv_ind. */ - uint16_t txWinOffset = LCTR_US_TO_CONN_IND(txWinOffsetUsec) - LCTR_DATA_CHAN_DLY; + refTime += LL_BLE_TIFS_US; + refTime += LCTR_CONN_IND_PKT_1M_US; + refTime += LCTR_CONN_IND_US(LCTR_DATA_CHAN_DLY); + + /* Now reference time is the start of transmitWindowOffset. */ + uint32_t txWinOffsetUsec = SchRmGetOffsetUsec(LCTR_CONN_IND_US(pCtx->data.init.connInterval), LCTR_GET_CONN_HANDLE(pConnCtx), refTime); + uint16_t txWinOffset = LCTR_US_TO_CONN_IND(txWinOffsetUsec); + UINT16_TO_BUF(pScan->pTxReqBuf + LCTR_CONN_IND_TX_WIN_OFFSET, txWinOffset); pCtx->data.init.connInd.txWinOffset = txWinOffset; - if (txWinOffsetUsec < LCTR_CONN_IND_US(LCTR_DATA_CHAN_DLY)) - { - LL_TRACE_WARN1("AE too close to initial CE deltaUsec=%u, suppressed LL_CONN_IND delivery", BB_TICKS_TO_US(pCtx->data.init.firstCeDue - advEndTs)); + /*** Update due time of first CE. ***/ + pConnBod->dueUsec = refTime + txWinOffsetUsec; - /* Restart scanning with better initial CE margin. */ - BbSetBodTerminateFlag(); - } - else if (txWinOffset > pCtx->data.init.connInterval) - { - LL_TRACE_WARN1("Scan period exceeded initial CE time by deltaUsec=%u, suppressed LL_CONN_IND delivery", BB_TICKS_TO_US(advEndTs - pCtx->data.init.firstCeDue)); + txConnInd = TRUE; - /* Restart scanning with CE in the future. */ - BbSetBodTerminateFlag(); + /*** Received advertising PDU post-processing. ***/ + + if ((pCtx->reqPduHdr.chSel == LL_CH_SEL_2) && /* local initiator supports CS#2 */ + (pAdvBuf[0] & (1 << LCTR_ADV_HDR_CH_SEL_SHIFT))) /* peer advertiser supports CS#2 */ + { + pCtx->data.init.usedChSel = LL_CH_SEL_2; } else { - txConnInd = TRUE; - - /*** Received advertising PDU post-processing. ***/ - - if ((pCtx->reqPduHdr.chSel == LL_CH_SEL_2) && /* local initiator supports CS#2 */ - (pAdvBuf[0] & (1 << LCTR_ADV_HDR_CH_SEL_SHIFT))) /* peer advertiser supports CS#2 */ - { - pCtx->data.init.usedChSel = LL_CH_SEL_2; - } - else - { - pCtx->data.init.usedChSel = LL_CH_SEL_1; - } - - pCtx->data.init.phy = pBle->chan.txPhy; - - pCtx->data.init.isLegacy = TRUE; + pCtx->data.init.usedChSel = LL_CH_SEL_1; } + + pCtx->data.init.phy = pBle->chan.txPhy; + + pCtx->data.init.isLegacy = TRUE; } return txConnInd; @@ -515,8 +464,6 @@ bool_t lctrMstInitiateRxExtAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf * * \param pOp Originating operation. * \param pAdvBuf Received advertising buffer. - * - * \return None. */ /*************************************************************************************************/ void lctrMstInitiateRxExtAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf) @@ -551,7 +498,7 @@ void lctrMstInitiateRxExtAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t do { /* Confirm auxiliary PHY is supported. */ - bool_t auxPhy = lctrConvertAuxPtrPhyToBbPhy(auxPtr.auxPhy); + uint8_t auxPhy = lctrConvertAuxPtrPhyToBbPhy(auxPtr.auxPhy); if ((auxPhy == BB_PHY_BLE_2M) && ((lmgrCb.features & LL_FEAT_LE_2M_PHY) == 0)) { /* 2M PHY requested, but not supported. */ @@ -565,20 +512,9 @@ void lctrMstInitiateRxExtAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t pOp->minDurUsec = 0; /* Update primary scan BOD min duration so that secondary scan can be scheduled. */ - /* TODO */ - /* Because of scheduling conflict between preallocated connection bod and aux scan bod, */ - /* connection cannot be established with small connection interval(< 30ms) when coded phy is used. */ - lctrInitiateMsg_t *pInitMsg = (lctrInitiateMsg_t *)pLctrMsg; - if ((auxPhy == BB_PHY_BLE_CODED) && (LCTR_CONN_IND_US(pExtInitCtx->data.init.connInterval) < 30000)) - { - lctrScanNotifyHostInitiateError(LL_ERROR_CODE_CONN_FAILED_TO_ESTABLISH, pInitMsg->peerAddrType, pInitMsg->peerAddr); - lctrSendExtInitMsg(pExtInitCtx, LCTR_EXT_INIT_MSG_RESET); - break; - } - - uint32_t endTs = pScan->advStartTs + - BB_US_TO_BB_TICKS(SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, pScan->advRxPhyOptions, LL_ADV_HDR_LEN + pScan->filtResults.pduLen)); - lctrMstAuxDiscoverOpCommit(pExtInitCtx, &auxPtr, pScan->advStartTs, endTs); + uint32_t endTs = pScan->advStartTsUsec + + SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, pScan->advRxPhyOptions, LL_ADV_HDR_LEN + pScan->filtResults.pduLen); + lctrMstAuxDiscoverOpCommit(pExtInitCtx, &auxPtr, pScan->advStartTsUsec, endTs); if (pExtInitCtx->auxOpPending) { @@ -629,7 +565,7 @@ bool_t lctrMstInitiateRxAuxAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf /* AdvA is mandatory. */ if ((extAdvHdrFlags & LL_EXT_HDR_ADV_ADDR_BIT) == 0) { - LL_TRACE_WARN0("Ignoring LL_PDU_AUX_ADV_IND due to missing mandatory advA."); + LL_TRACE_WARN0("Ignoring LL_PDU_AUX_ADV_IND due to missing mandatory advA"); return FALSE; } @@ -645,7 +581,6 @@ bool_t lctrMstInitiateRxAuxAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf /* Go through the extended PDU filter. */ if (BbBleExtPduFiltCheck(¶ms, &pOp->prot.pBle->pduFilt, FALSE, &pAuxScan->filtResults) == FALSE) { - LL_TRACE_WARN0("Ignoring LL_PDU_AUX_ADV_IND due to PDU filtering."); return FALSE; } @@ -662,18 +597,16 @@ bool_t lctrMstInitiateRxAuxAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf { /* Require peer match. */ } - else if (!pExtInitCtx->data.init.connBodLoaded) - { - BbSetBodTerminateFlag(); - } else if (pAuxScan->pTxAuxReqBuf) { lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(pExtInitCtx->data.init.connHandle); + BbOpDesc_t * const pConnBod = &pCtx->connBod; - uint32_t connReqEndTs = pAuxScan->auxStartTs + - BB_US_TO_BB_TICKS(SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, pAuxScan->auxRxPhyOptions, LL_ADV_HDR_LEN + advHdr.len) + + uint32_t connReqEndTs = pAuxScan->auxStartTsUsec + + SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, pAuxScan->auxRxPhyOptions, LL_ADV_HDR_LEN + advHdr.len) + LL_BLE_TIFS_US + - SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, (pBle->chan.tifsTxPhyOptions != BB_PHY_OPTIONS_DEFAULT) ? pBle->chan.tifsTxPhyOptions : pAuxScan->auxRxPhyOptions, LL_ADV_HDR_LEN + LL_CONN_IND_PDU_LEN)); + SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, (pBle->chan.tifsTxPhyOptions != BB_PHY_OPTIONS_DEFAULT) ? pBle->chan.tifsTxPhyOptions : pAuxScan->auxRxPhyOptions, LL_ADV_HDR_LEN + LL_CONN_IND_PDU_LEN); + uint32_t refTime = connReqEndTs; /* Update auxiliary connection request header's advertiser address. */ uint8_t *pAuxConnReqAdvA = pAuxScan->pTxAuxReqBuf + LL_ADV_HDR_LEN + BDA_ADDR_LEN; @@ -743,45 +676,24 @@ bool_t lctrMstInitiateRxAuxAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf lctrPackAdvbPduHdr(pExtInitCtx->reqBuf, &pExtInitCtx->reqPduHdr); /* Update txWinOffset field in AUX_CONN_REQ PDU. */ - uint32_t txWinOffsetUsec = BB_TICKS_TO_US(pExtInitCtx->data.init.firstCeDue - connReqEndTs); + uint16_t chanDelay = (pBle->chan.rxPhy == BB_PHY_BLE_CODED) ? LCTR_DATA_CHAN_DLY_AUX_CODED : LCTR_DATA_CHAN_DLY_AUX_UNCODED; + refTime += LCTR_CONN_IND_US(chanDelay); + + /* Now reference time is the start of transmitWindowOffset. */ + uint32_t txWinOffsetUsec = SchRmGetOffsetUsec(LCTR_CONN_IND_US(pCtx->connInterval), LCTR_GET_CONN_HANDLE(pCtx), refTime); uint16_t txWinOffset = LCTR_US_TO_CONN_IND(txWinOffsetUsec); - uint16_t chanDelay; - switch (pBle->chan.rxPhy) - { - case BB_PHY_BLE_1M: - case BB_PHY_BLE_2M: - default: - chanDelay = LCTR_DATA_CHAN_DLY_AUX_UNCODED; - break; - case BB_PHY_BLE_CODED: - chanDelay = LCTR_DATA_CHAN_DLY_AUX_CODED; - break; - } - UINT16_TO_BUF(pExtInitCtx->reqBuf + LCTR_CONN_IND_TX_WIN_OFFSET, txWinOffset - chanDelay); - if (txWinOffsetUsec < LCTR_CONN_IND_US(chanDelay)) - { - LL_TRACE_WARN1("AE too close to initial CE deltaUsec=%u, suppressed LL_CONN_IND delivery", BB_TICKS_TO_US(pExtInitCtx->data.init.firstCeDue - connReqEndTs)); + UINT16_TO_BUF(pExtInitCtx->reqBuf + LCTR_CONN_IND_TX_WIN_OFFSET, txWinOffset); - /* Restart scanning with better initial CE margin. */ - BbSetBodTerminateFlag(); - } - else if (txWinOffset > pCtx->connInterval) - { - LL_TRACE_WARN1("Scan period exceeded initial CE time by deltaUsec=%u, suppressed LL_CONN_IND delivery", BB_TICKS_TO_US(connReqEndTs - pExtInitCtx->data.init.firstCeDue)); + /*** Update due time of first CE. ***/ + pConnBod->dueUsec = refTime + txWinOffsetUsec; - /* Restart scanning with CE in the future. */ - BbSetBodTerminateFlag(); - } - else - { - txConnInd = TRUE; + txConnInd = TRUE; - pExtInitCtx->data.init.usedChSel = LL_CH_SEL_2; /* LL_PDU_AUX_CONNECT_REQ always uses Channel Selection #2. */ - pExtInitCtx->data.init.phy = pBle->chan.txPhy; + pExtInitCtx->data.init.usedChSel = LL_CH_SEL_2; /* LL_PDU_AUX_CONNECT_REQ always uses Channel Selection #2. */ + pExtInitCtx->data.init.phy = pBle->chan.txPhy; - pExtInitCtx->data.init.isLegacy = FALSE; - } + pExtInitCtx->data.init.isLegacy = FALSE; } return txConnInd; @@ -822,7 +734,7 @@ bool_t lctrMstInitiateRxAuxConnRspHandler(BbOpDesc_t *pOp, const uint8_t *pRspBu if (((extAdvHdrFlags & LL_EXT_HDR_ADV_ADDR_BIT) == 0) || ((extAdvHdrFlags & LL_EXT_HDR_TGT_ADDR_BIT) == 0)) { - LL_TRACE_WARN0("LL_PDU_AUX_CONNECT_RSP missing mandatory advA and tgtA."); + LL_TRACE_WARN0("LL_PDU_AUX_CONNECT_RSP missing mandatory advA and tgtA"); } bbBlePduExtFiltParams_t params; @@ -836,7 +748,7 @@ bool_t lctrMstInitiateRxAuxConnRspHandler(BbOpDesc_t *pOp, const uint8_t *pRspBu if (BbBleExtPduFiltCheck(¶ms, &pOp->prot.pBle->pduFilt, TRUE, &pAuxScan->filtResults) == FALSE) { - LL_TRACE_WARN0("LL_PDU_AUX_CONNECT_RSP failed PDU filtering."); + LL_TRACE_WARN0("LL_PDU_AUX_CONNECT_RSP failed PDU filtering"); } if ((pExtInitCtx->extAdvHdr.advMode & (LCTR_ADV_MODE_SCAN_BIT | LCTR_ADV_MODE_CONN_BIT)) != 0) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main.c index 25de41a96c..563a2bc9bf 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Main link layer controller implementation file. + * \file + * + * \brief Main link layer controller implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -29,6 +30,12 @@ #include "wsf_assert.h" #include "wsf_trace.h" +/************************************************************************************************** + Constants +**************************************************************************************************/ + +#define LCTR_NUM_CH_CLASS_HANDLERS 4 /*!< Number of channel class handlers. */ + /************************************************************************************************** Globals **************************************************************************************************/ @@ -45,14 +52,18 @@ LctrEvtHdlr_t lctrEventHdlrTbl[LCTR_EVENT_TOTAL]; /*! \brief Event message which triggered the current execution context. */ lctrMsgHdr_t *pLctrMsg; +/*! \brief Channel class update handlers. */ +static lctrChClassHdlr_t lctrChClassHandlerTbl[LCTR_NUM_CH_CLASS_HANDLERS]; + +/*! \brief Channel class update handler count. */ +static uint8_t lctrChClassHandlerCnt; + /*! \brief Reset enabled. */ -static bool_t lctrResetEnabled = FALSE; +bool_t lctrResetEnabled = FALSE; /*************************************************************************************************/ /*! * \brief Notify host reset confirm. - * - * \return None. */ /*************************************************************************************************/ static void lctrNotifyHostResetCnf(void) @@ -71,8 +82,6 @@ static void lctrNotifyHostResetCnf(void) /*************************************************************************************************/ /*! * \brief Set the supporting state bitmask. - * - * \return None. */ /*************************************************************************************************/ void LctrSetSupStates(void) @@ -170,12 +179,6 @@ void LctrSetSupStates(void) LL_SUP_STATE_INIT_SLV; } } - - LL_TRACE_INFO1(" LCTR_DISP_CONN_IND = %c", lctrMsgDispTbl[LCTR_DISP_CONN_IND] ? 'Y' : 'N'); - LL_TRACE_INFO1(" LCTR_DISP_CONN = %c", lctrMsgDispTbl[LCTR_DISP_CONN] ? 'Y' : 'N'); - LL_TRACE_INFO1(" LCTR_DISP_SCAN = %c", lctrMsgDispTbl[LCTR_DISP_SCAN] ? 'Y' : 'N'); - LL_TRACE_INFO1(" LCTR_DISP_INIT = %c", lctrMsgDispTbl[LCTR_DISP_INIT] ? 'Y' : 'N'); - LL_TRACE_INFO1(" LCTR_DISP_ADV = %c", lctrMsgDispTbl[LCTR_DISP_ADV] ? 'Y' : 'N'); } /*************************************************************************************************/ @@ -183,8 +186,6 @@ void LctrSetSupStates(void) * \brief Link layer controller message dispatch handler. * * \param pMsg WSF message. - * - * \return None. */ /*************************************************************************************************/ void LctrMsgDispatcher(lctrMsgHdr_t *pMsg) @@ -250,8 +251,6 @@ void LctrMsgDispatcher(lctrMsgHdr_t *pMsg) * \brief Link layer controller task event handler. * * \param event Event id. - * - * \return None. */ /*************************************************************************************************/ void LctrEventHandler(uint8_t event) @@ -269,8 +268,6 @@ void LctrEventHandler(uint8_t event) * \brief Notify host HW error indication. * * \param code Error code. - * - * \return None. */ /*************************************************************************************************/ void lctrNotifyHostHwErrInd(uint8_t code) @@ -320,3 +317,137 @@ uint32_t lctrCalcWindowWideningUsec(uint32_t unsyncTimeUsec, uint32_t caPpm) return 0; } } + +/*************************************************************************************************/ +/*! + * \brief Compute new access address. + * + * \return New access address value. + */ +/*************************************************************************************************/ +uint32_t lctrComputeAccessAddr(void) +{ + uint32_t accessAddr = LlMathRandNum(); + + /* + * The following code enforces a pattern to make sure the address meets all requirements + * (including requirements for the LE coded PHY). The pattern is + * + * 0byyyyyy1x 0xxxx1x0 xxxx1x0x xx11x0x1 + * + * with 2^5 choices for the upper six bits. This provides 2^5 * 2^16 = 2097152 variations. + */ + + /* Patterns for upper six bits. The lower row contains complemented values of the upper row. */ + static const uint8_t upperSixBits[] = + { + /* 000010 000100 000101 000110 001000 001100 001101 001110 010000 010001 010011 010111 010110 011000 011100 011110 */ + 0x08, 0x10, 0x14, 0x18, 0x20, 0x30, 0x34, 0x38, 0x40, 0x44, 0x4C, 0x5C, 0x58, 0x60, 0x70, 0x78, + /* 111101 111011 111010 111001 110111 110011 110010 110001 101111 101110 101100 101000 101001 100111 100011 100001 */ + 0xF4, 0xEC, 0xE8, 0xE4, 0xDC, 0xCC, 0xC8, 0xC4, 0xBC, 0xB8, 0xB0, 0xA0, 0xA4, 0x9C, 0x8C, 0x84 + }; + + /* Set the upper six bits. */ + accessAddr = (accessAddr & ~0xFC000000) | (upperSixBits[accessAddr >> 27] << 24); + + /* Set ones with the mask 0b00000010 00000100 00001000 00110001 */ + accessAddr |= 0x02040831; + + /* Clear zeros with the mask 0b00000000 10000001 00000010 00000100 */ + accessAddr &= ~0x00810204; + + return accessAddr; +} + +/*************************************************************************************************/ +/*! + * \brief Compute new seed access address. + * + * \return New seed access address value. + */ +/*************************************************************************************************/ +uint32_t lctrComputeSeedAccessAddr(void) +{ + uint32_t accessAddr = LlMathRandNum(); + + /* + * The following code enforces a pattern to make sure the address meets all requirements. + * The pattern is either the first one or the second one + * + * 0bxxxxxx0x 1yyyyyyy yxxxxxxx xxxxxxxx + * + * with 2^5 choices for the middle 8 bits(indicated by y). This provides 2^5 * 2^ (21 - 4(z)) = 2 ^ 22 = 4194304 variations. + * Z depends LL_MAX_BIS, 6 BISs require 4 bits or 16 combination to assure at least two bits are different. + */ + + /* Patterns for middle 8 bits with 32 combinations. The upper one follows the 1yy0yy10 and lower one follows the 0yy1yy01 */ + static const uint8_t upperSixBits[] = + { + /* 10000010 10000110 10001010 10001110 10100010 10100110 10101010 10101110 11000010 11000110 11001010 11001110 11100010 11100110 11101010 11101110 */ + 0x82, 0x86, 0x8A, 0x8E, 0xA2, 0xA6, 0xAA, 0xAE, 0xC2, 0xC6, 0xCA, 0xCE, 0xE2, 0xE6, 0xEA, 0xEE, + /* 00010001 00010101 00011001 00011101 00110001 00110101 00111001 00111101 01010001 01010101 01011001 01011101 01110001 01110101 01111001 01111101 */ + 0x11, 0x15, 0x19, 0x1D, 0x31, 0x35, 0x39, 0x3D, 0x51, 0x55, 0x59, 0x5D, 0x71, 0x75, 0x79, 0x7D, + }; + + /* Set the middle 8 bits. */ + accessAddr = (accessAddr & ~0x007F8000) | (upperSixBits[accessAddr >> 27] << 15); + + /* Set ones with the mask 0b00000000 10000000 00000000 00000000 */ + accessAddr |= 0x00800000; + + /* Clear zeros with the mask 0b00000010 00000000 00000000 00000000 */ + accessAddr &= ~0x02000000; + + /* TODO add code to make sure two BIG seedAccessAddress in the same device shall differ in at least two bits. */ + + return accessAddr; +} + +/*************************************************************************************************/ +/*! + * \brief Register channel class handler + * + * \param cback Callback function to register. + */ +/*************************************************************************************************/ +void lctrRegisterChClassHandler(lctrChClassHdlr_t cback) +{ + /* Ensure registration does not exceed limits. */ + WSF_ASSERT(lctrChClassHandlerCnt < LCTR_NUM_CH_CLASS_HANDLERS); + lctrChClassHandlerTbl[lctrChClassHandlerCnt++] = cback; +} + +/*************************************************************************************************/ +/*! + * \brief Set channel class. + * + * \param chanMap Channel map (0=bad, 1=usable). + * + * \return Status error code. + * + * Set the channel class. At least 2 bits must be set. + */ +/*************************************************************************************************/ +uint8_t LctrSetChannelClass(uint64_t chanMap) +{ + uint8_t result = LL_SUCCESS; + + lmgrCb.chanClass = chanMap; + + for (unsigned int i = 0; i < lctrChClassHandlerCnt; i++) + { + WSF_ASSERT(lctrChClassHandlerTbl[i]); + + /* Return first error. */ + if (result == LL_SUCCESS) + { + result = lctrChClassHandlerTbl[i](chanMap); + } + else + { + lctrChClassHandlerTbl[i](chanMap); + } + } + + return result; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_master.c index a3b6092836..8cd90fe3ce 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master scanning operation builder implementation file. + * \file + * + * \brief Link layer controller master scanning operation builder implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -45,8 +46,6 @@ lctrMstScanCtx_t lctrMstScan; /*************************************************************************************************/ /*! * \brief Master scan reset handler. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstScanResetHandler(void) @@ -61,8 +60,6 @@ static void lctrMstScanResetHandler(void) * \brief Master scan message dispatcher. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstScanDisp(lctrMsgHdr_t *pMsg) @@ -75,8 +72,6 @@ static void lctrMstScanDisp(lctrMsgHdr_t *pMsg) * \brief Advertising report notification. * * \param pRpt Advertising report. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstScanAdvRptNotify(LlAdvReportInd_t *pRpt) @@ -112,7 +107,7 @@ static void lctrMstScanAdvRptNotify(LlAdvReportInd_t *pRpt) * \param pRpt Advertising report indication. * \param pLocalMatch Checks if the received ADV packet matches with local address. * - * \return None. + * \return TRUE if report generated, FALSE if not. */ /*************************************************************************************************/ static bool_t lctrMstCreateAdvRpt(uint8_t *pAdvBuf, LlAdvReportInd_t *pRpt, bool_t *pLocalMatch) @@ -193,8 +188,6 @@ static bool_t lctrMstCreateAdvRpt(uint8_t *pAdvBuf, LlAdvReportInd_t *pRpt, bool /*************************************************************************************************/ /*! * \brief ADVB packet post-processing. - * - * \return None. */ /*************************************************************************************************/ void lctrMstRxAdvBPduHandler(void) @@ -222,8 +215,6 @@ void lctrMstRxAdvBPduHandler(void) /*************************************************************************************************/ /*! * \brief Direct ADVB packet post-processing. - * - * \return None. */ /*************************************************************************************************/ void lctrMstRxDirectAdvBPduHandler(void) @@ -262,8 +253,6 @@ void lctrMstRxDirectAdvBPduHandler(void) /*************************************************************************************************/ /*! * \brief Build scan discovery operation. - * - * \return None. */ /*************************************************************************************************/ void lctrMstDiscoverBuildOp(void) @@ -333,7 +322,7 @@ void lctrMstDiscoverBuildOp(void) { /* Attempt to obtain buffer on next advertising operation. */ LL_TRACE_ERR0("Could not allocate advertising buffer"); - // TODO need OOM recovery + /* TODO need OOM recovery */ WSF_ASSERT(FALSE); } @@ -345,7 +334,7 @@ void lctrMstDiscoverBuildOp(void) { /* Attempt to obtain buffer on next advertising operation. */ LL_TRACE_ERR0("Could not allocate advertising buffer"); - // TODO need OOM recovery + /* TODO need OOM recovery */ WSF_ASSERT(FALSE); } @@ -425,7 +414,7 @@ void lctrMstDiscoverBuildOp(void) lctrMstScan.shutdown = FALSE; SchInsertNextAvailable(pOp); - lctrMstScan.scanWinStart = pOp->due; + lctrMstScan.scanWinStartUsec = pOp->dueUsec; } @@ -434,8 +423,6 @@ void lctrMstDiscoverBuildOp(void) * \brief Cleanup resources on advertising operation termination. * * \param pCtx Scan context. - * - * \return None. */ /*************************************************************************************************/ void lctrMstScanCleanupOp(lctrMstScanCtx_t *pCtx) @@ -523,8 +510,6 @@ uint8_t lctrScanChanSelectNext(uint8_t chanIdx, uint8_t chanMap) * \param reason Status code. * \param peerAddrType Peer address type. * \param peerAddr Peer address. - * - * \return None. */ /*************************************************************************************************/ void lctrScanNotifyHostInitiateError(uint8_t reason, uint8_t peerAddrType, uint64_t peerAddr) @@ -555,8 +540,6 @@ void lctrScanNotifyHostInitiateError(uint8_t reason, uint8_t peerAddrType, uint6 * * \param pAdvFilt Advertising report filter data. * \param filtEna Enable advertising report filtering. - * - * \return None. */ /*************************************************************************************************/ void lctrAdvRptEnable(lctrAdvRptFilt_t *pAdvFilt, bool_t filtEna) @@ -688,8 +671,6 @@ bool_t lctrAdvRptCheckDuplicate(lctrAdvRptFilt_t *pAdvFilt, uint64_t hash) * * \param pAdvFilt Advertising report filter data. * \param hash Advertising report hash. - * - * \return None. */ /*************************************************************************************************/ void lctrAdvRptAddEntry(lctrAdvRptFilt_t *pAdvFilt, uint64_t hash) @@ -719,8 +700,6 @@ void lctrAdvRptAddEntry(lctrAdvRptFilt_t *pAdvFilt, uint64_t hash) /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for scanning master. - * - * \return None. */ /*************************************************************************************************/ void LctrMstScanInit(void) @@ -747,8 +726,6 @@ void LctrMstScanInit(void) /*************************************************************************************************/ /*! * \brief Set default values for scanning master. - * - * \return None. */ /*************************************************************************************************/ void LctrMstScanDefaults(void) @@ -759,8 +736,6 @@ void LctrMstScanDefaults(void) /*************************************************************************************************/ /*! * \brief Increment number of pending advertising reports. - * - * \return None. */ /*************************************************************************************************/ void lctrAdvReportsInc(void) @@ -777,8 +752,6 @@ void lctrAdvReportsInc(void) /*************************************************************************************************/ /*! * \brief Decrement number of pending advertising reports. - * - * \return None. */ /*************************************************************************************************/ void lctrAdvReportsDec(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_master_ae.c index ed92d2cee8..40f45ba3bb 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master scanning operation builder implementation file. + * \file + * + * \brief Link layer controller master scanning operation builder implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -25,6 +26,7 @@ #include "lctr_int_adv_master.h" #include "lctr_api_adv_master_ae.h" #include "lmgr_api_adv_master_ae.h" +#include "lctr_int_conn_master.h" #include "sch_api.h" #include "sch_api_ble.h" #include "bb_ble_api_reslist.h" @@ -32,19 +34,27 @@ #include "wsf_msg.h" #include "wsf_trace.h" #include "wsf_math.h" +#include "wsf_buf.h" #include "util/bstream.h" - -// TODO Hide in conn only file -#include "lctr_int_conn_master.h" - #include /************************************************************************************************** Globals **************************************************************************************************/ +/*! \brief Extended scan context for 1m */ +lctrExtScanCtx_t lctrMstExtScanOneMCtx; + +/*! \brief Extended scan context for coded */ +lctrExtScanCtx_t lctrMstExtScanCodedCtx; + /*! \brief Extended scan operational context. */ -lctrExtScanCtx_t lctrMstExtScanTbl[LCTR_SCAN_PHY_TOTAL]; // TODO: share memory with legacy lctrMstScan +lctrExtScanCtx_t * lctrMstExtScanTbl[LCTR_SCAN_PHY_TOTAL] = + { + &lctrMstExtScanOneMCtx, + NULL, /* 2M does not have extended scanning functionality. */ + &lctrMstExtScanCodedCtx /* TODO: share memory with legacy lctrMstScan */ + }; /*! \brief Extended scan control block. */ lctrExtScanCtrlBlk_t lctrMstExtScan; @@ -70,13 +80,14 @@ static uint8_t *lctrMstPerScanDataBufTbl[LL_MAX_PER_SCAN]; /*! \brief SyncInfo for periodic sync transfer. */ lctrSyncInfo_t trsfSyncInfo; +/*! \brief Active extended scan contexts. */ +lctrActiveExtScan_t lctrActiveExtScan; + /*************************************************************************************************/ /*! * \brief Master create sync message dispatcher. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstCreateSyncDisp(LctrPerScanMsg_t *pMsg) @@ -91,8 +102,6 @@ static void lctrMstCreateSyncDisp(LctrPerScanMsg_t *pMsg) * \brief Periodic sync transfer recipient message dispatcher. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstTransferSyncDisp(LctrPerScanMsg_t *pMsg) @@ -107,8 +116,6 @@ static void lctrMstTransferSyncDisp(LctrPerScanMsg_t *pMsg) * \brief Periodic scanning message dispatcher. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstPerScanDisp(LctrPerScanMsg_t *pMsg) @@ -135,8 +142,6 @@ static void lctrMstPerScanDisp(LctrPerScanMsg_t *pMsg) /*************************************************************************************************/ /*! * \brief Periodic scanning reset handler. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstPerScanResetHandler(void) @@ -147,8 +152,6 @@ static void lctrMstPerScanResetHandler(void) /*************************************************************************************************/ /*! * \brief Master extended scan reset handler. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstExtScanResetHandler(void) @@ -163,8 +166,6 @@ static void lctrMstExtScanResetHandler(void) * \brief Execute common master scan state machine. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstExtScanExecuteCommonSm(LctrExtScanMsg_t *pMsg) @@ -175,7 +176,7 @@ static void lctrMstExtScanExecuteCommonSm(LctrExtScanMsg_t *pMsg) case LCTR_EXT_SCAN_MSG_DISCOVER_ENABLE: LL_TRACE_INFO2("lctrMstExtScanExecuteCommonSm: numScanEnabled=%u, scanMode=%u, event=DISCOVER_ENABLE", lmgrCb.numScanEnabled, lmgrCb.scanMode); - lctrMstExtScan.scanTermByHost = FALSE; + lctrMstExtScan.scanTermByHost = 0; /* Enable filter. */ lctrMstExtScan.filtDup = pMsg->enable.filtDup; @@ -249,8 +250,6 @@ static void lctrMstExtScanExecuteCommonSm(LctrExtScanMsg_t *pMsg) * \brief Master extended scan message dispatcher. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstExtScanDisp(LctrExtScanMsg_t *pMsg) @@ -270,7 +269,7 @@ static void lctrMstExtScanDisp(LctrExtScanMsg_t *pMsg) switch (event) { case LCTR_EXT_SCAN_MSG_DISCOVER_DISABLE: - lctrMstExtScan.scanTermByHost = TRUE; + lctrMstExtScan.scanTermByHost++; break; default: break; @@ -310,7 +309,7 @@ static void lctrMstExtScanDisp(LctrExtScanMsg_t *pMsg) WSF_ASSERT(pMsg->hdr.handle < LCTR_SCAN_PHY_TOTAL); if (lctrMstExtScan.enaPhys & (1 << pMsg->hdr.handle)) { - pExtScanCtx = &lctrMstExtScanTbl[pMsg->hdr.handle]; + pExtScanCtx = LCTR_GET_EXT_SCAN_CTX(pMsg->hdr.handle); lctrMstExtScanExecuteSm(pExtScanCtx, event); } } @@ -320,7 +319,7 @@ static void lctrMstExtScanDisp(LctrExtScanMsg_t *pMsg) { if (lctrMstExtScan.enaPhys & (1 << i)) { - pExtScanCtx = &lctrMstExtScanTbl[i]; + pExtScanCtx = LCTR_GET_EXT_SCAN_CTX(i); lctrMstExtScanExecuteSm(pExtScanCtx, event); } } @@ -332,8 +331,6 @@ static void lctrMstExtScanDisp(LctrExtScanMsg_t *pMsg) /*************************************************************************************************/ /*! * \brief Send pending extended advertising report. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstSendPendingAdvRptHandler(void) @@ -343,7 +340,13 @@ static void lctrMstSendPendingAdvRptHandler(void) /* Extended advertising report. */ for (unsigned int i = 0; i < LCTR_SCAN_PHY_TOTAL; i++) { - lctrExtScanCtx_t *pExtScanCtx = &lctrMstExtScanTbl[i]; + if (!(lctrActiveExtScan.scanMask & (1 << i))) + { + continue; + } + + lctrExtScanCtx_t *pExtScanCtx = LCTR_GET_EXT_SCAN_CTX(i); + if (pExtScanCtx->data.scan.auxAdvRptState == LCTR_RPT_STATE_COMP) { @@ -381,6 +384,33 @@ static void lctrMstSendPendingAdvRptHandler(void) } } +/*************************************************************************************************/ +/*! + * \brief Get reference time(due time) of the periodic scan. + * + * \param tmHandle Handle from Topology manager. + * + * \return Due time in microseconds of the periodic scan. + */ +/*************************************************************************************************/ +static uint32_t lctrGetPerScanRefTime(uint8_t tmHandle) +{ + uint32_t refTime = 0; + + WSF_ASSERT(tmHandle >= LL_MAX_CONN); + + lctrPerScanCtx_t *pPerScanCtx = LCTR_GET_PER_SCAN_CTX(tmHandle - LL_MAX_CONN); + BbOpDesc_t * const pOp = &pPerScanCtx->bod; + BbBleData_t * const pBle = &pPerScanCtx->bleData; + + if (pPerScanCtx->enabled && (pBle->chan.opType == BB_BLE_OP_MST_PER_SCAN_EVENT)) + { + refTime = pOp->dueUsec; + } + + return refTime; +} + /*************************************************************************************************/ /*! * \brief Build extended scan discovery operation. @@ -405,7 +435,7 @@ uint8_t lctrMstExtDiscoverBuildOp(lctrExtScanCtx_t *pExtScanCtx) pOp->protId = BB_PROT_BLE; pOp->prot.pBle = pBle; pOp->endCback = lctrMstExtDiscoverEndOp; - pOp->abortCback = lctrMstExtDiscoverEndOp; + pOp->abortCback = lctrMstExtDiscoverAbortOp; pOp->pCtx = pExtScanCtx; /*** BLE General Setup ***/ @@ -551,21 +581,31 @@ uint8_t lctrMstExtDiscoverBuildOp(lctrExtScanCtx_t *pExtScanCtx) } /*** Commit operation ***/ + + pOp->minDurUsec = LCTR_MIN_SCAN_USEC; pOp->maxDurUsec = LCTR_BLE_TO_US(pExtScanCtx->scanParam.scanWindow); - if (lmgrCb.numExtScanPhys == 1) - { - pOp->minDurUsec = LCTR_MIN_SCAN_USEC; - } - else - { - pOp->minDurUsec = pOp->maxDurUsec - BB_SCH_SETUP_DELAY_US; - } pExtScanCtx->selfTerm = FALSE; pExtScanCtx->shutdown = FALSE; - SchInsertNextAvailable(pOp); - pExtScanCtx->scanWinStart = pOp->due; + uint8_t scanPhyIndex = (LCTR_GET_EXT_SCAN_HANDLE(pExtScanCtx) == LCTR_SCAN_PHY_CODED) ? LCTR_SCAN_PHY_CODED : LCTR_SCAN_PHY_1M; + + /* The first scan context is scheduled immediately. */ + /* Otherwise, it will be scheduled from the scheduler end callback. */ + if (lctrActiveExtScan.scanMask == 0) + { + SchInsertNextAvailable(pOp); + pExtScanCtx->scanWinStartUsec = pOp->dueUsec; + + lctrActiveExtScan.scanIndex = scanPhyIndex; + lctrActiveExtScan.bodSchMask |= (1 << scanPhyIndex); + } + else + { + lctrActiveExtScan.bodSchMask &= ~(1 << scanPhyIndex); + } + + lctrActiveExtScan.scanMask |= (1 << scanPhyIndex); return LL_SUCCESS; } @@ -630,6 +670,7 @@ uint8_t lctrMstAuxDiscoverBuildOp(lctrExtScanCtx_t *pExtScanCtx) } /*** BLE Scan Setup: Rx packets ***/ + pAuxScan->isInit = FALSE; pAuxScan->rxAuxAdvCback = lctrMstDiscoverRxAuxAdvPktHandler; @@ -710,8 +751,6 @@ uint8_t lctrMstAuxDiscoverBuildOp(lctrExtScanCtx_t *pExtScanCtx) * \param pAuxPtr Auxiliary Pointer. * \param startTs Start of ADV_EXT_IND packet (offset origin). * \param endTs End of ADV_EXT_IND packet. - * - * \return None. */ /*************************************************************************************************/ void lctrMstAuxDiscoverOpCommit(lctrExtScanCtx_t *pExtScanCtx, lctrAuxPtr_t *pAuxPtr, uint32_t startTs, uint32_t endTs) @@ -738,10 +777,10 @@ void lctrMstAuxDiscoverOpCommit(lctrExtScanCtx_t *pExtScanCtx, lctrAuxPtr_t *pAu if (auxOffsetUsec < LL_BLE_MAFS_US) { - LL_TRACE_WARN1("Peer requested AUX offset does not meet T_MAFS, actual afsUsec=%u", BB_US_TO_BB_TICKS(pOp->due - endTs)); + LL_TRACE_WARN1("Peer requested AUX offset does not meet T_MAFS, actual afsUsec=%u", pOp->dueUsec - endTs); } - pOp->due = startTs + BB_US_TO_BB_TICKS(auxOffsetUsec); + pOp->dueUsec = startTs + auxOffsetUsec; SchBleCalcAdvOpDuration(pOp, 0); if (SchInsertAtDueTime(pOp, NULL)) @@ -754,12 +793,9 @@ void lctrMstAuxDiscoverOpCommit(lctrExtScanCtx_t *pExtScanCtx, lctrAuxPtr_t *pAu } } - /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for scanning master. - * - * \return None. */ /*************************************************************************************************/ void LctrMstExtScanInit(void) @@ -779,14 +815,11 @@ void LctrMstExtScanInit(void) LctrMstExtScanDefaults(); lmgrPersistCb.extScanCtxSize = sizeof(lctrExtScanCtx_t); - } /*************************************************************************************************/ /*! * \brief Set default values for scanning master. - * - * \return None. */ /*************************************************************************************************/ void LctrMstExtScanDefaults(void) @@ -800,19 +833,23 @@ void LctrMstExtScanDefaults(void) .scanFiltPolicy = LL_SCAN_FILTER_NONE }; - memset(&lctrMstExtScanTbl, 0, sizeof(lctrMstExtScanTbl)); memset(&lctrMstExtScan, 0, sizeof(lctrMstExtScan)); - lmgrCb.numExtScanPhys = 1; - lctrMstExtScanTbl[LCTR_SCAN_PHY_1M].scanParam = defScanParam; - lctrMstExtScan.enaPhys = 1 << LCTR_SCAN_PHY_1M; - /* Assign buffers. */ for (unsigned int i = 0; i < LCTR_SCAN_PHY_TOTAL; i++) { - lctrMstExtScanTbl[i].pExtAdvData = lctrMstExtScanDataBufTbl[i]; + if (lctrMstExtScanTbl[i]) + { + memset(lctrMstExtScanTbl[i], 0, sizeof(lctrExtScanCtx_t)); + lctrMstExtScanTbl[i]->handle = i; + lctrMstExtScanTbl[i]->pExtAdvData = lctrMstExtScanDataBufTbl[i]; + } } + lmgrCb.numExtScanPhys = 1; + lctrMstExtScanTbl[LCTR_SCAN_PHY_1M]->scanParam = defScanParam; + lctrMstExtScan.enaPhys = 1 << LCTR_SCAN_PHY_1M; + /* Setup timers. */ lctrMsgHdr_t *pMsg; lctrMstExtScan.tmrScanDur.handlerId = lmgrPersistCb.handlerId; @@ -825,6 +862,8 @@ void LctrMstExtScanDefaults(void) /* pMsg->handle = 0; */ /* Unused. */ pMsg->dispId = LCTR_DISP_EXT_SCAN; pMsg->event = LCTR_EXT_SCAN_MSG_TMR_PER_EXP; + + lctrActiveExtScan.scanMask = 0; } /*************************************************************************************************/ @@ -896,9 +935,9 @@ bool_t LctrMstExtScanValidateParam(void) { if (lctrMstExtScan.enaPhys & (1 << i)) { - if (!LmgrIsAddressTypeAvailable(lctrMstExtScanTbl[i].scanParam.ownAddrType)) + if (!LmgrIsAddressTypeAvailable(lctrMstExtScanTbl[i]->scanParam.ownAddrType)) { - LL_TRACE_WARN1("Address type invalid or not available, ownAddrType=%u", lctrMstExtScanTbl[i].scanParam.ownAddrType); + LL_TRACE_WARN1("Address type invalid or not available, ownAddrType=%u", lctrMstExtScanTbl[i]->scanParam.ownAddrType); return FALSE; } } @@ -913,8 +952,6 @@ bool_t LctrMstExtScanValidateParam(void) * \brief Set enabled scanning PHY. * * \param scanPhy Enabled scanning PHY. - * - * \return None. */ /*************************************************************************************************/ void LctrMstExtScanSetScanPhy(uint8_t scanPhy) @@ -929,8 +966,6 @@ void LctrMstExtScanSetScanPhy(uint8_t scanPhy) * \brief Clear (disable) scanning PHY. * * \param scanPhy Disabled scanning PHY. - * - * \return None. */ /*************************************************************************************************/ void LctrMstExtScanClearScanPhy(uint8_t scanPhy) @@ -948,19 +983,17 @@ void LctrMstExtScanClearScanPhy(uint8_t scanPhy) * \param ownAddrType Address type used by this device. * \param scanFiltPolicy Scan filter policy. * \param pParam Extended scanning parameters. - * - * \return None. */ /*************************************************************************************************/ void LctrMstExtScanSetParam(uint8_t scanPhy, uint8_t ownAddrType, uint8_t scanFiltPolicy, const LlExtScanParam_t *pParam) { WSF_ASSERT(scanPhy < LCTR_SCAN_PHY_TOTAL); - lctrMstExtScanTbl[scanPhy].scanParam.scanInterval = pParam->scanInterval; - lctrMstExtScanTbl[scanPhy].scanParam.scanWindow = pParam->scanWindow; - lctrMstExtScanTbl[scanPhy].scanParam.scanType = pParam->scanType; - lctrMstExtScanTbl[scanPhy].scanParam.ownAddrType = ownAddrType; - lctrMstExtScanTbl[scanPhy].scanParam.scanFiltPolicy = scanFiltPolicy; + lctrMstExtScanTbl[scanPhy]->scanParam.scanInterval = pParam->scanInterval; + lctrMstExtScanTbl[scanPhy]->scanParam.scanWindow = pParam->scanWindow; + lctrMstExtScanTbl[scanPhy]->scanParam.scanType = pParam->scanType; + lctrMstExtScanTbl[scanPhy]->scanParam.ownAddrType = ownAddrType; + lctrMstExtScanTbl[scanPhy]->scanParam.scanFiltPolicy = scanFiltPolicy; } /*************************************************************************************************/ @@ -974,22 +1007,7 @@ void LctrMstExtScanSetParam(uint8_t scanPhy, uint8_t ownAddrType, uint8_t scanFi /*************************************************************************************************/ bool_t LctrMstExtScanIsEnabled(uint8_t scanPhy) { - return (lctrMstExtScanTbl[scanPhy].state != LCTR_EXT_SCAN_STATE_DISABLED); -} - -/*************************************************************************************************/ -/*! - * \brief Check if ext scan is using private addresses. - * - * \param scanPhy Extended scanning PHY. - * - * \return True if scan is not disabled, false if not. - */ -/*************************************************************************************************/ -bool_t LctrMstExtScanIsPrivAddr(uint8_t scanPhy) -{ - /* Check the private address bit. */ - return (lctrMstExtScanTbl[scanPhy].scanParam.ownAddrType & LL_ADDR_RANDOM_BIT); + return (lctrMstExtScanTbl[scanPhy]->state != LCTR_EXT_SCAN_STATE_DISABLED); } /*************************************************************************************************/ @@ -998,8 +1016,6 @@ bool_t LctrMstExtScanIsPrivAddr(uint8_t scanPhy) * * \param pExtScanCtx Extended scan context. * \param event Extended scan event. - * - * \return None. */ /*************************************************************************************************/ void lctrSendExtScanMsg(lctrExtScanCtx_t *pExtScanCtx, uint8_t event) @@ -1022,8 +1038,6 @@ void lctrSendExtScanMsg(lctrExtScanCtx_t *pExtScanCtx, uint8_t event) * * \param pCtx Periodic scanning context. * \param event Periodic scan event. - * - * \return None. */ /*************************************************************************************************/ void lctrSendCreateSyncMsg(lctrPerScanCtx_t *pCtx, uint8_t event) @@ -1045,8 +1059,6 @@ void lctrSendCreateSyncMsg(lctrPerScanCtx_t *pCtx, uint8_t event) * * \param pCtx Periodic scanning context. * \param event Periodic advertising event. - * - * \return None. */ /*************************************************************************************************/ void lctrSendPerScanMsg(lctrPerScanCtx_t *pCtx, uint8_t event) @@ -1122,8 +1134,6 @@ bool_t LctrMstPerIsSync(uint8_t advSID, uint8_t advAddrType, uint64_t advAddr) /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for master create sync. - * - * \return None. */ /*************************************************************************************************/ void LctrMstPerCreateSyncInit(void) @@ -1134,6 +1144,8 @@ void LctrMstPerCreateSyncInit(void) /* Add create sync task message dispatchers. */ lctrMsgDispTbl[LCTR_DISP_PER_CREATE_SYNC] = (LctrMsgDisp_t)lctrMstCreateSyncDisp; + LctrMstPerSyncPending = LctrMstPerIsSyncPending; + /* Set supported features. */ if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_5_0) { @@ -1144,8 +1156,6 @@ void LctrMstPerCreateSyncInit(void) /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for periodic sync transfer recipient. - * - * \return None. */ /*************************************************************************************************/ void LctrMstPerTransferSyncInit(void) @@ -1166,8 +1176,6 @@ void LctrMstPerTransferSyncInit(void) /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for master periodic scanning. - * - * \return None. */ /*************************************************************************************************/ void LctrMstPerScanInit(void) @@ -1207,7 +1215,7 @@ uint8_t lctrMstPerScanBuildOp(lctrPerScanCtx_t *pPerScanCtx) /*** General Setup ***/ - pOp->reschPolicy = BB_RESCH_PERIODIC; + pOp->reschPolicy = BB_RESCH_FIXED; pOp->protId = BB_PROT_BLE; pOp->prot.pBle = pBle; pOp->endCback = lctrMstPerScanEndOp; @@ -1215,10 +1223,13 @@ uint8_t lctrMstPerScanBuildOp(lctrPerScanCtx_t *pPerScanCtx) pOp->pCtx = pPerScanCtx; /*** BLE General Setup ***/ + pBle->chan.opType = BB_BLE_OP_MST_PER_SCAN_EVENT; /*** BLE Scan Setup: Rx advertising packet ***/ + /*** BLE Scan Setup: Rx chain packet ***/ + pPerScan->rxPerAdvCback = lctrMstPerScanRxPerAdvPktHandler; pPerScan->rxPerAdvPostCback = lctrMstPerScanRxPerAdvPktPostHandler; @@ -1238,8 +1249,6 @@ uint8_t lctrMstPerScanBuildOp(lctrPerScanCtx_t *pPerScanCtx) * \param pSyncInfo Sync info. * \param startTs Start of AUX_ADV_IND packet (offset origin). * \param endTs End of AUX_ADV_IND packet. - * - * \return None. */ /*************************************************************************************************/ void lctrMstPerScanOpCommit(lctrExtScanCtx_t *pExtScanCtx, lctrAuxPtr_t *pAuxPtr, @@ -1268,7 +1277,6 @@ void lctrMstPerScanOpCommit(lctrExtScanCtx_t *pExtScanCtx, lctrAuxPtr_t *pAuxPtr pBle->chan.accAddr = pSyncInfo->accAddr; pBle->chan.crcInit = pSyncInfo->crcInit; - /* FIXME: Only if scan enabled */ pBle->chan.txPhy = pBle->chan.rxPhy = lctrConvertAuxPtrPhyToBbPhy(pAuxPtr->auxPhy); #if (LL_ENABLE_TESTER == TRUE) @@ -1279,27 +1287,27 @@ void lctrMstPerScanOpCommit(lctrExtScanCtx_t *pExtScanCtx, lctrAuxPtr_t *pAuxPtr #endif /*** Commit operation ***/ + uint32_t syncOffsetUsec; uint32_t offsetUsec = pSyncInfo->syncOffset * ((pSyncInfo->offsetUnits == LCTR_OFFS_UNITS_30_USEC) ? 30 : 300); offsetUsec += (LL_SYNC_OFFS_ADJUST_USEC * pSyncInfo->offsetAdjust); - pPerScanCtx->lastAnchorPoint = startTs + BB_US_TO_BB_TICKS(offsetUsec); + pPerScanCtx->lastAnchorPointUsec = startTs + offsetUsec; pPerScanCtx->lastActiveEvent = pPerScanCtx->eventCounter; uint32_t caPpm = lctrCalcTotalAccuracy(pSyncInfo->sca); uint32_t wwUsec = lctrCalcWindowWideningUsec(offsetUsec + ((pSyncInfo->offsetUnits == LCTR_OFFS_UNITS_30_USEC) ? 30 : 300), caPpm); syncOffsetUsec = offsetUsec - wwUsec; pPerScanCtx->rxSyncDelayUsec = pBle->op.mstPerScan.rxSyncDelayUsec = (wwUsec << 1) + ((pSyncInfo->offsetUnits == LCTR_OFFS_UNITS_30_USEC) ? 30 : 300); /* rounding compensation */ - int16_t dueOffsetUsec = (offsetUsec - wwUsec) - BB_TICKS_TO_US(BB_US_TO_BB_TICKS(offsetUsec) - BB_US_TO_BB_TICKS(wwUsec)); if (syncOffsetUsec < LL_BLE_MAFS_US) { - LL_TRACE_WARN1("Peer requested AuxPtr offset does not meet T_MAFS, actual afsUsec=%u", BB_US_TO_BB_TICKS(pOp->due - endTs)); + LL_TRACE_WARN1("Peer requested AuxPtr offset does not meet T_MAFS, actual afsUsec=%u", pOp->dueUsec - endTs); return; } - pOp->due = startTs + BB_US_TO_BB_TICKS(syncOffsetUsec); - pOp->dueOffsetUsec = WSF_MAX(dueOffsetUsec, 0); - SchBleCalcAdvOpDuration(pOp, 0); - pPerScanCtx->minDurUsec = pOp->minDurUsec; + 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); uint16_t numUnsyncIntervals = 0; while (TRUE) @@ -1308,9 +1316,10 @@ void lctrMstPerScanOpCommit(lctrExtScanCtx_t *pExtScanCtx, lctrAuxPtr_t *pAuxPtr { LL_TRACE_INFO1(" >>> Periodic scan started, handle=%u <<<", LCTR_GET_PER_SCAN_HANDLE(pPerScanCtx)); LL_TRACE_INFO1(" pOp=%08x", pOp); - LL_TRACE_INFO1(" due=%u", pOp->due); + LL_TRACE_INFO1(" dueUsec=%u", pOp->dueUsec); LL_TRACE_INFO1(" eventCounter=%u", pPerScanCtx->eventCounter); - LL_TRACE_INFO1(" pBle->chan.chanIdx=%u", pBle->chan.chanIdx); + LL_TRACE_INFO1(" chanIdx=%u", pBle->chan.chanIdx); + LL_TRACE_INFO1(" pBod=0x%08x", pOp); break; } @@ -1321,19 +1330,19 @@ void lctrMstPerScanOpCommit(lctrExtScanCtx_t *pExtScanCtx, lctrAuxPtr_t *pAuxPtr pBle->chan.chanIdx = lctrPeriodicSelectNextChannel(&pPerScanCtx->chanParam, pPerScanCtx->eventCounter); numUnsyncIntervals++; - uint32_t unsyncTimeUsec = BB_TICKS_TO_US(pPerScanCtx->perInter * numUnsyncIntervals); - uint32_t unsyncTime = BB_US_TO_BB_TICKS(unsyncTimeUsec); + uint32_t unsyncTimeUsec = pPerScanCtx->perInterUsec * numUnsyncIntervals; uint32_t wwTotalUsec = lctrCalcWindowWideningUsec(unsyncTimeUsec, caPpm); - uint32_t wwTotal = BB_US_TO_BB_TICKS(wwTotalUsec); - dueOffsetUsec = (unsyncTimeUsec - wwTotalUsec) - BB_TICKS_TO_US(unsyncTime - wwTotal); /* Advance to next interval. */ - pOp->due = pPerScanCtx->lastAnchorPoint + unsyncTime - wwTotal; - pOp->dueOffsetUsec = WSF_MAX(dueOffsetUsec, 0); + pOp->dueUsec = pPerScanCtx->lastAnchorPointUsec + unsyncTimeUsec - wwTotalUsec; + pOp->minDurUsec = pPerScanCtx->minDurUsec + wwTotalUsec; pBle->op.mstPerScan.rxSyncDelayUsec = pPerScanCtx->rxSyncDelayUsec + (wwTotalUsec << 1); } + /* Update topology manager information. */ + SchTmAdd(LCTR_GET_PER_SCAN_TM_HANDLE(pPerScanCtx), pPerScanCtx->perInterUsec, pPerScanCtx->minDurUsec, FALSE, lctrGetPerScanRefTime); + lctrPerCreateSync.createSyncPending = TRUE; } @@ -1342,9 +1351,6 @@ void lctrMstPerScanOpCommit(lctrExtScanCtx_t *pExtScanCtx, lctrAuxPtr_t *pAuxPtr * \brief Commit periodic sync transferred scan operation. * * \param connHandle Connection handle. - * \param ceCounter Reference connection event counter. - * - * \return None. */ /*************************************************************************************************/ void lctrMstPerScanTransferOpCommit(uint16_t connHandle) @@ -1397,25 +1403,25 @@ void lctrMstPerScanTransferOpCommit(uint16_t connHandle) /* Calculate reference time: ceRef + offset. */ refTime = lctrConnGetAnchorPoint(pConnCtx, lctrPerTransferSync.ceRef); - refTime += BB_US_TO_BB_TICKS(offsetUsec); + refTime += offsetUsec; /* refTime needs to be future from the next connection event. */ startTs = lctrConnGetAnchorPoint(pConnCtx, pConnCtx->eventCounter); peC = trsfSyncInfo.eventCounter; - if ((refTime - (startTs + BB_US_TO_BB_TICKS(pConnOp->minDurUsec))) < LCTR_SCH_MAX_SPAN) + if (BbGetTargetTimeDelta(refTime, startTs + pConnOp->minDurUsec) > 0) { - numInterval = (refTime - (startTs + BB_US_TO_BB_TICKS(pConnOp->minDurUsec))) / pPerScanCtx->perInter; - refTime -= numInterval * pPerScanCtx->perInter; + numInterval = BbGetTargetTimeDelta(refTime, startTs + pConnOp->minDurUsec) / pPerScanCtx->perInterUsec; + refTime -= numInterval * pPerScanCtx->perInterUsec; peC -= numInterval; - offsetUsec = BB_TICKS_TO_US(refTime - startTs); + offsetUsec = BbGetTargetTimeDelta(refTime , startTs); } else /* refTime is in the past. */ { - numInterval = 1 + ((startTs + BB_US_TO_BB_TICKS(pConnOp->minDurUsec)) - refTime) / pPerScanCtx->perInter; - refTime += numInterval * pPerScanCtx->perInter; + numInterval = 1 + BbGetTargetTimeDelta(startTs + pConnOp->minDurUsec, refTime)/ pPerScanCtx->perInterUsec; + refTime += numInterval * pPerScanCtx->perInterUsec; peC += numInterval; - offsetUsec = BB_TICKS_TO_US(refTime - startTs); + offsetUsec = BbGetTargetTimeDelta(refTime , startTs); } pPerScanCtx->eventCounter = peC; @@ -1430,7 +1436,7 @@ void lctrMstPerScanTransferOpCommit(uint16_t connHandle) /* Da = |PEc – PEb| × PAI × (CAa + CAc) */ uint32_t deltaPA = ((uint16_t)(peC - lctrPerTransferSync.lastPECounter) < LCTR_MAX_INSTANT) ? (uint16_t)(peC - lctrPerTransferSync.lastPECounter) : 0; - deltaPA *= BB_TICKS_TO_US(pPerScanCtx->perInter); + deltaPA *= pPerScanCtx->perInterUsec; uint32_t dA = lctrCalcWindowWideningUsec(deltaPA, (scaPpmA + scaPpmC)); /* Db = |CEt – CEs| × CI × (CAb + CAc) */ @@ -1443,12 +1449,11 @@ void lctrMstPerScanTransferOpCommit(uint16_t connHandle) LL_TRACE_WARN3("Periodic scan transfer WW=%u: Da=%u, Db=%u", wwUsec, dA, dB); - pPerScanCtx->lastAnchorPoint = startTs + BB_US_TO_BB_TICKS(offsetUsec); + pPerScanCtx->lastAnchorPointUsec = startTs + offsetUsec; pPerScanCtx->lastActiveEvent = pPerScanCtx->eventCounter; pPerScanCtx->initEventCounter = pPerScanCtx->eventCounter; - pOp->due = startTs + BB_US_TO_BB_TICKS(offsetUsec - wwUsec); - pOp->dueOffsetUsec = 0; + pOp->dueUsec = startTs + offsetUsec - wwUsec; SchBleCalcAdvOpDuration(pOp, 0); pPerScanCtx->minDurUsec = pOp->minDurUsec; uint16_t numUnsyncIntervals = 0; @@ -1459,9 +1464,10 @@ void lctrMstPerScanTransferOpCommit(uint16_t connHandle) { 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(" due=%u", pOp->due); + LL_TRACE_INFO1(" dueUsec=%u", pOp->dueUsec); LL_TRACE_INFO1(" eventCounter=%u", pPerScanCtx->eventCounter); LL_TRACE_INFO1(" pBle->chan.chanIdx=%u", pBle->chan.chanIdx); + LL_TRACE_INFO1(" pBod=0x%08x", pOp); break; } @@ -1471,16 +1477,19 @@ void lctrMstPerScanTransferOpCommit(uint16_t connHandle) pBle->chan.chanIdx = lctrPeriodicSelectNextChannel(&pPerScanCtx->chanParam, pPerScanCtx->eventCounter); numUnsyncIntervals++; - uint32_t unsyncTimeUsec = BB_TICKS_TO_US(pPerScanCtx->perInter * numUnsyncIntervals); + uint32_t unsyncTimeUsec = pPerScanCtx->perInterUsec * numUnsyncIntervals; dA = lctrCalcWindowWideningUsec((deltaPA + unsyncTimeUsec), (scaPpmA + scaPpmC)); wwUsec = 16 + lctrCalcWindowWideningUsec((dA + dB), (1 + scaPpmA + scaPpmB + scaPpmC)); /* Advance to next interval. */ - pOp->due = pPerScanCtx->lastAnchorPoint + BB_US_TO_BB_TICKS(unsyncTimeUsec - wwUsec); + pOp->dueUsec = pPerScanCtx->lastAnchorPointUsec + unsyncTimeUsec - wwUsec; pOp->minDurUsec = pPerScanCtx->minDurUsec + wwUsec; pBle->op.mstPerScan.rxSyncDelayUsec = pPerScanCtx->rxSyncDelayUsec + (wwUsec << 1); } + + /* Update topology manager information. */ + SchTmAdd(LCTR_GET_PER_SCAN_TM_HANDLE(pPerScanCtx), pPerScanCtx->perInterUsec, pPerScanCtx->minDurUsec, FALSE, lctrGetPerScanRefTime); } /*************************************************************************************************/ @@ -1539,7 +1548,7 @@ lctrPerScanCtx_t *lctrAllocPerScanCtx(void) { lctrPerScanCtx_t *pCtx = LCTR_GET_PER_SCAN_CTX(index); - memset(&lctrMstPerScanTbl[index], 0, sizeof(lctrPerScanCtx_t)); + memset(pCtx, 0, sizeof(lctrPerScanCtx_t)); pCtx->enabled = TRUE; @@ -1585,19 +1594,23 @@ BbOpDesc_t *lctrPerScanResolveConflict(BbOpDesc_t *pNewOp, BbOpDesc_t *pExistOp) /* Only BLE uses periodic scan. */ WSF_ASSERT((pNewOp->protId == BB_PROT_BLE) && (pExistOp->protId == BB_PROT_BLE)); - WSF_ASSERT((pNewOp->prot.pBle->chan.opType == BB_BLE_OP_MST_PER_SCAN_EVENT) && - (pExistOp->prot.pBle->chan.opType == BB_BLE_OP_MST_PER_SCAN_EVENT)); + WSF_ASSERT(pNewOp->prot.pBle->chan.opType == BB_BLE_OP_MST_PER_SCAN_EVENT); + + if (pExistOp->prot.pBle->chan.opType != BB_BLE_OP_MST_PER_SCAN_EVENT) + { + return 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)(BB_TICKS_TO_US(pExistCtx->perInter) << 1)); - LL_TRACE_WARN2("New timeout=%u, interval=%u", pNewCtx->tmrSupTimeout.ticks * WSF_MS_PER_TICK * 1000, (uint32_t)(BB_TICKS_TO_US(pExistCtx->perInter) << 1)); - if ((pExistCtx->tmrSupTimeout.ticks * WSF_MS_PER_TICK * 1000) < (uint32_t)(BB_TICKS_TO_US(pExistCtx->perInter) << 1)) + 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)); return pExistOp; } - if ((pNewCtx->tmrSupTimeout.ticks * WSF_MS_PER_TICK * 1000) < (uint32_t)(BB_TICKS_TO_US(pNewCtx->perInter) << 1)) + if ((pNewCtx->tmrSupTimeout.ticks * WSF_MS_PER_TICK * 1000) < (uint32_t)(pNewCtx->perInterUsec << 1)) { LL_TRACE_WARN2("!!! Scheduling conflict, imminent SVT: incoming handle=%u prioritized over existing handle=%u", LCTR_GET_PER_SCAN_HANDLE(pNewCtx), LCTR_GET_PER_SCAN_HANDLE(pExistCtx)); return pNewOp; @@ -1605,12 +1618,12 @@ BbOpDesc_t *lctrPerScanResolveConflict(BbOpDesc_t *pNewOp, BbOpDesc_t *pExistOp) /* Less frequent perInterval (4x). */ - if ((LCTR_PER_INTER_TO_MS(BB_TICKS_TO_US(pExistCtx->perInter)) >> 2) > LCTR_PER_INTER_TO_MS(BB_TICKS_TO_US(pNewCtx->perInter))) + 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)); return pExistOp; } - if ((LCTR_PER_INTER_TO_MS(BB_TICKS_TO_US(pNewCtx->perInter)) >> 2) > LCTR_PER_INTER_TO_MS(BB_TICKS_TO_US(pExistCtx->perInter))) + if ((LCTR_PER_INTER_TO_MS(pNewCtx->perInterUsec) >> 2) > LCTR_PER_INTER_TO_MS(pExistCtx->perInterUsec)) { LL_TRACE_WARN2("!!! Scheduling conflict, PI frequency: incoming handle=%u prioritized over existing handle=%u", LCTR_GET_PER_SCAN_HANDLE(pNewCtx), LCTR_GET_PER_SCAN_HANDLE(pExistCtx)); return pNewOp; @@ -1649,8 +1662,6 @@ uint64_t LctrGetPerScanChanMap(uint16_t handle) * * \param status Status. * \param pPerScanCtx Periodic scan context. - * - * \return None. */ /*************************************************************************************************/ void LctrSendPerSyncTrsfRcvdEvt(uint8_t status, lctrPerScanCtx_t *pPerScanCtx) @@ -1670,7 +1681,7 @@ void LctrSendPerSyncTrsfRcvdEvt(uint8_t status, lctrPerScanCtx_t *pPerScanCtx) .advSID = pPerScanCtx->advSID, .addrType = pPerScanCtx->advAddrType, .advPhy = pPerScanCtx->rxPhys, - .perAdvInterval = LCTR_PER_INTER_TO_MS(BB_TICKS_TO_US(pPerScanCtx->perInter)), + .perAdvInterval = LCTR_PER_INTER_TO_MS(pPerScanCtx->perInterUsec), .advClkAccuracy = pPerScanCtx->sca }; @@ -1688,8 +1699,6 @@ void LctrSendPerSyncTrsfRcvdEvt(uint8_t status, lctrPerScanCtx_t *pPerScanCtx) * * \param syncHandle Periodic sync handle. * \param enable Enable or disable reporting. - * - * \return None. */ /*************************************************************************************************/ void LctrMstPerSetRcvEnable(uint16_t syncHandle, bool_t enable) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_slave.c index 502a0cd391..4d3779c30c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave advertising operation builder implementation file. + * \file + * + * \brief Link layer controller slave advertising operation builder implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -52,8 +53,6 @@ WSF_CT_ASSERT((BB_FIXED_ADVB_PKT_LEN == 0) || /*************************************************************************************************/ /*! * \brief Slave advertising reset handler. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvAdvResetHandler(void) @@ -68,8 +67,6 @@ static void lctrSlvAdvResetHandler(void) * \brief Slave advertising message dispatcher. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvAdvDisp(LctrAdvMsg_t *pMsg) @@ -77,52 +74,9 @@ static void lctrSlvAdvDisp(LctrAdvMsg_t *pMsg) lctrSlvAdvExecuteSm(pMsg->hdr.event); } -/*************************************************************************************************/ -/*! - * \brief Compute new access address. - * - * \return New access address value. - */ -/*************************************************************************************************/ -uint32_t lctrComputeAccessAddr(void) -{ - uint32_t accessAddr = LlMathRandNum(); - - /* - * The following code enforces a pattern to make sure the address meets all requirements - * (including requirements for the LE coded PHY). The pattern is - * - * 0byyyyyy1x 0xxxx1x0 xxxx1x0x xx11x0x1 - * - * with 2^5 choices for the upper six bits. This provides 2^5 * 2^16 = 2097152 variations. - */ - - /* Patterns for upper six bits. The lower row contains complemented values of the upper row. */ - static const uint8_t upperSixBits[] = - { - /* 000010 000100 000101 000110 001000 001100 001101 001110 010000 010001 010011 010111 010110 011000 011100 011110 */ - 0x08, 0x10, 0x14, 0x18, 0x20, 0x30, 0x34, 0x38, 0x40, 0x44, 0x4C, 0x5C, 0x58, 0x60, 0x70, 0x78, - /* 111101 111011 111010 111001 110111 110011 110010 110001 101111 101110 101100 101000 101001 100111 100011 100001 */ - 0xF4, 0xEC, 0xE8, 0xE4, 0xDC, 0xCC, 0xC8, 0xC4, 0xBC, 0xB8, 0xB0, 0xA0, 0xA4, 0x9C, 0x8C, 0x84 - }; - - /* Set the upper six bits. */ - accessAddr = (accessAddr & ~0xFC000000) | (upperSixBits[accessAddr >> 27] << 24); - - /* Set ones with the mask 0b00000010 00000100 00001000 00110001 */ - accessAddr |= 0x02040831; - - /* Clear zeros with the mask 0b00000000 10000001 00000010 00000100 */ - accessAddr &= ~0x00810204; - - return accessAddr; -} - /*************************************************************************************************/ /*! * \brief Scan request post-processing. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvRxScanReq(void) @@ -167,8 +121,6 @@ void lctrSlvRxScanReq(void) * \param peerAddrType Peer address type. * \param peerAddr Peer address. * \param pAdvA Storage for AdvA. - * - * \return None. */ /*************************************************************************************************/ void lctrChooseAdvA(BbBleData_t * const pBle, lctrAdvbPduHdr_t *pPduHdr, @@ -233,8 +185,6 @@ void lctrChooseAdvA(BbBleData_t * const pBle, lctrAdvbPduHdr_t *pPduHdr, * \param peerAddrType Peer address type. * \param peerAddr Peer address. * \param pPeerRpa Storage for peer RPA. - * - * \return None. */ /*************************************************************************************************/ void lctrChoosePeerAddr(BbBleData_t * const pBle, uint8_t ownAddrType, @@ -255,8 +205,6 @@ void lctrChoosePeerAddr(BbBleData_t * const pBle, uint8_t ownAddrType, /*************************************************************************************************/ /*! * \brief Build advertising operation. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvAdvBuildOp(void) @@ -345,9 +293,9 @@ void lctrSlvAdvBuildOp(void) break; case LL_ADV_CONN_DIRECT_HIGH_DUTY: /* Advertising interval is determined by LL not host. */ - lmgrSlvAdvCb.advParam.advInterMin = 0; - lmgrSlvAdvCb.advParam.advInterMax = BB_BLE_TO_BB_TICKS(LL_DIR_ADV_INTER_TICKS); - lmgrSlvAdvCb.advTermCntDown = BB_BLE_TO_BB_TICKS(LL_DIR_ADV_DUR_TICKS); + lmgrSlvAdvCb.advParam.advInterMinUsec = 0; + lmgrSlvAdvCb.advParam.advInterMaxUsec = BB_BLE_TO_US(LL_DIR_ADV_INTER_TICKS); + lmgrSlvAdvCb.advTermCntDownUsec = BB_BLE_TO_US(LL_DIR_ADV_DUR_TICKS); pAdv->firstAdvChIdx = 0; /* High duty cycle always start from channel 37. */ /* Fallthrough */ case LL_ADV_CONN_DIRECT_LOW_DUTY: @@ -433,20 +381,13 @@ void lctrSlvAdvBuildOp(void) case LL_ADV_CONN_DIRECT_LOW_DUTY: case LL_ADV_SCAN_UNDIRECT: { - lctrMsgHdr_t *pMsg; + /* Allocate an aligned static array for pAdv->pRxReqBuf */ + static int buffer[(sizeof(lctrMsgHdr_t) + BB_REQ_PDU_MAX_LEN + sizeof(int) - 1) / sizeof(int)]; + lctrMsgHdr_t *pMsg = (lctrMsgHdr_t*)buffer; - if ((pMsg = WsfMsgAlloc(sizeof(lctrMsgHdr_t) + BB_REQ_PDU_MAX_LEN)) != NULL) - { - pAdv->pRxReqBuf = (uint8_t *)(pMsg + 1); /* hide header */ - pAdv->rxReqCback = lctrSlvAdvHandler; - pAdv->rxReqPostCback = lctrSlvAdvPostProcessHandler; - } - else - { - /* Attempt to obtain buffer on next advertising operation. */ - LL_TRACE_ERR0("Could not allocate response buffer"); - // TODO need OOM recovery - } + pAdv->pRxReqBuf = (uint8_t *)(pMsg + 1); /* hide header */ + pAdv->rxReqCback = lctrSlvAdvHandler; + pAdv->rxReqPostCback = lctrSlvAdvPostProcessHandler; break; } case LL_ADV_NONCONN_UNDIRECT: @@ -497,25 +438,18 @@ void lctrSlvAdvBuildOp(void) SchBleCalcAdvOpDuration(pOp, 0); SchInsertNextAvailable(pOp); - LL_TRACE_INFO1("### AdvEvent ### Advertising enabled, due=%u", pOp->due); + LL_TRACE_INFO1("### AdvEvent ### Advertising enabled, dueUsec=%u", pOp->dueUsec); } /*************************************************************************************************/ /*! * \brief Cleanup resources on advertising operation termination. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvAdvCleanupOp(void) { - lctrMsgHdr_t *pMsg = (lctrMsgHdr_t *)lctrSlvAdv.bleData.op.slvAdv.pRxReqBuf; - - if (pMsg) - { - /* Recover header. */ - WsfMsgFree(pMsg - 1); - } + /* The storage for pRxReqBuf is a static array. */ + lctrSlvAdv.bleData.op.slvAdv.pRxReqBuf = NULL; LL_TRACE_INFO0("### AdvEvent ### Advertising disabled"); } @@ -523,8 +457,6 @@ void lctrSlvAdvCleanupOp(void) /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for advertising slave. - * - * \return None. */ /*************************************************************************************************/ void LctrSlvAdvInit(void) @@ -544,8 +476,6 @@ void LctrSlvAdvInit(void) /*************************************************************************************************/ /*! * \brief Set default values for advertising slave. - * - * \return None. */ /*************************************************************************************************/ void LctrSlvAdvDefaults(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_slave_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_slave_ae.c index 386811a718..d8dc6b8e3f 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_slave_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_adv_slave_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave extended advertising operation builder implementation file. + * \file + * + * \brief Link layer controller slave extended advertising operation builder implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -49,7 +50,7 @@ Globals **************************************************************************************************/ /*! \brief Advertising set table. */ -lctrAdvSet_t *pLctrAdvSetTbl; // TODO: share memory with legacy lctrSlvAdv +lctrAdvSet_t *pLctrAdvSetTbl; /* TODO: share memory with legacy lctrSlvAdv */ /*! \brief Common storage for task message data (parameter passing to action routines). */ LctrExtAdvMsg_t *pLctrSlvExtAdvMsg; @@ -66,22 +67,23 @@ static uint8_t *lctrExtAdvDataBufTbl[LL_MAX_ADV_SETS]; /*! \brief Periodic advertising data buffer table. */ static uint8_t *lctrPerAdvDataBufTbl[LL_MAX_ADV_SETS]; +/*! \brief Slave ACAD message. */ +lctrAcadSlvMsg_t *pLctrAcadSlvMsg; + /************************************************************************************************** Internal functions **************************************************************************************************/ /*************************************************************************************************/ /*! - * \brief Reset acad params - * - * \return None. + * \brief Reset ACAD params */ /*************************************************************************************************/ static void lctrSlvAcadResetHandler(void) { lctrAdvSet_t *pAdvSet; - for (uint8_t handle = 0; handle < pLctrRtCfg->maxAdvSets; handle++) + for (unsigned int handle = 0; handle < pLctrRtCfg->maxAdvSets; handle++) { if ((pAdvSet = lctrFindAdvSet(handle)) != NULL) { @@ -92,24 +94,23 @@ static void lctrSlvAcadResetHandler(void) /*************************************************************************************************/ /*! - * \brief Acad dispatch handler + * \brief ACAD dispatch handler * * \param pMsg Message to be handled. - * - * \return None. */ /*************************************************************************************************/ -static void lctrSlvAcadDisp(lctrChanMapUpdate_t *pMsg) +static void lctrSlvAcadDisp(lctrAcadSlvMsg_t *pMsg) { lctrAdvSet_t *pAdvSet; - LL_TRACE_INFO2("lctrSlvAcadDisp: handle=%u, evt=%u", pMsg->hdr.handle, pMsg->hdr.event); + LL_TRACE_INFO2("lctrSlvAcadDisp: handle=%u, event=%u", pMsg->hdr.handle, pMsg->hdr.event); if (pMsg->hdr.dispId != LCTR_DISP_BCST) { if ((pAdvSet = lctrFindAdvSet(pMsg->hdr.handle)) != NULL) { - pAdvSet->perParam.updChanMask = pMsg->chanMap; + pLctrAcadSlvMsg = pMsg; + lctrSlvAcadExecuteSm(pAdvSet, pMsg->hdr.event); } } @@ -177,7 +178,7 @@ static inline uint16_t lctrCalcMAM(uint16_t a, uint16_t b) /*************************************************************************************************/ static lctrAdvSet_t *lctrAllocAdvSet(uint8_t handle) { - for (uint8_t i = 0; i < pLctrRtCfg->maxAdvSets; i++) + for (unsigned int i = 0; i < pLctrRtCfg->maxAdvSets; i++) { lctrAdvSet_t *pAdvSet = &pLctrAdvSetTbl[i]; @@ -220,8 +221,6 @@ static lctrAdvSet_t *lctrAllocAdvSet(uint8_t handle) * \brief Free an advertising set. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrFreeAdvSet(lctrAdvSet_t *pAdvSet) @@ -262,8 +261,6 @@ lctrAdvSet_t *lctrFindAdvSet(uint8_t handle) * \brief Update auxiliary channel. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrSelectNextAuxChannel(lctrAdvSet_t *pAdvSet) @@ -282,8 +279,6 @@ void lctrSelectNextAuxChannel(lctrAdvSet_t *pAdvSet) * \brief Update periodic channel. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrSelectNextPerChannel(lctrAdvSet_t *pAdvSet) @@ -326,8 +321,6 @@ uint8_t lctrPeriodicSelectNextChannel(lmgrChanParam_t *pChanParam, uint16_t even uint16_t unmapChan = LL_MATH_MOD_37(prn_e & 0xFFFF); - pChanParam->lastChanIdx = unmapChan; - /* remappingIndex */ if (!((UINT64_C(1) << unmapChan) & pChanParam->chanMask)) @@ -343,8 +336,6 @@ uint8_t lctrPeriodicSelectNextChannel(lmgrChanParam_t *pChanParam, uint16_t even /*************************************************************************************************/ /*! * \brief Extended advertising reset handler. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvExtAdvResetHandler(void) @@ -359,8 +350,6 @@ static void lctrSlvExtAdvResetHandler(void) * \brief Slave extended advertising message dispatcher. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvExtAdvDisp(LctrExtAdvMsg_t *pMsg) @@ -392,8 +381,6 @@ static void lctrSlvExtAdvDisp(LctrExtAdvMsg_t *pMsg) /*************************************************************************************************/ /*! * \brief Scan request post-processing. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvRxExtScanReq(void) @@ -847,7 +834,7 @@ uint8_t lctrSlvExtAdvBuildOp(lctrAdvSet_t *pAdvSet, uint32_t maxStartMs) if (lmgrGetOpFlag(LL_OP_MODE_FLAG_ENA_ADV_CHAN_RAND)) { - pAdv->firstAdvChIdx = LlMathRandNum() % LL_NUM_CHAN_ADV; + pAdv->firstAdvChIdx = LlMathRandNum() & LL_NUM_CHAN_ADV; } else { @@ -862,9 +849,9 @@ uint8_t lctrSlvExtAdvBuildOp(lctrAdvSet_t *pAdvSet, uint32_t maxStartMs) if ((pAdvSet->param.advEventProp & LEGACY_HIGH_DUTY) == LEGACY_HIGH_DUTY ) { pAdv->firstAdvChIdx = 0; /* High duty cycle always start from channel 37. */ - pAdvSet->param.priAdvInterMin = 0; - pAdvSet->param.priAdvInterMax = BB_BLE_TO_BB_TICKS(LL_DIR_ADV_INTER_TICKS); - pAdvSet->param.priAdvTermCntDown = BB_US_TO_BB_TICKS(pLctrSlvExtAdvMsg->enable.durMs * 1000); + pAdvSet->param.priAdvInterMinUsec = 0; + pAdvSet->param.priAdvInterMaxUsec = BB_BLE_TO_US(LL_DIR_ADV_INTER_TICKS); + pAdvSet->param.priAdvTermCntDownUsec = pLctrSlvExtAdvMsg->enable.durMs * 1000; } pAdv->txAdvLen = lctrPackLegacyAdvPdu(pAdvSet, pAdvSet->advHdrBuf); @@ -930,9 +917,9 @@ uint8_t lctrSlvExtAdvBuildOp(lctrAdvSet_t *pAdvSet, uint32_t maxStartMs) if (pLctrSlvExtAdvMsg->enable.durMs) { - pOp->due = PalBbGetCurrentTime(USE_RTC_BB_CLK) + BB_US_TO_BB_TICKS(BbGetSchSetupDelayUs()); + pOp->dueUsec = PalBbGetCurrentTime() + BbGetSchSetupDelayUs(); - uint32_t maxTime = BB_US_TO_BB_TICKS(maxStartMs * 1000); + uint32_t maxTime = maxStartMs * 1000; if (!SchInsertEarlyAsPossible(pOp, 0, maxTime)) { LL_TRACE_WARN1("Could not enable ExtAdv operation within given durMs=%u", maxStartMs); @@ -944,7 +931,7 @@ uint8_t lctrSlvExtAdvBuildOp(lctrAdvSet_t *pAdvSet, uint32_t maxStartMs) SchInsertNextAvailable(pOp); } - LL_TRACE_INFO1("### ExtAdvEvent ### Advertising enabled, due=%u", pOp->due); + LL_TRACE_INFO1("### ExtAdvEvent ### Advertising enabled, dueUsec=%u", pOp->dueUsec); /* Advertising offloading to auxiliary channel. */ if (pAdvSet->pExtAdvAuxPtr) @@ -981,7 +968,7 @@ uint8_t lctrSlvExtAdvBuildOp(lctrAdvSet_t *pAdvSet, uint32_t maxStartMs) } /* Update AuxPtr now that AUX packet is ready. */ - lctrSlvTxSetupExtAdvHandler(pOp, pOp->due); + lctrSlvTxSetupExtAdvHandler(pOp, pOp->dueUsec); } return LL_SUCCESS; @@ -993,17 +980,15 @@ uint8_t lctrSlvExtAdvBuildOp(lctrAdvSet_t *pAdvSet, uint32_t maxStartMs) * * \param pAdvSet Advertising set. * \param pOp Auxiliary BOD. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvAuxRescheduleOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pOp) { - uint32_t auxOffsUsec = BB_US_TO_BB_TICKS(pAdvSet->advBod.minDurUsec + + uint32_t auxOffsUsec = pAdvSet->advBod.minDurUsec + WSF_MAX(BbGetSchSetupDelayUs(), LL_BLE_MAFS_US) + - WSF_MAX(pAdvSet->auxDelayUsec, pLctrRtCfg->auxDelayUsec)); + WSF_MAX(pAdvSet->auxDelayUsec, pLctrRtCfg->auxDelayUsec); - auxOffsUsec = WSF_MIN(auxOffsUsec, BB_US_TO_BB_TICKS(LL_AUX_PTR_MAX_USEC)); + auxOffsUsec = WSF_MIN(auxOffsUsec, LL_AUX_PTR_MAX_USEC); /* Round up auxOffsetUsec if necessary. */ auxOffsUsec = SchBleGetAlignedAuxOffsUsec(auxOffsUsec); @@ -1011,9 +996,9 @@ 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->due = pAdvSet->advBod.due + auxOffsUsec + pLctrRtCfg->auxPtrOffsetUsec; + pOp->dueUsec = pAdvSet->advBod.dueUsec + auxOffsUsec + pLctrRtCfg->auxPtrOffsetUsec; - if (pAdvSet->auxSkipInter == 0) + if (pAdvSet->auxSkipInterUsec == 0) { do { @@ -1023,10 +1008,10 @@ void lctrSlvAuxRescheduleOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pOp) break; } - LL_TRACE_WARN1("!!! AuxAdv schedule conflict at due=%u", BB_TICKS_TO_US(pOp->due)); + LL_TRACE_WARN1("!!! AuxAdv schedule conflict at dueUsec=%u", pOp->dueUsec); LL_TRACE_WARN1("!!! handle=%u", pAdvSet->handle); /* Try next advertising interval. */ - pOp->due += pAdvSet->param.priAdvInterMax; + pOp->dueUsec += pAdvSet->param.priAdvInterMaxUsec; } while (TRUE); } @@ -1035,17 +1020,17 @@ void lctrSlvAuxRescheduleOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pOp) do { /* Link multiple primary channel operations. */ - if (SchInsertLateAsPossible(pOp, 0, pAdvSet->auxSkipInter)) + if (SchInsertLateAsPossible(pOp, 0, pAdvSet->auxSkipInterUsec)) { break; } /* Try next skip interval. */ - pOp->due += pAdvSet->auxSkipInter; + pOp->dueUsec += pAdvSet->auxSkipInterUsec; /* TODO restart advertising at next skip interval or use large skip? */ - LL_TRACE_WARN1("!!! AuxAdv schedule conflict at due=%u", pOp->due); + LL_TRACE_WARN1("!!! AuxAdv schedule conflict at dueUsec=%u", pOp->dueUsec); LL_TRACE_WARN1("!!! handle=%u", pAdvSet->handle); } while (TRUE); @@ -1058,8 +1043,6 @@ void lctrSlvAuxRescheduleOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pOp) * * \param pAdvSet Advertising set. * \param pOp Auxiliary BOD. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvAuxCommitOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pOp) @@ -1068,16 +1051,16 @@ static void lctrSlvAuxCommitOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pOp) if (pAdvSet->param.secAdvMaxSkip) { - uint32_t advEvtDur = BB_US_TO_BB_TICKS(pAdvSet->advBod.minDurUsec); + uint32_t advEvtDurUsec = pAdvSet->advBod.minDurUsec; uint32_t skipTimeUsec = pAdvSet->param.secAdvMaxSkip * /* number of skip events */ - (BB_TICKS_TO_US(pAdvSet->param.priAdvInterMin) + /* 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 */ - pAdvSet->auxSkipInter = WSF_MAX(BB_US_TO_BB_TICKS(skipTimeUsec), advEvtDur); /* ensure minimum */ + pAdvSet->auxSkipInterUsec = WSF_MAX(skipTimeUsec, advEvtDurUsec); /* ensure minimum */ } lctrSlvAuxRescheduleOp(pAdvSet, pOp); @@ -1088,8 +1071,6 @@ static void lctrSlvAuxCommitOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pOp) * \brief Build auxiliary non-connectable and non-scannable operation. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvAuxNonConnNonScanBuildOp(lctrAdvSet_t *pAdvSet) @@ -1106,7 +1087,7 @@ void lctrSlvAuxNonConnNonScanBuildOp(lctrAdvSet_t *pAdvSet) /*** General Setup ***/ - pOp->reschPolicy = BB_RESCH_MOVEABLE_PREFERRED; + pOp->reschPolicy = BB_RESCH_FIXED; pOp->protId = BB_PROT_BLE; pOp->prot.pBle = pBle; pOp->endCback = lctrSlvAuxAdvEndOp; @@ -1183,8 +1164,6 @@ void lctrSlvAuxNonConnNonScanBuildOp(lctrAdvSet_t *pAdvSet) * \brief Build auxiliary scannable operation. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvAuxScanBuildOp(lctrAdvSet_t *pAdvSet) @@ -1304,8 +1283,6 @@ void lctrSlvAuxScanBuildOp(lctrAdvSet_t *pAdvSet) * \brief Build auxiliary connectable operation. * * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvAuxConnBuildOp(lctrAdvSet_t *pAdvSet) @@ -1418,9 +1395,45 @@ void lctrSlvAuxConnBuildOp(lctrAdvSet_t *pAdvSet) /*************************************************************************************************/ /*! - * \brief Initialize link layer controller resources for advertising slave. + * \brief Host channel class update handler for Periodic Advertising. * - * \return None. + * \param chanMap Updated channel map. + * + * \return Status code. + */ +/*************************************************************************************************/ +static uint8_t lctrSlvPeriodicChClassUpdate(uint64_t chanMap) +{ + lctrChanMapUpdate_t *pMsg; + + /* Update for periodic adv sets */ + for (uint8_t perAdvHandle = 0; perAdvHandle < pLctrRtCfg->maxAdvSets; perAdvHandle++) + { + if (LctrPerAdvEnabled(perAdvHandle) == TRUE) + { + if ((pMsg = (lctrChanMapUpdate_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->hdr.handle = (uint16_t)perAdvHandle; + pMsg->hdr.dispId = LCTR_DISP_ACAD; + pMsg->hdr.event = LCTR_ACAD_MSG_CHAN_UPDATE; + pMsg->chanMap = chanMap; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } + else + { + LL_TRACE_ERR0("lctrSlvPeriodicChClassUpdate: out of message buffers"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + } + } + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Initialize link layer controller resources for advertising slave. */ /*************************************************************************************************/ void LctrSlvExtAdvInit(void) @@ -1434,8 +1447,10 @@ void LctrSlvExtAdvInit(void) /* Add advertising task event handlers. */ lctrEventHdlrTbl[LCTR_EVENT_RX_SCAN_REQ] = lctrSlvRxExtScanReq; - /* Add acad message dispatchers. */ - lctrMsgDispTbl[LCTR_DISP_ACAD] = (LctrMsgDisp_t) lctrSlvAcadDisp; + /* Add ACAD message dispatchers. */ + lctrMsgDispTbl[LCTR_DISP_ACAD] = (LctrMsgDisp_t)lctrSlvAcadDisp; + + lctrRegisterChClassHandler(lctrSlvPeriodicChClassUpdate); /* Set supported features. */ if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_5_0) @@ -1449,8 +1464,6 @@ void LctrSlvExtAdvInit(void) /*************************************************************************************************/ /*! * \brief Set default values for advertising slave. - * - * \return None. */ /*************************************************************************************************/ void LctrSlvExtAdvDefaults(void) @@ -1751,8 +1764,6 @@ uint8_t LctrSetExtAdvSetRandAddr(uint8_t handle, const uint8_t *pAddr) * \param pPduHdr PDU header. * \param pBle BLE operation data. * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrChooseSetAdvA(lctrAdvbPduHdr_t *pPduHdr, BbBleData_t * const pBle, lctrAdvSet_t *pAdvSet) @@ -1815,8 +1826,6 @@ void lctrChooseSetAdvA(lctrAdvbPduHdr_t *pPduHdr, BbBleData_t * const pBle, lctr * \param pPduHdr PDU header. * \param pBle BLE data. * \param pAdvSet Advertising set. - * - * \return None. */ /*************************************************************************************************/ void lctrChooseSetPeerA(lctrAdvbPduHdr_t *pPduHdr, BbBleData_t * const pBle, lctrAdvSet_t *pAdvSet) @@ -1978,20 +1987,20 @@ uint8_t LctrSetExtAdvParam(uint8_t handle, LlExtAdvParam_t *pExtAdvParam) } } - pAdvSet->param.advEventProp = pExtAdvParam->advEventProp; - pAdvSet->param.priAdvInterMin = pExtAdvParam->priAdvInterMin; - pAdvSet->param.priAdvInterMax = pExtAdvParam->priAdvInterMax; - pAdvSet->param.priAdvChanMap = pExtAdvParam->priAdvChanMap; - pAdvSet->param.ownAddrType = pExtAdvParam->ownAddrType; - pAdvSet->param.peerAddrType = pExtAdvParam->peerAddrType; - pAdvSet->param.peerAddr = BstreamToBda64(pExtAdvParam->pPeerAddr); - pAdvSet->param.advFiltPolicy = pExtAdvParam->advFiltPolicy; - pAdvSet->param.advTxPwr = pExtAdvParam->advTxPwr; - pAdvSet->param.priAdvPhy = pExtAdvParam->priAdvPhy; - pAdvSet->param.secAdvMaxSkip = pExtAdvParam->secAdvMaxSkip; - pAdvSet->param.secAdvPhy = pExtAdvParam->secAdvPhy; - pAdvSet->param.advSID = pExtAdvParam->advSID; - pAdvSet->param.scanReqNotifEna = pExtAdvParam->scanReqNotifEna; + pAdvSet->param.advEventProp = pExtAdvParam->advEventProp; + pAdvSet->param.priAdvInterMinUsec = BB_BLE_TO_US(pExtAdvParam->priAdvInterMin); + pAdvSet->param.priAdvInterMaxUsec = BB_BLE_TO_US(pExtAdvParam->priAdvInterMax); + pAdvSet->param.priAdvChanMap = pExtAdvParam->priAdvChanMap; + pAdvSet->param.ownAddrType = pExtAdvParam->ownAddrType; + pAdvSet->param.peerAddrType = pExtAdvParam->peerAddrType; + pAdvSet->param.peerAddr = BstreamToBda64(pExtAdvParam->pPeerAddr); + pAdvSet->param.advFiltPolicy = pExtAdvParam->advFiltPolicy; + pAdvSet->param.advTxPwr = pExtAdvParam->advTxPwr; + pAdvSet->param.priAdvPhy = pExtAdvParam->priAdvPhy; + pAdvSet->param.secAdvMaxSkip = pExtAdvParam->secAdvMaxSkip; + pAdvSet->param.secAdvPhy = pExtAdvParam->secAdvPhy; + pAdvSet->param.advSID = pExtAdvParam->advSID; + pAdvSet->param.scanReqNotifEna = pExtAdvParam->scanReqNotifEna; return LL_SUCCESS; } @@ -2096,7 +2105,6 @@ uint8_t LctrSetPeriodicAdvParam(uint8_t handle, LlPerAdvParam_t *pPerAdvParam) return LL_ERROR_CODE_CMD_DISALLOWED; } -#if 0 uint16_t mafOffset = WSF_MAX(pAdvSet->auxDelayUsec, pLctrRtCfg->auxDelayUsec); uint32_t worstCaseUsec = SchBleCalcPerAdvDurationUsec(pAdvSet->param.secAdvPhy, 0, @@ -2109,7 +2117,6 @@ uint8_t LctrSetPeriodicAdvParam(uint8_t handle, LlPerAdvParam_t *pPerAdvParam) { return LL_ERROR_CODE_PKT_TOO_LONG; } -#endif /* Anonymous advertising is not allowed for periodic advertising. */ if (pAdvSet->param.advEventProp & LL_ADV_EVT_PROP_OMIT_AA_BIT) @@ -2117,8 +2124,8 @@ uint8_t LctrSetPeriodicAdvParam(uint8_t handle, LlPerAdvParam_t *pPerAdvParam) return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; } - pAdvSet->perParam.advInterMin = BB_US_TO_BB_TICKS(LCTR_PER_INTER_TO_US(pPerAdvParam->perAdvInterMin)); /* Convert parameter to bb ticks */ - pAdvSet->perParam.advInterMax = BB_US_TO_BB_TICKS(LCTR_PER_INTER_TO_US(pPerAdvParam->perAdvInterMax)); /* Convert parameter to bb ticks */ + pAdvSet->perParam.advInterMinUsec = LCTR_PER_INTER_TO_US(pPerAdvParam->perAdvInterMin); /* Convert parameter to bb ticks */ + pAdvSet->perParam.advInterMaxUsec = LCTR_PER_INTER_TO_US(pPerAdvParam->perAdvInterMax); /* Convert parameter to bb ticks */ pAdvSet->perParam.advEventProp = pPerAdvParam->perAdvProp; pAdvSet->perParam.advParamReady = TRUE; @@ -2156,10 +2163,10 @@ uint8_t LctrSetPeriodicAdvData(uint8_t handle, uint8_t op, uint8_t len, const ui return LL_ERROR_CODE_CMD_DISALLOWED; } -#if 0 + uint32_t worstCaseUsec; uint16_t mafOffset = WSF_MAX(pAdvSet->auxDelayUsec, pLctrRtCfg->auxDelayUsec); - uint32_t maxInterval = (pAdvSet->perParam.perAdvEnabled) ? BB_TICKS_TO_US(pAdvSet->perParam.perAdvInter) : BB_TICKS_TO_US(pAdvSet->perParam.advInterMax); + uint32_t maxInterval = (pAdvSet->perParam.perAdvEnabled) ? (pAdvSet->perParam.perAdvInterUsec) : (pAdvSet->perParam.advInterMaxUsec); if (op == LL_ADV_DATA_OP_FRAG_INTER || op == LL_ADV_DATA_OP_FRAG_LAST) /* Intermediate chained data. */ { @@ -2184,7 +2191,6 @@ uint8_t LctrSetPeriodicAdvData(uint8_t handle, uint8_t op, uint8_t len, const ui { return LL_ERROR_CODE_PKT_TOO_LONG; } -#endif if ((result = lctrSetPerAdvDataSm(pAdvSet, &pAdvSet->perAdvData, op, len, pData)) == LL_SUCCESS) { @@ -2201,8 +2207,6 @@ uint8_t LctrSetPeriodicAdvData(uint8_t handle, uint8_t op, uint8_t len, const ui * \param handle Advertising handle. * \param enable Set periodic advertising enabled/disabled. * - * \return None. - * * Enable/disable periodic advertising. */ /*************************************************************************************************/ @@ -2331,6 +2335,11 @@ uint8_t LctrRemoveAdvSet(uint8_t handle) return LL_ERROR_CODE_CMD_DISALLOWED; } + if (pAdvSet->removeCback) + { + pAdvSet->removeCback(handle); + } + lctrFreeAdvSet(pAdvSet); return LL_SUCCESS; @@ -2473,8 +2482,6 @@ uint8_t LctrSetExtAdvTxPhyOptions(uint8_t handle, uint8_t priPhyOpts, uint8_t se * * \param pAdvSet Advertising set. * \param event Extended advertising event. - * - * \return None. */ /*************************************************************************************************/ void lctrSendAdvSetMsg(lctrAdvSet_t *pAdvSet, uint8_t event) @@ -2496,8 +2503,6 @@ void lctrSendAdvSetMsg(lctrAdvSet_t *pAdvSet, uint8_t event) * \brief Slave periodic advertising message dispatcher. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvPeriodicAdvDisp(LctrPerAdvMsg_t *pMsg) @@ -2532,8 +2537,6 @@ static void lctrSlvPeriodicAdvDisp(LctrPerAdvMsg_t *pMsg) * * \param pAdvSet Advertising set. * \param event Periodic advertising event. - * - * \return None. */ /*************************************************************************************************/ void lctrSendPeriodicAdvSetMsg(lctrAdvSet_t *pAdvSet, uint8_t event) @@ -2554,7 +2557,9 @@ void lctrSendPeriodicAdvSetMsg(lctrAdvSet_t *pAdvSet, uint8_t event) /*! * \brief Get status of periodic adv handle. * - * \return returns True if periodic advertising is running on that handle, False if not + * \param handle Advertising handle. + * + * \return True if periodic advertising is running on that handle, False if not */ /*************************************************************************************************/ bool_t LctrIsPerAdvEnabled(uint8_t handle) @@ -2573,8 +2578,6 @@ bool_t LctrIsPerAdvEnabled(uint8_t handle) /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for periodic advertising slave. - * - * \return None. */ /*************************************************************************************************/ void LctrSlvPeriodicAdvInit(void) @@ -2601,20 +2604,18 @@ void LctrSlvPeriodicAdvInit(void) * * \param pAdvSet Advertising set. * \param pOp Periodic BOD. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvPeriodicCommitOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pOp) { - const uint32_t curTime = PalBbGetCurrentTime(USE_RTC_BB_CLK); - uint32_t offsetUsec = SchRmGetOffsetUsec(BB_TICKS_TO_US(pAdvSet->perParam.perAdvInter), + const uint32_t curTime = PalBbGetCurrentTime(); + uint32_t offsetUsec = SchRmGetOffsetUsec(pAdvSet->perParam.perAdvInterUsec, LL_MAX_CONN + LCTR_GET_EXT_ADV_INDEX(pAdvSet), curTime); /* RM is shared by connections and periodic advertising. */ - pOp->due = curTime + BB_US_TO_BB_TICKS(offsetUsec); + pOp->dueUsec = curTime + offsetUsec; /*** Commit operation ***/ - uint32_t anchorPoint = pOp->due; + uint32_t anchorPointUsec = pOp->dueUsec; uint16_t numIntervals = 0; while (TRUE) @@ -2629,16 +2630,13 @@ static void lctrSlvPeriodicCommitOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pO numIntervals += 1; pAdvSet->perParam.perEventCounter += 1; - uint32_t perInterUsec = numIntervals * BB_TICKS_TO_US(pAdvSet->perParam.perAdvInter); - uint32_t perInter = BB_US_TO_BB_TICKS(perInterUsec); - int16_t dueOffsetUsec = perInterUsec - BB_TICKS_TO_US(perInter); + uint32_t perInterUsec = numIntervals * pAdvSet->perParam.perAdvInterUsec; /* Advance to next interval. */ - pOp->due = anchorPoint + perInter; - pOp->dueOffsetUsec = WSF_MAX(dueOffsetUsec, 0); + pOp->dueUsec = anchorPointUsec + perInterUsec; } - LL_TRACE_INFO1("### ExtAdvEvent ### Periodic advertising enabled, due=%u", pOp->due); + LL_TRACE_INFO1("### ExtAdvEvent ### Periodic advertising enabled, dueUsec=%u", pOp->dueUsec); } /*************************************************************************************************/ @@ -2661,7 +2659,7 @@ uint8_t lctrSlvPeriodicAdvBuildOp(lctrAdvSet_t *pAdvSet) /*** General Setup ***/ - pOp->reschPolicy = BB_RESCH_PERIODIC; + pOp->reschPolicy = BB_RESCH_FIXED; pOp->protId = BB_PROT_BLE; pOp->prot.pBle = pBle; pOp->endCback = lctrSlvPeriodicAdvEndOp; @@ -2721,12 +2719,11 @@ uint8_t lctrSlvPeriodicAdvBuildOp(lctrAdvSet_t *pAdvSet) /*** Commit operation ***/ SchBleCalcAdvOpDuration(pOp, 0); - uint32_t interMinUsec = BB_TICKS_TO_US(pAdvSet->perParam.advInterMin); - uint32_t interMaxUsec = BB_TICKS_TO_US(pAdvSet->perParam.advInterMax); + uint32_t interMinUsec = pAdvSet->perParam.advInterMinUsec; + uint32_t interMaxUsec = pAdvSet->perParam.advInterMaxUsec; uint32_t durUsec = pOp->minDurUsec; uint32_t perInterUsec; -#if 0 /* Make sure the worst case advertising duration can make the intervals. */ uint16_t mafOffset = WSF_MAX(pAdvSet->auxDelayUsec, pLctrRtCfg->auxDelayUsec); uint32_t worstCaseUsec = SchBleCalcPerAdvDurationUsec(pAdvSet->param.secAdvPhy, @@ -2746,7 +2743,6 @@ uint8_t lctrSlvPeriodicAdvBuildOp(lctrAdvSet_t *pAdvSet) { interMinUsec = worstCaseUsec; } -#endif /* Max interval is preferred in resource manager. */ if (!SchRmAdd(LCTR_GET_PER_RM_HANDLE(pAdvSet), SCH_RM_PREF_CAPACITY, interMinUsec, interMaxUsec, durUsec, &perInterUsec, lctrGetPerRefTime)) @@ -2754,7 +2750,7 @@ uint8_t lctrSlvPeriodicAdvBuildOp(lctrAdvSet_t *pAdvSet) return LL_ERROR_CODE_LIMIT_REACHED; } - pAdvSet->perParam.perAdvInter = BB_US_TO_BB_TICKS(perInterUsec); + pAdvSet->perParam.perAdvInterUsec = perInterUsec; lctrSlvPeriodicCommitOp(pAdvSet, pOp); return LL_SUCCESS; @@ -2762,12 +2758,12 @@ uint8_t lctrSlvPeriodicAdvBuildOp(lctrAdvSet_t *pAdvSet) /*************************************************************************************************/ /*! - * \brief Get reference time(due time) of the periodic advertising. + * \brief Get reference time (due time) of the periodic advertising. * * \param perHandle Periodic advertising handle. * \param pDurUsec Pointer to duration of the BOD. * - * \return Due time in BB ticks of the periodic advertising handle. + * \return Due time in microseconds of the periodic advertising handle. */ /*************************************************************************************************/ uint32_t lctrGetPerRefTime(uint8_t perHandle, uint32_t *pDurUsec) @@ -2780,7 +2776,7 @@ uint32_t lctrGetPerRefTime(uint8_t perHandle, uint32_t *pDurUsec) pAdvSet = &pLctrAdvSetTbl[perHandle - LL_MAX_CONN]; if (pAdvSet->perParam.perState == LCTR_PER_ADV_STATE_ENABLED) { - refTime = pAdvSet->perParam.perAdvBod.due; + refTime = pAdvSet->perParam.perAdvBod.dueUsec; if (pDurUsec) { *pDurUsec = pAdvSet->perParam.perAdvBod.minDurUsec; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis.c new file mode 100644 index 0000000000..86a91a7acc --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis.c @@ -0,0 +1,1426 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller broadcast isochronous main implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_bis.h" +#include "lctr_int_iso.h" +#include "lctr_int_bis_master.h" +#include "wsf_assert.h" +#include "wsf_buf.h" +#include "wsf_math.h" +#include "wsf_trace.h" + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief Queue header. */ +#define LCTR_Q_ELEM_LEN 4 + +/************************************************************************************************** + Globals +**************************************************************************************************/ + +/*! \brief BIS context table. */ +lctrBisCtx_t *pLctrBisTbl; + +/*! \brief BIG context table. */ +lctrBigCtx_t *pLctrBigTbl; + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Assemble BIS Data PDU. + * + * \param pBuf Buffer to pack the Data PDU header. + * \param pduLen PDU length. + * \param llid LLID of PDU. + * \param pSegHdr Segmentation header or NULL if not required. + * + * \return Length of header. + */ +/*************************************************************************************************/ +static uint8_t lctrAssembleBisDataPdu(uint8_t *pBuf, uint16_t pduLen, LlIsoLlid_t llid, lctrIsoSegHdr_t *pSegHdr) +{ + uint8_t hdrLen; + + /* All additional fields must be zero'ed since flow control bits will be or'ed in at transmit. */ + lctrBisDataPduHdr_t dataHdr = + { + .llid = llid, + .cssn = 0, /* Completed in ISR. */ + .cstf = 0, /* Completed in ISR. */ + .len = pduLen + }; + + hdrLen = lctrBisPackDataPduHdr(pBuf, &dataHdr); + + if (pSegHdr) + { + hdrLen += lctrIsoPackSegHdr(pBuf, pSegHdr); + } + + return hdrLen; +} + +/*************************************************************************************************/ +/*! + * \brief Fragment an ISO SDU into a Data PDU descriptor. + * + * \param pBisCtx BIS context. + * \param pIsoHdr ISO SDU header. + * \param pIsoBuf ISO SDU Buffer. + * \param pDesc Fragmentation descriptor. + */ +/*************************************************************************************************/ +static void lctrBisFragmentIsoSdu(lctrBisCtx_t *pBisCtx, lctrIsoHdr_t *pIsoHdr, uint8_t *pIsoBuf, lctrIsoTxBufDesc_t *pDesc) +{ + lctrBigCtx_t *pBigCtx = pBisCtx->pBigCtx; + + pDesc->isoLen = pIsoHdr->sduLen; + pDesc->fragLen = pBisCtx->pBigCtx->maxPdu; + pDesc->fragCnt = 0; + pDesc->pIsoSdu = pIsoBuf; + pDesc->pPduBuf = pIsoBuf + (HCI_ISO_HDR_LEN + HCI_ISO_DL_MIN_LEN) + ((pIsoHdr->tsFlag) ? HCI_ISO_TS_LEN : 0); + + uint8_t *pSduBuf = pDesc->pPduBuf; + uint16_t fragOffset = 0; + + if (pDesc->isoLen > 0) + { + while (fragOffset < pDesc->isoLen) + { + const uint16_t dataRem = pDesc->isoLen - fragOffset; + const uint16_t fragSize = WSF_MIN(dataRem, pDesc->fragLen); + fragOffset += fragSize; + + LlIsoLlid_t llid; + + if (pBigCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED) + { + llid = (fragOffset == pDesc->isoLen) ? LL_LLID_ISO_UNF_END_PDU : LL_LLID_ISO_UNF_CONT_PDU; + } + else + { + llid = LL_LLID_ISO_FRA_PDU; + } + + pDesc->frag[pDesc->fragCnt].hdrLen = lctrAssembleBisDataPdu(pDesc->frag[pDesc->fragCnt].hdr, fragSize, llid, NULL); + + 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, + pSduBuf, + pDesc->frag[pDesc->fragCnt].trl)) + { + pDesc->frag[pDesc->fragCnt].trlLen = LL_DATA_MIC_LEN; + + #if (LL_ENABLE_TESTER) + pDesc->frag[pDesc->fragCnt].trl[0] ^= (llTesterCb.pktMic >> 0) & 0xFF; + pDesc->frag[pDesc->fragCnt].trl[1] ^= (llTesterCb.pktMic >> 8) & 0xFF; + pDesc->frag[pDesc->fragCnt].trl[2] ^= (llTesterCb.pktMic >> 16) & 0xFF; + pDesc->frag[pDesc->fragCnt].trl[3] ^= (llTesterCb.pktMic >> 24) & 0xFF; + #endif + } + else + { + pDesc->frag[pDesc->fragCnt].trlLen = 0; + } + + pSduBuf += fragSize; + pDesc->fragCnt++; + } + } + else + { + /* Zero length SDU. */ + + pDesc->frag[0].hdrLen = lctrAssembleBisDataPdu(pDesc->frag[0].hdr, 0, LL_LLID_ISO_UNF_END_PDU, NULL); + pDesc->frag[0].trlLen = 0; + + pDesc->fragCnt = 1; + } +} + +/*************************************************************************************************/ +/*! + * \brief Allocate a BIG context. + * + * \param bigHandle BIG handle. + * + * \return BIG context or NULL if at capacity. + */ +/*************************************************************************************************/ +lctrBigCtx_t *lctrAllocBigCtx(uint8_t bigHandle) +{ + for (unsigned int i = 0; i < pLctrRtCfg->maxBig; i++) + { + lctrBigCtx_t *pBigCtx = &pLctrBigTbl[i]; + + if (!pBigCtx->enabled) + { + memset(pBigCtx, 0, sizeof(lctrBigCtx_t)); + + pBigCtx->enabled = TRUE; + pBigCtx->handle = bigHandle; + + return pBigCtx; + } + } + + return NULL; +} + +/*************************************************************************************************/ +/*! + * \brief Free a BIG context. + * + * \param pBigCtx BIG context to free. + */ +/*************************************************************************************************/ +void lctrFreeBigCtx(lctrBigCtx_t *pBigCtx) +{ + WSF_ASSERT(pBigCtx->enabled); + + pBigCtx->enabled = FALSE; + + /* Free all BIS context associated with the BIG. */ + for (unsigned int i = 0; i < pBigCtx->numBis; i++) + { + lctrBisCtx_t *pBisCtx = pBigCtx->pBisCtx[i]; + + switch (pBigCtx->role) + { + case LL_ROLE_SLAVE: + lctrBisSetDataPath(pBisCtx, LL_ISO_DATA_DIR_INPUT, LL_ISO_DATA_PATH_DISABLED); + lctrNotifyIsoTxComplete(pBigCtx); + break; + case LL_ROLE_MASTER: + lctrBisSetDataPath(pBisCtx, LL_ISO_DATA_DIR_OUTPUT, LL_ISO_DATA_PATH_DISABLED); + break; + default: + break; + } + + lctrFreeBisCtx(pBisCtx); + } + + /* Flush BIG Control PDUs. */ + switch (pBigCtx->role) + { + case LL_ROLE_SLAVE: + while (!WsfQueueEmpty(&pBigCtx->roleData.slv.txCtrlQ)) + { + lctrBigTxCtrlQueuePopCleanup(pBigCtx); + } + break; + case LL_ROLE_MASTER: + default: + break; + } +} + +/*************************************************************************************************/ +/*! + * \brief Check if the periodic advertising handle is associated with another BIG. + * + * \param advHandle Periodic advertising handle. + * + * \return TRUE if periodic advertising handle is associated with another BIG, otherwise FALSE. + */ +/*************************************************************************************************/ +uint8_t lctrBigIsPerAdvUsed(uint8_t advHandle) +{ + for (unsigned int i = 0; i < pLctrRtCfg->maxBig; i++) + { + lctrBigCtx_t *pBigCtx = &pLctrBigTbl[i]; + + if ((pBigCtx->enabled) && + (pBigCtx->role == LL_ROLE_SLAVE) && + (pBigCtx->roleData.slv.pAdvSet)) + { + return TRUE; + } + } + return FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Find a BIG by BIG handle. + * + * \param bigHandle BIG handle. + * + * \return BIG context or NULL if not found. + */ +/*************************************************************************************************/ +lctrBigCtx_t *lctrFindBigByHandle(uint8_t bigHandle) +{ + for (unsigned int i = 0; i < pLctrRtCfg->maxBig; i++) + { + lctrBigCtx_t *pBigCtx = &pLctrBigTbl[i]; + + if ((pBigCtx->enabled) && + (pBigCtx->handle == bigHandle)) + { + return pBigCtx; + } + } + return NULL; +} + +/*************************************************************************************************/ +/*! + * \brief Find a BIG by SyncHandle. + * + * \param syncHandle BIG sync handle. + * + * \return BIG context or NULL if not found. + */ +/*************************************************************************************************/ +lctrBigCtx_t *lctrFindBigBySyncHandle(uint16_t syncHandle) +{ + for (unsigned int i = 0; i < pLctrRtCfg->maxBig; i++) + { + lctrBigCtx_t *pBigCtx = &pLctrBigTbl[i]; + + if ((pBigCtx->enabled) && + (pBigCtx->roleData.mst.pPerScanCtx == LCTR_GET_PER_SCAN_CTX(syncHandle))) + { + return pBigCtx; + } + } + return NULL; +} + +/*************************************************************************************************/ +/*! + * \brief Check is current BIG synchronization in progress. + * + * \return TRUE if syncrhonizing in progres, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lctrIsBigSynchronizing(void) +{ + for (unsigned int i = 0; i < pLctrRtCfg->maxBig; i++) + { + lctrBigCtx_t *pBigCtx = &pLctrBigTbl[i]; + + if ((pBigCtx->enabled) && + (pBigCtx->state == LCTR_MST_BIG_STATE_SYNCING)) + { + return TRUE; + } + } + return FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Allocate a BIS context. + * + * \param pBigCtx Pointer to the BIG context. + * + * \return BIS context or NULL if at capacity. + */ +/*************************************************************************************************/ +lctrBisCtx_t *lctrAllocBisCtx(lctrBigCtx_t *pBigCtx) +{ + for (unsigned int i = 0; i < pLctrRtCfg->maxBis; i++) + { + lctrBisCtx_t *pBisCtx = &pLctrBisTbl[i]; + + if (!pBisCtx->enabled) + { + memset(pBisCtx, 0, sizeof(lctrBisCtx_t)); + + /* State and context. */ + pBisCtx->enabled = TRUE; + pBisCtx->handle = LCTR_FIRST_BIS_HANDLE + i; + pBisCtx->pBigCtx = pBigCtx; + pBisCtx->bisNum = pBigCtx->numBis + 1; + + pBisCtx->path = LL_ISO_DATA_PATH_DISABLED; + + /* Parent context. */ + pBigCtx->pBisCtx[pBigCtx->numBis++] = pBisCtx; + + return pBisCtx; + } + } + + 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. + * + * \param pBisCtx BIS context to free. + */ +/*************************************************************************************************/ +void lctrFreeBisCtx(lctrBisCtx_t *pBisCtx) +{ + WSF_ASSERT(pBisCtx->enabled); + pBisCtx->enabled = FALSE; + + uint8_t *pPdu; + + /* Flush remaining packets. */ + switch (pBisCtx->pBigCtx->role) + { + case LL_ROLE_MASTER: + while ((pPdu = lctrBisDequeueRxDataPdu(pBisCtx, NULL)) != NULL) + { + lctrBisRxIsoDataPduFree(pPdu); + } + + lctrIsoalRxDataPathClear(&pBisCtx->roleData.mst.isoalRxCtx, pBisCtx->pBigCtx->framing); + break; + case LL_ROLE_SLAVE: + while (!WsfQueueEmpty(&pBisCtx->roleData.slv.txDataQ)) + { + lctrBisTxQueuePopCleanup(pBisCtx, 1); + } + + /* Free any IsoalTxPendQ */ + void *pIsoBuf; + uint8_t handlerId; + while ((pIsoBuf = WsfMsgDeq(&pBisCtx->roleData.slv.isoalTxCtx.pendingSduQ, &handlerId)) != NULL) + { + WsfMsgFree(pIsoBuf); + } + break; + default: + break; + } +} + +/*************************************************************************************************/ +/*! + * \brief Find a BIS by handle. + * + * \param bisHandle BIS handle. + * + * \return BIS context or NULL if not found. + */ +/*************************************************************************************************/ +lctrBisCtx_t *lctrFindBisByHandle(uint16_t bisHandle) +{ + for (unsigned int i = 0; i < pLctrRtCfg->maxBis; i++) + { + lctrBisCtx_t *pBisCtx = &pLctrBisTbl[i]; + + if ((pBisCtx->enabled) && + (pBisCtx->handle == bisHandle)) + { + return pBisCtx; + } + } + + return NULL; +} + +/*************************************************************************************************/ +/*! + * \brief Return the number of available BIS contexts. + * + * \return Number of available BIS contexts. + */ +/*************************************************************************************************/ +uint8_t lctrGetNumAvailBisCtx(void) +{ + uint8_t count = 0; + + for (unsigned int i = 0; i < pLctrRtCfg->maxBis; i++) + { + lctrBisCtx_t *pBisCtx = &pLctrBisTbl[i]; + + if (pBisCtx->enabled == FALSE) + { + count++; + } + } + + return count; +} + +/*************************************************************************************************/ +/*! + * \brief Compute new access address. + * + * \param seedAccAddr Seed access address. + * \param bisNum BIS number. + * + * \return New seed access address value. + */ +/*************************************************************************************************/ +uint32_t lctrComputeBisAccessAddr(uint32_t seedAccAddr, uint8_t bisNum) +{ + uint32_t accAddr = seedAccAddr; + uint16_t div; + uint32_t dw = 0; + uint8_t d0, d1, d2, d3, d4, d5, d6; + + d0 = d1 = d2 = d3 = d4 = d5 = d6 = 0; + + /* Diversifier = ((35 * n) + 42) MOD 128 */ + const uint16_t term = (35 * bisNum) + 42; + div = term - ((term >> 7) * 128); + + d0 = div & 1; + d1 = (div >> 1) & 1; + d2 = (div >> 2) & 1; + d3 = (div >> 3) & 1; + d4 = (div >> 4) & 1; + d5 = (div >> 5) & 1; + d6 = (div >> 6) & 1; + + /* DW = D0D0D0D0D0D0D1D6_D10D5D40D3D20_00000000_00000000b Note the digit after the letter is the index of the D. */ + dw = ((d0 << 31) | (d0 << 30) | (d0 << 29) | (d0 << 28) | (d0 << 27) | (d0 << 26) | (d1 << 25) | (d6 << 24) | \ + (d1 << 23) | (d5 << 21) | (d4 << 20) | (d3 << 18) | (d2 << 17)); + + /* SAA bit-wise XORed with DW */ + accAddr ^= dw; + + return accAddr; +} + +/*************************************************************************************************/ +/*! + * \brief Set up a new BIS. + * + * \param pBisCtx BIS context. + * \param seedAccAddr Seed access address. + * \param baseCrcInit Base CRC Init. + * \param chMap Channel map. + * \param phy PHY. + */ +/*************************************************************************************************/ +void lctrSetupBisContext(lctrBisCtx_t *pBisCtx, uint32_t seedAccAddr, uint16_t baseCrcInit, uint64_t chMap, LlPhy_t phy) +{ + pBisCtx->chan.opType = (pBisCtx->pBigCtx->role == LL_ROLE_SLAVE) ? BB_BLE_OP_SLV_BIS_EVENT : BB_BLE_OP_MST_BIS_EVENT; + + uint32_t accAddr = lctrComputeBisAccessAddr(seedAccAddr, pBisCtx->bisNum); + + pBisCtx->chSelInfo.chanMask = chMap; + pBisCtx->chSelInfo.usedChSel = LL_CH_SEL_2; + pBisCtx->chSelInfo.chIdentifier = (accAddr >> 16) ^ (accAddr >> 0); + LmgrBuildRemapTable(&pBisCtx->chSelInfo); + + pBisCtx->chan.accAddr = accAddr; + pBisCtx->chan.crcInit = (baseCrcInit << 8) | pBisCtx->bisNum; + pBisCtx->chan.txPower = lmgrCb.advTxPwr; + pBisCtx->chan.txPhy = pBisCtx->chan.rxPhy = phy; + pBisCtx->chan.initTxPhyOptions = BB_PHY_OPTIONS_DEFAULT; + pBisCtx->chan.tifsTxPhyOptions = BB_PHY_OPTIONS_DEFAULT; + /* pBisCtx->chan.peerTxStableModIdx = FALSE; */ + +#if (LL_ENABLE_TESTER) + pBisCtx->chan.accAddrRx = pBisCtx->chan.accAddr ^ llTesterCb.dataAccessAddrRx; + pBisCtx->chan.accAddrTx = pBisCtx->chan.accAddr ^ llTesterCb.dataAccessAddrTx; + pBisCtx->chan.crcInitRx = pBisCtx->chan.crcInit ^ llTesterCb.dataCrcInitRx; + pBisCtx->chan.crcInitTx = pBisCtx->chan.crcInit ^ llTesterCb.dataCrcInitTx; +#endif + + if (pBisCtx->pBigCtx->encrypt) + { + pBisCtx->chan.enc.enaEncrypt = TRUE; + pBisCtx->chan.enc.enaDecrypt = TRUE; + pBisCtx->chan.enc.enaAuth = TRUE; + pBisCtx->chan.enc.nonceMode = PAL_BB_NONCE_MODE_EXT64_CNTR; + + memcpy(pBisCtx->chan.enc.iv, pBisCtx->pBigCtx->giv, LL_IV_LEN); + pBisCtx->chan.enc.iv[0] ^= accAddr >> 0; + pBisCtx->chan.enc.iv[1] ^= accAddr >> 8; + pBisCtx->chan.enc.iv[2] ^= accAddr >> 16; + pBisCtx->chan.enc.iv[3] ^= accAddr >> 24; + + memcpy(pBisCtx->chan.enc.sk, pBisCtx->pBigCtx->bleData.chan.enc.sk, PAL_CRYPTO_LL_KEY_LEN); + + /* The directionBit shall be set to 1 for Broadcast Isochronous PDUs. */ + pBisCtx->chan.enc.dir = 1; + pBisCtx->chan.enc.type = PAL_BB_TYPE_BIS; + + lctrInitCipherBlkHdlr(&pBisCtx->chan.enc, pBisCtx->handle, 1); + } +} + +/*************************************************************************************************/ +/*! + * \brief Select all BIS channels and BIG Control channels. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +void lctrSelectBigChannels(lctrBigCtx_t *pBigCtx) +{ + /* Select BIS channels. */ + 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); + } + + /* 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; + +} + +/*************************************************************************************************/ +/*! + * \brief Remap all BIS channels and BIG Control channels. + * + * \param pBigCtx BIG context. + * \param chanMap New channel map. + */ +/*************************************************************************************************/ +void lctrRemapBigChannels(lctrBigCtx_t *pBigCtx, uint64_t chanMap) +{ + /* Select BIS channels. */ + for (unsigned int i = 0; i < pBigCtx->numBis; i++) + { + lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[i]; + pBisCtx->chSelInfo.chanMask = chanMap; + LmgrBuildRemapTable(&pBisCtx->chSelInfo); + } + + /* Select BIG Control channel. */ + pBigCtx->ctrChSelInfo.chanMask = chanMap; + LmgrBuildRemapTable(&pBigCtx->ctrChSelInfo); +} + +/*************************************************************************************************/ +/*! + * \brief Queue BIS ISO SDU onto Tx queue. + * + * \param pBisCtx BIS context. + * \param pIsoHdr ISO header. + * \param pIsoSdu ISO SDU buffer. + */ +/*************************************************************************************************/ +void lctrBisTxIsoPduQueue(lctrBisCtx_t *pBisCtx, lctrIsoHdr_t *pIsoHdr, uint8_t *pIsoSdu) +{ + lctrIsoTxBufDesc_t *pDesc; + + if ((pDesc = lctrAllocIsoTxBufDesc()) == NULL) + { + LL_TRACE_ERR1("Failed to allocate transmit buffer descriptor: bisHandle=%u", pIsoHdr->handle); + WsfMsgFree(pIsoSdu); + if (!pBisCtx->test.enabled) + { + uint16_t handle = pIsoHdr->handle; + uint16_t numSdu = 1; + + lmgrPersistCb.sendIsoCompCback(1, &handle, &numSdu); + } + lctrIsoSduTxIncAvailBuf(); + + lctrNotifyHostHwErrInd(LL_ERROR_CODE_MEM_CAP_EXCEEDED); + return; + } + + lctrBisFragmentIsoSdu(pBisCtx, pIsoHdr, pIsoSdu, pDesc); + WsfMsgEnq(&pBisCtx->roleData.slv.txDataQ, pIsoHdr->handle, (uint8_t *)pDesc); +} + +/*************************************************************************************************/ +/*! + * \brief Get top element in Tx queue. + * + * \param pBisCtx Connection context. + * \param burstIdx Burst index. + * \param descs Storage for BB descriptors. + * + * \return Number of BB descriptors. + */ +/*************************************************************************************************/ +uint8_t lctrBisTxQueuePeek(lctrBisCtx_t *pBisCtx, uint8_t burstIdx, PalBbBleTxBufDesc_t *descs) +{ + wsfHandlerId_t handlerId; + lctrIsoTxBufDesc_t *pDesc; + uint8_t descCnt = 0; + uint8_t sduCnt = 0; + + if (burstIdx > pBisCtx->pBigCtx->bn) + { + /* Advance to the pre-transmission PDU. */ + burstIdx += pBisCtx->pBigCtx->pto * pBisCtx->pBigCtx->bn; + } + + /* Do not remove from queue until burst completes. */ + while ((pDesc = WsfMsgNPeek(&pBisCtx->roleData.slv.txDataQ, sduCnt++, &handlerId)) != NULL) + { + if (pDesc->isoLen > 0) + { + unsigned int numFrag = LlMathDivideUint32RoundUp(pDesc->isoLen, pDesc->fragLen); + + if (burstIdx >= numFrag) + { + /* Advance to next SDU. */ + burstIdx -= numFrag; + continue; + } + + uint8_t fragCnt = burstIdx; + uint16_t fragOffs = pDesc->fragLen * fragCnt; + + if (fragOffs < pDesc->isoLen) + { + uint16_t fragSize = WSF_MIN(pDesc->isoLen - fragOffs, pDesc->fragLen); + + descs[0].len = pDesc->frag[fragCnt].hdrLen; + descs[0].pBuf = pDesc->frag[fragCnt].hdr; + descs[1].len = fragSize; + descs[1].pBuf = pDesc->pPduBuf + fragOffs; + descs[2].pBuf = NULL; + descCnt = 2; + if (pDesc->frag[fragCnt].trlLen) + { + descs[2].len = pDesc->frag[fragCnt].trlLen; + descs[2].pBuf = pDesc->frag[fragCnt].trl; + descCnt = 3; + } + + /* Exit loop. */ + break; + } + } + else + { + /* Zero length PDU. */ + descs[0].len = pDesc->frag[0].hdrLen; + descs[0].pBuf = pDesc->frag[0].hdr; + descs[1].pBuf = NULL; + descCnt = 1; + + /* Exit loop. */ + break; + } + } + + return descCnt; +} + +/*************************************************************************************************/ +/*! + * \brief Pop top element from Tx queue. + * + * \param pBisCtx BIS context. + * \param numFrag Number of fragments to cleanup. + */ +/*************************************************************************************************/ +void lctrBisTxQueuePopCleanup(lctrBisCtx_t *pBisCtx, uint8_t numFrag) +{ + lctrIsoTxBufDesc_t *pDesc; + wsfHandlerId_t handlerId; + + while (numFrag-- && + ((pDesc = WsfMsgPeek(&pBisCtx->roleData.slv.txDataQ, &handlerId)) != NULL)) + { + pDesc->fragCnt++; + + if ((pDesc->fragLen * pDesc->fragCnt) >= pDesc->isoLen) /* last fragment */ + { + WsfMsgDeq(&pBisCtx->roleData.slv.txDataQ, &handlerId); + WsfMsgFree(pDesc->pIsoSdu); + lctrFreeIsoTxBufDesc(pDesc); + lctrIsoSduTxIncAvailBuf(); + + if (pBisCtx->path == LL_ISO_DATA_PATH_HCI) + { + /* ISO Test does not send Tx Complete notifications. */ + if (!pBisCtx->test.enabled) + { + pBisCtx->roleData.slv.numTxSduComp++; + } + } + } + } +} + +/*************************************************************************************************/ +/*! + * \brief Allocate a Tx BIS Control PDU buffer. + * + * \param pduLen Control PDU length. + * + * \return BIS Control PDU buffer or NULL if out of memory. + */ +/*************************************************************************************************/ +uint8_t *lctrBigTxCtrlAlloc(uint8_t pduLen) +{ + uint8_t *pBuf; + + if ((pBuf = WsfBufAlloc(LCTR_Q_ELEM_LEN + + sizeof(uint32_t) /* ReTx data with padding */ + + LL_DATA_HDR_LEN + + sizeof(uint8_t) /* Opcode */ + + pduLen)) == NULL) + { + return NULL; + } + + /* Return pointer to start of header. */ + return pBuf + LCTR_Q_ELEM_LEN + sizeof(uint32_t); +} + +/*************************************************************************************************/ +/*! + * \brief Queue a BIS Control PDU for transmission. + * + * \param pBigCtx BIG context. + * \param pBuf BIS Control PDU buffer. + * \param numReTx Number of retransmissions. + */ +/*************************************************************************************************/ +void lctrBigTxCtrlQueue(lctrBigCtx_t *pBigCtx, uint8_t *pBuf, uint8_t numReTx) +{ + /* Recover start of buffer. */ + pBuf -= sizeof(uint32_t); + + /* First byte is the retransmission number. */ + pBuf[0] = numReTx; + + /* Recover start of queue element. */ + pBuf -= LCTR_Q_ELEM_LEN; + + WsfQueuePush(&pBigCtx->roleData.slv.txCtrlQ, pBuf); +} + +/*************************************************************************************************/ +/*! + * \brief Get top element in Tx BIG control queue. + * + * \param pBigCtx BIG context. + * + * \return Control PDU buffer or NULL if none available. + */ +/*************************************************************************************************/ +uint8_t *lctrBigTxCtrlQueuePeek(lctrBigCtx_t *pBigCtx) +{ + uint8_t *pBuf; + + /* Queue peek. */ + if ((pBuf = pBigCtx->roleData.slv.txCtrlQ.pHead) != NULL) + { + /* Return pointer to start of header. */ + return pBuf + LCTR_Q_ELEM_LEN + sizeof(uint32_t); + } + + /* No more BIS Control PDUs. */ + return NULL; +} + +/*************************************************************************************************/ +/*! + * \brief Pop top element in Tx BIG control queue if retransmissions completed. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +void lctrBigTxCtrlQueuePop(lctrBigCtx_t *pBigCtx) +{ + uint8_t *pBuf; + + /* Queue peek. */ + pBuf = pBigCtx->roleData.slv.txCtrlQ.pHead; + + if (pBuf) + { + /* Recover start buffer. */ + pBuf += LCTR_Q_ELEM_LEN; + + /* Decrease retransmission count. */ + pBuf[0]--; + + if (pBuf[0] == 0) + { + /* No more retransmissions; cleanup and skip to next BIS Control PDU. */ + lctrBigTxCtrlQueuePopCleanup(pBigCtx); + pBigCtx->bcp.cssn++; + } + } +} + +/*************************************************************************************************/ +/*! + * \brief Pop top element from Tx BIG control queue. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +void lctrBigTxCtrlQueuePopCleanup(lctrBigCtx_t *pBigCtx) +{ + uint8_t *pBuf = WsfQueueDeq(&pBigCtx->roleData.slv.txCtrlQ); + + if (pBuf) + { + WsfBufFree(pBuf); + } +} + +/*************************************************************************************************/ +/*! + * \brief Allocate a receive ISO Data PDU buffer. + * + * \return Pointer to the start of the ISO Data PDU buffer. + */ +/*************************************************************************************************/ +uint8_t *lctrBisRxIsoDataPduAlloc(void) +{ + const uint32_t allocLen = HCI_ISO_DL_MAX_LEN + pLctrRtCfg->maxIsoSduLen + BB_DATA_PDU_TAILROOM; + + if (lmgrIsoCb.availRxBuf == 0) + { + /* Flow control Rx path. */ + return NULL; + } + + uint8_t *pPdu; + + /* Use LL_ISO_PDU_MAX_LEN to ensure use of data buffers located in the large pool. */ + if ((pPdu = (uint8_t*)WsfMsgAlloc(allocLen)) != NULL) + { + /* Return start of ISO Data PDU. */ + pPdu += LCTR_ISO_SDU_START_OFFSET; + + /* Do not claim buffer until committed. */ + /* lctrIsoDataRxDecAvailBuf(); */ + } + + return pPdu; +} + +/*************************************************************************************************/ +/*! + * \brief Dequeue a received ISO SDU buffer. + * + * \param pBisCtx BIS context. + * + * \return Pointer to the start of the ISO SDU. + * + * \note Returned pointer must be freed with WsfMsgFree(). + */ +/*************************************************************************************************/ +uint8_t *lctrBisRxIsoSduDeq(lctrBisCtx_t *pBisCtx) +{ + wsfHandlerId_t bisHandle; + + uint8_t *pSdu = WsfMsgDeq(&pBisCtx->roleData.mst.rxIsoSduQ, &bisHandle); + + 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(); +} + +/*************************************************************************************************/ +/*! + * \brief Allocate a receive ISO Data PDU buffer. + * + * \param pPdu Pointer to the start of the ISO Data PDU buffer. + */ +/*************************************************************************************************/ +void lctrBisRxIsoDataPduFree(uint8_t *pPdu) +{ + /* Recover start of buffer. */ + WsfMsgFree(pPdu - LCTR_ISO_SDU_START_OFFSET); +} + +/*************************************************************************************************/ +/*! + * \brief Enqueue a receive ISO Data PDU buffer. + * + * \param pBisCtx BIS context. + * \param pRxBuf Received PDU data buffer to queue. + * \param evtCtr Event counter when packet was received. + */ +/*************************************************************************************************/ +void lctrBisEnqueueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t *pRxBuf, uint64_t evtCtr) +{ + WsfMsgEnq(&pBisCtx->roleData.mst.rxDataQ, (uint8_t)evtCtr, pRxBuf - LCTR_ISO_SDU_START_OFFSET); +} + +/*************************************************************************************************/ +/*! + * \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 *pBuf; + uint8_t temp8; + + if (pEvtCtrLsb == NULL) + { + pEvtCtrLsb = &temp8; + } + + if ((pBuf = WsfMsgDeq(&pBisCtx->roleData.mst.rxDataQ, pEvtCtrLsb)) == NULL) + { + return NULL; + } + + return pBuf + LCTR_ISO_SDU_START_OFFSET; +} + +/*************************************************************************************************/ +/*! + * \brief Enable BIS Tx test. + * + * \param pBisCtx BIS context. + * \param pldType Payload length type. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t lctrBisTxTest(lctrBisCtx_t *pBisCtx, uint8_t pldType) +{ + uint8_t status = LL_SUCCESS; + + if (pBisCtx->test.enabled || pBisCtx->test.term) + { + LL_TRACE_WARN0("Invalid ISO Test state, test mode already enabled"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + if (lmgrIsoCb.availTxBuf == 0) + { + LL_TRACE_WARN0("Out of memory, no ISO Tx buffers available"); + return LL_ERROR_CODE_MEM_CAP_EXCEEDED; + } + + /* BIS Data PDU generation occurs ever SDU Interval in lctrSlvBigEndOp(). */ + + pBisCtx->test.enabled = TRUE; + pBisCtx->test.term = FALSE; + pBisCtx->test.util.framed.payloadCtr = 0; +#if (LL_ENABLE_TESTER) + pBisCtx->test.util.framed.payloadCtr = llTesterCb.isoTxTestNumInit; +#endif + pBisCtx->test.pldType = pldType; + + return status; +} + +/*************************************************************************************************/ +/*! + * \brief Enable BIS Rx test. + * + * \param pBisCtx BIS context. + * \param pldType Payload length type. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t lctrBisRxTest(lctrBisCtx_t *pBisCtx, uint8_t pldType) +{ + uint8_t status = LL_SUCCESS; + + if (pBisCtx->test.enabled || pBisCtx->test.term) + { + LL_TRACE_WARN0("Invalid ISO Test state, test mode already enabled"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + pBisCtx->test.enabled = TRUE; + pBisCtx->test.term = FALSE; + pBisCtx->test.pendInit = TRUE; + pBisCtx->test.pldType = pldType; + memset(&pBisCtx->roleData.mst.stats, 0, sizeof(pBisCtx->roleData.mst.stats)); + + return status; +} + +/*************************************************************************************************/ +/*! + * \brief BIS read ISO test counters. + * + * \param pBisCtx BIS context. + * \param pStats Pointer to the statistics block. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrBisReadTestCounters(lctrBisCtx_t *pBisCtx, LlIsoTestCtrs_t *pStats) +{ + if (pBisCtx->test.enabled == FALSE) + { + LL_TRACE_WARN0("Invalid ISO Test state, test mode must be enabled"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + *pStats = pBisCtx->roleData.mst.stats; + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Initialize connected isochronous memory resources. + * + * \param pFreeMem Pointer to free memory. + * \param freeMemSize Size of pFreeMem. + * + * \return Amount of free memory consumed. + */ +/*************************************************************************************************/ +uint16_t LctrInitBisMem(uint8_t *pFreeMem, uint32_t freeMemSize) +{ + uint8_t *pAvailMem = pFreeMem; + + /*** Advertising Set Context ***/ + + if (((uint32_t)pAvailMem) & 3) + { + /* Align to next word. */ + pAvailMem = (uint8_t *)(((uint32_t)pAvailMem & ~3) + sizeof(uint32_t)); + } + + LL_TRACE_INFO2(" RAM: %u x %u bytes -- BIS context", pLctrRtCfg->maxBis, sizeof(lctrBisCtx_t)); + + /* Allocate BIS context memory. */ + pLctrBisTbl = (lctrBisCtx_t *)pAvailMem; + pAvailMem += sizeof(lctrBisCtx_t) * pLctrRtCfg->maxBis; + + if (((uint32_t)pAvailMem) & 3) + { + /* Align to next word. */ + pAvailMem = (uint8_t *)(((uint32_t)pAvailMem & ~3) + sizeof(uint32_t)); + } + + LL_TRACE_INFO2(" RAM: %u x %u bytes -- BIG context", pLctrRtCfg->maxBig, sizeof(lctrBigCtx_t)); + + /* Allocate BIG context memory. */ + pLctrBigTbl = (lctrBigCtx_t *)pAvailMem; + pAvailMem += sizeof(lctrBigCtx_t) * pLctrRtCfg->maxBig; + + if (((uint32_t)(pAvailMem - pFreeMem)) > freeMemSize) + { + LL_TRACE_ERR2("LctrInitBisMem: failed to allocate BIG, need=%u available=%u", (pAvailMem - pFreeMem), freeMemSize); + WSF_ASSERT(FALSE); + return 0; + } + + lmgrPersistCb.bisCtxSize = sizeof(lctrBisCtx_t); + lmgrPersistCb.bigCtxSize = sizeof(lctrBigCtx_t); + + return (pAvailMem - pFreeMem); +} + +/*************************************************************************************************/ +/*! + * \brief BIS Tx Data PDU complete handler. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +void lctrNotifyIsoTxComplete(lctrBigCtx_t *pBigCtx) +{ + uint8_t numHandles = 0; + uint16_t handle[LL_MAX_BIS] = { 0 }; + uint16_t numSdu[LL_MAX_BIS] = { 0 }; + + /* Tally total transmitted SDUs. */ + for (unsigned int i = 0; i < pBigCtx->numBis; i++) + { + lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[i]; + + if (pBisCtx->path == LL_ISO_DATA_PATH_HCI) + { + if (pBisCtx->roleData.slv.numTxSduComp) + { + handle[numHandles] = pBisCtx->handle; + numSdu[numHandles] = pBisCtx->roleData.slv.numTxSduComp; + pBisCtx->roleData.slv.numTxSduComp = 0; + numHandles++; + } + } + } + + if (numHandles) + { + /* Notify host completed SDUs. */ + lmgrPersistCb.sendIsoCompCback(numHandles, handle, numSdu); + } +} + +/*************************************************************************************************/ +/*! + * \brief Calculate Group session key. + * + * \param pGSKD Group Session Key Diversifier. + * \param pBC Broadcast Code. + * \param pGSK Group Session Key result. + */ +/*************************************************************************************************/ +void lctrBisCalcGroupSessionKey(const uint8_t *pGSKD, const uint8_t *pBC, uint8_t *pGSK) +{ + static const uint8_t big1[PAL_CRYPTO_LL_KEY_LEN] = { 0x31, 0x47, 0x49, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static const uint8_t big2[4] = { 0x32, 0x47, 0x49, 0x42 }; + static const uint8_t big3[4] = { 0x33, 0x47, 0x49, 0x42 }; + uint8_t igltk[PAL_CRYPTO_LL_KEY_LEN]; + uint8_t gltk[PAL_CRYPTO_LL_KEY_LEN]; + uint8_t ik[PAL_CRYPTO_LL_KEY_LEN]; + + /* IGLTK = h7("BIG1", Broadcast_Code) */ + PalCryptoAesCmac(big1, igltk, pBC, 16); + + /* GLTK = h6(IGLTK, "BIG2") */ + PalCryptoAesCmac(igltk, gltk, big2, 4); + + /* GSK = h8(GLTK, GSKD, "BIG3") */ + PalCryptoAesCmac(pGSKD, ik, gltk, 16); + 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. + * + * \param pBigCtx BIG context. + * \param pSeCtx Subevent context. + * \param numSePkts Total number of subevent packets. + * + * \return TRUE if more subevents pending, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lctrSlvBisCalcNextIdxSequential(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts) +{ + /* Burst loop. */ + + pSeCtx->burstIdx++; + + if (pSeCtx->burstIdx >= pBigCtx->bn) /* Last burst */ + { + pSeCtx->burstIdx = 0; + + /* Retransmission loop. */ + + pSeCtx->repIdx++; + + if (pSeCtx->repIdx >= pBigCtx->irc) /* Last retransmission */ + { + pSeCtx->repIdx = 0; + + if (numSePkts < pBigCtx->nse) + { + /* Pretransmission loop. */ + + pSeCtx->ptIdx++; + numSePkts++; + } + else + { + /* BIS loop. */ + + pSeCtx->bisEvtIdx++; + + if (pSeCtx->bisEvtIdx >= pBigCtx->numBis) /* Last BIS */ + { + /* Control SubEvent */ + return FALSE; + } + } + } + } + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Calculate next subevent index values, using interleaved packing. + * + * \param pBigCtx BIG context. + * \param pSeCtx Subevent context. + * \param numSePkts Total number of subevent packets. + * + * \return TRUE if more subevents pending, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lctrSlvBisCalcNextIdxInterleaved(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts) +{ + /* BIS loop. */ + + pSeCtx->bisEvtIdx++; + + if (pSeCtx->bisEvtIdx >= pBigCtx->numBis) /* Last BIS */ + { + pSeCtx->bisEvtIdx = 0; + + /* Burst loop. */ + + pSeCtx->burstIdx++; + + if (pSeCtx->burstIdx >= pBigCtx->bn) /* Last burst */ + { + pSeCtx->burstIdx = 0; + + /* Retransmission loop. */ + + pSeCtx->repIdx++; + + if (pSeCtx->repIdx >= pBigCtx->irc) /* Last retransmission */ + { + pSeCtx->repIdx = 0; + + /* Pretransmission loop. */ + + pSeCtx->ptIdx++; + numSePkts++; + + if (numSePkts > pBigCtx->nse) + { + /* Control SubEvent */ + return FALSE; + } + } + } + } + + return TRUE; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis_master.c new file mode 100644 index 0000000000..3b93cd3896 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis_master.c @@ -0,0 +1,517 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller master operation builder implementation file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_bis_master.h" +#include "lctr_api_bis_master.h" +#include "lctr_int_iso.h" +#include "sch_api.h" +#include "wsf_math.h" +#include "wsf_msg.h" +#include "wsf_timer.h" +#include + +/************************************************************************************************** + Globals +**************************************************************************************************/ + +/*! \brief BIG message data. */ +lctrMstBigMsg_t *pLctrMstBigMsg; + +/*************************************************************************************************/ +/*! + * \brief BIS master message dispatcher. + * + * \param pMsg Pointer to message buffer. + */ +/*************************************************************************************************/ +static void lctrMstBigDisp(lctrMsgHdr_t *pMsg) +{ + pLctrMstBigMsg = (lctrMstBigMsg_t *)pMsg; + + if ((pMsg->dispId != LCTR_DISP_BCST) && + (pMsg->event != LCTR_MST_BIG_ACAD_BIG_INFO)) + { + lctrBigCtx_t *pBigCtx; + + if ((pBigCtx = lctrFindBigByHandle(pMsg->handle)) != NULL) + { + lctrMstBigExecuteSm(pBigCtx, pMsg->event); + } + } + else + { + for (unsigned int i = 0; i < pLctrRtCfg->maxBig; i++) + { + if (pLctrBigTbl[i].enabled && (pLctrBigTbl[i].role == LL_ROLE_MASTER)) + { + pMsg->handle = pLctrBigTbl[i].handle; + lctrMstBigExecuteSm(&pLctrBigTbl[i], pMsg->event); + } + } + } +} + +/*************************************************************************************************/ +/*! + * \brief BIS master reset handler. + */ +/*************************************************************************************************/ +static void lctrMstBisResetHandler(void) +{ + lctrBisDefaults(); +} + +/*************************************************************************************************/ +/*! + * \brief Periodic sync termination handler. + * + * \param syncHandle Periodic Sync handle. + */ +/*************************************************************************************************/ +static void lctrMstPerTermSync(uint16_t syncHandle) +{ + lctrBigCtx_t *pBigCtx; + + if ((pBigCtx = lctrFindBigBySyncHandle(syncHandle)) != NULL) + { + WSF_ASSERT(pBigCtx->role == LL_ROLE_MASTER); + + if (pBigCtx->roleData.mst.pPerScanCtx) + { + pBigCtx->roleData.mst.pPerScanCtx = NULL; + } + } +} + +/*************************************************************************************************/ +/*! + * \brief Initialize link layer controller resources for BIS master. + */ +/*************************************************************************************************/ +void LctrMstBisInit(void) +{ + /* Add reset handler. */ + lctrResetHdlrTbl[LCTR_DISP_BIG_SYNC] = lctrMstBisResetHandler; + + /* Add BIS slave message dispatcher. */ + lctrMsgDispTbl[LCTR_DISP_BIG_SYNC] = (LctrMsgDisp_t)lctrMstBigDisp; + + lctrBisDefaults(); + + /* Set supported features. */ + if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_5_1) + { + lmgrPersistCb.featuresDefault |= LL_FEAT_ISO_BROADCASTER; + } +} + +/*************************************************************************************************/ +/*! + * \brief BIG create sync + * + * \param pParam BIG Create Sync parameters. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrMstBigCreateSync(LlBigCreateSync_t *pParam) +{ + lctrBigCtx_t *pBigCtx; + LctrAcadBigInfo_t *pBigInfo; + lctrPerScanCtx_t *pPerScanCtx; + + if (lctrIsBigSynchronizing()) + { + LL_TRACE_WARN0("LctrMstBigCreateSync: BIG synchronization in progress"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + if (lctrFindBigByHandle(pParam->bigHandle) != NULL) + { + LL_TRACE_WARN1("LctrMstBigCreateSync: bigHandle=%u already in use", pParam->bigHandle); + return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; + } + + pPerScanCtx = LCTR_GET_PER_SCAN_CTX(pParam->syncHandle); + + if ((pParam->syncHandle > LL_MAX_PER_SCAN) || + (pPerScanCtx->enabled == FALSE)) + { + LL_TRACE_WARN1("LctrMstBigCreateSync: syncHandle=%u not found", pParam->syncHandle); + return LL_ERROR_CODE_UNKNOWN_ADV_ID; + } + + if (lctrFindBigBySyncHandle(pParam->syncHandle) != NULL) + { + LL_TRACE_WARN1("LctrMstBigCreateSync: syncHandle=%u already in use", pParam->syncHandle); + return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; + } + + if (pPerScanCtx->acadParams[LCTR_ACAD_ID_BIG_INFO].hdr.len == 0) /* BIG Info received */ + { + LL_TRACE_WARN0("LctrMstBigCreateSync: synchronizer not ready; BIG Info not received"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + pBigInfo = &pPerScanCtx->acadParams[LCTR_ACAD_ID_BIG_INFO].bigInfo; + + if (pParam->numBis > lctrGetNumAvailBisCtx()) + { + LL_TRACE_WARN0("LctrMstBigCreateSync: insufficient BIS context"); + 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) || + (pParam->bis[i] > LL_MAX_BIS)) + { + LL_TRACE_WARN2("BIS=%u at index=%u out of range", pParam->bis[i], i); + return LL_ERROR_CODE_PARAM_OUT_OF_MANDATORY_RANGE; + } + } + + if (pParam->encrypt != pBigInfo->encrypt) + { + LL_TRACE_WARN0("LctrMstBigCreateSync: encryption mode mismatch"); + return LL_ERROR_CODE_ENCRYPT_MODE_NOT_ACCEPTABLE; + } + + if ((pBigCtx = lctrAllocBigCtx(pParam->bigHandle)) == NULL) + { + LL_TRACE_WARN0("LctrMstBigCreateSync: insufficient BIG context"); + return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES; + } + + pBigCtx->handle = pParam->bigHandle; + pPerScanCtx->termCback = lctrMstPerTermSync; + pBigCtx->roleData.mst.pPerScanCtx = pPerScanCtx; + pBigCtx->roleData.mst.mse = pParam->mse; + pBigCtx->roleData.mst.bigSyncTimeoutMs = pParam->bigSyncTimeout * 10; + pBigCtx->roleData.mst.numBisIdx = pParam->numBis; + memcpy(pBigCtx->roleData.mst.bisIdx, pParam->bis, pParam->numBis); + pBigCtx->encrypt = pParam->encrypt; + memcpy(pBigCtx->roleData.mst.bcstCode, pParam->bcstCode, LL_BC_LEN); + + /* Setup timer. */ + pBigCtx->roleData.mst.bigSyncTmr.handlerId = lmgrPersistCb.handlerId; + lctrMsgHdr_t *pMsg = (lctrMsgHdr_t *)&pBigCtx->roleData.mst.bigSyncTmr.msg; + pMsg->handle = pBigCtx->handle; + pMsg->dispId = LCTR_DISP_BIG_SYNC; + pMsg->event = LCTR_MST_BIG_INT_SYNC_TIMEOUT; + + if ((pMsg = WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->handle = pParam->bigHandle; + pMsg->dispId = LCTR_DISP_BIG_SYNC; + pMsg->event = LCTR_MST_BIG_API_CREATE_SYNC; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief BIG terminate sync + * + * \param bigHandle Used to identify the BIG. + */ +/*************************************************************************************************/ +void LctrMstBigTerminateSync(uint8_t bigHandle) +{ + lctrBigCtx_t *pBigCtx; + + if ((pBigCtx = lctrFindBigByHandle(bigHandle)) == NULL) + { + LL_TRACE_WARN1("LctrMstBigTerminateSync: unknown handle bigHandle=%u", bigHandle); + lctrNotifyHostBigTerminateComplete(LL_ERROR_CODE_UNKNOWN_ADV_ID, bigHandle); + return; + } + + if (pBigCtx->role != LL_ROLE_MASTER) + { + LL_TRACE_WARN0("LctrMstBigTerminateSync: invalid role"); + lctrNotifyHostBigTerminateComplete(LL_ERROR_CODE_CMD_DISALLOWED, bigHandle); + return; + } + + lctrMsgHdr_t *pMsg; + + if ((pMsg = WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->handle = bigHandle; + pMsg->dispId = LCTR_DISP_BIG_SYNC; + pMsg->event = LCTR_MST_BIG_API_TERMINATE_SYNC; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } +} + +/*************************************************************************************************/ +/*! + * \brief Build BIG operation. + * + * \param pBigCtx BIG Context. + * \param pBigInfo BIG Info parameters from Broadcaster. + */ +/*************************************************************************************************/ +void lctrMstBigBuildOp(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo) +{ + lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[0]; + + BbOpDesc_t * const pOp = &pBigCtx->bod; + BbBleData_t * const pBle = &pBigCtx->bleData; + BbBleMstBisEvent_t * const pBis = &pBle->op.mstBis; + + memset(pOp, 0, sizeof(BbOpDesc_t)); + memset(pBle, 0, sizeof(BbBleData_t)); + memset(pBis, 0, sizeof(BbBleMstBisEvent_t)); + + /*** General Setup ***/ + + pOp->reschPolicy = BB_RESCH_FIXED_PREFERRED; + pOp->protId = BB_PROT_BLE; + pOp->prot.pBle = pBle; + pOp->endCback = lctrMstBigEndOp; + pOp->abortCback = lctrMstBigEndOp; + pOp->pCtx = pBigCtx; + + /*** BLE General Setup ***/ + + pBle->chan = pBisCtx->chan; + + /*** General setup ***/ + + pOp->minDurUsec = pBigInfo->subEvtInterUsec; + pOp->maxDurUsec = pBigInfo->subEvtInterUsec * pBigInfo->bn; + + /*** BIS setup ***/ + + /* pBis->rxSyncDelayUsec = 0; */ /* Deferred until BOD scheduled. */ + pBis->execCback = lctrMstBigBeginOp; + + switch (pBigCtx->packing) + { + case LL_PACKING_INTERLEAVED: + pBis->rxDataCback = lctrMstBisRxCompletion; + break; + + case LL_PACKING_SEQUENTIAL: + default: + pBis->rxDataCback = lctrMstBisRxCompletion; + break; + } + + /*** Commit operation ***/ + + /* Originate from peer's N-1 anchor point timing. */ + 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; + uint32_t unsyncTimeUsec = 0; + + while (TRUE) + { + uint32_t wwTotalUsec = lctrCalcWindowWideningUsec(unsyncTimeUsec, pBigCtx->roleData.mst.totalAcc); + /* TODO Limit to half the ISO Interval size */ + + pOp->dueUsec = pBigCtx->roleData.mst.anchorPoint - wwTotalUsec; + /* Multiply 2 for before and after BIG Anchor Point. */ + pBis->rxSyncDelayUsec = (wwTotalUsec << 1) + pBigCtx->roleData.mst.extraWwUsec; + + lctrSelectBigChannels(pBigCtx); + + if (SchInsertAtDueTime(pOp, NULL)) + { + break; + } + + LL_TRACE_WARN1("!!! BIG schedule conflict handle=%u", pBigCtx->handle); + + /* Advance to next interval. */ + pBigCtx->eventCounter += 1; + pBigCtx->roleData.mst.anchorPoint += pBigCtx->isoInterUsec; + unsyncTimeUsec += pBigCtx->isoInterUsec; + } + + LL_TRACE_INFO2(" >>> BIG synced, handle=%u, numBis=%u <<<", pBigCtx->handle, pBigCtx->numBis); + LL_TRACE_INFO3(" bn=%u, nse=%u, irc=%u", pBigCtx->bn, pBigCtx->nse, pBigCtx->irc); + LL_TRACE_INFO3(" pto=%u, framing=%u, packing=%u", pBigCtx->pto, pBigCtx->framing, pBigCtx->packing); + LL_TRACE_INFO1(" isoInterUsec=%u", pBigCtx->isoInterUsec); + LL_TRACE_INFO1(" bisSpaceUsec=%u", pBigCtx->bisSpaceUsec); + LL_TRACE_INFO1(" subInterUsec=%u", pBigCtx->subInterUsec); + LL_TRACE_INFO1(" eventCounter=%u", pBigCtx->eventCounter); + LL_TRACE_INFO1(" seedAccAddr=0x%08x", pBigCtx->seedAccAddr); + LL_TRACE_INFO1(" pBod=0x%08x", pOp); +} + +/*************************************************************************************************/ +/*! + * \brief Setup BIG context. + * + * \param pBigCtx BIG context. + * \param pBigInfo BIG Info. + */ +/*************************************************************************************************/ +void lctrMstSetupBigContext(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo) +{ + /* Packet */ + pBigCtx->maxPdu = pBigInfo->maxPdu; + pBigCtx->maxSdu = pBigInfo->maxSdu; + pBigCtx->seedAccAddr = pBigInfo->seedAccAddr; + pBigCtx->baseCrcInit = pBigInfo->baseCrcInit; + + /* Event */ + pBigCtx->bn = pBigInfo->bn; + pBigCtx->nse = pBigInfo->nse; + pBigCtx->irc = pBigInfo->irc; + pBigCtx->pto = pBigInfo->pto; + pBigCtx->framing = pBigInfo->framing; + pBigCtx->eventCounter = pBigInfo->bisPldCtr / pBigInfo->bn; /* TODO use optimized 64-bit divide */ + if (pBigInfo->bisSpaceUsec >= pBigInfo->subEvtInterUsec) + { + pBigCtx->packing = LL_PACKING_SEQUENTIAL; + } + else + { + pBigCtx->packing = LL_PACKING_INTERLEAVED; + } + + /* Control */ + pBigCtx->bcp.cssn = 0xFF; /* ensure reception of initial BIS Control PDU */ + + /* Radio */ + pBigCtx->phy = pBigInfo->phy; + + /* Encryption */ + pBigCtx->encrypt = pBigInfo->encrypt; + if (pBigCtx->encrypt) + { + memcpy(pBigCtx->giv, pBigInfo->giv, sizeof(pBigCtx->giv)); + memcpy(pBigCtx->gskd, pBigInfo->gskd, sizeof(pBigCtx->gskd)); + + /* Setup encryption parameters. */ + lctrBisCalcGroupSessionKey(pBigCtx->gskd, pBigCtx->roleData.mst.bcstCode, pBigCtx->bleData.chan.enc.sk); + } + + /* Timing */ + pBigCtx->isoInterUsec = pBigInfo->isoInter * 1250; + pBigCtx->bisSpaceUsec = pBigInfo->bisSpaceUsec; + pBigCtx->subInterUsec = pBigInfo->subEvtInterUsec; + /* pBigCtx->syncDelayUsec = N/A; */ + pBigCtx->sduInterUsec = pBigInfo->sduInterUsec; + pBigCtx->roleData.mst.totalAcc = lctrCalcTotalAccuracy(LL_MCA_20_PPM); +} + +/*************************************************************************************************/ +/*! + * \brief Setup BIG channelization parameters. + * + * \param pBigCtx BIG context. + * \param pBigInfo BIG Info. + */ +/*************************************************************************************************/ +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->ctrChan.crcInit = (pBigCtx->baseCrcInit << 8) | 0; + pBigCtx->ctrChan.rxPhy = pBigCtx->phy; + +#if (LL_ENABLE_TESTER) + pBigCtx->ctrChan.accAddrRx = pBigCtx->ctrChan.accAddr ^ llTesterCb.dataAccessAddrRx; + pBigCtx->ctrChan.accAddrTx = pBigCtx->ctrChan.accAddr ^ llTesterCb.dataAccessAddrTx; + pBigCtx->ctrChan.crcInitRx = pBigCtx->ctrChan.crcInit ^ llTesterCb.dataCrcInitRx; + pBigCtx->ctrChan.crcInitTx = pBigCtx->ctrChan.crcInit ^ llTesterCb.dataCrcInitTx; +#endif + + if (pBigCtx->encrypt) + { + pBigCtx->ctrChan.enc.enaDecrypt = TRUE; + pBigCtx->ctrChan.enc.enaAuth = TRUE; + 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; + + memcpy(pBigCtx->ctrChan.enc.sk, pBigCtx->bleData.chan.enc.sk, PAL_CRYPTO_LL_KEY_LEN); + + /* The directionBit shall be set to 1 for Broadcast Isochronous PDUs. */ + pBigCtx->ctrChan.enc.dir = 1; + pBigCtx->ctrChan.enc.type = PAL_BB_TYPE_BIS; + + lctrInitCipherBlkHdlr(&pBigCtx->ctrChan.enc, LCTR_BIG_CTRL_ENC_ID(pBigCtx), 1); + } +} + +/*************************************************************************************************/ +/*! + * \brief Send internal master BIG subsystem message. + * + * \param pBigCtx BIG context. + * \param event Master BIG event. + */ +/*************************************************************************************************/ +void lctrMstBigSendMsg(lctrBigCtx_t *pBigCtx, LctrMstBigMsg_t event) +{ + lctrMsgHdr_t *pMsg; + + if ((pMsg = WsfMsgAlloc(sizeof(lctrMsgHdr_t))) != NULL) + { + pMsg->handle = pBigCtx->handle; + pMsg->dispId = LCTR_DISP_BIG_SYNC; + pMsg->event = event; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } +} + +/*************************************************************************************************/ +/*! + * \brief Set default values for BIS. + */ +/*************************************************************************************************/ +void lctrBisDefaults(void) +{ + memset(pLctrBisTbl, 0, sizeof(lctrBisCtx_t) * pLctrRtCfg->maxBis); + memset(pLctrBigTbl, 0, sizeof(lctrBigCtx_t) * pLctrRtCfg->maxBig); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis_slave.c new file mode 100644 index 0000000000..1928a6384b --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_bis_slave.c @@ -0,0 +1,966 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller slave operation builder implementation file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_bis_slave.h" +#include "lctr_pdu_adv_ae.h" +#include "lctr_int_iso.h" +#include "sch_api.h" +#include "sch_api_ble.h" +#include "wsf_assert.h" +#include "wsf_math.h" +#include + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +extern uint8_t lctrChoosePreferredPhy(uint8_t val); + +/************************************************************************************************** + Local Function +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Compute the maximum PDU transmission time in microseconds. + * + * \param phy Transmission PHY. + * \param maxPdu Maximum PDU size. + * \param encrypt Encryption enabled. + * + * \return BIS Space in microseconds. + * + * \note This value includes preamble, access address, CRC and T_MSS. + */ +/*************************************************************************************************/ +static uint32_t lctrBisCalcMaxPduTimeUsec(uint8_t phy, uint8_t maxPdu, uint8_t encrypt) +{ + uint32_t duration; + + switch (phy) + { + case BB_PHY_BLE_1M: + default: + duration = LL_DATA_LEN_TO_TIME_1M(maxPdu, encrypt); + break; + case BB_PHY_BLE_2M: + duration = LL_DATA_LEN_TO_TIME_2M(maxPdu, encrypt); + break; + case BB_PHY_BLE_CODED: + duration = LL_DATA_LEN_TO_TIME_CODED_S8(maxPdu, encrypt); + break; + } + + return duration + LL_BLE_TMSS_US; +} + +/*************************************************************************************************/ +/*! + * \brief Setup BIG context. + * + * \param pBigCtx BIG context. + * \param pCreateBig Create BIG parameters. + */ +/*************************************************************************************************/ +static void lctrSlvSetupBigContext(lctrBigCtx_t *pBigCtx, LlCreateBig_t *pCreateBig) +{ + pBigCtx->role = LL_ROLE_SLAVE; + + pBigCtx->framing = pCreateBig->framing; + pBigCtx->packing = pCreateBig->packing; + + pBigCtx->phy = lctrPhysBitToPhy(lctrChoosePreferredPhy(pCreateBig->phys)); + + pBigCtx->encrypt = pCreateBig->encrypt; + if (pBigCtx->encrypt) + { + /* Generate group parameters. */ + PalCryptoGenerateRandomNumber(pBigCtx->giv, LL_GIV_LEN); + PalCryptoGenerateRandomNumber(pBigCtx->gskd, LL_GSKD_LEN); + + /* Setup encryption parameters. */ + lctrBisCalcGroupSessionKey(pBigCtx->gskd, pCreateBig->bcstCode, pBigCtx->bleData.chan.enc.sk); + } + + /* Packet */ + pBigCtx->maxPdu = WSF_MIN(BB_DATA_PLD_MAX_LEN, pCreateBig->maxSdu); + pBigCtx->maxSdu = pCreateBig->maxSdu; + + /* Event */ + pBigCtx->bn = LlMathDivideUint32RoundUp(pCreateBig->maxSdu, pBigCtx->maxPdu); + pBigCtx->irc = pCreateBig->rtn + 1; + pBigCtx->pto = 0; + pBigCtx->nse = (pBigCtx->bn + pBigCtx->pto) * pBigCtx->irc; + + /* Timing */ + pBigCtx->sduInterUsec = pCreateBig->sduInterUsec; + pBigCtx->isoInterUsec = pCreateBig->sduInterUsec; + /* TODO consider MTL */ + /* TODO consider framing in BIS Space computation */ + + switch (pBigCtx->packing) + { + 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; + break; + } + + case LL_PACKING_SEQUENTIAL: + default: + { + pBigCtx->subInterUsec = lctrBisCalcMaxPduTimeUsec(pBigCtx->phy, pBigCtx->maxPdu, pCreateBig->encrypt); + pBigCtx->bisSpaceUsec = pBigCtx->subInterUsec * pBigCtx->nse; + pBigCtx->syncDelayUsec = pCreateBig->numBis * pBigCtx->bisSpaceUsec; + break; + } + } + + /* 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; + } + else + { + LL_TRACE_ERR0("Invalid BN or sduInterUsec value"); + pBigCtx->transLatUsec = LL_ISO_TRANSPORT_LAT_MIN; + } +} + +/*************************************************************************************************/ +/*! + * \brief Set up a new BIG with test command. + * + * \param pBigCtx BIG context. + * \param pCreateBigTest Create BIG test parameters. + */ +/*************************************************************************************************/ +static void lctrSlvSetupBigTestContext(lctrBigCtx_t *pBigCtx, LlCreateBigTest_t *pCreateBigTest) +{ + pBigCtx->role = LL_ROLE_SLAVE; + + pBigCtx->framing = pCreateBigTest->framing; + pBigCtx->packing = pCreateBigTest->packing; + + pBigCtx->phy = lctrPhysBitToPhy(lctrChoosePreferredPhy(pCreateBigTest->phys)); + + pBigCtx->encrypt = pCreateBigTest->encrypt; + if (pBigCtx->encrypt) + { + /* Generate group parameters. */ + PalCryptoGenerateRandomNumber(pBigCtx->giv, LL_GIV_LEN); + PalCryptoGenerateRandomNumber(pBigCtx->gskd, LL_GSKD_LEN); + + /* Setup encryption parameters. */ + lctrBisCalcGroupSessionKey(pBigCtx->gskd, pCreateBigTest->bcstCode, pBigCtx->bleData.chan.enc.sk); + } + + pBigCtx->maxPdu = pCreateBigTest->maxPdu; + pBigCtx->maxSdu = pCreateBigTest->maxSdu; + pBigCtx->sduInterUsec = pCreateBigTest->sduInterUsec; + pBigCtx->isoInterUsec = LCTR_ISO_INT_TO_US(pCreateBigTest->isoInter); + pBigCtx->bn = pCreateBigTest->bn; + pBigCtx->irc = pCreateBigTest->irc; + pBigCtx->pto = pCreateBigTest->pto; + pBigCtx->nse = (pBigCtx->bn + pBigCtx->pto) * pBigCtx->irc; + + 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; + break; + } + + case LL_PACKING_SEQUENTIAL: + default: + { + pBigCtx->subInterUsec = lctrBisCalcMaxPduTimeUsec(pBigCtx->phy, pBigCtx->maxPdu, pCreateBigTest->encrypt); + pBigCtx->bisSpaceUsec = pBigCtx->subInterUsec * pBigCtx->nse; + pBigCtx->syncDelayUsec = pCreateBigTest->numBis * pBigCtx->bisSpaceUsec; + break; + } + } + + /* 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; + } + else + { + LL_TRACE_ERR0("Invalid BN or sduInterUsec value"); + pBigCtx->transLatUsec = LL_ISO_TRANSPORT_LAT_MIN; + } +} + +/*************************************************************************************************/ +/*! + * \brief Setup BIG channelization parameters. + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +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->ctrChan.crcInit = (pBigCtx->baseCrcInit << 8) | 0; + pBigCtx->ctrChan.txPower = lmgrCb.advTxPwr; + pBigCtx->ctrChan.txPhy = pBigCtx->phy; + pBigCtx->ctrChan.initTxPhyOptions = BB_PHY_OPTIONS_DEFAULT; + pBigCtx->ctrChan.tifsTxPhyOptions = BB_PHY_OPTIONS_DEFAULT; + /* pBigCtx->ctrChan.peerTxStableModIdx = FALSE; */ + +#if (LL_ENABLE_TESTER) + pBigCtx->ctrChan.accAddrRx = pBigCtx->ctrChan.accAddr ^ llTesterCb.dataAccessAddrRx; + pBigCtx->ctrChan.accAddrTx = pBigCtx->ctrChan.accAddr ^ llTesterCb.dataAccessAddrTx; + pBigCtx->ctrChan.crcInitRx = pBigCtx->ctrChan.crcInit ^ llTesterCb.dataCrcInitRx; + pBigCtx->ctrChan.crcInitTx = pBigCtx->ctrChan.crcInit ^ llTesterCb.dataCrcInitTx; +#endif + + if (pBigCtx->encrypt) + { + pBigCtx->ctrChan.enc.enaEncrypt = TRUE; + pBigCtx->ctrChan.enc.enaAuth = TRUE; + 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; + + memcpy(pBigCtx->ctrChan.enc.sk, pBigCtx->bleData.chan.enc.sk, PAL_CRYPTO_LL_KEY_LEN); + + /* The directionBit shall be set to 1 for Broadcast Isochronous PDUs. */ + pBigCtx->ctrChan.enc.dir = 1; + pBigCtx->ctrChan.enc.type = PAL_BB_TYPE_BIS; + + lctrInitCipherBlkHdlr(&pBigCtx->ctrChan.enc, LCTR_BIG_CTRL_ENC_ID(pBigCtx), 1); + } +} + +/*************************************************************************************************/ +/*! + * \brief BIS slave reset handler. + */ +/*************************************************************************************************/ +static void lctrSlvBisResetHandler(void) +{ + lctrBisDefaults(); +} + +/*************************************************************************************************/ +/*! + * \brief BIG slave message dispatcher. + * + * \param pMsg Pointer to message buffer. + */ +/*************************************************************************************************/ +static void lctrSlvBigDisp(LctrSlvBigMsg_t *pMsg) +{ + if (pMsg->hdr.dispId != LCTR_DISP_BCST) + { + lctrBigCtx_t *pBigCtx; + + if ((pBigCtx = lctrFindBigByHandle(pMsg->hdr.handle)) != NULL) + { + lctrSlvBigExecuteSm(pBigCtx, pMsg->hdr.event); + } + } + else + { + for (unsigned int i = 0; i < pLctrRtCfg->maxBig; i++) + { + if (pLctrBigTbl[i].enabled && (pLctrBigTbl[i].role == LL_ROLE_SLAVE)) + { + pMsg->hdr.handle = pLctrBigTbl[i].handle; + lctrSlvBigExecuteSm(&pLctrBigTbl[i], pMsg->hdr.event); + } + } + } +} + +/*************************************************************************************************/ +/*! + * \brief Action function for ACAD BIG created. + * + * \param advHandle Advertising handle + */ +/*************************************************************************************************/ +static void lctrSlvBisAcadBigCreated(uint8_t advHandle) +{ + LctrAcadBigInfo_t *pBigInfo; + lctrAdvSet_t *pAdvSet = lctrFindAdvSet(advHandle); + lctrBigCtx_t *pBigCtx = lctrFindBigByHandle(pLctrAcadSlvMsg->bigCreated.bigHandle); + WSF_ASSERT(pBigCtx); + WSF_ASSERT(pAdvSet); + + pBigInfo = &pAdvSet->acadParams[LCTR_ACAD_ID_BIG_INFO].bigInfo; + + /* A new BigInfo cannot replace a currently running one. */ + WSF_ASSERT(pBigInfo->hdr.state != LCTR_ACAD_STATE_ENABLED); + + if (pBigCtx->encrypt) + { + pBigInfo->hdr.len = LL_ACAD_BIG_INFO_ENCRPT_LEN; + memcpy(pBigInfo->giv, pBigCtx->giv, LL_GIV_LEN); + memcpy(pBigInfo->gskd, pBigCtx->gskd, LL_GSKD_LEN); + } + else + { + pBigInfo->hdr.len = LL_ACAD_BIG_INFO_UNENCRPT_LEN; + } + + pBigInfo->hdr.state = LCTR_ACAD_STATE_ENABLED; + + /* pBigInfo->bigOffs = 0; */ /* deferred until timing values are known */ + /* pBigInfo->bigOffsUnits = 0; */ /* deferred until timing values are known */ + pBigInfo->isoInter = LL_MATH_DIV_1250(pBigCtx->isoInterUsec); + pBigInfo->numBis = pBigCtx->numBis; + pBigInfo->nse = pBigCtx->nse; + pBigInfo->bn = pBigCtx->bn; + pBigInfo->subEvtInterUsec = pBigCtx->subInterUsec; + pBigInfo->pto = pBigCtx->pto; + pBigInfo->bisSpaceUsec = pBigCtx->bisSpaceUsec; + pBigInfo->irc = pBigCtx->irc; + pBigInfo->maxPdu = pBigCtx->maxPdu; + pBigInfo->seedAccAddr = pBigCtx->seedAccAddr; + pBigInfo->sduInterUsec = pBigCtx->sduInterUsec; + pBigInfo->maxSdu = pBigCtx->maxSdu; + pBigInfo->baseCrcInit = pBigCtx->baseCrcInit; + pBigInfo->chanMap = pBigCtx->ctrChSelInfo.chanMask; + pBigInfo->phy = pBigCtx->phy; + pBigInfo->bisPldCtr = pBigCtx->eventCounter * pBigCtx->bn; + pBigInfo->framing = pBigCtx->framing; + pBigInfo->encrypt = pBigCtx->encrypt; +} + +/*************************************************************************************************/ +/*! + * \brief Action function for ACAD BIG created. + * + * \param advHandle Advertising handle + */ +/*************************************************************************************************/ +static void lctrSlvBisAcadBigTerminated(uint8_t advHandle) +{ + lctrAdvSet_t *pAdvSet = lctrFindAdvSet(advHandle); + WSF_ASSERT(pAdvSet) + + lctrSlvAcadDisable(&pAdvSet->acadParams[LCTR_ACAD_ID_BIG_INFO]); +} + +/*************************************************************************************************/ +/*! + * \brief Action function for ACAD BIG created. + * + * \param advHandle Advertising handle + */ +/*************************************************************************************************/ +static void lctrSlvBisRemoveAdvSet(uint8_t advHandle) +{ + lctrAdvSet_t *pAdvSet = lctrFindAdvSet(advHandle); + + for (unsigned int i = 0; i < pLctrRtCfg->maxBig; i++) + { + lctrBigCtx_t *pBigCtx = &pLctrBigTbl[i]; + + if ((pBigCtx->role == LL_ROLE_SLAVE) && + (pBigCtx->roleData.slv.pAdvSet == pAdvSet)) + { + pBigCtx->roleData.slv.pAdvSet = NULL; + break; + } + } +} + +/*************************************************************************************************/ +/*! + * \brief Get reference time (due time) of the next BIG. + * + * \param rmHandle RM handle. + * \param pDurUsec Pointer to duration of the connection BOD. + * + * \return Due time in microseconds of the connection handle. + */ +/*************************************************************************************************/ +static uint32_t lctrGetBigRefTime(uint8_t rmHandle, uint32_t *pDurUsec) +{ + uint32_t refTime = 0; + lctrBigCtx_t *pBigCtx = LCTR_RM_HANDLE_TO_BIG(rmHandle); + + if (pBigCtx->enabled) + { + WSF_ASSERT(pBigCtx->bleData.chan.opType == BB_BLE_OP_SLV_BIS_EVENT); + + refTime = pBigCtx->bod.dueUsec; + + if (pDurUsec) + { + *pDurUsec = pBigCtx->bod.minDurUsec; + } + } + + return refTime; +} + +/*************************************************************************************************/ +/*! + * \brief Host channel class update handler for CIS master. + * + * \param chanMap Updated channel map. + * + * \return Status code. + */ +/*************************************************************************************************/ +static uint8_t lctrMstBigChClassUpdate(uint64_t chanMap) +{ + for (unsigned int i = 0; i < pLctrRtCfg->maxBig; i++) + { + lctrBigCtx_t *pBigCtx = &pLctrBigTbl[i]; + + if (pBigCtx->enabled && (pBigCtx->role == LL_ROLE_SLAVE)) + { + lctrMsgHdr_t *pMsg; + + if ((pMsg = WsfMsgAlloc(sizeof(lctrMsgHdr_t))) != NULL) + { + pMsg->handle = pBigCtx->handle; + pMsg->dispId = LCTR_DISP_BIG_BCST; + pMsg->event = LCTR_SLV_BIG_MSG_CH_MAP_UPD; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } + else + { + LL_TRACE_ERR0("lctrMstBigChClassUpdate: out of message buffers"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + } + } + + return LL_SUCCESS; +} + +/************************************************************************************************** + External Function +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Initialize link layer controller resources for BIS slave. + */ +/*************************************************************************************************/ +void LctrSlvBisInit(void) +{ + /* Add reset handler. */ + lctrResetHdlrTbl[LCTR_DISP_BIG_BCST] = lctrSlvBisResetHandler; + + /* Add BIS slave message dispatcher. */ + lctrMsgDispTbl[LCTR_DISP_BIG_BCST] = (LctrMsgDisp_t)lctrSlvBigDisp; + + lctrRegisterChClassHandler(lctrMstBigChClassUpdate); + + lctrBisDefaults(); + + /* Set supported features. */ + if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_5_1) + { + lmgrPersistCb.featuresDefault |= LL_FEAT_ISO_BROADCASTER; + } +} + +/*************************************************************************************************/ +/*! + * \brief BIG Create Sync. + * + * \param pCreateBig BIG create sync parameters. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrSlvBisCreateBig(LlCreateBig_t *pCreateBig) +{ + lctrBigCtx_t *pBigCtx; + + if (pCreateBig->numBis > pLctrRtCfg->maxBis) + { + LL_TRACE_WARN0("LctrSlvBisCreateBig: exceeds maximum allowed BIS context"); + return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES; + } + + if (pCreateBig->numBis > lctrGetNumAvailBisCtx()) + { + LL_TRACE_WARN0("LctrSlvBisCreateBig: insufficient BIS context"); + return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES; + } + + if ((pBigCtx = lctrFindBigByHandle(pCreateBig->bigHandle)) != NULL) + { + LL_TRACE_WARN1("LctrSlvBisCreateBig: bigHandle=%u already in use", pCreateBig->bigHandle); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + else + { + if (lctrBigIsPerAdvUsed(pCreateBig->advHandle) == TRUE) + { + LL_TRACE_WARN1("LctrSlvBisCreateBig: advHandle=%u not available", pCreateBig->advHandle); + return LL_ERROR_CODE_UNKNOWN_ADV_ID; + } + + if ((pBigCtx = lctrAllocBigCtx(pCreateBig->bigHandle)) == NULL) + { + LL_TRACE_WARN0("LctrSlvBisCreateBig: insufficient BIG context"); + return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES; + } + } + + lctrSlvSetupBigContext(pBigCtx, pCreateBig); + lctrSlvSetupBigChannel(pBigCtx); + + if (LlMathDivideUint32RoundUp(pBigCtx->maxSdu, pBigCtx->maxPdu) > LL_MAX_FRAG) + { + LL_TRACE_WARN1("LctrSlvBisCreateBig: exceeds maximum fragments max=%u", LL_MAX_FRAG); + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + + for (unsigned int i = 0; i < pCreateBig->numBis; i++) + { + lctrBisCtx_t *pBisCtx; + + pBisCtx = lctrAllocBisCtx(pBigCtx); + + if (pBisCtx) + { + lctrSetupBisContext(pBisCtx, pBigCtx->seedAccAddr, pBigCtx->baseCrcInit, lmgrCb.chanClass, pBigCtx->phy); + } + else + { + lctrFreeBigCtx(pBigCtx); + return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES; + } + } + + /* Assign function pointer for ACAD BIG. */ + lctrAdvSet_t *pAdvSet = lctrFindAdvSet(pCreateBig->advHandle); + if (pAdvSet) + { + pBigCtx->roleData.slv.pAdvSet = pAdvSet; + pAdvSet->bigCreated = &lctrSlvBisAcadBigCreated; + pAdvSet->bigTerminated = &lctrSlvBisAcadBigTerminated; + pAdvSet->removeCback = lctrSlvBisRemoveAdvSet; + } + + lctrMsgHdr_t *pMsg; + + if ((pMsg = WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->handle = pCreateBig->bigHandle; + pMsg->dispId = LCTR_DISP_BIG_BCST; + pMsg->event = LCTR_SLV_BIG_MSG_CREATE_BIG; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Create BIG test command. + * + * \param pCreateBigTest Create BIG test parameters. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrSlvBisCreateBigTest(LlCreateBigTest_t *pCreateBigTest) +{ + lctrBigCtx_t *pBigCtx; + + if (pCreateBigTest->numBis > lctrGetNumAvailBisCtx()) + { + LL_TRACE_WARN0("LctrSlvBisCreateBigTest: insufficient BIS context"); + return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES; + } + + if ((pBigCtx = lctrFindBigByHandle(pCreateBigTest->bigHandle)) != NULL) + { + LL_TRACE_WARN1("LctrSlvBisCreateBigTest: bigHandle=%u already in use", pCreateBigTest->bigHandle); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + else + { + if (lctrBigIsPerAdvUsed(pCreateBigTest->advHandle) == TRUE) + { + LL_TRACE_WARN1("LctrSlvBisCreateBigTest: advHandle=%u not available", pCreateBigTest->advHandle); + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + + if ((pBigCtx = lctrAllocBigCtx(pCreateBigTest->bigHandle)) == NULL) + { + LL_TRACE_WARN0("LctrSlvBisCreateBigTest: insufficient BIG context"); + return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES; + } + } + + lctrSlvSetupBigTestContext(pBigCtx, pCreateBigTest); + lctrSlvSetupBigChannel(pBigCtx); + + if (LlMathDivideUint32RoundUp(pBigCtx->maxSdu, pBigCtx->maxPdu) > LL_MAX_FRAG) + { + LL_TRACE_WARN1("LctrSlvBisCreateBig: exceeds maximum fragments max=%u", LL_MAX_FRAG); + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + + for (unsigned int i = 0; i < pCreateBigTest->numBis; i++) + { + lctrBisCtx_t *pBisCtx; + + pBisCtx = lctrAllocBisCtx(pBigCtx); + + if (pBisCtx) + { + lctrSetupBisContext(pBisCtx, pBigCtx->seedAccAddr, pBigCtx->baseCrcInit, lmgrCb.chanClass, pBigCtx->phy); + } + else + { + lctrFreeBigCtx(pBigCtx); + return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES; + } + } + + /* Enable BIG Info ACAD. */ + lctrAdvSet_t *pAdvSet = lctrFindAdvSet(pCreateBigTest->advHandle); + if (pAdvSet) + { + pBigCtx->roleData.slv.pAdvSet = pAdvSet; + pAdvSet->bigCreated = lctrSlvBisAcadBigCreated; + pAdvSet->bigTerminated = lctrSlvBisAcadBigTerminated; + pAdvSet->removeCback = lctrSlvBisRemoveAdvSet; + } + + lctrMsgHdr_t *pMsg; + + if ((pMsg = WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->handle = pCreateBigTest->bigHandle; + pMsg->dispId = LCTR_DISP_BIG_BCST; + pMsg->event = LCTR_SLV_BIG_MSG_CREATE_BIG; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Terminate BIG. + * + * \param bigHandle BIG handle. + * \param reason Termination reason. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrSlvBisTerminateBig(uint8_t bigHandle, uint8_t reason) +{ + lctrBigCtx_t *pBigCtx; + + if ((pBigCtx = lctrFindBigByHandle(bigHandle)) == NULL) + { + LL_TRACE_WARN1("LctrSlvBisTerminateBig: invalid BIG handle=%u", bigHandle); + return LL_ERROR_CODE_UNKNOWN_ADV_ID; + } + + if (pBigCtx->role != LL_ROLE_SLAVE) + { + LL_TRACE_WARN0("LctrSlvBisTerminateBig: invalid role"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + if (pBigCtx->state != LCTR_SLV_BIG_STATE_ENABLED) + { + LL_TRACE_WARN0("LctrSlvBisTerminateBig: invalid state"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + /* Store reason code. */ + pBigCtx->bcp.term.reason = reason; + + lctrMsgHdr_t *pMsg; + + if ((pMsg = WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->handle = bigHandle; + pMsg->dispId = LCTR_DISP_BIG_BCST; + pMsg->event = LCTR_SLV_BIG_MSG_TERMINATE_BIG; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Notify host of Create BIG complete event + * + * \param pBigCtx BIG context. + * \param status Status. + */ +/*************************************************************************************************/ +void lctrNotifyHostCreateBigComplete(lctrBigCtx_t *pBigCtx, uint8_t status) +{ + LlCreateBigCnf_t evt; + + /* Clear not required; all values are written. */ + /* memset(&evt, 0, sizeof(LlCreateBigCnf_t)); */ + + evt.hdr.param = pBigCtx->handle; + evt.hdr.event = LL_CREATE_BIG_CNF; + evt.hdr.status = status; + + evt.status = status; + evt.bigHandle = pBigCtx->handle; + + if (evt.status == LL_SUCCESS) + { + evt.syncDelayUsec = pBigCtx->syncDelayUsec; + evt.transLatUsec = pBigCtx->transLatUsec; + evt.phy = pBigCtx->phy; + evt.nse = pBigCtx->nse; + evt.bn = pBigCtx->bn; + evt.pto = pBigCtx->pto; + 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++) + { + evt.bisHandle[i] = pBigCtx->pBisCtx[i]->handle; + } + } + + LL_TRACE_INFO2("### LlEvent ### LL_CREATE_BIG_CNF, bigHandle=%u, status=%u", pBigCtx->handle, status); + + LmgrSendEvent((LlEvt_t *)&evt); +} + +/*************************************************************************************************/ +/*! + * \brief Notify host of Create BIG complete event + * + * \param pBigCtx BIG context. + */ +/*************************************************************************************************/ +void lctrNotifyHostTerminateBigComplete(lctrBigCtx_t *pBigCtx) +{ + LlTerminateBigInd_t evt; + + /* Clear not required; all values are written. */ + /* memset(&evt, 0, sizeof(LlTerminateBigInd_t)); */ + + evt.hdr.param = pBigCtx->handle; + evt.hdr.event = LL_TERM_BIG_IND; + evt.hdr.status = LL_SUCCESS; + + evt.bigHandle = pBigCtx->handle; + evt.reason = pBigCtx->bcp.term.reason; + + LL_TRACE_INFO2("### LlEvent ### LL_TERM_BIG_IND, bigHandle=%u, reason=%u", pBigCtx->handle, pBigCtx->bcp.term.reason); + + LmgrSendEvent((LlEvt_t *)&evt); +} + +/*************************************************************************************************/ +/*! + * \brief Send internal slave BIG subsystem message. + * + * \param pBigCtx BIG context. + * \param event Slave BIS event. + */ +/*************************************************************************************************/ +void lctrSlvBigSendMsg(lctrBigCtx_t *pBigCtx, uint8_t event) +{ + lctrMsgHdr_t *pMsg; + + if ((pMsg = WsfMsgAlloc(sizeof(lctrMsgHdr_t))) != NULL) + { + pMsg->handle = pBigCtx->handle; + pMsg->dispId = LCTR_DISP_BIG_BCST; + pMsg->event = event; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } +} + +/*************************************************************************************************/ +/*! + * \brief Send internal slave BIS ACAD subsystem message. + * + * \param pBigCtx BIG context. + * \param event Slave BIS event. + */ +/*************************************************************************************************/ +void lctrSlvBigSendAcadMsg(lctrBigCtx_t *pBigCtx, uint8_t event) +{ + if (!pBigCtx->roleData.slv.pAdvSet) + { + return; + } + + lctrBigCreated_t *pMsg; + + if ((pMsg = (lctrBigCreated_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->hdr.handle = pBigCtx->roleData.slv.pAdvSet->handle; + pMsg->hdr.dispId = LCTR_DISP_ACAD; + pMsg->hdr.event = event; + pMsg->bigHandle = pBigCtx->handle; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } +} + +/*************************************************************************************************/ +/*! + * \brief Build BIG operation. + * + * \param pBigCtx BIG context. + * + * \return Error status code. + */ +/*************************************************************************************************/ +uint8_t lctrSlvBigBuildOp(lctrBigCtx_t *pBigCtx) +{ + lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[0]; + + BbOpDesc_t * const pOp = &pBigCtx->bod; + BbBleData_t * const pBle = &pBigCtx->bleData; + BbBleSlvBisEvent_t * const pBis = &pBle->op.slvBis; + + memset(pOp, 0, sizeof(BbOpDesc_t)); + memset(pBle, 0, sizeof(BbBleData_t)); + memset(pBis, 0, sizeof(BbBleSlvBisEvent_t)); + + /*** General Setup ***/ + + pOp->reschPolicy = BB_RESCH_FIXED_PREFERRED; + pOp->protId = BB_PROT_BLE; + pOp->prot.pBle = pBle; + pOp->endCback = lctrSlvBigEndOp; + pOp->abortCback = lctrSlvBigAbortOp; + pOp->pCtx = pBigCtx; + + /*** BLE General Setup ***/ + + pBle->chan = pBisCtx->chan; + + /*** General setup ***/ + + pOp->minDurUsec = pBigCtx->syncDelayUsec; + pOp->maxDurUsec = pBigCtx->syncDelayUsec; + + /*** BIS setup ***/ + + pBis->execCback = lctrSlvBigBeginOp; + + switch (pBigCtx->packing) + { + case LL_PACKING_INTERLEAVED: + pBis->txDataCback = lctrSlvBisTxCompletionInterleaved; + break; + + case LL_PACKING_SEQUENTIAL: + default: + pBis->txDataCback = lctrSlvBisTxCompletionSequential; + break; + } + + /*** Commit operation ***/ + + if (!SchRmAdd(LCTR_BIG_TO_RM_HANDLE(pBigCtx), SCH_RM_PREF_PERFORMANCE, + pBigCtx->isoInterUsec, pBigCtx->isoInterUsec, pOp->minDurUsec, + NULL, lctrGetBigRefTime)) + { + LL_TRACE_WARN1("Could not schedule bigHandle=%u", pBigCtx->handle); + 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; + + while (TRUE) + { + lctrSelectBigChannels(pBigCtx); + + if (SchInsertAtDueTime(pOp, NULL)) + { + break; + } + + LL_TRACE_WARN1("!!! BIG schedule conflict handle=%u", pBigCtx->handle); + + /* Advance to next interval. */ + pBigCtx->eventCounter += 1; + pOp->dueUsec += pBigCtx->isoInterUsec; + } + + LL_TRACE_INFO2(" >>> BIG started, handle=%u, numBis=%u <<<", pBigCtx->handle, pBigCtx->numBis); + LL_TRACE_INFO3(" bn=%u, nse=%u, irc=%u", pBigCtx->bn, pBigCtx->nse, pBigCtx->irc); + LL_TRACE_INFO3(" pto=%u, framing=%u, packing=%u", pBigCtx->pto, pBigCtx->framing, pBigCtx->packing); + LL_TRACE_INFO1(" isoInterUsec=%u", pBigCtx->isoInterUsec); + LL_TRACE_INFO1(" bisSpaceUsec=%u", pBigCtx->bisSpaceUsec); + LL_TRACE_INFO1(" subInterUsec=%u", pBigCtx->subInterUsec); + LL_TRACE_INFO1(" seedAccAddr=0x%08x", pBigCtx->seedAccAddr); + LL_TRACE_INFO1(" pBod=0x%08x", pOp); + + return LL_SUCCESS; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis.c new file mode 100644 index 0000000000..7bba985c83 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis.c @@ -0,0 +1,1843 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller connected isochronous stream main implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_cis.h" +#include "lctr_int_iso.h" +#include "lctr_int_conn.h" +#include "lctr_int.h" +#include "sch_api.h" +#include "sch_api_ble.h" +#include "bb_api.h" +#include "pal_bb.h" +#include "pal_crypto.h" +#include "wsf_assert.h" +#include "wsf_buf.h" +#include "wsf_msg.h" +#include "wsf_math.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include + +/************************************************************************************************** + Globals +**************************************************************************************************/ + +/*! \brief CIS context table. */ +lctrCisCtx_t *pLctrCisTbl; + +/*! \brief CIG context table. */ +lctrCigCtx_t *pLctrCigTbl; + +/*! \brief CIS message. */ +lctrCisMsg_t *pLctrCisMsg; + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Update channel parameter. + * + * \param pCisCtx CIS context. + * \param chanMask Channel mask. + */ +/*************************************************************************************************/ +static void LctrCisUpdateChanParam(lctrCisCtx_t *pCisCtx, uint64_t chanMask) +{ + LL_TRACE_INFO1("LctrCisUpdateChanParam cisHandle=%u", pCisCtx->cisHandle); + LL_TRACE_INFO1("LctrCisUpdateChanParam, chanMask=%u", chanMask); + + pCisCtx->chanParam.chanMask = chanMask; + LmgrBuildRemapTable(&pCisCtx->chanParam); + pCisCtx->chIdx = LmgrSelectNextChannel(&pCisCtx->chanParam, pCisCtx->cisEvtCounter, 0, TRUE); + pCisCtx->nextSubEvtChanIdx = LmgrSelectNextSubEvtChannel(&pCisCtx->chanParam); +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Allocate a CIS context. + * + * \param pCigCtx Pointer to the CIG context. + * + * \return CIS context or NULL if at capacity. + */ +/*************************************************************************************************/ +lctrCisCtx_t *lctrAllocCisCtx(lctrCigCtx_t *pCigCtx) +{ + for (uint16_t i = 0; i < pLctrRtCfg->maxCis; i++) + { + lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i]; + + if (!pCisCtx->enabled) + { + memset(pCisCtx, 0, sizeof(lctrCisCtx_t)); + + pCisCtx->enabled = TRUE; + pCisCtx->cisHandle = LCTR_FIRST_CIS_HANDLE + i; + + /* Setup LLCP timer. */ + pCisCtx->tmrProcRsp.handlerId = lmgrPersistCb.handlerId; + lctrMsgHdr_t *pMsg = (lctrMsgHdr_t *)&pCisCtx->tmrProcRsp.msg; + pMsg->handle = pCisCtx->aclHandle; + pMsg->dispId = LCTR_DISP_CONN; + pMsg->event = LCTR_CONN_TMR_CIS_LLCP_RSP_EXP; + + /* Setup supervision timer. */ + pCisCtx->tmrSupTimeout.handlerId = lmgrPersistCb.handlerId; + pMsg = (lctrMsgHdr_t *)&pCisCtx->tmrSupTimeout.msg; + pMsg->handle = pCisCtx->cisHandle; + pMsg->dispId = LCTR_DISP_CIS; + pMsg->event = LCTR_CONN_TERM_SUP_TIMEOUT; + + /* Initialize data path info. */ + pCisCtx->dataPathInCtx.id = LL_ISO_DATA_PATH_DISABLED; + pCisCtx->dataPathOutCtx.id = LL_ISO_DATA_PATH_DISABLED; + + /* TODO: Update this value when needed. */ + pCisCtx->transLatUsec = LL_ISO_TRANSPORT_LAT_MIN; + + pCisCtx->cigId = pCigCtx->cigId; /* Save the CIG ID. */ + + return pCisCtx; + } + } + + return NULL; +} + +/*************************************************************************************************/ +/*! + * \brief Cleanup context, clean CIG context if necessary for slave. + * + * \param pCisCtx CIS context to free. + */ +/*************************************************************************************************/ +void lctrCleanupCtx(lctrCisCtx_t *pCisCtx) +{ + lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); + WSF_ASSERT(pCigCtx); + + if (lctrCisIsHeadCis(&pCigCtx->list, pCisCtx) == TRUE) + { + pCigCtx->headCisRmved = TRUE; + pCigCtx->firstRxStartTsUsec = pCisCtx->data.slv.firstRxStartTsUsec; + + if (pCigCtx->packing == LL_PACKING_INTERLEAVED) + { + pCigCtx->offsetUsec = pCisCtx->delayUsec; + } + else + { + pCigCtx->offsetUsec = pCisCtx->subIntervUsec * pCisCtx->nse; + } + } + + if (pCisCtx->role == LL_ROLE_SLAVE) + { + lctrFreeCisCtx(pCisCtx); + + (void)lctrCisRemove(&pCigCtx->list, pCisCtx); /* Result could be FALSE since BOD might not be in list. */ + + if (lctrCisIsListEmpty(&pCigCtx->list)) + { + lctrFreeCigCtx(pCigCtx); + } + } + else + { + /* CIS context for master will not be freed until CIG is removed. */ + + (void)lctrCisRemove(&pCigCtx->list, pCisCtx); /* Result could be FALSE since BOD might not be in list. */ + + if (lctrCisIsListEmpty(&pCigCtx->list)) + { + if (pCigCtx->isRmAdded == TRUE) + { + SchRmRemove(LCTR_GET_CIG_RM_HANDLE(pCigCtx)); + pCigCtx->isRmAdded = FALSE; + } + } + + /* CIG is removed through host command, unless resetted. */ + + if ((lctrResetEnabled == TRUE)) + { + lctrFreeCisCtx(pCisCtx); + + if (lctrCisIsListEmpty(&pCigCtx->list)) + { + lctrFreeCigCtx(pCigCtx); + } + } + } + + /* Send CIS message to continue reset. This message will not be processed since the CIS context has been cleared. */ + if (lctrResetEnabled) + { + lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_CLOSED); + } + + void *pIsoBuf; + uint8_t handlerId; + while ((pIsoBuf = WsfMsgDeq(&pCisCtx->isoalTxCtx.pendingSduQ, &handlerId)) != NULL) + { + WsfMsgFree(pIsoBuf); + } + + lctrIsoalRxDataPathClear(&pCisCtx->isoalRxCtx, pCisCtx->framing); +} + +/*************************************************************************************************/ +/*! + * \brief Free a CIS context. + * + * \param pCisCtx CIS context to free. + */ +/*************************************************************************************************/ +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); + +} + +/*************************************************************************************************/ +/*! + * \brief Find a CIS by handle. + * + * \param cisHandle CIS handle. + * + * \return CIS or NULL if not found. + */ +/*************************************************************************************************/ +lctrCisCtx_t *lctrFindCisByHandle(uint16_t cisHandle) +{ + for (unsigned int i = 0; i < pLctrRtCfg->maxCis; i++) + { + lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i]; + + if ((pCisCtx->cisHandle == cisHandle) && + (pCisCtx->enabled)) + { + return pCisCtx; + } + } + return NULL; +} + +/*************************************************************************************************/ +/*! + * \brief Find a CIS by CIG ID and CIS ID. + * + * \param cigId CIG identifier. + * \param cisId CIS identifier. + * + * \return CIS or NULL if not found. + */ +/*************************************************************************************************/ +lctrCisCtx_t *lctrFindCisById(uint8_t cigId, uint8_t cisId) +{ + for (unsigned int i = 0; i < pLctrRtCfg->maxCis; i++) + { + lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i]; + + if ((pCisCtx->enabled) && + (pCisCtx->cigId == cigId) && + (pCisCtx->cisId == cisId)) + { + return pCisCtx; + } + } + return NULL; +} + +/*************************************************************************************************/ +/*! + * \brief Allocate a CIG context. + * + * \param cigId CIG ID. + * + * \return CIG context or NULL if at capacity. + */ +/*************************************************************************************************/ +lctrCigCtx_t *lctrAllocCigCtx(uint8_t cigId) +{ + for (uint16_t i = 0; i < pLctrRtCfg->maxCig; i++) + { + lctrCigCtx_t *pCigCtx = &pLctrCigTbl[i]; + + if (!pCigCtx->enabled) + { + memset(pCigCtx, 0, sizeof(lctrCigCtx_t)); + + /* pCigCtx->numCisEsted = 0; */ + pCigCtx->enabled = TRUE; + pCigCtx->cigId = cigId; + pCigCtx->cigHandle = i; + + /* Initialize the CIS list. */ + pCigCtx->list.numNodes = 0; + pCigCtx->list.pHead = NULL; + pCigCtx->list.pTail = NULL; + + LmgrIncResetRefCount(); + + /* Enable BB. */ + BbStart(BB_PROT_BLE); + + return pCigCtx; + } + } + + return NULL; +} + +/*************************************************************************************************/ +/*! + * \brief Free a CIG context. + * + * \param pCigCtx CIG context to free. + */ +/*************************************************************************************************/ +void lctrFreeCigCtx(lctrCigCtx_t *pCigCtx) +{ + WSF_ASSERT(pCigCtx->enabled); + + pCigCtx->enabled = FALSE; + pCigCtx->roleData.slv.lastActiveEvent = 0; + pCigCtx->isBodBuilt = FALSE; + pCigCtx->isBodStarted = FALSE; + pCigCtx->numCisEsted = 0; + + LmgrDecResetRefCount(); + + /* Disable BB. */ + BbStop(BB_PROT_BLE); +} + +/*************************************************************************************************/ +/*! + * \brief Find a CIG by CIG ID. + * + * \param cigId CIG identifier. + * + * \return CIG or NULL if not found. + */ +/*************************************************************************************************/ +lctrCigCtx_t *lctrFindCigById(uint8_t cigId) +{ + for (unsigned int i = 0; i < pLctrRtCfg->maxCig; i++) + { + lctrCigCtx_t *pCigCtx = &pLctrCigTbl[i]; + + if ((pCigCtx->enabled) && + (pCigCtx->cigId == cigId)) + { + return pCigCtx; + } + } + return NULL; +} + +/*************************************************************************************************/ +/*! + * \brief Return the number of available CIG contexts. + * + * \return Number of available CIS contexts. + */ +/*************************************************************************************************/ +uint8_t lctrGetNumAvailCigCtx() +{ + uint8_t count = 0; + + for (unsigned int i = 0; i < pLctrRtCfg->maxCig; i++) + { + lctrCigCtx_t *pCigCtx = &pLctrCigTbl[i]; + + if (pCigCtx->enabled == FALSE) + { + count++; + } + } + + return count; +} + +/*************************************************************************************************/ +/*! + * \brief Initialize connected isochronous stream memory resources. + * + * \param pFreeMem Pointer to free memory. + * \param freeMemSize Size of pFreeMem. + * + * \return Amount of free memory consumed. + */ +/*************************************************************************************************/ +uint16_t LctrInitCisMem(uint8_t *pFreeMem, uint32_t freeMemSize) +{ + uint8_t *pAvailMem = pFreeMem; + + /*** Advertising Set Context ***/ + + if (((uint32_t)pAvailMem) & 3) + { + /* Align to next word. */ + pAvailMem = (uint8_t *)(((uint32_t)pAvailMem & ~3) + sizeof(uint32_t)); + } + + LL_TRACE_INFO2(" RAM: %u x %u bytes -- CIS context", pLctrRtCfg->maxCis, sizeof(lctrCisCtx_t)); + + /* Allocate CIS context memory. */ + pLctrCisTbl = (lctrCisCtx_t *)pAvailMem; + pAvailMem += sizeof(lctrCisCtx_t) * pLctrRtCfg->maxCis; + + + if (((uint32_t)pAvailMem) & 3) + { + /* Align to next word. */ + pAvailMem = (uint8_t *)(((uint32_t)pAvailMem & ~3) + sizeof(uint32_t)); + } + + LL_TRACE_INFO2(" RAM: %u x %u bytes -- CIG context", pLctrRtCfg->maxCig, sizeof(lctrCigCtx_t)); + + /* Allocate CIG context memory. */ + pLctrCigTbl = (lctrCigCtx_t *)pAvailMem; + pAvailMem += sizeof(lctrCigCtx_t) * pLctrRtCfg->maxCig; + + if (((uint32_t)(pAvailMem - pFreeMem)) > freeMemSize) + { + LL_TRACE_ERR2("LctrInitCisMem: failed to allocate CIS, need=%u available=%u", (pAvailMem - pFreeMem), freeMemSize); + WSF_ASSERT(FALSE); + return 0; + } + + lmgrPersistCb.cisCtxSize = sizeof(lctrCisCtx_t); + lmgrPersistCb.cigCtxSize = sizeof(lctrCigCtx_t); + + return (pAvailMem - pFreeMem); +} + +/*************************************************************************************************/ +/*! + * \brief Initialize flush timeout parameters. + * + * \param pFtParam Pointer to the flush parameter. + * \param bn Burst number. + * \param ft Flush time. + * \param nse Number of subevent. + */ +/*************************************************************************************************/ +void lctrCisInitFtParam(lctrFtParam_t *pFtParam, uint8_t bn, uint8_t ft, uint8_t nse) +{ + pFtParam->pduRcved = FALSE; + pFtParam->pduAcked = FALSE; + pFtParam->pduCounter = 0; + pFtParam->subEvtCounter = 0; + pFtParam->bn = bn; + pFtParam->intervalTotal = ft; + pFtParam->intervalCounter = 0; + + if (bn == 1) + { + /* BN = 1, numSubEvtFt[0] = BN * NSE */ + pFtParam->lastSubEvtFt[0] = bn * nse; + pFtParam->isPduDone[0] = FALSE; + pFtParam->pduType[0] = LCTR_CIS_PDU_DEFAULT; + } + else + { + /* BN > 1, i = 0, numSubEvtFt[i] = FLOOR(NSE/BN) + MOD(NSE, BN) */ + uint8_t floor = nse / bn; + + pFtParam->lastSubEvtFt[0] = floor + (nse - (floor * bn)); + pFtParam->isPduDone[0] = FALSE; + + /* BN > 1, i > 0, numSubEvtFt[i] = floor */ + for (unsigned int i = 1; i < WSF_MIN(bn, LCTR_MAX_BN); i++) + { + pFtParam->lastSubEvtFt[i] = floor + pFtParam->lastSubEvtFt[i-1]; + pFtParam->isPduDone[i] = FALSE; + pFtParam->pduType[i] = LCTR_CIS_PDU_DEFAULT; + } + } +} + +/*************************************************************************************************/ +/*! + * \brief Check if the CIS is established or not. + * + * \param pCisCtx CIS context. + * + * \return TRUE if CIS is established. + */ +/*************************************************************************************************/ +bool_t lctrIsCisEst(lctrCisCtx_t *pCisCtx) +{ + return (pCisCtx->state == LCTR_CIS_STATE_EST) ? TRUE : FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Return the number of available CIS contexts. + * + * \return Number of available CIS contexts. + */ +/*************************************************************************************************/ +uint8_t lctrGetNumAvailCisCtx() +{ + uint8_t count = 0; + + for (unsigned int i = 0; i < pLctrRtCfg->maxCis; i++) + { + lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i]; + + if (pCisCtx->enabled == FALSE) + { + count++; + } + } + + return count; +} + +/*************************************************************************************************/ +/*! + * \brief Return the number of CIS contexts that are already set up(enabled). + * + * \param pSetCigParam Set CIG parameters. + * + * \return Number of CIS contexts that are already set up(enabled). + */ +/*************************************************************************************************/ +uint8_t lctrGetNumEnabledCisCtx(LlCisCigParams_t *pSetCigParam) +{ + uint8_t count = 0; + + for (unsigned int i = 0; i < pSetCigParam->numCis; i++) + { + if (lctrFindCisById(pSetCigParam->cigId, pSetCigParam->pCisParam[i].cisId)) + { + count++; + } + } + + return count; +} + +/*************************************************************************************************/ +/*! + * \brief Return the number of CIS contexts that are enabled(in use). + * + * \param pSetCigParam Set CIG parameters. + * + * \return Number of CIS contexts that are already set up(enabled). + */ +/*************************************************************************************************/ +uint8_t lctrGetNumEnabledCisCtxTest(LlCisCigParamsTest_t *pSetCigParam) +{ + uint8_t count = 0; + + for (unsigned int i = 0; i < pSetCigParam->numCis; i++) + { + if (lctrFindCisById(pSetCigParam->cigId, pSetCigParam->pCisParam[i].cisId)) + { + count++; + } + } + + return count; +} + +/*************************************************************************************************/ +/*! + * \brief Return the number of CIS contexts that are already established. + * + * \param pSetCigParam Set CIG parameters. + * + * \return Number of CIS contexts that are established. + */ +/*************************************************************************************************/ +uint8_t lctrGetNumEstCisCtx(LlCisCigParams_t *pSetCigParam) +{ + uint8_t count = 0; + + for (unsigned int i = 0; i < pSetCigParam->numCis; i++) + { + lctrCisCtx_t *pCisCtx; + + if ((pCisCtx = lctrFindCisById(pSetCigParam->cigId, pSetCigParam->pCisParam[i].cisId))) + { + if (lctrIsCisEst(pCisCtx)) + { + count++; + } + } + } + + return count; +} + +/*************************************************************************************************/ +/*! + * \brief Return the number of CIS contexts that are already established(enabled) for testing. + * + * \param pSetCigParam Set CIG parameters. + * + * \return Number of CIS contexts that are established. + */ +/*************************************************************************************************/ +uint8_t lctrGetNumEstCisCtxTest(LlCisCigParamsTest_t *pSetCigParam) +{ + uint8_t count = 0; + + for (unsigned int i = 0; i < pSetCigParam->numCis; i++) + { + lctrCisCtx_t *pCisCtx; + + if ((pCisCtx = lctrFindCisById(pSetCigParam->cigId, pSetCigParam->pCisParam[i].cisId))) + { + if (lctrIsCisEst(pCisCtx)) + { + count++; + } + } + } + + return count; +} + +/*************************************************************************************************/ +/*! + * \brief Return the number of CIS contexts that are already established(enabled) in a CIG. + * + * \param pCigCtx CIG context. + * + * \return Number of CIS contexts that are established. + */ +/*************************************************************************************************/ +uint8_t lctrGetNumEstCisCtxByCigCtx(lctrCigCtx_t *pCigCtx) +{ + WSF_ASSERT(pCigCtx); + + return pCigCtx->numCisEsted; +} + +/*************************************************************************************************/ +/*! + * \brief CIS message dispatcher. + * + * \param pMsg Pointer to message buffer. + */ +/*************************************************************************************************/ +void lctrCisDisp(lctrCisMsg_t *pMsg) +{ + lctrCisCtx_t *pCisCtx; + + if (pMsg->hdr.dispId != LCTR_DISP_BCST) + { + WSF_ASSERT(pMsg->hdr.handle < (LCTR_FIRST_BIS_HANDLE)); /* The beginning of BIS handles is the upper bound of CIS handles. */ + + if ((pCisCtx = lctrFindCisByHandle(pMsg->hdr.handle)) != NULL) + { + pLctrCisMsg = pMsg; + + lctrCisExecuteSm(pCisCtx, pMsg->hdr.event); + } + } + else + { + /* Clear CIG handles. */ + lctrCleanupCigCtx(); + } +} + +/*************************************************************************************************/ +/*! + * \brief CIS conflict resolution handler. + * + * \param pNewOp New BOD. + * \param pExistOp Existing BOD. + * + * \return Prioritized BOD. + * + * Prioritize BLE connection at most risk for termination. + */ +/*************************************************************************************************/ +BbOpDesc_t *lctrCisResolveConflict(BbOpDesc_t *pNewOp, BbOpDesc_t *pExistOp) +{ + /* TODO Add conflict resolution handler */ + + return pExistOp; +} + +/*************************************************************************************************/ +/*! + * \brief Set up the channel parameter. + * + * \param pCisCtx CIS context. + * \param chanMask Channel mask. + */ +/*************************************************************************************************/ +void lctrCisSetupChanParam(lctrCisCtx_t *pCisCtx, uint64_t chanMask) +{ + pCisCtx->chanParam.chanMask = chanMask; + LmgrBuildRemapTable(&pCisCtx->chanParam); + pCisCtx->chanParam.usedChSel = LL_CH_SEL_2; + pCisCtx->chanParam.chIdentifier = (pCisCtx->accessAddr >> 16) ^ + (pCisCtx->accessAddr >> 0); + pCisCtx->chIdx = LmgrSelectNextChannel(&pCisCtx->chanParam, pCisCtx->cisEvtCounter, 0, TRUE); + pCisCtx->nextSubEvtChanIdx = LmgrSelectNextSubEvtChannel(&pCisCtx->chanParam); + pCisCtx->subEvtCounter = 0; +} + +/*************************************************************************************************/ +/*! + * \brief Update channel map triggered by host or peer. + * + * \param aclHandle ACL handle. + */ +/*************************************************************************************************/ +void LctrCisUpdateChanMap(uint16_t aclHandle) +{ + LL_TRACE_INFO1("LctrCisUpdateChanMap aclHandle=%u", aclHandle); + + for (unsigned int i = 0; i < pLctrRtCfg->maxCis; i++) + { + lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i]; + + if ((pCisCtx->aclHandle == aclHandle) && + (pCisCtx->enabled)) + { + lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); + + LctrCisUpdateChanParam(pCisCtx, pCtx->chanMask); + } + } +} + +/*************************************************************************************************/ +/*! + * \brief Initialize cipher block for CIS. + * + * \param pCisCtx Connection context. + */ +/*************************************************************************************************/ +void lctrCisSetupEncrypt(lctrCisCtx_t *pCisCtx) +{ + lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); + WSF_ASSERT(pCtx); + + PalCryptoEnc_t * const pEnc = &pCisCtx->bleData.chan.enc; + + 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; + UINT32_TO_BSTREAM(pTemp, pCisCtx->accessAddr) + pEnc->iv[0] ^= accAddr[0]; + pEnc->iv[1] ^= accAddr[1]; + pEnc->iv[2] ^= accAddr[2]; + pEnc->iv[3] ^= accAddr[3]; + 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); + + pEnc->enaEncrypt = pCtx->bleData.chan.enc.enaEncrypt; + pEnc->enaDecrypt = pCtx->bleData.chan.enc.enaDecrypt; +} + +/************************************************************************************************** + Utility functions to manipulate the CIS linked list. +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Create a node. + * + * \param pCisCtx CIS context. + * + * \return Pointer to the node or NULL if creation fails. + */ +/*************************************************************************************************/ +static lctrCisNode_t * lctrCisCreateNode(lctrCisCtx_t *pCisCtx) +{ + lctrCisNode_t *pNew = NULL; + + if ((pNew = (lctrCisNode_t *)WsfBufAlloc(sizeof(lctrCisNode_t))) != NULL) + { + pNew->pNext = NULL; + pNew->pCisCtx = pCisCtx; + } + + return pNew; +} + +/*************************************************************************************************/ +/*! + * \brief Insert at the head of the list. + * + * \param pList Pointer to the list. + * \param pCisCtx CIS context. + * + * \return True if successfully insert at the head, False otherwise. + */ +/*************************************************************************************************/ +bool_t lctrCisInsertHead(lctrCisList_t *pList, lctrCisCtx_t *pCisCtx) +{ + lctrCisNode_t *pTemp = NULL; + + if ((pTemp = lctrCisCreateNode(pCisCtx)) == NULL) + { + return FALSE; + } + + if (lctrCisIsListEmpty(pList)) + { + /* List is empty. */ + pList->pHead = pList->pTail = pTemp; + } + else + { + /* List is not empty. */ + pTemp->pNext = pList->pHead; + pList->pHead = pTemp; + } + pList->numNodes++; + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Insert at the tail of the list. + * + * \param pList Pointer to the list. + * \param pCisCtx CIS context. + * + * \return True if successfully insert at the head, False otherwise. + */ +/*************************************************************************************************/ +bool_t lctrCisInsertTail(lctrCisList_t *pList, lctrCisCtx_t *pCisCtx) +{ + lctrCisNode_t *pTemp = NULL; + + if ((pTemp = lctrCisCreateNode(pCisCtx)) == NULL) + { + return FALSE; + } + + if (lctrCisIsListEmpty(pList)) + { + /* List is empty. */ + pList->pHead = pList->pTail = pTemp; + } + else + { + /* List is not empty. */ + pList->pTail->pNext = pTemp; + pList->pTail = pTemp; + } + pList->numNodes++; + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Remove at the head of the list. + * + * \param pList Pointer to the list. + * + * \return True if successfully remove at the head, False otherwise. + */ +/*************************************************************************************************/ +bool_t lctrCisRemoveHead(lctrCisList_t *pList) +{ + lctrCisNode_t *pTemp = NULL; + + if (lctrCisIsListEmpty(pList)) + { + /* List is empty. */ + return FALSE; + } + else + { + /* List is not empty. */ + pTemp = pList->pHead; + pList->pHead = pTemp->pNext; + WsfBufFree(pTemp); + } + pList->numNodes--; + + if (lctrCisIsListEmpty(pList)) + { + pList->pTail = NULL; + } + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Remove at the tail of the list. + * + * \param pList Pointer to the list. + * + * \return True if successfully remove at the tail, False otherwise. + */ +/*************************************************************************************************/ +bool_t lctrCisRemoveTail(lctrCisList_t *pList) +{ + lctrCisNode_t *pTemp = NULL; + + if (lctrCisIsListEmpty(pList)) + { + /* List is empty. */ + return FALSE; + } + else if (pList->numNodes == 1) + { + /* List has only one node. */ + pTemp = pList->pTail; + WsfBufFree(pTemp); + pList->pHead = pList->pTail = NULL; + } + else + { + /* List has more than one node. */ + pTemp = pList->pHead; + + /* Traverse to the second last. */ + while (pTemp->pNext->pNext != NULL) + { + pTemp = pTemp->pNext; + } + + WsfBufFree(pTemp->pNext); /* Free the tail. */ + pTemp->pNext = NULL; + pList->pTail = pTemp; + } + pList->numNodes--; + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Remove at the middle of the list. + * + * \param pList Pointer to the list. + * \param pCisCtx Pointer to the CIS context to remove + * + * \return True if successfully remove at the head, False otherwise. + */ +/*************************************************************************************************/ +bool_t lctrCisRemoveMiddle(lctrCisList_t *pList, lctrCisCtx_t *pCisCtx) +{ + lctrCisNode_t *pTemp = NULL; + lctrCisNode_t *pRemove = NULL; + + if (lctrCisIsListEmpty(pList)) + { + /* List is empty. */ + return FALSE; + } + else + { + /* List is not empty. */ + pTemp = pList->pHead; + + while (pTemp->pNext != pList->pTail) + { + if (pTemp->pNext->pCisCtx == pCisCtx) + { + pRemove = pTemp->pNext; + pTemp->pNext = pTemp->pNext->pNext; + WsfBufFree(pRemove); + pList->numNodes--; + return TRUE; + } + pTemp = pTemp->pNext; + } + } + + /* Cannot fine the CIS context in the linked list. */ + return FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Remove a CIS context from the list. + * + * \param pList Pointer to the list. + * \param pCisCtx Pointer to the CIS context to remove + * + * \return True if successfully remove at the head, False otherwise. + */ +/*************************************************************************************************/ +bool_t lctrCisRemove(lctrCisList_t *pList, lctrCisCtx_t *pCisCtx) +{ + if (lctrCisIsListEmpty(pList)) + { + /* List is empty. */ + return FALSE; + } + + if (pList->pHead->pCisCtx == pCisCtx) + { + return lctrCisRemoveHead(pList); + } + else if (pList->pTail->pCisCtx == pCisCtx) + { + return lctrCisRemoveTail(pList); + } + else + { + return lctrCisRemoveMiddle(pList, pCisCtx); + } +} + +/*************************************************************************************************/ +/*! + * \brief Check if the list is empty or not. + * + * \param pList Pointer to the list. + * + * \return True if successfully remove at the tail, False otherwise. + */ +/*************************************************************************************************/ +bool_t lctrCisIsListEmpty(lctrCisList_t *pList) +{ + return (pList->numNodes == 0) ? TRUE : FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Return the number of elements in the list. + * + * \param pList Pointer to the list. + * + * \return Number of elements in the list. + */ +/*************************************************************************************************/ +uint8_t lctrCisGetListCount(lctrCisList_t *pList) +{ + return pList->numNodes; +} + +/*************************************************************************************************/ +/*! + * \brief Return the CIS context at the head of the linked list. + * + * \param pList Pointer to the list. + * + * \return NULL or pointer to the CIS context at the head of the linked list. + */ +/*************************************************************************************************/ +lctrCisCtx_t * lctrCisGetHeadCis(lctrCisList_t *pList) +{ + if (lctrCisIsListEmpty(pList)) + { + return NULL; + } + + return pList->pHead->pCisCtx; +} + +/*************************************************************************************************/ +/*! + * \brief Check if the input context is the head in the linked list. + * + * \param pList Pointer to the list. + * \param pCisCtx Pointer to the CIS context. + * + * \return TRUE if the input context is the head in the linked list, FALSE otherwise + */ +/*************************************************************************************************/ +bool_t lctrCisIsHeadCis(lctrCisList_t *pList, lctrCisCtx_t *pCisCtx) +{ + if (lctrCisIsListEmpty(pList)) + { + return FALSE; + } + + return (pList->pHead->pCisCtx == pCisCtx ? TRUE : FALSE); +} + +/*************************************************************************************************/ +/*! + * \brief Return the next CIS context after the current CIS context in the linked list. + * + * \param pList Pointer to the list. + * \param pCurCisCtx Current CIS. + * + * \return NULL or pointer to the next CIS context after the current CIS context in the linked list. + */ +/*************************************************************************************************/ +lctrCisCtx_t * lctrCisGetNextCis(lctrCisList_t *pList, lctrCisCtx_t *pCurCisCtx) +{ + if (lctrCisIsListEmpty(pList)) + { + return NULL; + } + + lctrCisNode_t *pTempNode = pList->pHead; + + while (pTempNode) + { + if (pTempNode->pCisCtx == pCurCisCtx) + { + if (pTempNode->pNext) + { + return pTempNode->pNext->pCisCtx; + } + else + { + return NULL; + } + } + + pTempNode = pTempNode->pNext; + } + + return NULL; +} + +/*************************************************************************************************/ +/*! + * \brief Return the next CIS context after the current CIS context in the linked list. + * + * \param pList Pointer to the list. + * \param pCurCisCtx Current CIS. + * + * \return NULL or pointer to the next CIS context after the current CIS context in the linked list. + */ +/*************************************************************************************************/ +lctrCisCtx_t * lctrCisGetPreCis(lctrCisList_t *pList, lctrCisCtx_t *pCurCisCtx) +{ + if (lctrCisIsListEmpty(pList)) + { + return NULL; + } + + lctrCisNode_t *pTempNode = pList->pHead; + + while (pTempNode->pNext) + { + if (pTempNode->pNext->pCisCtx == pCurCisCtx) + { + return pTempNode->pCisCtx; + } + pTempNode = pTempNode->pNext; + } + + return NULL; +} + +/*************************************************************************************************/ +/*! + * \brief Check whether all the interleaved CISs in the CIG are done or not. + * + * \param pList Pointer to the CIS list in the CIG. + * + * \return TRUE if all the CISs in the CIG are done, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lctrCisAreCisCtxDone(lctrCisList_t *pList) +{ + lctrCisNode_t *pTempNode = pList->pHead; + + while (pTempNode) + { + if (pTempNode->pCisCtx->cisDone == FALSE) + { + return FALSE; + } + + pTempNode = pTempNode->pNext; + } + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Clear the cisDone flag for all the CISs in the CIG. + * + * \param pList Pointer to the CIS list in the CIG. + */ +/*************************************************************************************************/ +void lctrCisClearCisDone(lctrCisList_t *pList) +{ + lctrCisNode_t *pTempNode = pList->pHead; + + while (pTempNode) + { + pTempNode->pCisCtx->cisDone = FALSE; + pTempNode = pTempNode->pNext; + } +} + +/*************************************************************************************************/ +/*! + * \brief Set the cisDone flag for all the CISs after the CIS, including the current one. + * + * \param pList Pointer to the CIS list in the CIG. + * \param pCurCisCtx Current CIS. + */ +/*************************************************************************************************/ +void lctrCisSetCisDone(lctrCisList_t *pList, lctrCisCtx_t *pCurCisCtx) +{ + lctrCisNode_t *pTgtNode = NULL, *pTempNode = pList->pHead; + + while (pTempNode) + { + if (pTempNode->pCisCtx == pCurCisCtx) + { + pTgtNode = pTempNode; + break; + } + pTempNode = pTempNode->pNext; + } + + if (pTgtNode == NULL) + { + return; + } + else + { + pTempNode = pTgtNode; + + while (pTempNode) + { + pTempNode->pCisCtx->cisDone = TRUE; + pTempNode = pTempNode->pNext; + } + } +} + +/************************************************************************************************** + Utility functions to manipulate the CIS Tx/Rx Ft list. +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Create a flush timeout node. + * + * \param pFtParam Flush timeout parameters. + * + * \return Pointer to the node or NULL if creation fails. + */ +/*************************************************************************************************/ +lctrFtParamNode_t * lctrCisFtCreateFtParamNode(lctrFtParam_t *pFtParam) +{ + lctrFtParamNode_t *pNew = NULL; + + if ((pNew = (lctrFtParamNode_t *)WsfBufAlloc(sizeof(lctrFtParamNode_t))) != NULL) + { + pNew->pNext = NULL; + memcpy(&pNew->ftParam, pFtParam, sizeof(lctrFtParam_t)); + } + + return pNew; +} + +/*************************************************************************************************/ +/*! + * \brief Insert at the head of the list. + * + * \param pList Pointer to the list. + * \param pFtParam Flush timeout parameters. + * + * \return True if successfully insert at the head, False otherwise. + */ +/*************************************************************************************************/ +bool_t lctrCisFtInsertHead(lctrFtParamList_t *pList, lctrFtParam_t *pFtParam) +{ + lctrFtParamNode_t *pTemp = NULL; + + if ((pTemp = lctrCisFtCreateFtParamNode(pFtParam)) == NULL) + { + return FALSE; + } + + if (lctrCisFtIsListEmpty(pList)) + { + /* List is empty. */ + pList->pHead = pList->pTail = pTemp; + } + else + { + /* List is not empty. */ + pTemp->pNext = pList->pHead; + pList->pHead = pTemp; + } + pList->numNodes++; + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Insert at the tail of the list. + * + * \param pList Pointer to the list. + * \param pFtParam Flush timeout parameters. + * + * \return True if successfully insert at the head, False otherwise. + */ +/*************************************************************************************************/ +bool_t lctrCisFtInsertTail(lctrFtParamList_t *pList, lctrFtParam_t *pFtParam) +{ + lctrFtParamNode_t *pTemp = NULL; + + if ((pTemp = lctrCisFtCreateFtParamNode(pFtParam)) == NULL) + { + return FALSE; + } + + if (lctrCisFtIsListEmpty(pList)) + { + /* List is empty. */ + pList->pHead = pList->pTail = pTemp; + } + else + { + /* List is not empty. */ + pList->pTail->pNext = pTemp; + pList->pTail = pTemp; + } + pList->numNodes++; + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Remove at the head of the list. + * + * \param pList Pointer to the list. + * + * \return True if successfully remove at the head, False otherwise. + */ +/*************************************************************************************************/ +bool_t lctrCisFtRemoveHead(lctrFtParamList_t *pList) +{ + lctrFtParamNode_t *pTemp = NULL; + + if (lctrCisFtIsListEmpty(pList)) + { + /* List is empty. */ + return FALSE; + } + else + { + /* List is not empty. */ + pTemp = pList->pHead; + pList->pHead = pTemp->pNext; + WsfBufFree(pTemp); + } + pList->numNodes--; + + if (lctrCisFtIsListEmpty(pList)) + { + pList->pTail = NULL; + } + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Remove at the tail of the list. + * + * \param pList Pointer to the list. + * + * \return True if successfully remove at the tail, False otherwise. + */ +/*************************************************************************************************/ +bool_t lctrCisFtRemoveTail(lctrFtParamList_t *pList) +{ + lctrFtParamNode_t *pTemp = NULL; + + if (lctrCisFtIsListEmpty(pList)) + { + /* List is empty. */ + return FALSE; + } + else if (pList->numNodes == 1) + { + /* List has only one node. */ + pTemp = pList->pTail; + WsfBufFree(pTemp); + pList->pHead = pList->pTail = NULL; + } + else + { + /* List has more than one node. */ + pTemp = pList->pHead; + + /* Traverse to the second last. */ + while (pTemp->pNext->pNext != NULL) + { + pTemp = pTemp->pNext; + } + + WsfBufFree(pTemp->pNext); /* Free the tail. */ + pTemp->pNext = NULL; + pList->pTail = pTemp; + } + pList->numNodes--; + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Clear the flush timeout list. + * + * \param pList Pointer to the list. + */ +/*************************************************************************************************/ +void lctrCisFtListClear(lctrFtParamList_t *pList) +{ + if (lctrCisFtIsListEmpty(pList)) + { + /* List is empty. */ + return; + } + + lctrFtParamNode_t *pTemp = pList->pHead; + + while (pTemp) + { + lctrCisFtRemoveHead(pList); + pTemp = pTemp->pNext; + } +} + +/*************************************************************************************************/ +/*! + * \brief Check if the list is empty or not. + * + * \param pList Pointer to the list. + * + * \return True if successfully remove at the tail, False otherwise. + */ +/*************************************************************************************************/ +bool_t lctrCisFtIsListEmpty(lctrFtParamList_t *pList) +{ + return pList->numNodes == 0 ? TRUE : FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Set flags for CIS link termination. + * + * \param aclHandle ACL connection handle. + * + * \return TRUE if CIS is terminated, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lctrCheckForCisLinkTerm(uint16_t aclHandle) +{ + lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(aclHandle); + lctrCisCtx_t *pCisCtx = lctrFindCisByHandle(pCtx->llcpCisHandle); + + if (pCisCtx == NULL) + { + return FALSE; + } + + if (pCisCtx->termState == LCTR_CIS_TERM_STATE_TERMINATING) + { + /* Peer device is LL_TERMINATE_IND initiator. */ + if (pCtx->termAckReqd) /* Tx Ack required after Rx of LL_TERMINATE_IND */ + { + pCtx->termAckReqd = FALSE; + + if (pCtx->ackAfterCtrlPdu) /* guarantee Ack Tx'ed */ + { + lctrSendCisLlcpMsg(pCisCtx, LCTR_CIS_TERM_EVENT_CIS_TERM); + return TRUE; + } + } + /* Local device is LL_CIS_TERMINATE_IND initiator. */ + else if ((pCtx->llcpState == LCTR_LLCP_STATE_IDLE) || /* LL_TERMINATE_IND not pending */ + (pCtx->txArqQ.pHead == NULL)) /* guarantee LL_TERMINATE_IND is Ack'ed */ + /* i.e. "WsfQueueEmpty(&pCtx->txArqQ)" (optimized for ISR) */ + { + lctrSendCisLlcpMsg(pCisCtx, LCTR_CIS_TERM_EVENT_CIS_TERM); + return TRUE; + } + } + + return FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Check if there is a CIS established for the ACL indicated by the aclHandle. + * + * \param aclHandle ACL connection handle. + * + * \return TRUE if there is a CIS established, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lctrCheckIsCisEstAcl(uint16_t aclHandle) +{ + for (uint16_t i = 0; i < pLctrRtCfg->maxCis; i++) + { + lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i]; + + if ((pCisCtx->enabled == TRUE) && + (pCisCtx->aclHandle == aclHandle) && + lctrIsCisEst(pCisCtx)) + + { + return TRUE; + } + } + return FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Check if CIS is established indicated by the cisHandle. + * + * \param cisHandle CIS connection handle. + * + * \return TRUE if CIS is established, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lctrCheckIsCisEstCis(uint16_t cisHandle) +{ + lctrCisCtx_t *pCisCtx = lctrFindCisByHandle(cisHandle); + + if ((pCisCtx->enabled == TRUE) && + lctrIsCisEst(pCisCtx)) + { + return TRUE; + } + + return FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Start LLCP timer. + * + * \param pCtx ACL Connection context. + * \param pCisCtx CIS Context. + */ +/*************************************************************************************************/ +void lctrCisStartLlcpTimer(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + if (lctrGetConnOpFlag(pCtx, LL_OP_MODE_FLAG_ENA_LLCP_TIMER)) + { + WsfTimerStartSec(&pCisCtx->tmrProcRsp, LL_T_PRT_SEC); + } +} + +/*************************************************************************************************/ +/*! + * \brief Stop LLCP timer. + * + * \param pCtx ACL Connection context. + * \param pCisCtx CIS Context. + */ +/*************************************************************************************************/ +void lctrCisStopLlcpTimer(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + if (lctrGetConnOpFlag(pCtx, LL_OP_MODE_FLAG_ENA_LLCP_TIMER)) + { + WsfTimerStop(&pCisCtx->tmrProcRsp); + } +} + +/*************************************************************************************************/ +/*! + * \brief Compute the duration in microseconds of an subevent for sequential packing. + * + * \param phyMToS PHY master to slave. + * \param phySToM PHY slave to master. + * \param plMToS Payload master to slave. + * \param plSToM Payload master to slave. + * + * \return Time in microseconds for the packet to be transferred on the medium. + */ +/*************************************************************************************************/ +uint32_t lctrCisCalcSubEvtDurationUsecSeq(uint8_t phyMToS, uint8_t phySToM, uint8_t plMToS, uint8_t plSToM) +{ + uint32_t duration = 0; + + /* MIC is always included since the scheduling is done when a CIS in the CIG is enabled for the first time + * and the encryption mode of other CISs in the CIG are unknown. */ + switch (phyMToS) + { + case BB_PHY_BLE_1M: + duration += LL_DATA_LEN_TO_TIME_1M(plMToS, TRUE); + break; + case BB_PHY_BLE_2M: + 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); + break; + } + + duration += LL_BLE_TIFS_US; + + /* MIC is always included since the scheduling is done when a CIS in the CIG is enabled for the first time + * and the encryption mode of other CISs in the CIG are unknown. */ + switch (phySToM) + { + case BB_PHY_BLE_1M: + duration += LL_DATA_LEN_TO_TIME_1M(plSToM, TRUE); + break; + case BB_PHY_BLE_2M: + 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); + break; + } + + duration += LL_BLE_TMSS_US; + + duration += pLctrRtCfg->cisSubEvtSpaceDelay; /* Add runtime config delay. */ + + return duration; +} + +/*************************************************************************************************/ +/*! + * \brief Compute the duration in microseconds of an sub event for interleaved packing. + * + * \param pSetCigParam CIG parameters. + * + * \return Time in microseconds for the packet to be transferred on the medium. + * + * \note This value includes preamble, access address, CRC and T_IFS. + */ +/*************************************************************************************************/ +uint32_t lctrCisCalcSubEvtDurationUsecInter(LlCisCigParams_t *pSetCigParam) +{ + uint32_t duration = 0; + + lctrCisCtx_t *pCisCtx; + + for (unsigned int i = 0; i < pSetCigParam->numCis; i++) + { + pCisCtx = lctrFindCisById(pSetCigParam->cigId, pSetCigParam->pCisParam[i].cisId); + + duration += lctrCisCalcSubEvtDurationUsecSeq(pCisCtx->phyMToS, pCisCtx->phySToM, + pCisCtx->localDataPdu.maxTxLen, pCisCtx->localDataPdu.maxRxLen); + } + return duration; +} + +/*************************************************************************************************/ +/*! + * \brief Set default values for CIS. + */ +/*************************************************************************************************/ +void lctrCisDefaults(void) +{ + memset(pLctrCisTbl, 0, sizeof(lctrCisCtx_t) * pLctrRtCfg->maxCis); + memset(pLctrCigTbl, 0, sizeof(lctrCigCtx_t) * pLctrRtCfg->maxCig); +} + +/*************************************************************************************************/ +/*! + * \brief Generate and send a test payload. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrCisTxTestPayloadHandler(lctrCisCtx_t * pCisCtx) +{ + uint16_t maxSdu = (pCisCtx->role == LL_ROLE_MASTER) ? pCisCtx->sduSizeMToS : pCisCtx->sduSizeSToM; + uint8_t * pIsoBuf; + uint32_t pktCtr; + if ((pCisCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED) && (pCisCtx->testTxPktCtr == 0)) + { + pCisCtx->testTxPktCtr = pCisCtx->txPktCounter; + } + + pktCtr = pCisCtx->testTxPktCtr++; + pIsoBuf = lctrGenerateIsoTestData(pCisCtx->cisHandle, pCisCtx->testPldType, maxSdu, pktCtr); + + if (lmgrIsoCb.availTxBuf == 0) + { + LL_TRACE_WARN0("!!! ISO flow control detected; dropping Tx data PDU"); + + /* Drop packet due to out of Tx buffers condition. */ + WsfMsgFree(pIsoBuf); + pIsoBuf = NULL; /* Returned below. */ + } + + if (pIsoBuf == NULL) + { + /* Restore last payload counter since packet could not be generated. */ + pCisCtx->testTxPktCtr--; + return; + } + + LctrTxIso(pIsoBuf); +} + +/*************************************************************************************************/ +/*! + * \brief Action function for cis power monitoring. + * + * \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) +{ + if (!(pConnCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST)) + { + pConnCtx->monitoringState = LCTR_PC_MONITOR_DISABLED; + return; + } + + if (lmgrCb.opModeFlags & LL_OP_MODE_DISABLE_POWER_MONITOR) + { + return; + } + + int8_t sendReqDelta = 0; + + if ((rssi < pConnCtx->pclMonitorParam.autoMonitor.lowThreshold) || + (status != BB_STATUS_SUCCESS)) + { + pConnCtx->cisRssiExtremeTimeSpent++; + + if (pConnCtx->cisRssiExtremeTimeSpent >= pConnCtx->pclMonitorParam.autoMonitor.minTimeSpent) + { + if (!(pConnCtx->peerPwrLimits & LL_PWR_CONTROL_LIMIT_MAX_BIT)) + { + LL_TRACE_INFO1("RSSI too low, requesting increase in power. phy=%u", phy); + sendReqDelta = pConnCtx->pclMonitorParam.autoMonitor.requestVal; + } + pConnCtx->cisRssiExtremeTimeSpent = 0; + } + } + else if (rssi > pConnCtx->pclMonitorParam.autoMonitor.highThreshold) + { + pConnCtx->cisRssiExtremeTimeSpent++; + + 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 + { + pConnCtx->cisRssiExtremeTimeSpent = 0; + } + + if (sendReqDelta != 0) + { + lctrMsgPwrCtrlReq_t *pMsg; + if ((pMsg = (lctrMsgPwrCtrlReq_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->hdr.handle = LCTR_GET_CONN_HANDLE(pConnCtx); + pMsg->hdr.dispId = LCTR_DISP_CONN; + pMsg->hdr.event = LCTR_CONN_MSG_API_PWR_CTRL_REQ; + pMsg->delta = sendReqDelta; + pMsg->phy = phy; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } + } +} + +/*************************************************************************************************/ +/*! + * \brief Cleanup CIG contexts. + */ +/*************************************************************************************************/ +void lctrCleanupCigCtx() +{ + lctrCigCtx_t *pCigCtx; + for (uint8_t i = 0; i < pLctrRtCfg->maxCig; i++) + { + pCigCtx = &pLctrCigTbl[i]; + if (pCigCtx->enabled) + { + if (pCigCtx->numCisEsted == 0) + { + lctrFreeCigCtx(pCigCtx); + } + else + { + SchRemove(&pCigCtx->cigBod); + } + } + } +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis_master.c new file mode 100644 index 0000000000..da28cbc1c4 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis_master.c @@ -0,0 +1,1127 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller connected isochronous stream master operation builder implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_cis.h" +#include "lctr_int_iso.h" +#include "lctr_int_cis_master.h" +#include "lctr_int_cis_slave.h" +#include "lctr_int_conn_master.h" +#include "lctr_int.h" +#include "sch_api.h" +#include "sch_api_ble.h" +#include "bb_api.h" +#include "pal_bb.h" +#include "wsf_assert.h" +#include "wsf_buf.h" +#include "wsf_cs.h" +#include "wsf_math.h" +#include "wsf_msg.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include + +/************************************************************************************************** + Globals +**************************************************************************************************/ + +/*! \brief Create CIS pending parameters. */ +lctrCreateCisPend_t lctrMstCreateCisPend; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ +extern uint8_t lctrChoosePreferredPhy(uint8_t val); + +/************************************************************************************************** + Internal functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief CIS master reset handler. + */ +/*************************************************************************************************/ +static void lctrCisMstResetHandler(void) +{ + BbBleCisSlaveInit(); + BbBleCisMasterInit(); + lctrCisDefaults(); + LmgrMstCisInit(); +} + +/*************************************************************************************************/ +/*! + * \brief Master Tx data pending task event handler. + */ +/*************************************************************************************************/ +static void lctrIsoTxPendingHandler(void) +{ + unsigned int i; + + for (i = 0; i < pLctrRtCfg->maxCis; i++) + { + lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i]; + + if ((pCisCtx->enabled) && + !WsfQueueEmpty(&pCisCtx->txArqQ)) + { + lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); + SchReload(&pCigCtx->cigBod); + } + } +} + +/*************************************************************************************************/ +/*! + * \brief Host channel class update handler for CIS master. + * + * \param chanMap Updated channel map. + * + * \return Status code. + */ +/*************************************************************************************************/ +static uint8_t lctrMstCisChClassUpdate(uint64_t chanMap) +{ + uint16_t handle; + + /* 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. */ + LctrCisUpdateChanMap(handle); + } + } + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Check whether the parameters for the CIG can be scheduled or not. + * + * \param pCigCtx CIG context. + * + * \return TRUE if schedule is successful, otherwise FALSE. + */ +/*************************************************************************************************/ +static bool_t lctrCisMstCheckCigParams(lctrCigCtx_t *pCigCtx) +{ + /* Check whether the CIG could be scheduled within the interval. */ + if (pCigCtx->cigSyncDelayUsec >= (uint32_t)(LCTR_ISO_INT_TO_US(pCigCtx->isoInterval) - LL_BLE_TMSS_US)) + { + return FALSE; + } + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Compute the duration in microseconds of an sub event for interleaved packing for + * testing purpose. + * + * \param pSetCigParamTest CIG parameter for test. + * + * \return Time in microseconds for the packet to be transferred on the medium. + * + * \note This value includes preamble, access address, CRC and T_IFS. + */ +/*************************************************************************************************/ +static uint32_t lctrCalcSubEvtDurationUsecInterTest(LlCisCigParamsTest_t *pSetCigParamTest) +{ + uint32_t duration = 0; + + lctrCisCtx_t *pCisCtx; + + for (unsigned int i = 0; i < pSetCigParamTest->numCis; i++) + { + pCisCtx = lctrFindCisById(pSetCigParamTest->cigId, pSetCigParamTest->pCisParam[i].cisId); + + duration += lctrCisCalcSubEvtDurationUsecSeq(pCisCtx->phyMToS, pCisCtx->phySToM, + pCisCtx->localDataPdu.maxTxLen, pCisCtx->localDataPdu.maxRxLen); + } + return duration; +} + +/*************************************************************************************************/ +/*! + * \brief Set up a new CIS or update an existing CIS. + * + * \param pCisCtx CIS context. + * \param pSetCigParam CIG parameters. + * \param pCisParam CIS parameters. + */ +/*************************************************************************************************/ +static void lctrSetCis(lctrCisCtx_t *pCisCtx, LlCisCigParams_t *pSetCigParam, LlCisCisParams_t *pCisParam) +{ + pCisCtx->cisId = pCisParam->cisId; + pCisCtx->sca = pSetCigParam->sca; + pCisCtx->packing = pSetCigParam->packing; + pCisCtx->framing = pSetCigParam->framing; + pCisCtx->accessAddr = lctrComputeAccessAddr(); + + if (pCisCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED) + { + if (pSetCigParam->sduIntervalMToS <= 1250) + { + pSetCigParam->sduIntervalMToS = 1250; + } + if (pSetCigParam->sduIntervalSToM <= 1250) + { + pSetCigParam->sduIntervalSToM = 1250; + } + + pCisCtx->isoInterval = LL_MATH_DIV_1250(pSetCigParam->sduIntervalMToS); /* Make sure PDU interval the same as the SDU interval. Assume sduIntervalMToS equals sduIntervalSToM */ + pCisCtx->sduIntervalMToS = pSetCigParam->sduIntervalMToS; + pCisCtx->sduIntervalSToM = pSetCigParam->sduIntervalSToM; + pCisCtx->localDataPdu.maxTxLen = WSF_MIN(pCisParam->sduSizeMToS, pLctrRtCfg->maxIsoPduLen); + pCisCtx->localDataPdu.maxRxLen = WSF_MIN(pCisParam->sduSizeSToM, pLctrRtCfg->maxIsoPduLen); + pCisCtx->sduSizeMToS = pCisParam->sduSizeMToS; + pCisCtx->sduSizeSToM = pCisParam->sduSizeSToM; + pCisCtx->phyMToS = lctrPhysBitToPhy(lctrChoosePreferredPhy(pCisParam->phyMToS)); + pCisCtx->phySToM = lctrPhysBitToPhy(lctrChoosePreferredPhy(pCisParam->phySToM)); + 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) + { + pCisCtx->bnMToS = pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen + 1; + } + else + { + pCisCtx->bnMToS = pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen; + } + + if (pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen * pCisCtx->localDataPdu.maxRxLen < pCisCtx->sduSizeSToM) + { + pCisCtx->bnSToM = pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen + 1; + } + else + { + pCisCtx->bnSToM = pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen; + } + + pCisCtx->nse = WSF_MAX(pCisCtx->bnSToM, pCisCtx->bnMToS) + WSF_MAX(pCisParam->rteMToS, pCisParam->rteSToM); + + LL_TRACE_INFO1("lctrSetCis, maxTxLen=%d", pCisCtx->localDataPdu.maxTxLen); + LL_TRACE_INFO1("lctrSetCis, sduMToS=%d", pCisCtx->sduSizeMToS); + LL_TRACE_INFO1("lctrSetCis, bnMToS=%d", pCisCtx->bnMToS); + + } + else /* LL_ISO_PDU_TYPE_FRAMED */ + { + if (pSetCigParam->sduIntervalMToS <= 1250) + { + pSetCigParam->sduIntervalMToS = 1250; + } + if (pSetCigParam->sduIntervalSToM <= 1250) + { + pSetCigParam->sduIntervalSToM = 1250; + } + + pCisCtx->isoInterval = LL_MATH_DIV_1250(pSetCigParam->sduIntervalMToS); /* Make sure PDU interval the same as the SDU interval. Assume sduIntervalMToS equals sduIntervalSToM */ + pCisCtx->sduIntervalMToS = pSetCigParam->sduIntervalMToS; + pCisCtx->sduIntervalSToM = pSetCigParam->sduIntervalSToM; + pCisCtx->localDataPdu.maxTxLen = WSF_MIN(pCisParam->sduSizeMToS, pLctrRtCfg->maxIsoPduLen); + pCisCtx->localDataPdu.maxRxLen = WSF_MIN(pCisParam->sduSizeSToM, pLctrRtCfg->maxIsoPduLen); + pCisCtx->sduSizeMToS = pCisParam->sduSizeMToS; + pCisCtx->sduSizeSToM = pCisParam->sduSizeSToM; + pCisCtx->phyMToS = lctrPhysBitToPhy(lctrChoosePreferredPhy(pCisParam->phyMToS)); + pCisCtx->phySToM = lctrPhysBitToPhy(lctrChoosePreferredPhy(pCisParam->phySToM)); + 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) + { + pCisCtx->bnMToS = pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen + 1; + } + else + { + pCisCtx->bnMToS = pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen; + } + + if (pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen * pCisCtx->localDataPdu.maxRxLen < pCisCtx->sduSizeSToM) + { + pCisCtx->bnSToM = pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen + 1; + } + else + { + pCisCtx->bnSToM = pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen; + } + + pCisCtx->nse = WSF_MAX(pCisCtx->bnSToM, pCisCtx->bnMToS) + WSF_MAX(pCisParam->rteMToS, pCisParam->rteSToM); + + LL_TRACE_INFO1("lctrSetCis, maxTxLen=%d", pCisCtx->localDataPdu.maxTxLen); + LL_TRACE_INFO1("lctrSetCis, sduMToS=%d", pCisCtx->sduSizeMToS); + LL_TRACE_INFO1("lctrSetCis, bnMToS=%d", pCisCtx->bnMToS); + } +} + +/*************************************************************************************************/ +/*! + * \brief Set up a new CIG. + * + * \param pCigCtx CIG context. + * \param pSetCigParam CIG parameters. + */ +/*************************************************************************************************/ +static void lctrSetCig(lctrCigCtx_t *pCigCtx, LlCisCigParams_t *pSetCigParam) +{ + lctrCisCtx_t *pCisCtx, *pCisCtxTemp, *pCisCtxFirst; + + /* Calculate subevent interval and offset for each CIS. */ + for (unsigned int i = 0; i < pSetCigParam->numCis; i++) + { + pCisCtx = lctrFindCisById(pSetCigParam->cigId, pSetCigParam->pCisParam[i].cisId); + + WSF_ASSERT(pCisCtx); + + if (pSetCigParam->packing == LL_PACKING_INTERLEAVED) + { + pCisCtx->subIntervUsec = lctrCisCalcSubEvtDurationUsecInter(pSetCigParam); + pCisCtx->delayUsec = lctrCisCalcSubEvtDurationUsecSeq(pCisCtx->phyMToS, pCisCtx->phySToM, + pCisCtx->localDataPdu.maxTxLen, pCisCtx->localDataPdu.maxRxLen); + } + else + { + /* LL_PACKING_SEQUENTIAL */ + pCisCtx->subIntervUsec = lctrCisCalcSubEvtDurationUsecSeq(pCisCtx->phyMToS, pCisCtx->phySToM, + pCisCtx->localDataPdu.maxTxLen, pCisCtx->localDataPdu.maxRxLen); + pCisCtx->delayUsec = pCisCtx->subIntervUsec; + } + + /* The formula is (2 * CIS_interval * (master_sca + slave_sca) / 1000000) */ + WSF_ASSERT((uint64_t)pCisCtx->subIntervUsec > WSF_MIN(LL_BLE_TMSS_US, LL_MATH_DIV_10E6(2 * LCTR_ISO_INT_TO_US(pCisCtx->isoInterval) * ((uint64_t)lctrCalcTotalAccuracy(pSetCigParam->sca))))); + LL_TRACE_INFO1("lctrSetCig, subIntervUsec=%d", pCisCtx->subIntervUsec); + LL_TRACE_INFO1("lctrSetCig, delayUsec=%d", pCisCtx->delayUsec); + } + + /* Calculate CIG sync delay and CIS sync delay. */ + if (pSetCigParam->packing == LL_PACKING_INTERLEAVED) + { + pCisCtxFirst = lctrFindCisById(pSetCigParam->cigId, pSetCigParam->pCisParam[0].cisId); + WSF_ASSERT(pCisCtxFirst); + + pCigCtx->cigSyncDelayUsec = pCisCtxFirst->cigSyncDelayUsec = pCisCtxFirst->cisSyncDelayUsec = pCisCtxFirst->subIntervUsec * pCisCtxFirst->nse; + pCigCtx->isoInterval = pCisCtxFirst->isoInterval; /* CISs have the same ISO interval and it is the same as CIG. */ + + for (unsigned int i = 1; i < pSetCigParam->numCis; i++) + { + pCisCtx = lctrFindCisById(pSetCigParam->cigId, pSetCigParam->pCisParam[i].cisId); + + WSF_ASSERT(pCisCtx); + + uint32_t durationUs = 0; + + for (unsigned int j = 0; j < i; j++) + { + pCisCtxTemp = lctrFindCisById(pSetCigParam->cigId, pSetCigParam->pCisParam[j].cisId); + durationUs += lctrCisCalcSubEvtDurationUsecSeq(pCisCtxTemp->phyMToS, pCisCtxTemp->phySToM, + pCisCtxTemp->localDataPdu.maxTxLen, pCisCtxTemp->localDataPdu.maxRxLen); + } + pCisCtx->cisSyncDelayUsec = pCisCtxFirst->cisSyncDelayUsec - durationUs; + pCisCtx->cigSyncDelayUsec = pCisCtxFirst->cisSyncDelayUsec; /* CIG_SYNC_DELAY = CIS_SYNC_DELAY[0] */ + } + } + else + { + /* LL_PACKING_SEQUENTIAL */ + pCisCtxFirst = lctrFindCisById(pSetCigParam->cigId, pSetCigParam->pCisParam[0].cisId); + + WSF_ASSERT(pCisCtxFirst); + + for (unsigned int i = 0; i < pSetCigParam->numCis; i++) + { + pCisCtx = lctrFindCisById(pSetCigParam->cigId, pSetCigParam->pCisParam[i].cisId); + + WSF_ASSERT(pCisCtx); + + for (unsigned int j = i; j < pSetCigParam->numCis; j++) + { + pCisCtxTemp = lctrFindCisById(pSetCigParam->cigId, pSetCigParam->pCisParam[j].cisId); + + pCisCtx->cisSyncDelayUsec += (pCisCtxTemp->subIntervUsec * pCisCtxTemp->nse); + } + + pCisCtx->cigSyncDelayUsec = pCisCtxFirst->cisSyncDelayUsec; /* CIG_SYNC_DELAY = CIS_SYNC_DELAY[0] */ + LL_TRACE_INFO1("LL_PACKING_SEQUENTIAL, cisSyncDelayUsec=%d", pCisCtx->cisSyncDelayUsec); + } + pCigCtx->cigSyncDelayUsec = pCisCtxFirst->cisSyncDelayUsec; /* CIG_SYNC_DELAY = CIS_SYNC_DELAY[0] */ + pCigCtx->isoInterval = pCisCtxFirst->isoInterval; /* CISs have the same ISO interval and it is the same as CIG. */ + } + + pCigCtx->packing = pSetCigParam->packing; + pCigCtx->isValid = lctrCisMstCheckCigParams(pCigCtx); +} + +/*************************************************************************************************/ +/*! + * \brief Set up a new CIG for testing purpose. + * + * \param pCigCtx CIS context. + * \param pSetCigParamTest CIG test parameters. + */ +/*************************************************************************************************/ +static void lctrSetCigTest(lctrCigCtx_t *pCigCtx, LlCisCigParamsTest_t *pSetCigParamTest) +{ + lctrCisCtx_t *pCisCtx, *pCisCtxTemp, *pCisCtxFirst; + + /* Calculate subevent interval for each CIS. */ + for (unsigned int i = 0; i < pSetCigParamTest->numCis; i++) + { + pCisCtx = lctrFindCisById(pSetCigParamTest->cigId, pSetCigParamTest->pCisParam[i].cisId); + + WSF_ASSERT(pCisCtx); + + if (pSetCigParamTest->packing == LL_PACKING_INTERLEAVED) + { + pCisCtx->subIntervUsec = lctrCalcSubEvtDurationUsecInterTest(pSetCigParamTest); + pCisCtx->delayUsec = lctrCisCalcSubEvtDurationUsecSeq(pCisCtx->phyMToS, pCisCtx->phySToM, + pCisCtx->localDataPdu.maxTxLen, pCisCtx->localDataPdu.maxRxLen); + } + else + { + /* LL_PACKING_SEQUENTIAL */ + pCisCtx->subIntervUsec = lctrCisCalcSubEvtDurationUsecSeq(pCisCtx->phyMToS, pCisCtx->phySToM, + pCisCtx->localDataPdu.maxTxLen, pCisCtx->localDataPdu.maxRxLen); + pCisCtx->delayUsec = pCisCtx->subIntervUsec; + } + + /* The formula is (2 * CIS_interva *(master_sca + slave_sca) / 1000000) */ + WSF_ASSERT((uint64_t)pCisCtx->subIntervUsec > WSF_MIN(LL_BLE_TMSS_US, LL_MATH_DIV_10E6(2 * LCTR_ISO_INT_TO_US(pCisCtx->isoInterval) * ((uint64_t)lctrCalcTotalAccuracy(pSetCigParamTest->sca))))); + } + + /* Calculate CIG sync delay and CIS sync delay. */ + if (pSetCigParamTest->packing == LL_PACKING_INTERLEAVED) + { + pCisCtxFirst = lctrFindCisById(pSetCigParamTest->cigId, pSetCigParamTest->pCisParam[0].cisId); + WSF_ASSERT(pCisCtxFirst); + + pCigCtx->cigSyncDelayUsec = pCisCtxFirst->cigSyncDelayUsec = pCisCtxFirst->cisSyncDelayUsec = pCisCtxFirst->subIntervUsec * pCisCtxFirst->nse; + pCigCtx->isoInterval = pCisCtxFirst->isoInterval; /* CISs have the same ISO interval and it is the same as CIG. */ + + for (unsigned int i = 1; i < pSetCigParamTest->numCis; i++) + { + pCisCtx = lctrFindCisById(pSetCigParamTest->cigId, pSetCigParamTest->pCisParam[i].cisId); + + WSF_ASSERT(pCisCtx); + + uint32_t durationUs = 0; + + for (unsigned int j = 0; j < i; j++) + { + pCisCtxTemp = lctrFindCisById(pSetCigParamTest->cigId, pSetCigParamTest->pCisParam[j].cisId); + durationUs += lctrCisCalcSubEvtDurationUsecSeq(pCisCtxTemp->phyMToS, pCisCtxTemp->phySToM, + pCisCtxTemp->localDataPdu.maxTxLen, pCisCtxTemp->localDataPdu.maxRxLen); + } + pCisCtx->cisSyncDelayUsec = pCisCtxFirst->cisSyncDelayUsec - durationUs; + pCisCtx->cigSyncDelayUsec = pCisCtxFirst->cisSyncDelayUsec; /* CIG_SYNC_DELAY = CIS_SYNC_DELAY[0] */ + } + } + else + { + pCisCtxFirst = lctrFindCisById(pSetCigParamTest->cigId, pSetCigParamTest->pCisParam[0].cisId); + + WSF_ASSERT(pCisCtxFirst); + + /* LL_PACKING_SEQUENTIAL */ + for (unsigned int i = 0; i < pSetCigParamTest->numCis; i++) + { + pCisCtx = lctrFindCisById(pSetCigParamTest->cigId, pSetCigParamTest->pCisParam[i].cisId); + + WSF_ASSERT(pCisCtx); + + for (unsigned int j = i; j < pSetCigParamTest->numCis; j++) + { + pCisCtxTemp = lctrFindCisById(pSetCigParamTest->cigId, pSetCigParamTest->pCisParam[j].cisId); + + pCisCtx->cisSyncDelayUsec += (pCisCtxTemp->subIntervUsec * pCisCtxTemp->nse); + } + + pCisCtx->cigSyncDelayUsec = pCisCtxFirst->cisSyncDelayUsec; /* CIG_SYNC_DELAY = CIS_SYNC_DELAY[0] */ + } + pCigCtx->cigSyncDelayUsec = pCisCtxFirst->cisSyncDelayUsec; /* CIG_SYNC_DELAY = CIS_SYNC_DELAY[0] */ + pCigCtx->isoInterval = pCisCtxFirst->isoInterval; /* CISs have the same ISO interval and it is the same as CIG. */ + } + + pCigCtx->packing = pSetCigParamTest->packing; + pCigCtx->isValid = lctrCisMstCheckCigParams(pCigCtx); +} + +/*************************************************************************************************/ +/*! + * \brief Set up a new CIS or update an existing CIS for testing purpose. + * + * \param pCisCtx CIS context. + * \param pSetCigParamTest CIG parameters. + * \param pCigCisParamTest CIS parameters. + */ +/*************************************************************************************************/ +static void lctrSetCisTest(lctrCisCtx_t *pCisCtx, LlCisCigParamsTest_t *pSetCigParamTest, + LlCisCigCisParamsTest_t *pCigCisParamTest) +{ + pCisCtx->sduIntervalMToS = pSetCigParamTest->sduIntervalMToS; + pCisCtx->sduIntervalSToM = pSetCigParamTest->sduIntervalSToM; + pCisCtx->ftMToS = pSetCigParamTest->ftMToS; + pCisCtx->ftSToM = pSetCigParamTest->ftSToM; + pCisCtx->isoInterval = pSetCigParamTest->isoInterval; + pCisCtx->sca = pSetCigParamTest->sca; + pCisCtx->packing = pSetCigParamTest->packing; + pCisCtx->framing = pSetCigParamTest->framing; + + pCisCtx->cisId = pCigCisParamTest->cisId; + pCisCtx->nse = pCigCisParamTest->nse; + pCisCtx->sduSizeMToS = pCigCisParamTest->sduSizeMToS; + pCisCtx->sduSizeSToM = pCigCisParamTest->sduSizeSToM; + pCisCtx->phyMToS = lctrPhysBitToPhy(lctrChoosePreferredPhy(pCigCisParamTest->phyMToS)); + pCisCtx->phySToM = lctrPhysBitToPhy(lctrChoosePreferredPhy(pCigCisParamTest->phySToM)); + pCisCtx->bnMToS = pCigCisParamTest->bnMToS; + pCisCtx->bnSToM = pCigCisParamTest->bnSToM; + + pCisCtx->accessAddr = lctrComputeAccessAddr(); + lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); + WSF_ASSERT(pCtx); + pCisCtx->crcInit = pCtx->crcInit; + pCisCtx->supTimeoutMs = pCtx->supTimeoutMs; + + pCisCtx->localDataPdu.maxTxLen = pCigCisParamTest->pduSizeMToS; + pCisCtx->localDataPdu.maxRxLen = pCigCisParamTest->pduSizeSToM; +} + +/*************************************************************************************************/ +/*! + * \brief Set CIG parameters. + * + * \param pSetCigParam CIG parameters. + * \param pCisHandles Returned CIS handles. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrSetCigParam(LlCisCigParams_t *pSetCigParam, uint16_t *pCisHandles) +{ + lctrCigCtx_t *pCigCtx; + + if ((pCigCtx = lctrFindCigById(pSetCigParam->cigId)) == NULL) + { + if ((pCigCtx = lctrAllocCigCtx(pSetCigParam->cigId)) == NULL) + { + LL_TRACE_WARN0("LctrSetCigParam, there is no more CIG context"); + return LL_ERROR_CODE_MEM_CAP_EXCEEDED; + } + } + + if (pCigCtx->numCisEsted > 0) + { + LL_TRACE_WARN0("LctrSetCigParam, there is an established CIS"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + if (lmgrCisMstCb.createCisPend == TRUE) + { + LL_TRACE_WARN0("LctrSetCigParam, there is a pending CIS"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + lctrCisCtx_t *pCisCtx; + + uint8_t numEnableCis = lctrGetNumEnabledCisCtx(pSetCigParam); + + if (numEnableCis == 0) + { + /* Set up new CIS contexts. */ + if (pSetCigParam->numCis > lctrGetNumAvailCisCtx()) + { + LL_TRACE_WARN0("LctrSetCigParam, there is no more CIS context"); + return LL_ERROR_CODE_CONN_LIMIT_EXCEEDED; + } + else + { + for (unsigned int i = 0; i < pSetCigParam->numCis; i++) + { + pCisCtx = lctrAllocCisCtx(pCigCtx); + pCisCtx->role = LL_ROLE_MASTER; + lctrSetCis(pCisCtx, pSetCigParam, &pSetCigParam->pCisParam[i]); + pCisHandles[i] = pCisCtx->cisHandle; + } + lctrSetCig(pCigCtx, pSetCigParam); + } + } + else + { + if ((pSetCigParam->numCis - numEnableCis) > lctrGetNumAvailCisCtx()) + { + return LL_ERROR_CODE_MEM_CAP_EXCEEDED; + } + else + { + for (unsigned int i = 0; i < pSetCigParam->numCis; i++) + { + if ((pCisCtx = lctrFindCisById(pSetCigParam->cigId, pSetCigParam->pCisParam[i].cisId)) != NULL) + { + /* Update the context which is already set up. */ + lctrSetCis(pCisCtx, pSetCigParam, &pSetCigParam->pCisParam[i]); + } + else + { + /* Allocate new context, no allocation error, already checked. */ + pCisCtx = lctrAllocCisCtx(pCigCtx); + pCisCtx->role = LL_ROLE_MASTER; + lctrSetCis(pCisCtx, pSetCigParam, &pSetCigParam->pCisParam[i]); + } + pCisHandles[i] = pCisCtx->cisHandle; + } + lctrSetCig(pCigCtx, pSetCigParam); + } + } + + pCigCtx->roleData.mst.numCis = pSetCigParam->numCis; + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Set CIG parameters for testing purpose. + * + * \param pSetCigParamTest CIG parameters for testing. + * \param pCisHandles Returned CIS handles. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrSetCigParamTest(LlCisCigParamsTest_t *pSetCigParamTest, uint16_t *pCisHandles) +{ + lctrCigCtx_t *pCigCtx; + + if ((pCigCtx = lctrFindCigById(pSetCigParamTest->cigId)) == NULL) + { + if ((pCigCtx = lctrAllocCigCtx(pSetCigParamTest->cigId)) == NULL) + { + LL_TRACE_WARN0("LctrSetCigParamTest, there is no more CIG context"); + return LL_ERROR_CODE_MEM_CAP_EXCEEDED; + } + } + + if (pCigCtx->numCisEsted > 0) + { + LL_TRACE_WARN0("LctrSetCigParamTest, there is an established CIS"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + lctrCisCtx_t *pCisCtx; + + uint8_t numEnableCis = lctrGetNumEnabledCisCtxTest(pSetCigParamTest); + + if (numEnableCis == 0) + { + /* Set up new CIS contexts. */ + if (pSetCigParamTest->numCis > lctrGetNumAvailCisCtx()) + { + LL_TRACE_WARN0("LctrSetCigParamTest, there is no more CIS context"); + return LL_ERROR_CODE_CONN_LIMIT_EXCEEDED; + } + else + { + for (unsigned int i = 0; i < pSetCigParamTest->numCis; i++) + { + pCisCtx = lctrAllocCisCtx(pCigCtx); + pCisCtx->role = LL_ROLE_MASTER; + lctrSetCisTest(pCisCtx, pSetCigParamTest, &pSetCigParamTest->pCisParam[i]); + pCisHandles[i] = pCisCtx->cisHandle; + } + lctrSetCigTest(pCigCtx, pSetCigParamTest); + } + } + else + { + if ((pSetCigParamTest->numCis - numEnableCis) > lctrGetNumAvailCisCtx()) + { + return LL_ERROR_CODE_MEM_CAP_EXCEEDED; + } + else + { + for (unsigned int i = 0; i < pSetCigParamTest->numCis; i++) + { + if ((pCisCtx = lctrFindCisById(pSetCigParamTest->cigId, pSetCigParamTest->pCisParam[i].cisId)) != NULL) + { + /* Update the context which is already set up. */ + lctrSetCisTest(pCisCtx, pSetCigParamTest, &pSetCigParamTest->pCisParam[i]); + } + else + { + /* Allocate new context, no allocation error, already checked. */ + pCisCtx = lctrAllocCisCtx(pCigCtx); + pCisCtx->role = LL_ROLE_MASTER; + lctrSetCisTest(pCisCtx, pSetCigParamTest, &pSetCigParamTest->pCisParam[i]); + } + pCisHandles[i] = pCisCtx->cisHandle; + } + lctrSetCigTest(pCigCtx, pSetCigParamTest); + } + } + + pCigCtx->roleData.mst.numCis = pSetCigParamTest->numCis; + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Remove CIG. + * + * \param cigId Identifier for CIG. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrRemoveCig(uint8_t cigId) +{ + lctrCigCtx_t *pCigCtx; + + if ((pCigCtx = lctrFindCigById(cigId)) == NULL) + { + LL_TRACE_WARN1("LctrRemoveCig, invalid CIG_ID=%d.", cigId); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + /* Return LL_ERROR_CODE_CMD_DISALLOWED if anyone of the CIS is pending or slave role in the CIG. */ + for (unsigned int i = 0; i < pLctrRtCfg->maxCis; i++) + { + lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i]; + + if ((pCisCtx->enabled == TRUE) && + (pCisCtx->cigId == cigId)) + { + if (pCisCtx->role == LL_ROLE_SLAVE) + { + LL_TRACE_WARN0("LctrRemoveCig, invalid role"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + if (pCisCtx->isCisReqPend == TRUE) + { + LL_TRACE_WARN0("LctrRemoveCig, there is a pending CIS"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + } + } + + if (lctrGetNumEstCisCtxByCigCtx(pCigCtx) > 0) + { + LL_TRACE_WARN0("LctrRemoveCig, there is an established CIS"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + for (unsigned int i = 0; i < pLctrRtCfg->maxCis; i++) + { + lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i]; + + if ((pCisCtx->enabled == TRUE) && + (pCisCtx->cigId == cigId) && + (pCisCtx->role == LL_ROLE_MASTER)) + { + lctrFreeCisCtx(pCisCtx); + } + } + + lctrFreeCigCtx(pCigCtx); + + return LL_SUCCESS; +} + + + +/*************************************************************************************************/ +/*! + * \brief Initialize link layer controller resources for CIS master. + */ +/*************************************************************************************************/ +void LctrMstCisInit(void) +{ + /* Add reset handler. */ + lctrResetHdlrTbl[LCTR_DISP_CIS] = lctrCisMstResetHandler; + + /* Add CIS message dispatcher. */ + lctrMsgDispTbl[LCTR_DISP_CIS] = (LctrMsgDisp_t)lctrCisDisp; + + /* Add CIS function pointers */ + LctrUpdateCisChanMapFn = LctrCisUpdateChanMap; + lctrRegisterChClassHandler(lctrMstCisChClassUpdate); + + /* Add CIS event handlers. */ + lctrEventHdlrTbl[LCTR_EVENT_CIS_TX_PENDING] = lctrIsoTxPendingHandler; + lctrEventHdlrTbl[LCTR_EVENT_CIS_RX_PENDING] = lctrCisRxPendingHandler; + lctrEventHdlrTbl[LCTR_EVENT_ISO_TX_COMPLETE] = lctrIsoTxCompletedHandler; + + /* Add LLCP SM handler. */ + lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_EST] = lctrMstLlcpExecuteCisEstSm; + lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM] = lctrLlcpExecuteCisTermSm; + + lctrCisDefaults(); + LmgrMstCisInit(); + + /* Set supported features. */ + if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_5_1) + { + lmgrPersistCb.featuresDefault |= LL_FEAT_CIS_MASTER_ROLE; + } +} + +/*************************************************************************************************/ +/*! + * \brief Create CIS. + * + * \param numCis Number of streams to create. + * \param pCreateCisParam CIS parameters. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrCreateCis(uint8_t numCis, LlCisCreateCisParams_t *pCreateCisParam) +{ + /* Return error if the previous create CIS is pending. */ + if (lmgrCisMstCb.createCisPend == TRUE) + { + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + /* Make sure handle is valid and CIS is not yet established. */ + for (unsigned int i = 0; i < numCis; i++) + { + lctrCisCtx_t *pCisCtx; + + if ((pCisCtx = lctrFindCisByHandle(pCreateCisParam->pCisHandle[i])) == NULL) + { + LL_TRACE_WARN0("LctrCreateCis, invalid CIS handle"); + return LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + + if (lctrIsCisEst(pCisCtx) == TRUE) + { + LL_TRACE_WARN0("LctrCreateCis, CIS is already established"); + return LL_ERROR_CODE_ACL_CONN_ALREADY_EXISTS; + } + } + + lmgrCisMstCb.createCisPend = TRUE; + + lctrMstCreateCisPend.numCis = numCis; + /* Save the handles */ + for (unsigned int i = 0; i < numCis; i++) + { + lctrMstCreateCisPend.cisHandle[i] = pCreateCisParam->pCisHandle[i]; + lctrMstCreateCisPend.aclHandle[i] = pCreateCisParam->pAclHandle[i]; + lctrMstCreateCisPend.isCreateCisDone[i] = FALSE; + } + + /* Only start first CIS establishment procedure. */ + lctrCreateCis_t *pMsg; + + if ((pMsg = (lctrCreateCis_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->hdr.handle = lctrMstCreateCisPend.aclHandle[0]; + pMsg->hdr.dispId = LCTR_DISP_CONN; + pMsg->hdr.event = LCTR_CONN_MSG_API_CIS_REQ; + + pMsg->cisHandle = lctrMstCreateCisPend.cisHandle[0]; + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Build a CIG operation. + * + * \param pCigCtx CIG context. + */ +/*************************************************************************************************/ +void lctrMstCisBuildCigOp(lctrCigCtx_t *pCigCtx) +{ + /* Pre-resolve common structures for efficient access. */ + BbOpDesc_t * const pOp = &pCigCtx->cigBod; + + /* When build the BOD, always setup channel use the first CIS context in the CIG. */ + lctrCisCtx_t *pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + pCigCtx->pCisCtx = pCisCtx; + + BbBleData_t * const pBle = &pCisCtx->bleData; + BbBleMstCisEvent_t * const pCis = &pBle->op.mstCis; + + memset(pOp, 0, sizeof(BbOpDesc_t)); + memset(pBle, 0, sizeof(BbBleData_t)); + memset(pCis, 0, sizeof(BbBleMstCisEvent_t)); + + /*** CIS context setup ***/ + + /* pFirstCisCtx->cisEvtCounter = 0; */ /* cleared in alloc. */ + /* pFirstCisCtx->txHdr.sn = 0; */ /* cleared in alloc */ + /* pFirstCisCtx->txHdr.nesn = 0; */ /* cleared in alloc */ + + /*** BLE general setup ***/ + + pBle->chan.opType = BB_BLE_OP_MST_CIS_EVENT; + + pBle->chan.chanIdx = pCisCtx->chIdx; /* Set in the lctrCisSetupChanParam. */ + pBle->chan.txPower = pLctrRtCfg->defTxPwrLvl; + pBle->chan.accAddr = pCisCtx->accessAddr; + pBle->chan.crcInit = pCisCtx->crcInit; + pBle->chan.txPhy = pCisCtx->phyMToS; + pBle->chan.rxPhy = pCisCtx->phySToM;; + 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 (LL_ENABLE_TESTER) + pBle->chan.accAddrRx = pCisCtx->accessAddr ^ llTesterCb.cisAccessAddrRx; + pBle->chan.accAddrTx = pCisCtx->accessAddr ^ llTesterCb.cisAccessAddrRx; + pBle->chan.crcInitRx = pCisCtx->crcInit ^ llTesterCb.cisCrcInitRx; + pBle->chan.crcInitTx = pCisCtx->crcInit ^ llTesterCb.cisCrcInitTx; +#endif + + /* pBle->chan.enc.enaEncrypt = FALSE; */ /* cleared in alloc */ + /* pBle->chan.enc.enaDecrypt = FALSE; */ + pBle->chan.enc.enaAuth = TRUE; + pBle->chan.enc.nonceMode = PAL_BB_NONCE_MODE_EXT64_CNTR; + pBle->chan.enc.pTxPktCounter = &pCisCtx->txPktCounter; + pBle->chan.enc.pRxPktCounter = &pCisCtx->rxPktCounter; + + /*** General setup ***/ + + /* pOp->minDurUsec = pFirstCisCtx->subIntervUsec * WSF_MAX(pFirstCisCtx->bnMToS, pFirstCisCtx->bnSToM); */ /* Guarantee at least Max BN */ + pOp->minDurUsec = pCigCtx->cigSyncDelayUsec; + pOp->maxDurUsec = pCigCtx->cigSyncDelayUsec; + + /* pOp->due = 0 */ /* set in lctrMstCisCigOpCommit() */ + pOp->reschPolicy = BB_RESCH_FIXED_PREFERRED; + pOp->protId = BB_PROT_BLE; + pOp->prot.pBle = pBle; + pOp->endCback = lctrMstCisCigEndOp; + pOp->abortCback = lctrMstCisCigAbortOp; + pOp->pCtx = pCigCtx; + + /*** BLE stream setup ***/ + + pCis->checkContOpCback = lctrMstCisCheckContOp; + pCis->execCback = lctrMstCisCigBeginOp; + pCis->contExecCback = lctrMstCisCigContOp; + pCis->postSubEvtCback = lctrMstCisCigPostSubEvt; + pCis->cancelCback = lctrMstCisCigCleanupOp; + pCis->txDataCback = lctrMstCisCigTxCompletion; + pCis->rxDataCback = lctrMstCisCigRxCompletion; + + /*** Commit operation ***/ + + /* Postponed in lctrMstCisCigOpCommit(). */ + pCigCtx->isBodBuilt = TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Build a CIG operation. + * + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrMstCisBuildCisData(lctrCisCtx_t *pCisCtx) +{ + BbBleData_t * const pBle = &pCisCtx->bleData; + BbBleMstCisEvent_t * const pCis = &pBle->op.mstCis; + lctrConnCtx_t * pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); + + memset(pBle, 0, sizeof(BbBleData_t)); + memset(pCis, 0, sizeof(BbBleMstCisEvent_t)); + + /*** CIS context setup ***/ + + /* pCisCtx->cisEvtCounter = 0; */ /* cleared in alloc. */ + /* pCisCtx->txHdr.sn = 0; */ /* cleared in alloc */ + /* pCisCtx->txHdr.nesn = 0; */ /* cleared in alloc */ + + /*** BLE general setup ***/ + + pBle->chan.opType = BB_BLE_OP_MST_CIS_EVENT; + + pBle->chan.chanIdx = pCisCtx->chIdx; /* Set in the lctrCisSetupChanParam. */ + pBle->chan.txPower = pLctrRtCfg->defTxPwrLvl; + pBle->chan.accAddr = pCisCtx->accessAddr; + pBle->chan.crcInit = pCisCtx->crcInit; + pBle->chan.txPhy = pCisCtx->phyMToS; + pBle->chan.rxPhy = pCisCtx->phySToM;; + 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) + { + /* Set PHY options to host defined behavior. */ + pBle->chan.initTxPhyOptions = pConnCtx->bleData.chan.tifsTxPhyOptions; + } + else + { + pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S8; + } + +#if (LL_ENABLE_TESTER) + pBle->chan.accAddrRx = pCisCtx->accessAddr ^ llTesterCb.cisAccessAddrRx; + pBle->chan.accAddrTx = pCisCtx->accessAddr ^ llTesterCb.cisAccessAddrRx; + pBle->chan.crcInitRx = pCisCtx->crcInit ^ llTesterCb.cisCrcInitRx; + pBle->chan.crcInitTx = pCisCtx->crcInit ^ llTesterCb.cisCrcInitTx; +#endif + + /* pBle->chan.enc.enaEncrypt = FALSE; */ /* cleared in alloc */ + /* pBle->chan.enc.enaDecrypt = FALSE; */ + pBle->chan.enc.enaAuth = TRUE; + pBle->chan.enc.nonceMode = PAL_BB_NONCE_MODE_EXT64_CNTR; + pBle->chan.enc.pTxPktCounter = &pCisCtx->txPktCounter; + pBle->chan.enc.pRxPktCounter = &pCisCtx->rxPktCounter; + + /*** BLE stream setup ***/ + + pCis->checkContOpCback = lctrMstCisCheckContOp; + pCis->execCback = lctrMstCisCigBeginOp; + pCis->contExecCback = lctrMstCisCigContOp; + pCis->postSubEvtCback = lctrMstCisCigPostSubEvt; + pCis->cancelCback = lctrMstCisCigCleanupOp; + pCis->txDataCback = lctrMstCisCigTxCompletion; + pCis->rxDataCback = lctrMstCisCigRxCompletion; +} + +/*************************************************************************************************/ +/*! + * \brief Commit a CIG operation. + * + * \param pCigCtx CIG context. + * \param pCtx ACL connection context. + * \param pCisCtx CIS connection context. + */ +/*************************************************************************************************/ +void lctrMstCisCigOpCommit(lctrCigCtx_t *pCigCtx, lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + BbOpDesc_t * const pOp = &pCigCtx->cigBod; + BbOpDesc_t *pConnBod = &pCtx->connBod; + uint32_t refTime; + + if (pCisCtx->ceRef <= pCtx->eventCounter) + { + /* 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 */ + + refTime = pConnBod->dueUsec + (pCisCtx->ceRef - pCtx->eventCounter) * LCTR_CONN_IND_US(pCtx->connInterval); + + pCisCtx->offsetUsec = SchRmGetOffsetUsec(LCTR_ISO_INT_TO_US(pCigCtx->isoInterval), + LCTR_GET_CIG_RM_HANDLE(pCigCtx), refTime); + } + else + { + refTime = pConnBod->dueUsec + (pCisCtx->ceRef - pCtx->eventCounter) * LCTR_CONN_IND_US(pCtx->connInterval); + } + + pOp->dueUsec = refTime + pCisCtx->offsetUsec; + + (void)SchInsertAtDueTime(pOp, lctrCisResolveConflict); /* CIS has the highest priority so scheduling will never fail. */ + + pCigCtx->isBodStarted = TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Get reference time(due time) of the CIG BOD. + * + * \param rmHandle Reservation manager handle of CIG BOD. + * \param pDurUsec Pointer to duration of the CIG BOD. + * + * \return Due time in microseconds of the CIG BOD. + */ +/*************************************************************************************************/ +uint32_t lctrGetCigRefTime(uint8_t rmHandle, uint32_t *pDurUsec) +{ + uint32_t refTime = 0; + lctrCigCtx_t *pCigCtx = LCTR_GET_CIG_RM_CTX(rmHandle); + + WSF_ASSERT(pCigCtx); + + if (pCigCtx->isBodStarted) + { + refTime = pCigCtx->cigBod.dueUsec; + if (pDurUsec) + { + *pDurUsec = pCigCtx->cigBod.minDurUsec; + } + } + + return refTime; +} + +/*************************************************************************************************/ +/*! + * \brief Create CIS procedure finishes. + * + * \param pCisCtx CIS connection context. + */ +/*************************************************************************************************/ +void lctrMstCreateCisDone(lctrCisCtx_t *pCisCtx) +{ + /* Update the create CIS pending data structure. */ + for (unsigned int i = 0; i < lctrMstCreateCisPend.numCis; i++) + { + if (pCisCtx->cisHandle == lctrMstCreateCisPend.cisHandle[i]) + { + lctrMstCreateCisPend.isCreateCisDone[i] = TRUE; + break; + } + } + + /* Continue creating next CIS. */ + for (unsigned int i = 0; i < lctrMstCreateCisPend.numCis; i++) + { + if (lctrMstCreateCisPend.isCreateCisDone[i] == FALSE) + { + lctrCreateCis_t *pMsg; + + if ((pMsg = (lctrCreateCis_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->hdr.handle = lctrMstCreateCisPend.aclHandle[i]; + pMsg->hdr.dispId = LCTR_DISP_CONN; + pMsg->hdr.event = LCTR_CONN_MSG_API_CIS_REQ; + + pMsg->cisHandle = lctrMstCreateCisPend.cisHandle[i]; + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } + return; + } + } + + /* No create CIS is pending. */ + lmgrCisMstCb.createCisPend = FALSE; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis_slave.c new file mode 100644 index 0000000000..34baaddec4 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_cis_slave.c @@ -0,0 +1,416 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller connected isochronous stream slave operation builder implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_iso.h" +#include "lctr_int_cis_slave.h" +#include "lctr_int_conn_slave.h" +#include "lctr_int_conn.h" +#include "lctr_int.h" +#include "sch_api.h" +#include "sch_api_ble.h" +#include "bb_api.h" +#include "pal_bb.h" +#include "wsf_assert.h" +#include "wsf_buf.h" +#include "wsf_cs.h" +#include "wsf_math.h" +#include "wsf_msg.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include + +/************************************************************************************************** + Globals +**************************************************************************************************/ + +/************************************************************************************************** + Internal functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief CIS slave reset handler. + */ +/*************************************************************************************************/ +static void lctrSlvCisResetHandler(void) +{ + BbBleCisSlaveInit(); + BbBleCisMasterInit(); + lctrCisDefaults(); +} + +/*************************************************************************************************/ +/*! + * \brief Initialize link layer controller resources for CIS slave. + */ +/*************************************************************************************************/ +void LctrCisSlvInit(void) +{ + /* Add reset handler. */ + lctrResetHdlrTbl[LCTR_DISP_CIS] = lctrSlvCisResetHandler; + + /* Add connection message dispatcher. */ + if (lctrMsgDispTbl[LCTR_DISP_CIS] != NULL) + { + lctrMsgDispTbl[LCTR_DISP_CIS] = (LctrMsgDisp_t)lctrCisDisp; + } + + lctrCisDefaults(); + + /* Add connection event handlers. */ + lctrEventHdlrTbl[LCTR_EVENT_CIS_RX_PENDING] = lctrCisRxPendingHandler; + lctrEventHdlrTbl[LCTR_EVENT_ISO_TX_COMPLETE] = lctrIsoTxCompletedHandler; + + /* Add LLCP SM handler. */ + lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_EST] = lctrSlvLlcpExecuteCisEstSm; + lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM] = lctrLlcpExecuteCisTermSm; + + /* Set supported features. */ + if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_5_1) + { + lmgrPersistCb.featuresDefault |= LL_FEAT_CIS_SLAVE_ROLE; + } +} + +/*************************************************************************************************/ +/*! + * \brief Reject CIS request. + * + * \param cisHandle CIS handle. + * \param reason Reason. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrRejectCisReq(uint16_t cisHandle, uint8_t reason) +{ + lctrCisCtx_t *pCisCtx = lctrFindCisByHandle(cisHandle); + + if (pCisCtx == NULL) + { + LL_TRACE_WARN0("LctrRejectCisReq, invalid CIS handle"); + return LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + + lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); + + if (pCtx == NULL) + { + LL_TRACE_WARN0("LctrRejectCisReq, invalid ACL handle"); + return LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + + if (pCtx->role == LL_ROLE_MASTER) + { + LL_TRACE_WARN0("LctrRejectCisReq, invalid role"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + lctrRejCisReq_t *pMsg; + + if ((pMsg = (lctrRejCisReq_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->hdr.handle = pCisCtx->aclHandle; + pMsg->hdr.dispId = LCTR_DISP_CONN; + pMsg->hdr.event = LCTR_CONN_MSG_API_CIS_REQ_REJECT; + pMsg->reason = reason; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Accept CIS request. + * + * \param cisHandle CIS handle. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrAcceptCisReq(uint16_t cisHandle) +{ + lctrCisCtx_t *pCisCtx = lctrFindCisByHandle(cisHandle); + + if (pCisCtx == NULL) + { + LL_TRACE_WARN0("LctrAcceptCisReq, invalid CIS handle"); + return LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + + lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle); + + if (pCtx == NULL) + { + LL_TRACE_WARN0("LctrAcceptCisReq, invalid ACL handle"); + return LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + + if (pCtx->role == LL_ROLE_MASTER) + { + LL_TRACE_WARN0("LctrAcceptCisReq, invalid role"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + lctrMsgHdr_t *pMsg; + + if ((pMsg = (lctrMsgHdr_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->handle = pCisCtx->aclHandle; + pMsg->dispId = LCTR_DISP_CONN; + pMsg->event = LCTR_CONN_MSG_API_CIS_REQ_ACCEPT; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Build a CIG operation. + * + * \param pCigCtx CIG context. + */ +/*************************************************************************************************/ +void lctrSlvCisBuildCigOp(lctrCigCtx_t *pCigCtx) +{ + /* Pre-resolve common structures for efficient access. */ + BbOpDesc_t * const pOp = &pCigCtx->cigBod; + + /* When build the BOD, always setup channel use the first CIS context in the CIG. */ + lctrCisCtx_t *pCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + pCigCtx->pCisCtx = pCisCtx; + + BbBleData_t * const pBle = &pCisCtx->bleData; + BbBleSlvCisEvent_t * const pCis = &pBle->op.slvCis; + + memset(pOp, 0, sizeof(BbOpDesc_t)); + memset(pBle, 0, sizeof(BbBleData_t)); + memset(pCis, 0, sizeof(BbBleMstCisEvent_t)); + + /*** CIG context setup ***/ + + /* pCigCtx->cigEvtCounter = 0; */ /* cleared in alloc. */ + + /*** CIS context setup ***/ + + /* pCisCtx->cisEvtCounter = 0; */ /* cleared in alloc. */ + /* pCisCtx->txHdr.sn = 0; */ /* cleared in alloc */ + /* pCisCtx->txHdr.nesn = 0; */ /* cleared in alloc */ + + /*** BLE general setup ***/ + + pBle->chan.opType = BB_BLE_OP_SLV_CIS_EVENT; + + pBle->chan.chanIdx = pCisCtx->chIdx; /* Set in the lctrCisSetupChanParam. */ + pBle->chan.txPower = pLctrRtCfg->defTxPwrLvl; + pBle->chan.accAddr = pCisCtx->accessAddr; + pBle->chan.crcInit = pCisCtx->crcInit; + pBle->chan.txPhy = pCisCtx->phySToM; + pBle->chan.rxPhy = pCisCtx->phyMToS; + 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 (LL_ENABLE_TESTER) + pBle->chan.accAddrRx = pCisCtx->accessAddr ^ llTesterCb.cisAccessAddrRx; + pBle->chan.accAddrTx = pCisCtx->accessAddr ^ llTesterCb.cisAccessAddrRx; + pBle->chan.crcInitRx = pCisCtx->crcInit ^ llTesterCb.cisCrcInitRx; + pBle->chan.crcInitTx = pCisCtx->crcInit ^ llTesterCb.cisCrcInitTx; +#endif + + /* pBle->chan.enc.enaEncrypt = FALSE; */ /* cleared in alloc */ + /* pBle->chan.enc.enaDecrypt = FALSE; */ /* cleared in alloc */ + pBle->chan.enc.enaAuth = TRUE; + pBle->chan.enc.nonceMode = PAL_BB_NONCE_MODE_EXT64_CNTR; + pBle->chan.enc.pTxPktCounter = &pCisCtx->txPktCounter; + pBle->chan.enc.pRxPktCounter = &pCisCtx->rxPktCounter; + + /*** General setup ***/ + + pOp->minDurUsec = pCisCtx->subIntervUsec * WSF_MAX(pCisCtx->bnMToS, pCisCtx->bnSToM); /* Guarantee at least Max BN */ + pOp->maxDurUsec = pCigCtx->cigSyncDelayUsec; + + /* pOp->due = 0 */ /* set in lctrCisMstCigOpCommit() */ + pOp->reschPolicy = BB_RESCH_FIXED_PREFERRED; + pOp->protId = BB_PROT_BLE; + pOp->prot.pBle = pBle; + pOp->endCback = lctrSlvCisCigEndOp; + pOp->abortCback = lctrSlvCisCigAbortOp; + pOp->pCtx = pCigCtx; + + /*** BLE stream setup ***/ + + pCis->checkContOpCback = lctrSlvCisCheckContOp; + pCis->execCback = lctrSlvCisCigBeginOp; + pCis->contExecCback = lctrSlvCisCigContOp; + pCis->postSubEvtCback = lctrSlvCisCigPostSubEvt; + pCis->cancelCback = lctrSlvCisCigCleanupOp; + pCis->txDataCback = lctrSlvCisCigTxCompletion; + pCis->rxDataCback = lctrSlvCisCigRxCompletion; + + /*** Commit operation ***/ + + /* Postponed in lctrCisMstCigOpCommit(). */ + pCigCtx->isBodBuilt = TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Build a CIG operation. + * + * \param pCisCtx CIG context. + */ +/*************************************************************************************************/ +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); + + memset(pBle, 0, sizeof(BbBleData_t)); + memset(pCis, 0, sizeof(BbBleMstCisEvent_t)); + + /*** CIS context setup ***/ + + /* pCisCtx->cisEvtCounter = 0; */ /* cleared in alloc. */ + /* pCisCtx->txHdr.sn = 0; */ /* cleared in alloc */ + /* pCisCtx->txHdr.nesn = 0; */ /* cleared in alloc */ + + /*** BLE general setup ***/ + + pBle->chan.opType = BB_BLE_OP_SLV_CIS_EVENT; + + pBle->chan.chanIdx = pCisCtx->chIdx; /* Set in the lctrCisSetupChanParam. */ + pBle->chan.txPower = pLctrRtCfg->defTxPwrLvl; + pBle->chan.accAddr = pCisCtx->accessAddr; + pBle->chan.crcInit = pCisCtx->crcInit; + pBle->chan.txPhy = pCisCtx->phySToM; + pBle->chan.rxPhy = pCisCtx->phyMToS; + 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) + { + /* Set PHY options to host defined behavior. */ + pBle->chan.initTxPhyOptions = pConnCtx->bleData.chan.tifsTxPhyOptions; + } + else + { + pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S8; + } + +#if (LL_ENABLE_TESTER) + pBle->chan.accAddrRx = pCisCtx->accessAddr ^ llTesterCb.cisAccessAddrRx; + pBle->chan.accAddrTx = pCisCtx->accessAddr ^ llTesterCb.cisAccessAddrRx; + pBle->chan.crcInitRx = pCisCtx->crcInit ^ llTesterCb.cisCrcInitRx; + pBle->chan.crcInitTx = pCisCtx->crcInit ^ llTesterCb.cisCrcInitTx; +#endif + + /* pBle->chan.enc.enaEncrypt = FALSE; */ /* cleared in alloc */ + /* pBle->chan.enc.enaDecrypt = FALSE; */ /* cleared in alloc */ + pBle->chan.enc.enaAuth = TRUE; + pBle->chan.enc.nonceMode = PAL_BB_NONCE_MODE_EXT64_CNTR; + pBle->chan.enc.pTxPktCounter = &pCisCtx->txPktCounter; + pBle->chan.enc.pRxPktCounter = &pCisCtx->rxPktCounter; + + /*** BLE stream setup ***/ + + pCis->checkContOpCback = lctrSlvCisCheckContOp; + pCis->execCback = lctrSlvCisCigBeginOp; + pCis->contExecCback = lctrSlvCisCigContOp; + pCis->postSubEvtCback = lctrSlvCisCigPostSubEvt; + pCis->cancelCback = lctrSlvCisCigCleanupOp; + pCis->txDataCback = lctrSlvCisCigTxCompletion; + pCis->rxDataCback = lctrSlvCisCigRxCompletion; +} + +/*************************************************************************************************/ +/*! + * \brief Commit a CIG operation. + * + * \param pCigCtx CIG context. + * \param pCtx ACL Context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +void lctrSlvCisCigOpCommit(lctrCigCtx_t *pCigCtx, lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + BbOpDesc_t * const pOp = &pCigCtx->cigBod; + /* When commit the BOD, always setup channel use the first CIS context in the CIG. */ + lctrCisCtx_t *pFirstCisCtx = lctrCisGetHeadCis(&pCigCtx->list); + BbBleData_t * const pBle = &pFirstCisCtx->bleData; + BbBleSlvCisEvent_t * const pCis = &pBle->op.slvCis; + + pCigCtx->roleData.slv.totalAcc = pCtx->data.slv.totalAcc; + + pCigCtx->roleData.slv.anchorPointUsec = pCtx->data.slv.anchorPointUsec + LCTR_CONN_IND_US(pCtx->connInterval) + pCisCtx->data.slv.anchorOffsetUsec; + + /* Add WW to the offset. */ + const uint32_t wwOffsetUsec = lctrCalcWindowWideningUsec(pCisCtx->data.slv.anchorOffsetUsec, pCigCtx->roleData.slv.totalAcc); + pOp->dueUsec = pCigCtx->roleData.slv.anchorPointUsec - wwOffsetUsec; + pOp->minDurUsec += (wwOffsetUsec << 1); + + /*** BLE CIS setup ***/ + + pCis->rxSyncDelayUsec = (wwOffsetUsec << 1) + 1; /* rounding compensation when computing reqEndTs */ + + /*** Commit operation ***/ + + const uint32_t ceDurUsec = pOp->minDurUsec; + const uint32_t ceSyncDlyUsec = pCis->rxSyncDelayUsec; + + while (TRUE) + { + if (SchInsertAtDueTime(pOp, lctrCisResolveConflict)) + { + LL_TRACE_INFO1(" >>> CIS established, cisHandle=%u <<<", pCisCtx->cisHandle); + LL_TRACE_INFO1(" isoInterval=%u", LCTR_ISO_INT_TO_US(pCigCtx->isoInterval)); + LL_TRACE_INFO1(" dueUsec=%u", pOp->dueUsec); + pCigCtx->isBodStarted = TRUE; + break; + } + + LL_TRACE_WARN1("!!! Establish CIS schedule conflict handle=%u", LCTR_GET_CONN_HANDLE(pCtx)); + + pFirstCisCtx->cisEvtCounter++; + pBle->chan.chanIdx = LmgrSelectNextChannel(&pCisCtx->chanParam, pFirstCisCtx->cisEvtCounter, 0, TRUE); + pCisCtx->nextSubEvtChanIdx = LmgrSelectNextSubEvtChannel(&pCisCtx->chanParam); + + /* Initial eventCounter starts at 0; equivalent to unsynchronized intervals. */ + uint32_t unsyncTimeUsec = LCTR_ISO_INT_TO_US(pCigCtx->isoInterval * pFirstCisCtx->cisEvtCounter); + uint32_t wwTotalUsec = lctrCalcWindowWideningUsec(unsyncTimeUsec, pCtx->data.slv.totalAcc); + + /* Advance to next interval. */ + pOp->dueUsec = pCigCtx->roleData.slv.anchorPointUsec + unsyncTimeUsec - wwTotalUsec; + pOp->minDurUsec = ceDurUsec + wwTotalUsec; + pCis->rxSyncDelayUsec = ceSyncDlyUsec + (wwTotalUsec << 1); + } +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn.c index b3e7e61e2b..766c5170ec 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller data path implementation file. + * \file + * + * \brief Link layer controller data path implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -25,6 +26,8 @@ #include "lctr_pdu_conn.h" #include "lmgr_api_conn.h" #include "ll_math.h" +#include "ll_api.h" +#include "pal_radio.h" #include "wsf_assert.h" #include "wsf_cs.h" #include "wsf_math.h" @@ -88,6 +91,39 @@ 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 lctrSendPowerChangeInd function. */ +lctrPcPowInd_t lctrSendPowerChangeIndCback = NULL; + +/*! \brief Pointer to lctrNotifyPowerReportInd function. */ +lctrPcNotifyPwr_t lctrNotifyPowerReportIndCback = NULL; + +/*************************************************************************************************/ +/*! + * \brief Return PHYs supported by LL. + * + * \return Bit field of supported PHYs. + */ +/*************************************************************************************************/ +static uint8_t llGetSupportedPhys(void) +{ + uint8_t supportPhyBits = LL_PHYS_LE_1M_BIT; + + if ((lmgrCb.features & LL_FEAT_LE_2M_PHY)) + { + supportPhyBits |= LL_PHYS_LE_2M_BIT; + } + + if ((lmgrCb.features & LL_FEAT_LE_CODED_PHY)) + { + supportPhyBits |= LL_PHYS_LE_CODED_BIT; + } + + return supportPhyBits; +} + /*************************************************************************************************/ /*! * \brief Initialize the connection memory resources. @@ -146,8 +182,6 @@ uint16_t LctrInitConnMem(uint8_t *pFreeMem, uint32_t freeMemSize) * \brief Assign vendor specific PDU handlers. * * \param pHdlrs Static definition for VS handlers. - * - * \return None. */ /*************************************************************************************************/ void LctrVsConnInit(const LctrVsHandlers_t *pHdlrs) @@ -166,16 +200,35 @@ void LctrVsConnInit(const LctrVsHandlers_t *pHdlrs) /*************************************************************************************************/ uint8_t LctrValidateConnSpec(const LlConnSpec_t *pConnSpec) { - if ((pConnSpec->connIntervalMin < LL_MIN_CONN_INTERVAL) || - (pConnSpec->connIntervalMax > LL_MAX_CONN_INTERVAL) || - (pConnSpec->connIntervalMin > pConnSpec->connIntervalMax) || - /* (pConnSpec->connLatency < connLatencyMin) || */ - (pConnSpec->connLatency > LL_MAX_CONN_LATENCY) || - (pConnSpec->supTimeout < LL_MIN_SUP_TIMEOUT) || - (pConnSpec->supTimeout > LL_MAX_SUP_TIMEOUT) || - (pConnSpec->supTimeout <= ((1 + pConnSpec->connLatency) * pConnSpec->connIntervalMax >> 2))) + /* Connection interval. */ + if ((LL_API_PARAM_CHECK == 1) && + ((pConnSpec->connIntervalMin > pConnSpec->connIntervalMax) || + (pConnSpec->connIntervalMax < HCI_CONN_INTERVAL_MIN) || + (pConnSpec->connIntervalMin < HCI_CONN_INTERVAL_MIN) || + (pConnSpec->connIntervalMax > HCI_CONN_INTERVAL_MAX) || + (pConnSpec->connIntervalMin > HCI_CONN_INTERVAL_MAX) )) { - LL_TRACE_WARN0("LctrValidateConnSpec: invalid parameters"); + LL_TRACE_WARN0("LctrValidateConnSpec: Connection interval is invalid"); + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + + /* Connection latency. */ + if ((LL_API_PARAM_CHECK == 1) && + ((pConnSpec->connLatency > HCI_CONN_LATENCY_MAX))) + { + LL_TRACE_WARN0("LctrValidateConnSpec: connection latency is invalid"); + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + + /* Supervision timeout. */ + uint32_t supTimeoutMin = ((uint32_t) pConnSpec->connLatency + 1) * LCTR_CONN_IND_US((uint32_t) pConnSpec->connIntervalMax) * 2; + uint32_t supTimeoutUs = LCTR_SUP_TIMEOUT_VAL_TO_US((uint32_t) pConnSpec->supTimeout); + if ((LL_API_PARAM_CHECK == 1) && + ((supTimeoutUs <= supTimeoutMin) || + (pConnSpec->supTimeout < HCI_SUP_TIMEOUT_MIN) || + (pConnSpec->supTimeout > HCI_SUP_TIMEOUT_MAX))) + { + LL_TRACE_WARN0("LctrValidateConnSpec: supervision timeout is invalid"); return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; } @@ -241,8 +294,6 @@ bool_t LctrIsProcActPended(uint16_t handle, uint8_t event) * \param handle Connection handle. * \param pMode New encryption mode. * - * \return None. - * * Get the encryption mode used by a connection. */ /*************************************************************************************************/ @@ -294,8 +345,6 @@ bool_t LctrSetEncMode(uint16_t handle, const LlEncMode_t *pMode) * \param flags Flags. * \param enable TRUE to set flags or FALSE to clear flags. * - * \return None. - * * Set mode flags governing LL operations of a given connection. */ /*************************************************************************************************/ @@ -371,7 +420,7 @@ lctrConnCtx_t *lctrAllocConnCtx(void) pCtx->localDataPdu.maxRxLen = WSF_MIN(LCTR_MAX_DATA_LEN_MAX, pLctrRtCfg->maxAclLen); pCtx->localDataPdu.maxTxTime = lmgrConnCb.maxTxTime; /* Limit with absolute time. lctrSendDataLengthPdu() limits time by PHY capability. */ - pCtx->localDataPdu.maxRxTime = LL_DATA_LEN_TO_TIME_CODED_S8(pCtx->localDataPdu.maxRxLen); + pCtx->localDataPdu.maxRxTime = LL_DATA_LEN_TO_TIME_CODED_S8(pCtx->localDataPdu.maxRxLen, TRUE); pCtx->effDataPdu.maxTxLen = LL_MAX_DATA_LEN_MIN; pCtx->effDataPdu.maxRxLen = LL_MAX_DATA_LEN_MIN; pCtx->effDataPdu.maxTxTime = LL_MAX_DATA_TIME_MIN; @@ -407,6 +456,18 @@ lctrConnCtx_t *lctrAllocConnCtx(void) pLctrVsHdlrs->connSetup(connIdx); } + /* Power control initialization. */ + if (pCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST) + { + 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; + } + LmgrIncResetRefCount(); lmgrCb.numConnEnabled++; @@ -425,8 +486,6 @@ lctrConnCtx_t *lctrAllocConnCtx(void) * \brief Free a connection context. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrFreeConnCtx(lctrConnCtx_t *pCtx) @@ -537,8 +596,6 @@ uint8_t lctrSelectNextDataChannel(lctrConnCtx_t *pCtx, uint16_t numSkip) * \brief Build channel remapping table. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrBuildRemapTable(lctrConnCtx_t *pCtx) @@ -562,8 +619,6 @@ void lctrBuildRemapTable(lctrConnCtx_t *pCtx) /*************************************************************************************************/ /*! * \brief Tx data completed task event handler. - * - * \return None. */ /*************************************************************************************************/ void lctrConnTxCompletedHandler(void) @@ -611,8 +666,6 @@ void lctrConnTxCompletedHandler(void) /*************************************************************************************************/ /*! * \brief Rx data pending task event handler. - * - * \return None. */ /*************************************************************************************************/ void lctrConnRxPendingHandler(void) @@ -760,8 +813,6 @@ void lctrConnRxPendingHandler(void) * \brief Transmit ACL data path. * * \param pAclBuf ACL buffer. - * - * \return None. */ /*************************************************************************************************/ void LctrTxAcl(uint8_t *pAclBuf) @@ -772,7 +823,7 @@ void LctrTxAcl(uint8_t *pAclBuf) lctrUnpackAclHdr(&aclHdr, pAclBuf); - /*** Assemble data PDU. ***/ + /*** Resolve Connection context. ***/ if (aclHdr.connHandle >= pLctrRtCfg->maxConn) { @@ -815,7 +866,7 @@ void LctrTxAcl(uint8_t *pAclBuf) if ((aclHdr.pktBound == LCTR_PB_START_NON_AUTO_FLUSH) && (aclHdr.len == 0)) { pCtx->forceStartPdu = TRUE; /* If this was supposed to be the start fragment, make the next packet a start fragment. */ - LL_TRACE_INFO0("Next ACL header will be forced to a start fragment."); + LL_TRACE_INFO0("Next ACL header will be forced to a start fragment"); } WsfMsgFree(pAclBuf); lmgrPersistCb.sendCompCback(aclHdr.connHandle, 1); @@ -873,8 +924,6 @@ uint8_t *LctrRxAcl(void) * * \param numBufs Number of completed packets. * - * \return None. - * * Indicate that received ACL data buffer has been deallocated. */ /*************************************************************************************************/ @@ -944,6 +993,31 @@ int8_t LctrGetRssi(uint16_t handle) return pLctrConnTbl[handle].rssi; } +/*************************************************************************************************/ +/*! + * \brief Get connection's TX power level for the selected phy. + * + * \param handle Connection handle. + * \param phy PHY. + * + * \return Transmit power level. + */ +/*************************************************************************************************/ +int8_t LctrGetPhyTxPowerLevel(uint16_t handle, uint8_t phy) +{ + lctrConnCtx_t * pCtx = LCTR_GET_CONN_CTX(handle); + uint8_t option = BB_PHY_OPTIONS_BLE_S8; + + if (phy == LL_PC_PHY_CODED_S2) + { + phy = LL_PHY_LE_CODED; + option = BB_PHY_OPTIONS_BLE_S2; + } + + int8_t txPower = LCTR_GET_TXPOWER(pCtx, phy, option); + return (txPower == LL_PWR_CTRL_TXPOWER_UNMANAGED) ? 0 : txPower; +} + /*************************************************************************************************/ /*! * \brief Get the transmit power level of a connection. @@ -960,17 +1034,121 @@ int8_t LctrGetTxPowerLevel(uint16_t handle) /*************************************************************************************************/ /*! - * \brief Set the transmit power level of a connection. + * \brief Set the transmit power level of a connection (all PHYs). * * \param handle Connection handle. * \param level Transmit power level. - * - * \return None. */ /*************************************************************************************************/ void LctrSetTxPowerLevel(uint16_t handle, int8_t level) { - pLctrConnTbl[handle].bleData.chan.txPower = level; + lctrConnCtx_t * pCtx = LCTR_GET_CONN_CTX(handle); + BbBleData_t * pBle = &pCtx->bleData; + int8_t txPhyPwr = pBle->chan.txPower; + int8_t txPwrOld[LL_PC_PHY_TOTAL]; + memcpy(txPwrOld, pCtx->phyTxPower, LL_PC_PHY_TOTAL); + int8_t adjustedLevel = PalRadioGetActualTxPower(level, FALSE); + + if (adjustedLevel != level) + { + LL_TRACE_WARN2("Transmit Power set to %d instead of %d, due to hardware limitations.", adjustedLevel, level); + } + + pBle->chan.txPower = adjustedLevel; + memset(pCtx->phyTxPower, adjustedLevel, LL_PC_PHY_TOTAL); + + /* If supported, notify peer of power change on currently transmitting PHY. */ + if ((pCtx->state == LCTR_CONN_STATE_ESTABLISHED_READY) && + (txPhyPwr != adjustedLevel) && + (pCtx->usedFeatSet & LL_FEAT_POWER_CHANGE_IND) && + lctrSendPowerChangeIndCback) + { + lctrSendPowerChangeIndCback(pCtx, pBle->chan.txPhy, adjustedLevel - txPhyPwr, adjustedLevel, FALSE); + } + + /* If enabled, notify host of power change on affected PHYs. */ + if (pCtx->powerRptLocal) + { + int phy; + for (phy = 0; phy < LL_PC_PHY_TOTAL; phy++) + { + if (txPwrOld[phy] != adjustedLevel) + { + if (lctrNotifyPowerReportIndCback) + { + lctrNotifyPowerReportIndCback(pCtx, LL_POWER_REPORT_REASON_LOCAL, phy, adjustedLevel, + lctrGetPowerLimits(adjustedLevel), + adjustedLevel - txPwrOld[phy]); + } + } + } + } + +} + +/*************************************************************************************************/ +/*! + * \brief Set the transmit power level of a connection. + * + * \param handle Connection handle. + * \param level Transmit power level. + * \param phy PHY to set power level for. + */ +/*************************************************************************************************/ +void LctrSetPhyTxPowerLevel(uint16_t handle, int8_t level, uint8_t phy) +{ + lctrConnCtx_t * pCtx = LCTR_GET_CONN_CTX(handle); + BbBleData_t * pBle = &pCtx->bleData; + int8_t txPwrOld = pBle->chan.txPower; + int8_t adjustedLevel; + int8_t delta; + + /* Not specifying a PHY will set the current transmitting PHY. */ + if (phy == LL_PHY_NONE) + { + phy = pBle->chan.txPhy; + } + + adjustedLevel = PalRadioGetActualTxPower(level, FALSE); + + if (adjustedLevel != level) + { + LL_TRACE_WARN2("Transmit Power set to %d instead of %d, due to hardware limitations.", adjustedLevel, level); + } + + delta = adjustedLevel - txPwrOld; + if (delta == 0) + { + return; + } + + if (phy == pBle->chan.txPhy) + { + pBle->chan.txPower = adjustedLevel; + + /* If supported, notify peer of power change. */ + if ((pCtx->state == LCTR_CONN_STATE_ESTABLISHED_READY) && + (txPwrOld != adjustedLevel) && + (pCtx->usedFeatSet & LL_FEAT_POWER_CHANGE_IND) && + lctrSendPowerChangeIndCback) + { + lctrSendPowerChangeIndCback(pCtx, pBle->chan.txPhy, adjustedLevel - txPwrOld, adjustedLevel, FALSE); + } + } + + LCTR_SET_TXPOWER(pCtx, phy, adjustedLevel); + + + /* If enabled, notify host of power change. */ + if (pCtx->powerRptLocal) + { + if (lctrNotifyPowerReportIndCback) + { + lctrNotifyPowerReportIndCback(pCtx, LL_POWER_REPORT_REASON_LOCAL, pBle->chan.txPhy, adjustedLevel, + lctrGetPowerLimits(pBle->chan.txPower), + delta); + } + } } /*************************************************************************************************/ @@ -998,9 +1176,6 @@ uint64_t LctrGetChannelMap(uint16_t handle) /*************************************************************************************************/ uint64_t LctrGetUsedFeatures(uint16_t handle) { -// LL_TRACE_INFO1("LctrGetUsedFeatures, lmgrCb.features=%x", lmgrCb.features); -// LL_TRACE_INFO1("LctrGetUsedFeatures, pLctrConnTbl[handle].usedFeatSet=%x", pLctrConnTbl[handle].usedFeatSet); - return pLctrConnTbl[handle].usedFeatSet; } @@ -1079,8 +1254,6 @@ bool_t LctrIsWaitingForReply(uint16_t handle, uint8_t reply) * * \param pCtx Connection context. * \param event Connection event. - * - * \return None. */ /*************************************************************************************************/ void lctrSendConnMsg(lctrConnCtx_t *pCtx, uint8_t event) @@ -1247,12 +1420,12 @@ uint8_t lctrComputeSca(void) /*************************************************************************************************/ /*! - * \brief Get reference time(due time) of the connection handle. + * \brief Get reference time (due time) of the connection handle. * * \param connHandle Connection handle. * \param pDurUsec Pointer to duration of the connection BOD. * - * \return Due time in BB ticks of the connection handle. + * \return Due time in microseconds of the connection handle. */ /*************************************************************************************************/ uint32_t lctrGetConnRefTime(uint8_t connHandle, uint32_t *pDurUsec) @@ -1262,7 +1435,7 @@ uint32_t lctrGetConnRefTime(uint8_t connHandle, uint32_t *pDurUsec) if (pCtx->enabled && (pCtx->bleData.chan.opType == BB_BLE_OP_MST_CONN_EVENT)) { - refTime = pCtx->connBod.due; + refTime = pCtx->connBod.dueUsec; if (pDurUsec) { *pDurUsec = pCtx->connBod.minDurUsec; @@ -1291,12 +1464,12 @@ uint32_t lctrConnGetAnchorPoint(lctrConnCtx_t *pCtx, uint16_t ceCounter) if ((uint16_t)(ceCounter - pCtx->eventCounter) < (uint16_t)LCTR_MAX_INSTANT) /* ceCounter is in the future. */ { numCe = ceCounter - pCtx->eventCounter; - return (pCtx->connBod.due + BB_US_TO_BB_TICKS(LCTR_CONN_IND_US(pCtx->connInterval * numCe))); + return pCtx->connBod.dueUsec + LCTR_CONN_IND_US(pCtx->connInterval * numCe); } else { numCe = pCtx->eventCounter - ceCounter; - return (pCtx->connBod.due - BB_US_TO_BB_TICKS(LCTR_CONN_IND_US(pCtx->connInterval * numCe))); + return pCtx->connBod.dueUsec - LCTR_CONN_IND_US(pCtx->connInterval * numCe); } } else @@ -1304,12 +1477,12 @@ uint32_t lctrConnGetAnchorPoint(lctrConnCtx_t *pCtx, uint16_t ceCounter) if ((uint16_t)(ceCounter - (pCtx->data.slv.lastActiveEvent - 1)) < (uint16_t)LCTR_MAX_INSTANT) /* ceCounter is in the future. */ { numCe = ceCounter - (pCtx->data.slv.lastActiveEvent - 1); - return (pCtx->data.slv.anchorPoint + BB_US_TO_BB_TICKS(LCTR_CONN_IND_US(pCtx->connInterval * numCe))); + return pCtx->data.slv.anchorPointUsec + LCTR_CONN_IND_US(pCtx->connInterval * numCe); } else { numCe = (pCtx->data.slv.lastActiveEvent - 1) - ceCounter; - return (pCtx->data.slv.anchorPoint - BB_US_TO_BB_TICKS(LCTR_CONN_IND_US(pCtx->connInterval * numCe))); + return pCtx->data.slv.anchorPointUsec - LCTR_CONN_IND_US(pCtx->connInterval * numCe); } } } @@ -1332,3 +1505,146 @@ bool_t LctrIsCisEnabled(uint16_t handle) return FALSE; } + + +/*************************************************************************************************/ +/*! + * \brief Set up transmit levels. + * + * \param pCtx Connection Context. + */ +/*************************************************************************************************/ +void lctrInitPhyTxPower(lctrConnCtx_t *pCtx) +{ + /* All transmit powers start unmanaged or unavailable. */ + uint8_t supportedPhys = llGetSupportedPhys(); + supportedPhys |= (supportedPhys & LL_PHYS_LE_CODED_BIT) ? LL_PC_CODED_S2_BIT : 0; + + uint8_t phyIdx = 0; + for (uint8_t phy = LL_PC_1M_BIT; phy <= LL_PC_MAX_BIT; phy = phy << 1) + { + if (supportedPhys & phy) + { + pCtx->phyTxPower[phyIdx++] = LL_PWR_CTRL_TXPOWER_UNMANAGED; + } + else + { + pCtx->phyTxPower[phyIdx++] = LL_PWR_CTRL_TXPOWER_UNAVAILABLE; + } + } + + /* Peer transmit power will start as unavailable until we know it through a remote read or request. */ + pCtx->peerTxPower = LL_PWR_CTRL_TXPOWER_UNAVAILABLE; +} + +/*************************************************************************************************/ +/*! + * \brief Set transmit power reporting parameters. + * + * \param handle Connection handle. + * \param enableLocal Enable local txPower change reporting. + * \param enableRemote Enable remote txPower change reporting. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t lctrSetTxPowerReporting(uint16_t handle, uint8_t enableLocal, uint8_t enableRemote) +{ + lctrConnCtx_t * pCtx = LCTR_GET_CONN_CTX(handle); + + pCtx->powerRptLocal = enableLocal; + pCtx->powerRptRemote = enableRemote; + + if (enableRemote) + { + pCtx->controllerInitRead = TRUE; + lctrMsgPwrCtrlReq_t *pMsg; + if ((pMsg = (lctrMsgPwrCtrlReq_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->hdr.handle = LCTR_GET_CONN_HANDLE(pCtx); + pMsg->hdr.dispId = LCTR_DISP_CONN; + pMsg->hdr.event = LCTR_CONN_MSG_API_PWR_CTRL_REQ; + pMsg->delta = 0; + pMsg->phy = pCtx->bleData.chan.rxPhy + ((pCtx->bleData.chan.rxPhy == BB_PHY_BLE_CODED) && (pCtx->bleData.chan.initTxPhyOptions == BB_PHY_OPTIONS_BLE_S2)) ? 1 : 0; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } + } + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Set enable state for power monitoring. + * + * \param handle Handle identifier for connection. + * \param enable Enable status for power monitor. + * + * \return Status error code. + * + * \note Path loss must be disabled. + */ +/*************************************************************************************************/ +uint8_t lctrSetPowerMonitorEnable(uint16_t handle, bool_t enable) +{ + lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(handle); + + if (!(pCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST)) + { + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + if ((pCtx->powerMonitorScheme == LCTR_PC_MONITOR_PATH_LOSS) && + (pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED)) + { + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + 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; + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Get power limit bit of specified txPower. + * + * \param txPower Current transmit power. + * + * \return Limit status of txPower + */ +/*************************************************************************************************/ +uint8_t lctrGetPowerLimits(int8_t txPower) +{ + int8_t min; + int8_t max; + +#if (LL_ENABLE_TESTER == TRUE) + if (llTesterCb.powerLimits) + { + return llTesterCb.powerLimits; + } +#endif + + PalRadioGetSupTxPower(&min, &max); + + if (txPower == min) + { + return LL_PWR_CONTROL_LIMIT_MIN_BIT; + } + else if (txPower == max) + { + return LL_PWR_CONTROL_LIMIT_MAX_BIT; + } + else + { + return 0; + } +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_cs2.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_cs2.c index 643d72e755..0ce66da637 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_cs2.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_cs2.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller data path implementation file. + * \file + * + * \brief Link layer controller data path implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -119,8 +120,6 @@ uint8_t lctrSelectNextChannel2(lctrConnCtx_t *pCtx, uint16_t numSkip) /*************************************************************************************************/ /*! * \brief Initialize the channel selection 2 resources. - * - * \return None. */ /*************************************************************************************************/ void LctrChannelSelection2Init(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_data.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_data.c index eeb4b6af8d..47d2ae670a 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_data.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_data.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller data path implementation file. + * \file + * + * \brief Link layer controller data path implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -40,10 +41,14 @@ Macros **************************************************************************************************/ -#define LCTR_DATA_TX_PDU_START_OFFSET 0 /*!< Data PDU start offset in a buffer. */ +/*! \brief Data PDU start offset in a buffer. */ +#define LCTR_DATA_TX_PDU_START_OFFSET 0 -#define LCTR_FRAG_HDR_MAX_LEN LL_DATA_HDR_LEN /*!< Fragment header maximum length. */ -#define LCTR_FRAG_TRL_MAX_LEN LL_DATA_MIC_LEN /*!< Fragment trailer maximum length. */ +/*! \brief Fragment header maximum length. */ +#define LCTR_FRAG_HDR_MAX_LEN LL_DATA_HDR_LEN + +/*! \brief Fragment trailer maximum length. */ +#define LCTR_FRAG_TRL_MAX_LEN LL_DATA_MIC_LEN /************************************************************************************************** Data Types @@ -96,8 +101,6 @@ static wsfHandlerId_t lctrTxCompBufHandlerId; * latency is not zero and there is data to send. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrCheckAbortSlvLatency(lctrConnCtx_t *pCtx) @@ -110,11 +113,11 @@ static void lctrCheckAbortSlvLatency(lctrConnCtx_t *pCtx) if (pCtx->maxLatency) { - const uint32_t curTime = PalBbGetCurrentTime(USE_RTC_BB_CLK); - uint32_t connInterval = BB_US_TO_BB_TICKS(LCTR_CONN_IND_US(pCtx->connInterval)); + const uint32_t curTime = PalBbGetCurrentTime(); + uint32_t connIntervalUsec = LCTR_CONN_IND_US(pCtx->connInterval); BbOpDesc_t *pOp = &pCtx->connBod; - if (((pOp->due - curTime) > connInterval) && ((pOp->due - curTime) < LCTR_SCH_MAX_SPAN)) + if (BbGetTargetTimeDelta(pOp->dueUsec, curTime) > connIntervalUsec) { /* If the connection BOD is due in the future and after the next immediate anchor point, * set the flag to adjust the connection BOD later. */ @@ -247,8 +250,6 @@ static uint16_t lctrMaxNumBytesWithinUsecCoded(uint16_t timeUsec) * * \param pCtx Connection context. * \param txPhys Transmit PHYs for PHY update in progress. - * - * \return None. */ /*************************************************************************************************/ void lctrSetPacketTimeRestriction(lctrConnCtx_t *pCtx, uint8_t txPhys) @@ -261,8 +262,6 @@ void lctrSetPacketTimeRestriction(lctrConnCtx_t *pCtx, uint8_t txPhys) * \brief Remove packet time restriction. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrRemovePacketTimeRestriction(lctrConnCtx_t *pCtx) @@ -289,16 +288,16 @@ static inline uint16_t lctrGetMaxConnDurationUsec(uint8_t phy, uint16_t maxLen, { default: case BB_PHY_BLE_1M: - maxDur = WSF_MIN(LL_DATA_LEN_TO_TIME_1M(maxLen), maxTime); + maxDur = WSF_MIN(LL_DATA_LEN_TO_TIME_1M(maxLen, TRUE), maxTime); break; case BB_PHY_BLE_2M: - maxDur = WSF_MIN(LL_DATA_LEN_TO_TIME_2M(maxLen), maxTime); + maxDur = WSF_MIN(LL_DATA_LEN_TO_TIME_2M(maxLen, TRUE), maxTime); break; case BB_PHY_BLE_CODED: /* maximum time may be less than minimum packet for coded PHY */ - maxDur = WSF_MIN(LL_DATA_LEN_TO_TIME_CODED_S8(maxLen), + maxDur = WSF_MIN(LL_DATA_LEN_TO_TIME_CODED_S8(maxLen, TRUE), WSF_MAX(maxTime, - LL_DATA_LEN_TO_TIME_CODED_S8(LL_MAX_DATA_LEN_MIN))); + LL_DATA_LEN_TO_TIME_CODED_S8(LL_MAX_DATA_LEN_MIN, TRUE))); break; } @@ -385,7 +384,7 @@ uint16_t lctrTxFragLen(lctrConnCtx_t *pCtx) * \return A Tx buffer descriptor, NULL if allocation fails. */ /*************************************************************************************************/ -static lctrTxBufDesc_t *lctrAllocTxBufDesc(void) +static lctrTxBufDesc_t *lctrAllocConnTxBufDesc(void) { uint8_t *pElem; @@ -404,11 +403,9 @@ static lctrTxBufDesc_t *lctrAllocTxBufDesc(void) * \brief Free a Tx buffer descriptor. * * \param pDesc Pointer to a Tx buffer descriptor. - * - * \return None. */ /*************************************************************************************************/ -static void lctrFreeTxBufDesc(lctrTxBufDesc_t *pDesc) +static void lctrFreeConnTxBufDesc(lctrTxBufDesc_t *pDesc) { uint8_t *pElem = (uint8_t *)pDesc; pElem -= (2 * sizeof(uint32_t)); /* recover header */ @@ -423,8 +420,6 @@ static void lctrFreeTxBufDesc(lctrTxBufDesc_t *pDesc) * \param pCtx Connection context. * \param pAclHdr ACL header. * \param pBuf Buffer to pack the Data PDU header. - * - * \return None. */ /*************************************************************************************************/ static void lctrAssembleDataPdu(lctrConnCtx_t *pCtx, lctrAclHdr_t *pAclHdr, uint8_t *pBuf) @@ -469,8 +464,6 @@ static void lctrAssembleDataPdu(lctrConnCtx_t *pCtx, lctrAclHdr_t *pAclHdr, uint * \param fragLen Fragment length. * \param pAclHdr ACL header. * \param pAclBuf ACL buffer. - * - * \return None. */ /*************************************************************************************************/ void lctrTxDataPduQueue(lctrConnCtx_t *pCtx, uint16_t fragLen, lctrAclHdr_t *pAclHdr, uint8_t *pAclBuf) @@ -480,7 +473,7 @@ void lctrTxDataPduQueue(lctrConnCtx_t *pCtx, uint16_t fragLen, lctrAclHdr_t *pAc lctrTxBufDesc_t *pDesc; - if ((pDesc = lctrAllocTxBufDesc()) == NULL) + if ((pDesc = lctrAllocConnTxBufDesc()) == NULL) { LL_TRACE_ERR1("Failed to allocate transmit buffer descriptor: connHandle=%u", pAclHdr->connHandle); WsfMsgFree(pAclBuf); @@ -609,8 +602,6 @@ void lctrTxDataPduQueue(lctrConnCtx_t *pCtx, uint16_t fragLen, lctrAclHdr_t *pAc * * \param pCtx Connection context. * \param pBuf Data PDU buffer. - * - * \return None. */ /*************************************************************************************************/ void lctrTxCtrlPduQueue(lctrConnCtx_t *pCtx, uint8_t *pBuf) @@ -834,8 +825,6 @@ bool_t lctrTxQueuePop(lctrConnCtx_t *pCtx) * \brief Pop top element from Tx queue. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrTxQueuePopCleanup(lctrConnCtx_t *pCtx) @@ -849,7 +838,7 @@ void lctrTxQueuePopCleanup(lctrConnCtx_t *pCtx) #ifndef LCTR_CONN_NO_TIFS_REASSEMBLY WsfMsgFree(pDesc->pAclPdu - HCI_ACL_HDR_LEN); #endif - lctrFreeTxBufDesc(pDesc); + lctrFreeConnTxBufDesc(pDesc); lctrDataTxIncAvailBuf(); pCtx->numTxComp++; } @@ -887,7 +876,7 @@ uint8_t lctrTxQueueClear(lctrConnCtx_t *pCtx) #ifndef LCTR_CONN_NO_TIFS_REASSEMBLY WsfMsgFree(pDesc->pAclPdu - HCI_ACL_HDR_LEN); #endif - lctrFreeTxBufDesc(pDesc); + lctrFreeConnTxBufDesc(pDesc); lctrDataTxIncAvailBuf(); numTxBufs++; @@ -932,8 +921,6 @@ uint8_t *lctrRxPduAlloc(uint16_t maxRxLen) * \brief Free a receive data PDU buffer. * * \param pBuf PDU data buffer to free. - * - * \return None. */ /*************************************************************************************************/ void lctrRxPduFree(uint8_t *pBuf) @@ -951,8 +938,6 @@ void lctrRxPduFree(uint8_t *pBuf) * \param pBuf PDU data buffer to queue. * \param eventCounter Event counter. * \param connHandle Connection handle. - * - * \return None. */ /*************************************************************************************************/ void lctrRxEnq(uint8_t *pBuf, uint16_t eventCounter, uint16_t connHandle) @@ -994,10 +979,8 @@ uint8_t *lctrRxDeq(uint16_t *pConnHandle) /*! * \brief Enqueue a receive data PDU buffer for a connection. * - * \param pCtx Connection context; + * \param pCtx Connection context. * \param pBuf PDU data buffer to queue. - * - * \return None. */ /*************************************************************************************************/ void lctrRxConnEnq(lctrConnCtx_t *pCtx, uint8_t *pBuf) @@ -1010,7 +993,7 @@ void lctrRxConnEnq(lctrConnCtx_t *pCtx, uint8_t *pBuf) /*! * \brief Dequeue a receive data PDU buffer for a connection as a ACL message. * - * \param pCtx Connection context; + * \param pCtx Connection context. * * \return Pointer to the start of the ACL message. * @@ -1051,12 +1034,6 @@ uint8_t *lctrRxConnDeqAcl(lctrConnCtx_t *pCtx) } lctrPackAclHdr(pAclBuf, &aclHdr); - - /* Move ACL data beside the header if necessary. */ - if (LCTR_DATA_PDU_START_OFFSET + LL_DATA_HDR_LEN > HCI_ACL_HDR_LEN) - { - memmove(pAclBuf + HCI_ACL_HDR_LEN, pAclBuf + LCTR_DATA_PDU_START_OFFSET + LL_DATA_HDR_LEN, aclHdr.len); - } } return pAclBuf; @@ -1066,7 +1043,7 @@ uint8_t *lctrRxConnDeqAcl(lctrConnCtx_t *pCtx) /*! * \brief Clear receive queue for a connection. * - * \param pCtx Connection context; + * \param pCtx Connection context. * * \return Number of freed buffers. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_master.c index 1f97b53793..b099194ac0 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master connection operation builder implementation file. + * \file + * + * \brief Link layer controller master connection operation builder implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -44,8 +45,6 @@ * * \param pCtx Connection context. * \param pBuf PDU buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstProcessDataPdu(lctrConnCtx_t *pCtx, uint8_t *pBuf) @@ -99,8 +98,6 @@ static void lctrMstProcessDataPdu(lctrConnCtx_t *pCtx, uint8_t *pBuf) /*************************************************************************************************/ /*! * \brief Master Tx data pending task event handler. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstConnTxPendingHandler(void) @@ -129,8 +126,6 @@ static void lctrMstConnTxPendingHandler(void) /*************************************************************************************************/ /*! * \brief Master connection reset handler. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstConnResetHandler(void) @@ -138,6 +133,7 @@ static void lctrMstConnResetHandler(void) BbBleConnSlaveInit(); BbBleConnMasterInit(); SchRmInit(); + SchTmInit(); lctrConnDefaults(); LmgrConnInit(); } @@ -147,8 +143,6 @@ static void lctrMstConnResetHandler(void) * \brief Execute master state machine. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstConnExecute(lctrConnMsg_t *pMsg) @@ -176,34 +170,87 @@ static void lctrMstConnExecute(lctrConnMsg_t *pMsg) * \brief Master connection message dispatcher. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstConnDisp(lctrConnMsg_t *pMsg) { if (pMsg->hdr.dispId != LCTR_DISP_BCST) { - WSF_ASSERT(pMsg->hdr.handle < (pLctrRtCfg->maxConn + (pLctrRtCfg->maxCis * pLctrRtCfg->maxCig))); + pLctrConnMsg = pMsg; + + WSF_ASSERT(pMsg->hdr.handle < (pLctrRtCfg->maxConn + pLctrRtCfg->maxCis)); lctrMstConnExecute(pMsg); } else { for (pMsg->hdr.handle = 0; pMsg->hdr.handle < pLctrRtCfg->maxConn; pMsg->hdr.handle++) { + pLctrConnMsg = pMsg; + lctrMstConnExecute(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. * * \param pCtx Connection context. * \param pConnInd Connection indication. - * - * \return None. */ /*************************************************************************************************/ void lctrMstConnBuildOp(lctrConnCtx_t *pCtx, lctrConnInd_t *pConnInd) @@ -219,8 +266,8 @@ void lctrMstConnBuildOp(lctrConnCtx_t *pCtx, lctrConnInd_t *pConnInd) /*** Connection context setup ***/ - /* pCtx->lastChanIdx = 0; */ /* cleared in lctrMstConnAdjustOpStart() */ - /* pCtx->eventCounter = 0; */ /* cleared in lctrMstConnAdjustOpStart() */ + pCtx->lastChanIdx = 0; + pCtx->eventCounter = 0; pCtx->chanMask = pConnInd->chanMask; pCtx->hopInc = pConnInd->hopInc; pCtx->connInterval = pConnInd->interval; @@ -252,6 +299,7 @@ void lctrMstConnBuildOp(lctrConnCtx_t *pCtx, lctrConnInd_t *pConnInd) /* Set PHY options to default behavior for connection. */ pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S8; /* TODO: Change to scanned PHY options from extended advertiser. */ + lctrInitPhyTxPower(pCtx); #if (LL_ENABLE_TESTER) pBle->chan.accAddrRx = pConnInd->accessAddr ^ llTesterCb.dataAccessAddrRx; @@ -272,8 +320,7 @@ void lctrMstConnBuildOp(lctrConnCtx_t *pCtx, lctrConnInd_t *pConnInd) /*** General setup ***/ - /* pOp->dueOffsetUsec = 0; */ /* cleared in alloc */ - pOp->minDurUsec = pCtx->localConnDurUsec; + pOp->minDurUsec = pCtx->effConnDurUsec; pOp->maxDurUsec = LCTR_CONN_IND_US(pCtx->connInterval); /* pOp->due = scanRefTime + BB_US_TO_BB_TICKS(maxOffsetUsec); */ /* set in lctrMstConnAdjustOpStart() */ @@ -301,8 +348,6 @@ void lctrMstConnBuildOp(lctrConnCtx_t *pCtx, lctrConnInd_t *pConnInd) * \brief Set the establish connection state. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrMstSetEstablishConn(lctrConnCtx_t *pCtx) @@ -325,14 +370,12 @@ 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(" due=%u", pCtx->connBod.due); + LL_TRACE_INFO1(" dueUsec=%u", pCtx->connBod.dueUsec); } /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for connectable master. - * - * \return None. */ /*************************************************************************************************/ void LctrMstConnInit(void) @@ -358,6 +401,8 @@ void LctrMstConnInit(void) /* Add channel selection handler. */ lctrChSelHdlr[LL_CH_SEL_1] = lctrSelectNextDataChannel; + lctrRegisterChClassHandler(lctrConnChClassUpdate); + lctrConnDefaults(); /* Set supported features. */ @@ -411,70 +456,3 @@ uint8_t lctrComputeHopInc(void) /* Valid value range is 5 to 16. */ return (((randNum >> 0) & 7) + ((randNum >> 8) & 3) + ((randNum >> 16) & 1)) + 5; } - -/*************************************************************************************************/ -/*! - * \brief Adjust the start time of a pre-established connection BOD. - * - * \param pCtx Connection context. - * \param scanRefTime Scan BOD reference time. - * \param scanMinDurUsec Scan BOD minimum duration. - * \param pConnInd Connection indication. - * - * \return First CE due time. - */ -/*************************************************************************************************/ -uint32_t lctrMstConnAdjustOpStart(lctrConnCtx_t *pCtx, uint32_t scanRefTime, uint32_t scanMinDurUsec, lctrConnInd_t *pConnInd) -{ - /* Pre-resolve common structures for efficient access. */ - BbOpDesc_t * const pOp = &pCtx->connBod; - - /*** Connection context setup ***/ - - pCtx->lastChanIdx = 0; - pCtx->eventCounter = 0; - - /*** General setup ***/ - - /* Use maximum txWindowOffset (i.e. connInterval) to maximize scan opportunity. */ - uint32_t maxOffsetUsec = SchRmGetOffsetUsec(LCTR_CONN_IND_US(pConnInd->interval), LCTR_GET_CONN_HANDLE(pCtx), scanRefTime); - - if (maxOffsetUsec <= scanMinDurUsec) - { - /* To avoid the case that the connection BOD might kill the scan BOD which does the scan for the connection. */ - maxOffsetUsec += LCTR_CONN_IND_US(pConnInd->interval); - } - - pOp->due = scanRefTime + BB_US_TO_BB_TICKS(maxOffsetUsec); - - /*** Commit operation ***/ - - WSF_ASSERT(pCtx->connInterval); - - uint32_t firstCeDue = pOp->due; - uint32_t anchorPoint = pOp->due; - uint16_t numIntervals = 0; - - while (TRUE) - { - if (SchInsertAtDueTime(pOp, lctrConnResolveConflict)) - { - break; - } - - LL_TRACE_WARN1("!!! Establish CE schedule conflict handle=%u", LCTR_GET_CONN_HANDLE(pCtx)); - - numIntervals += 1; - pCtx->eventCounter += 1; - - uint32_t connInterUsec = LCTR_CONN_IND_US(numIntervals * pCtx->connInterval); - uint32_t connInter = BB_US_TO_BB_TICKS(connInterUsec); - int16_t dueOffsetUsec = connInterUsec - BB_TICKS_TO_US(connInter); - - /* Advance to next interval. */ - pOp->due = anchorPoint + connInter; - pOp->dueOffsetUsec = WSF_MAX(dueOffsetUsec, 0); - } - - return firstCeDue; -} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_slave.c index 10dda5c75c..79830502ee 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_conn_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave connection operation builder implementation file. + * \file + * + * \brief Link layer controller slave connection operation builder implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -39,16 +40,18 @@ /************************************************************************************************** Global Variables **************************************************************************************************/ + +/*! \brief SCA PPM table. */ const uint16_t scaPpmTbl[] = { - 500, /* LL_MCA_500_PPM */ - 250, /* LL_MCA_250_PPM */ - 150, /* LL_MCA_150_PPM */ - 100, /* LL_MCA_100_PPM */ - 75, /* LL_MCA_75_PPM */ - 50, /* LL_MCA_50_PPM */ - 30, /* LL_MCA_30_PPM */ - 20 /* LL_MCA_20_PPM */ + 500, /*!< LL_MCA_500_PPM */ + 250, /*!< LL_MCA_250_PPM */ + 150, /*!< LL_MCA_150_PPM */ + 100, /*!< LL_MCA_100_PPM */ + 75, /*!< LL_MCA_75_PPM */ + 50, /*!< LL_MCA_50_PPM */ + 30, /*!< LL_MCA_30_PPM */ + 20 /*!< LL_MCA_20_PPM */ }; /*************************************************************************************************/ @@ -56,8 +59,6 @@ const uint16_t scaPpmTbl[] = * \brief Process a received connection indication PDU in slave role. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvProcessConnInd(lctrConnMsg_t *pMsg) @@ -92,8 +93,6 @@ static void lctrSlvProcessConnInd(lctrConnMsg_t *pMsg) * * \param pCtx Connection context. * \param pBuf PDU buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvProcessDataPdu(lctrConnCtx_t *pCtx, uint8_t *pBuf) @@ -128,14 +127,13 @@ static void lctrSlvProcessDataPdu(lctrConnCtx_t *pCtx, uint8_t *pBuf) /*************************************************************************************************/ /*! * \brief Slave connection reset handler. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvConnResetHandler(void) { BbBleConnSlaveInit(); SchRmInit(); + SchTmInit(); lctrConnDefaults(); LmgrConnInit(); } @@ -145,8 +143,6 @@ static void lctrSlvConnResetHandler(void) * \brief Execute slave state machine. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvConnExecute(lctrConnMsg_t *pMsg) @@ -167,26 +163,50 @@ static void lctrSlvConnExecute(lctrConnMsg_t *pMsg) * \brief Slave connection message dispatcher. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvConnDisp(lctrConnMsg_t *pMsg) { if (pMsg->hdr.dispId != LCTR_DISP_BCST) { + pLctrConnMsg = pMsg; + WSF_ASSERT(pMsg->hdr.handle < pLctrRtCfg->maxConn); lctrSlvConnExecute(pMsg); -} + } else { for (pMsg->hdr.handle = 0; pMsg->hdr.handle < pLctrRtCfg->maxConn; pMsg->hdr.handle++) { + pLctrConnMsg = pMsg; + lctrSlvConnExecute(pMsg); } } } +/*************************************************************************************************/ +/*! + * \brief Get reference time(due time) of the slave connection handle. + * + * \param connHandle Connection handle. + * + * \return Due time in microseconds of the connection handle. + */ +/*************************************************************************************************/ +static uint32_t lctrGetSlvConnRefTime(uint8_t connHandle) +{ + uint32_t refTime = 0; + lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(connHandle); + + if (pCtx->enabled && (pCtx->bleData.chan.opType == BB_BLE_OP_SLV_CONN_EVENT)) + { + refTime = pCtx->connBod.dueUsec; + } + + return refTime; +} + /*************************************************************************************************/ /*! * \brief Compute the total clock accuracy. @@ -215,8 +235,6 @@ uint16_t lctrCalcTotalAccuracy(uint8_t mstScaIdx) * * \param pCtx Connection context. * - * \return None. - * * This routine is called in response to a received CONNECTION_REQ PDU. The PDU must already * be decoded in the lctrPduSlvAdvb variable prior to this call. */ @@ -294,6 +312,7 @@ void lctrSlvConnBuildOp(lctrConnCtx_t *pCtx) pBle->chan.accAddr = pConnInd->accessAddr; pBle->chan.crcInit = pConnInd->crcInit; pBle->chan.txPhy = pBle->chan.rxPhy = pLctrConnMsg->connEstablish.phy; + lctrInitPhyTxPower(pCtx); #if (LL_ENABLE_TESTER) pBle->chan.accAddrRx = pConnInd->accessAddr ^ llTesterCb.dataAccessAddrRx; @@ -315,18 +334,14 @@ void lctrSlvConnBuildOp(lctrConnCtx_t *pCtx) /*** General setup ***/ const uint32_t txWinOffsetUsec = LCTR_CONN_IND_US(txWinOffsetCnt); - const uint32_t txWinOffset = BB_US_TO_BB_TICKS(txWinOffsetUsec); const uint32_t txWinSizeUsec = LCTR_CONN_IND_US(pConnInd->txWinSize); const uint32_t wwOffsetUsec = lctrCalcWindowWideningUsec((txWinOffsetUsec + txWinSizeUsec), pCtx->data.slv.totalAcc); - const uint32_t wwOffset = BB_US_TO_BB_TICKS(wwOffsetUsec); - int16_t dueOffsetUsec = (txWinOffsetUsec - wwOffsetUsec) - BB_TICKS_TO_US(txWinOffset - wwOffset); - pCtx->data.slv.anchorPoint = pLctrConnMsg->connEstablish.connIndEndTs + txWinOffset; /* estimated initial anchor point */ + pCtx->data.slv.anchorPointUsec = pLctrConnMsg->connEstablish.connIndEndTsUsec + txWinOffsetUsec; /* estimated initial anchor point */ pCtx->data.slv.txWinSizeUsec = txWinSizeUsec; - pOp->due = pCtx->data.slv.anchorPoint - wwOffset; - pOp->dueOffsetUsec = WSF_MAX(dueOffsetUsec, 0); - pOp->minDurUsec = txWinSizeUsec + pCtx->localConnDurUsec + (wwOffsetUsec << 1); + pOp->dueUsec = pCtx->data.slv.anchorPointUsec - wwOffsetUsec; + pOp->minDurUsec = txWinSizeUsec + pCtx->effConnDurUsec + (wwOffsetUsec << 1); /* pOp->maxDurUsec = 0; */ /* cleared in alloc */ pOp->reschPolicy = BB_RESCH_FIXED; @@ -339,7 +354,7 @@ void lctrSlvConnBuildOp(lctrConnCtx_t *pCtx) /*** BLE connection setup ***/ pConn->rxSyncDelayUsec = txWinSizeUsec + (wwOffsetUsec << 1) + - BB_TICKS_TO_US(1); /* rounding compensation when computing reqEndTs */ + 1; /* rounding compensation when computing reqEndTs */ pConn->execCback = lctrSlvConnBeginOp; pConn->cancelCback = lctrSlvConnCleanupOp; pConn->txDataCback = lctrSlvConnTxCompletion; @@ -358,9 +373,8 @@ void lctrSlvConnBuildOp(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(" due=%u", pOp->due); - LL_TRACE_INFO1(" offsetUsec=%u", pOp->dueOffsetUsec); - + LL_TRACE_INFO1(" dueUsec=%u", pOp->dueUsec); + LL_TRACE_INFO1(" minDurUsec=%u", pOp->minDurUsec); break; } @@ -370,24 +384,22 @@ void lctrSlvConnBuildOp(lctrConnCtx_t *pCtx) /* Initial eventCounter starts at 0; equivalent to unsynchronized intervals. */ uint32_t unsyncTimeUsec = LCTR_CONN_IND_US(pCtx->connInterval * pCtx->eventCounter); - uint32_t unsyncTime = BB_US_TO_BB_TICKS(unsyncTimeUsec); uint32_t wwTotalUsec = lctrCalcWindowWideningUsec(unsyncTimeUsec, pCtx->data.slv.totalAcc); - uint32_t wwTotal = BB_US_TO_BB_TICKS(wwTotalUsec); - dueOffsetUsec = (unsyncTimeUsec - wwTotalUsec) - BB_TICKS_TO_US(unsyncTime - wwTotal); /* Advance to next interval. */ - pOp->due = pCtx->data.slv.anchorPoint + unsyncTime - wwTotal; - pOp->dueOffsetUsec = WSF_MAX(dueOffsetUsec, 0); + pOp->dueUsec = pCtx->data.slv.anchorPointUsec + unsyncTimeUsec - wwTotalUsec; + pOp->minDurUsec = ceDurUsec + wwTotalUsec; pConn->rxSyncDelayUsec = ceSyncDlyUsec + (wwTotalUsec << 1); } + + /* Update topology manager information. */ + SchTmAdd(LCTR_GET_CONN_HANDLE(pCtx), LCTR_CONN_IND_US(pCtx->connInterval), pCtx->effConnDurUsec, TRUE, lctrGetSlvConnRefTime); } /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for connectable slave. - * - * \return None. */ /*************************************************************************************************/ void LctrSlvConnInit(void) @@ -450,8 +462,6 @@ void LctrSlvConnInit(void) /*************************************************************************************************/ /*! * \brief Set default values for connection. - * - * \return None. */ /*************************************************************************************************/ void lctrConnDefaults(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_enc_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_enc_master.c index d58c4ab9a2..db7d60f372 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_enc_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_enc_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master encryption implementation file. + * \file + * + * \brief Link layer controller master encryption implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -35,8 +36,6 @@ * * \param pCtx Connection context. * \param pBuf PDU buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstEncProcessDataPdu(lctrConnCtx_t *pCtx, uint8_t *pBuf) @@ -92,8 +91,6 @@ static void lctrMstEncProcessDataPdu(lctrConnCtx_t *pCtx, uint8_t *pBuf) /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for connectable encrypted master. - * - * \return None. */ /*************************************************************************************************/ void LctrMstConnEncInit(void) @@ -108,7 +105,7 @@ void LctrMstConnEncInit(void) lctrCtrlPduHdlr = lctrMstEncProcessDataPdu; /* Add packet encryption handlers. */ - lctrInitCipherBlkHdlr = PalCryptoAesSetupCipherBlock; + lctrInitCipherBlkHdlr = PalCryptoAesEnable; #if (!BB_ENABLE_INLINE_ENC_TX) lctrPktEncryptHdlr = PalCryptoAesCcmEncrypt; #else diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_enc_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_enc_slave.c index a296d96fc3..1a506a943c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_enc_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_enc_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave encryption implementation file. + * \file + * + * \brief Link layer controller slave encryption implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -34,8 +35,6 @@ * * \param pCtx Connection context. * \param pBuf PDU buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrSlvEncProcessDataPdu(lctrConnCtx_t *pCtx, uint8_t *pBuf) @@ -70,8 +69,6 @@ static void lctrSlvEncProcessDataPdu(lctrConnCtx_t *pCtx, uint8_t *pBuf) /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for connectable encrypted slave. - * - * \return None. */ /*************************************************************************************************/ void LctrSlvConnEncInit(void) @@ -87,7 +84,7 @@ void LctrSlvConnEncInit(void) } /* Add packet encryption handlers. */ - lctrInitCipherBlkHdlr = PalCryptoAesSetupCipherBlock; + lctrInitCipherBlkHdlr = PalCryptoAesEnable; #if (!BB_ENABLE_INLINE_ENC_TX) lctrPktEncryptHdlr = PalCryptoAesCcmEncrypt; #else @@ -132,7 +129,7 @@ uint32_t LctrGetAuthPayloadTimeout(uint16_t handle) * \param handle Connection handle. * \param timeoutMs New timeout value in milliseconds. * - * \return None. + * \return TRUE if successful, FALSE if not. */ /*************************************************************************************************/ bool_t LctrSetAuthPayloadTimeout(uint16_t handle, uint32_t timeoutMs) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_init_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_init_master.c index b03fe50bc8..a03d60bec0 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_init_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_init_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master scanning operation builder implementation file. + * \file + * + * \brief Link layer controller master scanning operation builder implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -43,8 +44,6 @@ lctrMstScanCtx_t lctrMstInit; /*************************************************************************************************/ /*! * \brief Master initiate reset handler. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstInitResetHandler(void) @@ -57,8 +56,6 @@ static void lctrMstInitResetHandler(void) * \brief Master initiate message dispatcher. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstInitDisp(lctrMsgHdr_t *pMsg) @@ -66,26 +63,6 @@ static void lctrMstInitDisp(lctrMsgHdr_t *pMsg) lctrMstInitExecuteSm(pMsg->event); } -/*************************************************************************************************/ -/*! - * \brief Handler for pre-initiate scan execution. - * - * \param pOp BB operation descriptor. - * - * \return None. - */ -/*************************************************************************************************/ -static void lctrMstPreInitiateExecHandler(BbOpDesc_t *pOp) -{ - /* Setup connection's initial CE now that RM is synchronized BB. This step must be performed - * before initiate's scan operation sets up its executing duration (i.e. "pre-execute"). */ - lctrMstInit.data.init.firstCeDue = lctrMstConnAdjustOpStart(LCTR_GET_CONN_CTX(lctrMstInit.data.init.connHandle), - pOp->due, - pOp->minDurUsec, - &lctrMstInit.data.init.connInd); - lctrMstInit.data.init.connBodLoaded = TRUE; -} - /*************************************************************************************************/ /*! * \brief Build initiate connection operation. @@ -93,8 +70,6 @@ static void lctrMstPreInitiateExecHandler(BbOpDesc_t *pOp) * \param pConnSpec Connection spec. * \param peerAddrType Peer address type. * \param peerAddr Peer address. - * - * \return None. */ /*************************************************************************************************/ void lctrMstInitiateBuildOp(LlConnSpec_t *pConnSpec, uint8_t peerAddrType, uint64_t peerAddr) @@ -146,14 +121,13 @@ void lctrMstInitiateBuildOp(LlConnSpec_t *pConnSpec, uint8_t peerAddrType, uint6 pScan->scanChMap = lmgrMstScanCb.scanChanMap; - pScan->preExecCback = lctrMstPreInitiateExecHandler; pScan->rxAdvCback = lctrMstInitiateAdvPktHandler; if ((pScan->pRxAdvBuf = WsfMsgAlloc(LCTR_ADVB_BUF_SIZE)) == NULL) { /* Attempt to obtain buffer on next advertising operation. */ LL_TRACE_ERR0("Could not allocate advertising buffer"); - // TODO need OOM recovery + /* TODO need OOM recovery */ WSF_ASSERT(FALSE); } @@ -251,8 +225,6 @@ void lctrMstInitiateBuildOp(LlConnSpec_t *pConnSpec, uint8_t peerAddrType, uint6 /*************************************************************************************************/ /*! * \brief Commit initiate connection operation. - * - * \return None. */ /*************************************************************************************************/ void lctrMstInitiateOpCommit(void) @@ -269,14 +241,12 @@ void lctrMstInitiateOpCommit(void) lctrMstInit.shutdown = FALSE; SchInsertNextAvailable(pOp); - lctrMstInit.scanWinStart = pOp->due; + lctrMstInit.scanWinStartUsec = pOp->dueUsec; } /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for initiating master. - * - * \return None. */ /*************************************************************************************************/ void LctrMstInitInit(void) @@ -293,8 +263,6 @@ void LctrMstInitInit(void) /*************************************************************************************************/ /*! * \brief Set default values for scanning master. - * - * \return None. */ /*************************************************************************************************/ void LctrMstInitDefaults(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_init_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_init_master_ae.c index a3c48c35e2..6921013794 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_init_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_init_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master scanning operation builder implementation file. + * \file + * + * \brief Link layer controller master scanning operation builder implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -34,6 +35,21 @@ #include #include +/************************************************************************************************** + Macros +**************************************************************************************************/ +/*! \brief Resolve the extended initiate handle from the context pointer. */ +#define LCTR_GET_EXT_INIT_HANDLE(pCtx) (pCtx - lctrMstExtInitTbl) + +/*! \brief Typical PDU length of ADV_EXT_IND when initiating connection. */ +#define LCTR_INIT_ADV_EXT_IND_LEN 7 /*!< Includes Flags + ADI + AuxPtr. */ + +/*! \brief Typical PDU length of AUX_ADV_IND when initiating connection. */ +#define LCTR_INIT_AUX_ADV_IND_LEN 10 /*!< Includes Flags + AdvA + ADI. */ + +/*! \brief Typical PDU length of ADV_IND when initiating connection with legacy packets. */ +#define LCTR_INIT_ADV_IND_LEN 6 + /************************************************************************************************** Globals **************************************************************************************************/ @@ -47,8 +63,6 @@ lctrExtInitCtrlBlk_t lctrMstExtInit; /*************************************************************************************************/ /*! * \brief Master initiate reset handler. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstExtInitResetHandler(void) @@ -61,8 +75,6 @@ static void lctrMstExtInitResetHandler(void) * \brief Execute common master initiate state machine. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstExtInitExecuteCommonSm(LctrExtScanMsg_t *pMsg) @@ -94,7 +106,7 @@ static void lctrMstExtInitExecuteCommonSm(LctrExtScanMsg_t *pMsg) if ((status = lctrExtInitSetupInitiate(&lctrMstExtInitTbl[i], pExtInitMsg->peerAddrType, pExtInitMsg->peerAddr, pExtInitMsg->filterPolicy, pExtInitMsg->ownAddrType)) != LL_SUCCESS) { - // TODO for multiple scanners, cleanup upon failure + /* TODO for multiple scanners, cleanup upon failure */ break; } } @@ -145,8 +157,6 @@ static void lctrMstExtInitExecuteCommonSm(LctrExtScanMsg_t *pMsg) * \brief Master initiate message dispatcher. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrMstExtInitDisp(LctrExtScanMsg_t *pMsg) @@ -270,7 +280,6 @@ uint8_t lctrMstExtInitiateBuildOp(lctrExtScanCtx_t *pExtInitCtx, LlConnSpec_t *p pScan->scanChMap = lmgrMstScanCb.scanChanMap; - pScan->preExecCback = lctrMstExtPreInitiateExecHandler; pScan->rxAdvCback = lctrMstInitiateRxExtAdvPktHandler; pScan->rxAdvPostCback = lctrMstInitiateRxExtAdvPktPostProcessHandler; @@ -284,7 +293,7 @@ uint8_t lctrMstExtInitiateBuildOp(lctrExtScanCtx_t *pExtInitCtx, LlConnSpec_t *p pScan->txReqCback = lctrMstExtConnIndTxCompHandler; - // TODO move to common/shared init + /* TODO move to common/shared init */ lctrConnInd_t * const pConnInd = &pExtInitCtx->data.init.connInd; pConnInd->accessAddr = lctrComputeAccessAddr(); @@ -371,8 +380,6 @@ uint8_t lctrMstExtInitiateBuildOp(lctrExtScanCtx_t *pExtInitCtx, LlConnSpec_t *p * \brief Commit initiate connection operation. * * \param pExtInitCtx Extended scan context of the initiator. - * - * \return None. */ /*************************************************************************************************/ void lctrMstExtInitiateOpCommit(lctrExtScanCtx_t *pExtInitCtx) @@ -390,7 +397,7 @@ void lctrMstExtInitiateOpCommit(lctrExtScanCtx_t *pExtInitCtx) pExtInitCtx->shutdown = FALSE; SchInsertNextAvailable(pOp); - pExtInitCtx->data.init.scanWinStart = pOp->due; + pExtInitCtx->data.init.scanWinStartUsec = pOp->dueUsec; } /*************************************************************************************************/ @@ -524,8 +531,6 @@ uint8_t lctrMstAuxInitiateBuildOp(lctrExtScanCtx_t *pExtInitCtx, LlConnSpec_t *p /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for initiating master. - * - * \return None. */ /*************************************************************************************************/ void LctrMstExtInitInit(void) @@ -548,8 +553,6 @@ void LctrMstExtInitInit(void) /*************************************************************************************************/ /*! * \brief Set default values for scanning master. - * - * \return None. */ /*************************************************************************************************/ void LctrMstExtInitDefaults(void) @@ -566,8 +569,6 @@ void LctrMstExtInitDefaults(void) * \brief Set enabled initiate scanning PHY. * * \param scanPhy Enabled scanning PHY. - * - * \return None. */ /*************************************************************************************************/ void LctrMstExtInitSetScanPhy(uint8_t scanPhy) @@ -582,8 +583,6 @@ void LctrMstExtInitSetScanPhy(uint8_t scanPhy) * \brief Clear (disable) scanning PHY. * * \param scanPhy Disabled scanning PHY. - * - * \return None. */ /*************************************************************************************************/ void LctrMstExtInitClearScanPhy(uint8_t scanPhy) @@ -600,8 +599,6 @@ void LctrMstExtInitClearScanPhy(uint8_t scanPhy) * \param initPhy Extended initiating PHY. * \param pScanParam Extended initiating scan parameters. * \param pConnSpec Connection specification. - * - * \return None. */ /*************************************************************************************************/ void LctrMstExtInitParam(uint8_t initPhy, const LlExtInitScanParam_t *pScanParam, const LlConnSpec_t *pConnSpec) @@ -621,8 +618,6 @@ void LctrMstExtInitParam(uint8_t initPhy, const LlExtInitScanParam_t *pScanParam * * \param pExtInitCtx Extended initiate context. * \param event Extended scan event. - * - * \return None. */ /*************************************************************************************************/ void lctrSendExtInitMsg(lctrExtScanCtx_t *pExtInitCtx, uint8_t event) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_iso.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_iso.c new file mode 100644 index 0000000000..369609871c --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_iso.c @@ -0,0 +1,1196 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller connected isochronous stream main implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_cis.h" +#include "lctr_int_bis.h" +#include "lctr_int_iso.h" +#include "hci_defs.h" +#include "wsf_assert.h" +#include "wsf_math.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include "pal_codec.h" +#include + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*! \brief Codec event handlers (function pointers to decouple linker dependencies). */ +lctrCodecHandlers_t lctrCodecHdlr; + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Process received ISO test data. + * + * \param pCisCtx CIS context. + * \param pDataBuf Data buffer. + * \param dataLen Data length. + */ +/*************************************************************************************************/ +static void lctrIsoProcessRxTestData(lctrCisCtx_t *pCisCtx, uint8_t *pDataBuf, uint8_t dataLen) +{ + uint16_t pldType = 0; + uint64_t plTestCounter = pCisCtx->rxPktCounter; + + if (pCisCtx->rxPendInit) + { + memcpy(&pCisCtx->expectedPkt, pDataBuf, 4); + pCisCtx->rxPendInit = FALSE; + LL_TRACE_INFO1("lctrCisRxPostProcessing, Rx counter initialized to %d", pCisCtx->expectedPkt); + } + + switch (pCisCtx->isoRxPldType) + { + case LL_ISO_PLD_TYPE_MAX_LEN: + + pldType = (pCisCtx->role == LL_ROLE_MASTER) ? pCisCtx->sduSizeSToM : pCisCtx->sduSizeMToS; + break; + + case LL_ISO_PLD_TYPE_VAR_LEN: + pldType = plTestCounter * 4; + pldType = WSF_MIN(pCisCtx->localDataPdu.maxRxLen, pldType); + break; + + case LL_ISO_PLD_TYPE_ZERO_LEN: + default: + break; + } + + uint32_t pktNum = 0; + if (dataLen >= LL_ISO_TEST_VAR_MIN_LEN) + { + memcpy(&pktNum, pDataBuf, 4); + } + + switch (pCisCtx->isoRxPldType) + { + case LL_ISO_PLD_TYPE_MAX_LEN: + if ((dataLen == pldType) && + (pktNum == pCisCtx->expectedPkt)) + { + pCisCtx->numRxSuccess++; + } + else + { + pCisCtx->expectedPkt = pktNum + 1; + pCisCtx->numRxFailed++; + } + break; + + case LL_ISO_PLD_TYPE_VAR_LEN: + if ((dataLen >= LL_ISO_TEST_VAR_MIN_LEN) && + (pktNum == pCisCtx->expectedPkt)) + { + pCisCtx->numRxSuccess++; + } + else + { + pCisCtx->expectedPkt = pktNum + 1; + pCisCtx->numRxFailed++; + } + break; + + case LL_ISO_PLD_TYPE_ZERO_LEN: + if (dataLen == 0) + { + pCisCtx->numRxSuccess++; + } + else + { + pCisCtx->numRxFailed++; + } + break; + + default: + LL_TRACE_ERR1("Invalid value pldType=%u", pldType); + break; + } +} + +/*************************************************************************************************/ +/*! + * \brief Enable ISO Tx test. + * + * \param pCisCtx CIS context. + * \param pldType Payload length type. + * + * \return Status error code. + */ +/*************************************************************************************************/ +static uint8_t lctrCisTxTest(lctrCisCtx_t *pCisCtx, uint8_t pldType) +{ + lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); + + if (((pCisCtx->bnMToS == 0) && (pCisCtx->role == LL_ROLE_MASTER)) || + ((pCisCtx->bnSToM == 0) && (pCisCtx->role == LL_ROLE_SLAVE))) + { + LL_TRACE_WARN0("Transmit burst number must be greater than 0"); + return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; + } + + if (pldType > LL_ISO_PLD_TYPE_MAX_LEN) + { + LL_TRACE_WARN1("Unknown payload type=%u", pldType); + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + + pCisCtx->testTxPktCtr = 0; +#if (LL_ENABLE_TESTER) + pCisCtx->testTxPktCtr = llTesterCb.isoTxTestNumInit; +#endif + pCisCtx->testSduTs = pCigCtx->cigBod.dueUsec; + pCisCtx->testPldType = pldType; + pCisCtx->txTestEnabled = TRUE; + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief CIS read ISO test counters. + * + * \param pCisCtx CIS context. + * \param pStats Pointer to the statistics block. + * + * \return Status error code. + */ +/*************************************************************************************************/ +static uint8_t LctrCisReadTestCounters(lctrCisCtx_t *pCisCtx, LlIsoTestCtrs_t *pStats) +{ + + if (!pCisCtx->rxTestEnabled && + !pCisCtx->txTestEnabled) + { + LL_TRACE_WARN0("Invalid ISO Test state, test mode must be enabled"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + if (pCisCtx->rxTestEnabled) + { + pStats->numSuccess = pCisCtx->numRxSuccess; + pStats->numMissed = pCisCtx->numRxMissed; + pStats->numFailed = pCisCtx->numRxFailed; + } + else /* if (pCisCtx->txTestEnabled) */ + { + pStats->numSuccess = 0; + pStats->numMissed = 0; + pStats->numFailed = 0; + } + + return LL_SUCCESS; +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Initialize codec resources. + * + * Map codec handlers for codec operations. Function pointer abstraction is used to decouple + * linker dependencies when a codec is not required by the system. + */ +/*************************************************************************************************/ +void LctrInitCodec(void) +{ + /* Add codec. */ + lctrCodecHdlr.start = PalCodecDataStartStream; + lctrCodecHdlr.stop = PalCodecDataStopStream; + lctrCodecHdlr.in = PalCodecDataStreamIn; + lctrCodecHdlr.out = PalCodecDataStreamOut; +} + +/*************************************************************************************************/ +/*! + * \brief Tx data completed task event handler. + */ +/*************************************************************************************************/ +void lctrIsoTxCompletedHandler(void) +{ + WSF_CS_INIT(cs); + + uint8_t numHandles = 0; + uint16_t handle[LL_MAX_CIS] = { 0 }; + uint16_t numSdu[LL_MAX_CIS] = { 0 }; + + /* Cache buffer count within single CS. */ + WSF_CS_ENTER(cs); + for (unsigned int i = 0; i < pLctrRtCfg->maxCis; i++) + { + lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i]; + + if (pCisCtx->enabled && !pCisCtx->txTestEnabled) + { + if (pCisCtx->numTxComp && (pCisCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED)) + { + numSdu[numHandles] = pCisCtx->numTxComp; + handle[numHandles] = pCisCtx->cisHandle; + pCisCtx->numTxComp = 0; + numHandles++; + } + else if ((pCisCtx->framing == LL_ISO_PDU_TYPE_FRAMED) && pCisCtx->isoalTxCtx.compSdu) + { + numSdu[numHandles] = pCisCtx->isoalTxCtx.compSdu; + handle[numHandles] = pCisCtx->cisHandle; + pCisCtx->numTxComp = 0; /* numTxComp is still recorded in framed, so clear it here. */ + pCisCtx->isoalTxCtx.compSdu = 0; + numHandles++; + } + } + } + + WSF_CS_EXIT(cs); + + if (numHandles) + { + /* Notify host. */ + lmgrPersistCb.sendIsoCompCback(numHandles, handle, numSdu); + } +} + +/*************************************************************************************************/ +/*! + * \brief Rx data pending task event handler. + */ +/*************************************************************************************************/ +void lctrCisRxPendingHandler(void) +{ + uint16_t cisHandle = 0; + uint8_t *pRxBuf; + + /* Route and demux received Data PDUs. */ + + while ((pRxBuf = lctrCisRxDeq(&cisHandle)) != NULL) + { + WSF_ASSERT(pRxBuf); + + lctrCisCtx_t *pCisCtx = lctrFindCisByHandle(cisHandle); + lctrIsoalRxCtx_t *pRxCtx = &pCisCtx->isoalRxCtx; + + if (!pCisCtx->enabled) + { + LL_TRACE_ERR1("!!! Data received on terminated cisHandle=%u", cisHandle); + lctrCisRxPduFree(pRxBuf); + continue; + } + + /* Disassemble PDU. */ + lctrCisDataPduHdr_t rxHdr; + lctrCisUnpackDataPduHdr(&rxHdr, pRxBuf); + + /* Decrypt PDU. */ + if (lctrPktDecryptHdlr) + { + if (lctrPktDecryptHdlr(&pCisCtx->bleData.chan.enc, pRxBuf) == FALSE) + { + LL_TRACE_ERR1("!!! MIC verification failed on connHandle=%u", cisHandle); + LL_TRACE_ERR1("!!! MIC verification failed on cisEvtCounter=%u", pCisCtx->cisEvtCounter); + lctrCisRxPduFree(pRxBuf); + lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_TERM_MIC_FAILED); + continue; + } + } + + /* 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 }; + switch (rxHdr.llid) + { + /* Received a end/complete PDU. */ + case LL_LLID_ISO_UNF_END_PDU: + switch (pRxCtx->rxState) + { + case LL_ISO_SDU_STATE_NEW: + isoHdr.pb = LCTR_PB_COMP; + break; + case LL_ISO_SDU_STATE_CONT: + isoHdr.pb = LCTR_PB_LAST; + pRxCtx->rxState = LL_ISO_SDU_STATE_NEW; + break; + default: + 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; + } + break; + + /* Received a continuation/start PDU. */ + case LL_LLID_ISO_UNF_CONT_PDU: + isoHdr.pb = (pRxCtx->rxState == LL_ISO_SDU_STATE_NEW) ? LCTR_PB_FIRST : LCTR_PB_CONT; + pRxCtx->rxState = LL_ISO_SDU_STATE_CONT; + break; + + /* Unknown LLID. */ + 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; + } + + /* Pack isoHdr and queue PDU. */ + if (pRxBuf) + { + 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) + { + isoHdr.ts = 0xFF; + } + isoHdr.len = pRxBuf[LCTR_ISO_DATA_PDU_LEN_OFFSET]; + /* isoHdr.pktSn = 0; */ + + /* LCTR_PB_COMP and LCTR_PB_FIRST will have their headers re-packed in lctrIsoUnframedRxSduPendQueue. */ + uint8_t headerOffset = lctrIsoPackHdr(pSduBuf, &isoHdr); + + /* Process received buffer for Rx testing purpose. */ + 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) + { + 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)) + { + break; + } + + /* If it is time to enqueue the SDU, do so here. */ + uint8_t handlerId; + while ((pSduBuf = WsfMsgDeq(&pRxCtx->data.unframed.pendSduQ, &handlerId)) != NULL) + { + /* Enqueue SDU for processing. */ + if (!lctrIsoRxConnEnq(&pCisCtx->dataPathOutCtx, pCisCtx->cisHandle, pSduBuf)) + { + /* The buffer was not freed, so free it now. */ + WsfMsgFree(pSduBuf); + } + } + } + } + else /* LL_ISO_PDU_TYPE_FRAMED */ + { + switch (rxHdr.llid) + { + case LL_LLID_ISO_FRA_PDU: + { + 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 */ + 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); + WsfMsgFree(pTestRxBuf); + LctrRxIsoComplete(1); + pCisCtx->dataPathOutCtx.cfg.hci.numRxPend--; + } + } + lctrCisRxPduFree(pRxBuf); + break; + } + + default: + lctrCisRxPduFree(pRxBuf); + LL_TRACE_ERR2("!!! Invalid LLID; dropping Rx data PDU, connHandle=%u llid=%u", cisHandle, rxHdr.llid); + break; + } + } + } + + /* Notify host of pending Rx data. */ + WSF_CS_INIT(cs); + uint8_t numHandles = 0; + uint16_t numSdu[LL_MAX_CIS] = { 0 }; + uint16_t handle[LL_MAX_CIS] = { 0 }; + + /* Cache buffer count within single CS. */ + WSF_CS_ENTER(cs); + for (unsigned int i = 0; i < pLctrRtCfg->maxCis; i++) + { + lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i]; + + if (pCisCtx->enabled && + 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++; + } + } + } + WSF_CS_EXIT(cs); + + if (numHandles) + { + /* Notify host. */ + lmgrPersistCb.recvIsoPendCback(numHandles, handle, numSdu); + } +} + +/*************************************************************************************************/ +/*! + * \brief Initialize ISO memory resources. + * + * \param pFreeMem Pointer to free memory. + * \param freeMemSize Size of pFreeMem. + * + * \return Amount of free memory consumed. + */ +/*************************************************************************************************/ +uint16_t LctrInitIsoMem(uint8_t *pFreeMem, uint32_t freeMemSize) +{ + uint8_t *pAvailMem = pFreeMem; + + if (((uint32_t)pAvailMem) & 3) + { + /* Align to next word. */ + pAvailMem = (uint8_t *)(((uint32_t)pAvailMem & ~3) + sizeof(uint32_t)); + } + + /*** Tx Memory ***/ + + freeMemSize -= pAvailMem - pFreeMem; + uint16_t memUsed = lctrIsoTxInitMem(pAvailMem, freeMemSize); + if (memUsed == 0) + { + LL_TRACE_ERR2("LctrInitIsoMem: failed to allocate descriptors, need=%u available=%u", (pAvailMem - pFreeMem), freeMemSize); + WSF_ASSERT(FALSE); + return 0; + } + + pAvailMem += memUsed; + + return (pAvailMem - pFreeMem); +} + +/*************************************************************************************************/ +/*! + * \brief Transmit ISO data path. + * + * \param pIsoBuf ISO buffer. + */ +/*************************************************************************************************/ +void LctrTxIso(uint8_t *pIsoBuf) +{ + lctrIsoHdr_t isoHdr; + + /*** Disassemble ISO packet. ***/ + + lctrIsoUnpackHdr(&isoHdr, pIsoBuf); + + if (isoHdr.sduLen > pLctrRtCfg->maxIsoSduLen) + { + LL_TRACE_ERR2("Invalid ISO header: invalid packet length, actLen=%u, maxLen=%u", isoHdr.sduLen, pLctrRtCfg->maxIsoSduLen); + WsfMsgFree(pIsoBuf); + lmgrPersistCb.sendCompCback(isoHdr.handle, 1); + return; + } + + if (lmgrIsoCb.availTxBuf == 0) + { + LL_TRACE_ERR1("ISO Tx path flow controlled, handle=%u", isoHdr.handle); + WsfMsgFree(pIsoBuf); + lmgrPersistCb.sendCompCback(isoHdr.handle, 1); + return; + } + + 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); + return; + } + + /*** Resolve ISO context. ***/ + + lctrCisCtx_t *pCisCtx; + lctrBisCtx_t *pBisCtx; + + if ((pCisCtx = lctrFindCisByHandle(isoHdr.handle)) != NULL) + { + if (!lctrCheckIsCisEstCis(pCisCtx->cisHandle)) + { + LL_TRACE_ERR1("Invalid ISO handle: link not established cisHandle=%u; dropping packet", isoHdr.handle); + lmgrPersistCb.sendCompCback(isoHdr.handle, 1); + WsfMsgFree(pIsoBuf); + return; + } + + if ((pCisCtx->localDataPdu.maxTxLen == 0) || + ((pCisCtx->bnMToS == 0) && (pCisCtx->role == LL_ROLE_MASTER)) || + ((pCisCtx->bnSToM == 0) && (pCisCtx->role == LL_ROLE_SLAVE))) + { + LL_TRACE_ERR1("Invalid CIS state: handle=%u does not accept transmissions; dropping packet", isoHdr.handle); + WsfMsgFree(pIsoBuf); + lmgrPersistCb.sendCompCback(isoHdr.handle, 1); + return; + } + + if (pCisCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED) + { + lctrIsoSduTxDecAvailBuf(); + + /*** Queue for transmit. ***/ + + lctrCisTxDataPduQueue(pCisCtx, &isoHdr, pIsoBuf); + } + else /* LL_ISO_PDU_TYPE_FRAMED */ + { + /* Queue up for transmission. */ + WsfMsgEnq(&pCisCtx->isoalTxCtx.pendingSduQ, 0, pIsoBuf); + pCisCtx->isoalTxCtx.pendQueueSize++; + + /* PDU assembly handled in the EndOp. */ + } + } + else if ((pBisCtx = lctrFindBisByHandle(isoHdr.handle)) != NULL) + { + if (isoHdr.sduLen > pBisCtx->pBigCtx->maxSdu) + { + 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); + return; + } + + lctrIsoSduTxDecAvailBuf(); + + /*** Queue for transmit. ***/ + + if (pBisCtx->pBigCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED) + { + lctrBisTxIsoPduQueue(pBisCtx, &isoHdr, pIsoBuf); + } + else /* LL_ISO_PDU_TYPE_FRAMED */ + { + /* Queue up for transmission. */ + WsfMsgEnq(&pBisCtx->roleData.slv.isoalTxCtx.pendingSduQ, 0, pIsoBuf); + pBisCtx->roleData.slv.isoalTxCtx.pendQueueSize++; + } + } + else + { + LL_TRACE_ERR1("Invalid ISO handle: unknown handle handle=%u; dropping packet", isoHdr.handle); + WsfMsgFree(pIsoBuf); + /* Do not inform host of the number of completed event. */ + } +} + +/*************************************************************************************************/ +/*! + * \brief Receive ISO data path. + * + * \return Received data PDU buffer or NULL if queue empty or data consumed by a data path. + */ +/*************************************************************************************************/ +uint8_t *LctrRxIso(void) +{ + uint8_t *pBuf; + + for (unsigned int i = 0; i < pLctrRtCfg->maxCis; i++) + { + lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i]; + + if ((pCisCtx->enabled) && + ((pBuf = lctrIsoRxConnDeq(&pCisCtx->dataPathOutCtx)) != NULL)) + { + return pBuf; + } + } + + for (unsigned int i = 0; i < pLctrRtCfg->maxBis; i++) + { + lctrBisCtx_t *pBisCtx = &pLctrBisTbl[i]; + + if ((pBisCtx->enabled) && + (pBisCtx->pBigCtx->role == LL_ROLE_MASTER) && + ((pBuf = lctrBisRxIsoSduDeq(pBisCtx)) != NULL)) + { + return pBuf; + } + } + + return NULL; +} + +/*************************************************************************************************/ +/*! + * \brief Indicate that received ISO data buffer has been deallocated + * + * \param numBufs Number of completed packets. + * + * Indicate that received ISO data buffer has been deallocated. + */ +/*************************************************************************************************/ +void LctrRxIsoComplete(uint8_t numBufs) +{ + lctrIsoDataRxIncAvailBuf(numBufs); +} + +/*************************************************************************************************/ +/*! + * \brief Used to identify and enable the isochronous data path between the host and the + * controller for each connected isochronous or broadcast isochronous stream. + * + * \param handle BIS or CIS handle. + * \param pPktSn Packet sequence number. + * \param pTs Timestamp. + * \param pTimeOffs Time offset. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrReadIsoTxSync(uint16_t handle, uint16_t *pPktSn, uint32_t *pTs, uint32_t *pTimeOffs) +{ + uint8_t status = LL_SUCCESS; + lctrCisCtx_t *pCisCtx; + lctrBisCtx_t *pBisCtx; + + if ((pCisCtx = lctrFindCisByHandle(handle)) != NULL) + { + lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId); + + *pPktSn = pCisCtx->cisEvtCounter; + *pTs = pCigCtx->cigBod.dueUsec; + *pTimeOffs = 0; + } + else if ((pBisCtx = lctrFindBisByHandle(handle)) != NULL) + { + *pPktSn = pBisCtx->pBigCtx->eventCounter * pBisCtx->pBigCtx->bn; + *pTs = pBisCtx->pBigCtx->bod.dueUsec; + *pTimeOffs = 0; + } + else + { + LL_TRACE_WARN1("LctrReadIsoTxSync: handle=%u not found", handle); + status = LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + + return status; +} + +/*************************************************************************************************/ +/*! + * \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. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrSetupIsoDataPath(LlIsoSetupDataPath_t *pSetupDataPath) +{ + uint8_t status = LL_SUCCESS; + lctrCisCtx_t *pCisCtx; + lctrBisCtx_t *pBisCtx; + lctrDataPathCtx_t *pDataPathDir; + + if ((pCisCtx = lctrFindCisByHandle(pSetupDataPath->handle)) != NULL) + { + switch (pSetupDataPath->dpDir) + { + case LL_ISO_DATA_DIR_INPUT: + pDataPathDir = (lctrDataPathCtx_t *) (&pCisCtx->dataPathInCtx); + break; + case LL_ISO_DATA_DIR_OUTPUT: + pDataPathDir = (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) + { + switch (pSetupDataPath->dpDir) + { + case LL_ISO_DATA_DIR_INPUT: + if (pBisCtx->pBigCtx->role == LL_ROLE_SLAVE) + { + status = lctrBisSetDataPath(pBisCtx, pSetupDataPath->dpDir, pSetupDataPath->dpId); + } + else + { + LL_TRACE_WARN1("LctrSetupIsoDataPath: handle=%u invalid input direction for master", pSetupDataPath->handle); + status = 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); + } + else + { + LL_TRACE_WARN1("LctrSetupIsoDataPath: handle=%u invalid output direction for slave", pSetupDataPath->handle); + status = LL_ERROR_CODE_CMD_DISALLOWED; + } + break; + default: + break; + } + } + else + { + LL_TRACE_WARN1("LctrSetupIsoDataPath: handle=%u not found", pSetupDataPath->handle); + status = LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + + return status; +} + +/*************************************************************************************************/ +/*! + * \brief Used to remove the isochronous data path associated with the + * connected isochronous stream or broadcast isochronous stream. + * + * \param handle CIS or BIS handle. + * \param dpDir Direction of data path to remove. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrRemoveIsoDataPath(uint16_t handle, uint8_t dpDir) +{ + uint8_t status = LL_SUCCESS; + lctrCisCtx_t *pCisCtx; + lctrBisCtx_t *pBisCtx; + + if ((pCisCtx = lctrFindCisByHandle(handle)) != NULL) + { + /* Check for validity of parameters before operating on them. */ + 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 (pCisCtx->dataPathOutCtx.id == LL_ISO_DATA_PATH_DISABLED) + { + return LL_ERROR_CODE_CMD_DISALLOWED; + } + } + + if (dpDir | LL_ISO_DATA_PATH_INPUT_BIT) + { + pCisCtx->dataPathInCtx.id = LL_ISO_DATA_PATH_DISABLED; + } + if (dpDir | LL_ISO_DATA_PATH_OUTPUT_BIT) + { + pCisCtx->dataPathOutCtx.id = LL_ISO_DATA_PATH_DISABLED; + } + } + else if ((pBisCtx = lctrFindBisByHandle(handle)) != NULL) + { + pBisCtx->path = LL_ISO_DATA_PATH_DISABLED; + } + else + { + LL_TRACE_WARN1("LctrRemoveIsoDataPath: handle=%u not found", handle); + status = LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + + return status; +} + +/*************************************************************************************************/ +/*! + * \brief Enable ISO Tx test. + * + * \param handle CIS or BIS handle. + * \param pldType Payload length type. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrIsoTxTest(uint16_t handle, uint8_t pldType) +{ + uint8_t status; + lctrCisCtx_t *pCisCtx; + lctrBisCtx_t *pBisCtx; + + if ((pCisCtx = lctrFindCisByHandle(handle)) != NULL) + { + status = lctrCisTxTest(pCisCtx, pldType); + } + else if ((pBisCtx = lctrFindBisByHandle(handle)) != NULL) + { + status = lctrBisTxTest(pBisCtx, pldType); + } + else + { + LL_TRACE_WARN0("LctrIsoTxTest: handle=%u not found"); + return LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + + return status; +} + +/*************************************************************************************************/ +/*! + * \brief Enable ISO Rx test. + * + * \param handle CIS or BIS handle. + * \param pldType Payload length type. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrIsoRxTest(uint16_t handle, uint8_t pldType) +{ + uint8_t status; + lctrCisCtx_t *pCisCtx; + lctrBisCtx_t *pBisCtx; + + if ((pCisCtx = lctrFindCisByHandle(handle)) != NULL) + { + pCisCtx->rxPendInit = (pldType == LL_ISO_TEST_PL_LEN_ZERO) ? FALSE : TRUE; + + pCisCtx->rxTestEnabled = TRUE; + pCisCtx->numRxSuccess = 0; + pCisCtx->numRxMissed = 0; + pCisCtx->numRxFailed = 0; + pCisCtx->isoRxPldType = pldType; + + status = LL_SUCCESS; + } + else if ((pBisCtx = lctrFindBisByHandle(handle)) != NULL) + { + status = lctrBisRxTest(pBisCtx, pldType); + } + else + { + LL_TRACE_WARN0("LctrIsoRxTest: handle=%u not found"); + return LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + + return status; +} + +/*************************************************************************************************/ +/*! + * \brief ISO read test counter. + * + * \param handle CIS or BIS handle. + * \param pStats Pointer to the statistics block. + * + * \return Status code. + */ +/*************************************************************************************************/ +uint8_t LctrIsoReadTestCounter(uint16_t handle, LlIsoTestCtrs_t *pStats) +{ + uint8_t status; + lctrCisCtx_t *pCisCtx; + lctrBisCtx_t *pBisCtx; + + if ((pCisCtx = lctrFindCisByHandle(handle)) != NULL) + { + status = LctrCisReadTestCounters(pCisCtx, pStats); + } + else if ((pBisCtx = lctrFindBisByHandle(handle)) != NULL) + { + status = LctrBisReadTestCounters(pBisCtx, pStats); + } + else + { + LL_TRACE_WARN1("LctrIsoReadTestCounter: handle=%u not found", handle); + status = LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + + return status; +} + +/*************************************************************************************************/ +/*! + * \brief Terminate ISO Rx test. + * + * \param handle CIS or BIS handle. + * \param pStats Pointer to the statistics block. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrIsoTestEnd(uint16_t handle, LlIsoTestCtrs_t *pStats) +{ + uint8_t status; + lctrCisCtx_t *pCisCtx; + lctrBisCtx_t *pBisCtx; + + if ((pCisCtx = lctrFindCisByHandle(handle)) != NULL) + { + if (!pCisCtx->rxTestEnabled && + !pCisCtx->txTestEnabled) + { + LL_TRACE_WARN0("Invalid ISO Test state, test mode must be enabled"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + if (pCisCtx->rxTestEnabled) + { + status = LctrCisReadTestCounters(pCisCtx, pStats); + pCisCtx->rxTestEnabled = FALSE; + + /* Counters will be reset on re-initialization of Rx test. */ + } + if (pCisCtx->txTestEnabled) + { + pCisCtx->txTestEnabled = FALSE; + } + } + else if ((pBisCtx = lctrFindBisByHandle(handle)) != NULL) + { + status = LctrBisReadTestCounters(pBisCtx, pStats); + + pBisCtx->test.term = TRUE; + } + else + { + LL_TRACE_WARN1("LctrIsoTestEnd: handle=%u not found", handle); + status = LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + + return status; +} + +/*************************************************************************************************/ +/*! + * \brief Read ISO Link Quality action. + * + * \param handle CIS or BIS handle. + * \param pStats Storage for statistics. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LctrReadIsoLinkQual(uint16_t handle, LlIsoLinkQual_t *pStats) +{ + lctrCisCtx_t *pCisCtx; + lctrBisCtx_t *pBisCtx; + if ((pCisCtx = lctrFindCisByHandle(handle)) != NULL) + { + memcpy(pStats, &pCisCtx->isoLinkQualStats, sizeof(LlIsoLinkQual_t)); + return LL_SUCCESS; + } + else if ((pBisCtx = lctrFindBisByHandle(handle)) != NULL) + { + return LL_SUCCESS; + } + else + { + LL_TRACE_WARN1("LctrReadIsoLinkQual: handle=%u not found", handle); + return LL_ERROR_CODE_UNKNOWN_CONN_ID; + } +} + +/*************************************************************************************************/ +/*! + * \brief ISO event complete enable. + * + * \param enable Set to TRUE to enable, FALSE to disable. + * + * Enable or disable reports about the scanners from which an advertiser receives scan requests. + */ +/*************************************************************************************************/ +void LlIsoEventCompleteEnable(uint8_t enable) +{ + lmgrCb.sendIsoCmplEvt = enable; +} + +/*************************************************************************************************/ +/*! + * \brief Notify host ISO Event completion. + * + * \param handle CIG or BIG Handle. + * \param evtCtr Event Counter. + */ +/*************************************************************************************************/ +void lctrNotifyHostIsoEventComplete(uint8_t handle, uint32_t evtCtr) +{ + LlIsoEventCmplInd_t evt; + + evt.hdr.param = handle; + evt.hdr.event = LL_ISO_EVT_CMPL_IND; + evt.hdr.status = LL_SUCCESS; + + evt.handle = handle; + evt.evtCtr = evtCtr; + + LL_TRACE_INFO1("### LlEvent ### LL_ISO_EVT_CMPL_IND, handle=%u", handle); + + LmgrSendEvent((LlEvt_t *)&evt); +} + +/*************************************************************************************************/ +/*! + * \brief Send Codec SDU data. + * + * \param handle Stream ID. + */ +/*************************************************************************************************/ +void lctrIsoSendCodecSdu(uint16_t handle) +{ + 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; + } + + lctrIsoHdr_t hdr = + { + .handle = handle, + .pb = LCTR_PB_COMP, + .tsFlag = TRUE, + .len = len, + .ts = 0, + .pktSn = pktCtr, + .sduLen = len, + .ps = LCTR_PS_VALID + }; + + lctrIsoPackHdr(pSduBuf, &hdr); + LctrTxIso(pSduBuf); +} + +/*************************************************************************************************/ +/*! + * \brief Setup ISO data path. + * + * \param pSetupDataPath Data path setup parameters. + * \param pDataPathCtx Generic data path context. + */ +/*************************************************************************************************/ +uint8_t lctrSetupIsoDataPath(LlIsoSetupDataPath_t *pSetupDataPath, lctrDataPathCtx_t *pDataPathCtx) +{ + switch (pSetupDataPath->dpDir) + { + case LL_ISO_DATA_DIR_INPUT: + { + if (pSetupDataPath->dpId == pDataPathCtx->in.id) + { + return LL_SUCCESS; + } + + /* No teardown needed. */ + pDataPathCtx->in.id = pSetupDataPath->dpId; + /* No setup needed. */ + break; + } + + case LL_ISO_DATA_DIR_OUTPUT: + { + if (pSetupDataPath->dpId == pDataPathCtx->out.id) + { + return LL_SUCCESS; + } + + lctrIsoOutDataPathClear(&pDataPathCtx->out); + pDataPathCtx->out.id = pSetupDataPath->dpId; + lctrIsoOutDataPathSetup(&pDataPathCtx->out); + break; + } + + default: + LL_TRACE_ERR1("Invalid value dpDir=%u", pSetupDataPath->dpDir); + break; + } + + return LL_SUCCESS; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_iso_data.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_iso_data.c new file mode 100644 index 0000000000..424a2ee589 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_iso_data.c @@ -0,0 +1,1181 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller data path implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_iso.h" +#include "lctr_pdu_iso.h" +#include "lctr_int_cis.h" +#include "ll_math.h" +#include "wsf_assert.h" +#include "wsf_cs.h" +#include "wsf_math.h" +#include "wsf_msg.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include "hci_defs.h" +#include "pal_bb.h" +#include + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*! \brief Free list of Tx buffer descriptors. */ +static wsfQueue_t lctrIsoTxBufDescQ; + +/*! \brief Completed transmit buffer. */ +static uint8_t *pLctrTxCompBuf; + +/*! \brief Completed transmit buffer handle ID. */ +static wsfHandlerId_t lctrTxCompBufHandlerId; + +/*************************************************************************************************/ +/*! + * \brief Assemble CIS Data PDU. + * + * \param pIsoHdr ISO header. + * \param pBuf Buffer to pack the Data PDU header. + * \param llid CIS LLID + */ +/*************************************************************************************************/ +static void lctrAssembleCisDataPdu(lctrIsoHdr_t *pIsoHdr, uint8_t *pBuf, uint8_t llid) +{ + /* All additional fields must be zero'ed since flow control bits will be or'ed in at transmit. */ + lctrCisDataPduHdr_t dataHdr = { 0 }; + + dataHdr.llid = llid; + dataHdr.len = pIsoHdr->sduLen; + + lctrCisPackDataPduHdr(pBuf, &dataHdr); +} + + +/*************************************************************************************************/ +/*! + * \brief Initialize the transmit memory resources. + * + * \param pFreeMem Pointer to free memory. + * \param freeMemSize Size of pFreeMem. + * + * \return Amount of free memory consumed. + */ +/*************************************************************************************************/ +uint16_t lctrIsoTxInitMem(uint8_t *pFreeMem, uint32_t freeMemSize) +{ + pLctrTxCompBuf = NULL; + + WSF_ASSERT(pLctrRtCfg->numIsoTxBuf); + WSF_ASSERT(pLctrRtCfg->maxIsoSduLen); + + uint8_t *pAvailMem = pFreeMem; + + const uint16_t descSize = sizeof(lctrIsoTxBufDesc_t) + (LL_MAX_FRAG * sizeof(((lctrIsoTxBufDesc_t *)0)->frag[0])); + + LL_TRACE_INFO2(" RAM: %u x %u bytes -- Tx buffer descriptors", pLctrRtCfg->numIsoTxBuf, sizeof(void *) + descSize); + + lctrIsoTxBufDescQ.pHead = NULL; + lctrIsoTxBufDescQ.pTail = NULL; + + unsigned int i; + + for (i = 0; i < pLctrRtCfg->numIsoTxBuf; i++) + { + lctrIsoTxBufDesc_t *pDesc; + + if (((uint32_t)pAvailMem) & 3) + { + /* Align to next word. */ + pAvailMem = (uint8_t *)(((uint32_t)pAvailMem & ~3) + sizeof(uint32_t)); + } + + /* Allocate memory. */ + pDesc = (lctrIsoTxBufDesc_t *)pAvailMem; + pAvailMem += (2 * sizeof(uint32_t)) + descSize; /* wsfMsg_t header is at most 2 words */ + + if (((uint32_t)(pAvailMem - pFreeMem)) > freeMemSize) + { + return 0; + } + + /* Add to free list. */ + WsfQueueEnq(&lctrIsoTxBufDescQ, pDesc); + } + + return (pAvailMem - pFreeMem); +} + +/*************************************************************************************************/ +/*! + * \brief Allocate a Tx buffer descriptor. + * + * \return A Tx buffer descriptor, NULL if allocation fails. + */ +/*************************************************************************************************/ +lctrIsoTxBufDesc_t *lctrAllocIsoTxBufDesc(void) +{ + uint8_t *pElem; + + if ((pElem = WsfQueueDeq(&lctrIsoTxBufDescQ)) == NULL) + { + return NULL; + } + + pElem += (2 * sizeof(uint32_t)); /* hide header */ + + return (lctrIsoTxBufDesc_t *)pElem; +} + +/*************************************************************************************************/ +/*! + * \brief Free a Tx buffer descriptor. + * + * \param pDesc Pointer to a Tx buffer descriptor. + */ +/*************************************************************************************************/ +void lctrFreeIsoTxBufDesc(lctrIsoTxBufDesc_t *pDesc) +{ + uint8_t *pElem = (uint8_t *)pDesc; + pElem -= (2 * sizeof(uint32_t)); /* recover header */ + + WsfQueueEnq(&lctrIsoTxBufDescQ, pElem); +} + +/*************************************************************************************************/ +/*! + * \brief Queue data PDU onto ARQ queue. + * + * \param pCisCtx CIS context. + * \param pIsoHdr ISO header. + * \param pIsoBuf ISO buffer. + */ +/*************************************************************************************************/ +void lctrCisTxDataPduQueue(lctrCisCtx_t *pCisCtx, lctrIsoHdr_t *pIsoHdr, uint8_t *pIsoBuf) +{ + uint16_t fragOffset = 0; + uint16_t isoLen = pIsoHdr->sduLen; + uint16_t fragLen = pCisCtx->localDataPdu.maxTxLen; + + lctrIsoTxBufDesc_t *pDesc; + + if ((pDesc = lctrAllocIsoTxBufDesc()) == NULL) + { + LL_TRACE_ERR1("Failed to allocate transmit buffer descriptor: cisHandle=%u", pIsoHdr->handle); + WsfMsgFree(pIsoBuf); + if (pCisCtx->txTestEnabled == FALSE) + { + uint16_t handle = pIsoHdr->handle; + uint16_t numSdu = 1; + lmgrPersistCb.sendIsoCompCback(1, &handle, &numSdu); + } + lctrIsoSduTxIncAvailBuf(); + + lctrNotifyHostHwErrInd(LL_ERROR_CODE_MEM_CAP_EXCEEDED); + return; + } + + if (fragLen >= pIsoHdr->sduLen) + { + fragLen = pIsoHdr->sduLen; + } + + pDesc->isoLen = pIsoHdr->sduLen; + pDesc->fragLen = fragLen; + pDesc->fragCnt = 0; + + /* Get the start of the buffer. */ + pDesc->pIsoSdu = pIsoBuf; + pIsoBuf += LCTR_GET_ISO_DATA_HDR_LEN(pIsoHdr); + pDesc->pPduBuf = pIsoBuf; + uint8_t fragCnt = 0; + + uint8_t llid; + + do + { + const uint16_t dataRem = isoLen - fragOffset; + const uint16_t fragSize = WSF_MIN(dataRem, fragLen); + + if (pCisCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED) + { + llid = (fragSize == dataRem) ? LL_LLID_ISO_UNF_END_PDU : LL_LLID_ISO_UNF_CONT_PDU; + } + else + { + llid = LL_LLID_ISO_FRA_PDU; + } + + pIsoHdr->sduLen = fragSize; + lctrAssembleCisDataPdu(pIsoHdr, pDesc->frag[fragCnt].hdr, llid); + pDesc->frag[fragCnt].hdrLen = LL_DATA_HDR_LEN; + + if (lctrPktEncryptHdlr && lctrPktEncryptHdlr(&pCisCtx->bleData.chan.enc, pDesc->frag[fragCnt].hdr, pIsoBuf, pDesc->frag[fragCnt].trl)) + { + pDesc->frag[fragCnt].trlLen = LL_DATA_MIC_LEN; + + #if (LL_ENABLE_TESTER) + pDesc->frag[fragCnt].trl[0] ^= (llTesterCb.pktMic >> 0) & 0xFF; + pDesc->frag[fragCnt].trl[1] ^= (llTesterCb.pktMic >> 8) & 0xFF; + pDesc->frag[fragCnt].trl[2] ^= (llTesterCb.pktMic >> 16) & 0xFF; + pDesc->frag[fragCnt].trl[3] ^= (llTesterCb.pktMic >> 24) & 0xFF; + #endif + } + else + { + pDesc->frag[fragCnt].trlLen = 0; + } + + fragOffset += fragSize; + pIsoBuf += fragSize; + fragCnt++; + } + while (fragOffset < isoLen); + + WsfMsgEnq(&pCisCtx->txArqQ, pIsoHdr->handle, (uint8_t *)pDesc); +} + +/*************************************************************************************************/ +/*! + * \brief Get top element in Tx queue. + * + * \param pCisCtx CIS context. + * \param pDescs Storage for BB descriptors. + * + * \return Number of BB descriptors. + */ +/*************************************************************************************************/ +uint8_t lctrCisTxQueuePeek(lctrCisCtx_t *pCisCtx, PalBbBleTxBufDesc_t *pDescs) +{ + wsfHandlerId_t handlerId; + uint8_t *pTxBuf; + uint8_t descCnt = 0; + + /* Do not remove from ARQ until acknowledged by peer. */ + pTxBuf = WsfMsgPeek(&pCisCtx->txArqQ, &handlerId); + if (pTxBuf != NULL) + { + /*** Send Data PDU ***/ + + lctrIsoTxBufDesc_t *pDesc = (lctrIsoTxBufDesc_t *)pTxBuf; + uint8_t fragCnt = pDesc->fragCnt; + uint16_t fragSize = pDesc->fragLen; + uint16_t fragOff = fragSize * fragCnt; + + if ((fragOff + fragSize) > pDesc->isoLen) + { + fragSize = pDesc->isoLen - fragOff; + } + pDescs[0].len = pDesc->frag[fragCnt].hdrLen; + pDescs[0].pBuf = pDesc->frag[fragCnt].hdr; + pDescs[1].len = fragSize; + pDescs[1].pBuf = pDesc->pPduBuf + fragOff; + descCnt = 2; + if (pDesc->frag[fragCnt].trlLen) + { + pDescs[2].len = pDesc->frag[fragCnt].trlLen; + pDescs[2].pBuf = pDesc->frag[fragCnt].trl; + descCnt = 3; + } + } + + return descCnt; +} + +/*************************************************************************************************/ +/*! + * \brief Pop top element from Tx queue. + * + * \param pCisCtx CIS context. + * + * \return TRUE if element popped. + */ +/*************************************************************************************************/ +bool_t lctrCisTxQueuePop(lctrCisCtx_t *pCisCtx) +{ + wsfHandlerId_t handlerId; + uint8_t *pBuf; + + WSF_ASSERT(pLctrTxCompBuf == NULL); + + /* Remove last transmitted PDU. */ + if ((pBuf = WsfMsgPeek(&pCisCtx->txArqQ, &handlerId)) != NULL) + { + lctrIsoTxBufDesc_t *pDesc = (lctrIsoTxBufDesc_t *)pBuf; + uint16_t fragSize = pDesc->fragLen; + + if ((fragSize * (pDesc->fragCnt + 1)) >= pDesc->isoLen) /* last fragment */ + { + /* Store buffer for post setup cleanup. */ + pLctrTxCompBuf = pBuf; + lctrTxCompBufHandlerId = handlerId; + + WsfMsgDeq(&pCisCtx->txArqQ, &handlerId); + } + else + { + /* Move to next fragment. */ + pDesc->fragCnt++; + } + return TRUE; + } + + return FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Pop top element from Tx queue. + * + * \param pCisCtx Connection context. + */ +/*************************************************************************************************/ +void lctrCisTxQueuePopCleanup(lctrCisCtx_t *pCisCtx) +{ + if (pLctrTxCompBuf) + { + lctrIsoTxBufDesc_t *pDesc = (lctrIsoTxBufDesc_t *)pLctrTxCompBuf; + + WsfMsgFree(pDesc->pIsoSdu); + lctrFreeIsoTxBufDesc(pDesc); + lctrIsoSduTxIncAvailBuf(); + pCisCtx->numTxComp++; + + pLctrTxCompBuf = NULL; + + WsfSetEvent(lmgrPersistCb.handlerId, (1 << LCTR_EVENT_ISO_TX_COMPLETE)); + } +} + +/*************************************************************************************************/ +/*! + * \brief Clear Tx queue. + * + * \param pCisCtx CIS context. + * + * \return Number of freed buffers. + */ +/*************************************************************************************************/ +uint8_t lctrCisTxQueueClear(lctrCisCtx_t *pCisCtx) +{ + uint8_t *pBuf; + uint8_t numTxBufs = 0; + wsfHandlerId_t handlerId; + + /* Clear the pending Tx buffer. */ + if (pLctrTxCompBuf) + { + lctrCisTxQueuePopCleanup(pCisCtx); + } + + /* Clear the rest of the Tx buffer. */ + while ((pBuf = WsfMsgDeq(&pCisCtx->txArqQ, &handlerId)) != NULL) + { + lctrIsoTxBufDesc_t *pDesc = (lctrIsoTxBufDesc_t *)pBuf; + + WsfMsgFree(pDesc->pIsoSdu); + + lctrFreeIsoTxBufDesc(pDesc); + + lctrIsoSduTxIncAvailBuf(); + numTxBufs++; + } + + return numTxBufs; +} + +/*************************************************************************************************/ +/*! + * \brief Allocate a receive data PDU buffer. + * + * \param maxRxLen Maximum receive length. + * + * \return Pointer to the start of the PDU data buffer. + */ +/*************************************************************************************************/ +uint8_t *lctrCisRxPduAlloc(uint16_t maxRxLen) +{ + /* 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; + + uint8_t *pBuf; + + /* Include ISO header. */ + if ((pBuf = WsfMsgAlloc(HCI_ISO_DL_MAX_LEN + allocLen)) != NULL) + { + /* Return start of data PDU. */ + pBuf += LCTR_CIS_DATA_PDU_START_OFFSET + HCI_ISO_DL_MAX_LEN; + } + + return pBuf; +} + +/*************************************************************************************************/ +/*! + * \brief Free a receive CIS data PDU buffer. + * + * \param pBuf PDU data buffer to free. + */ +/*************************************************************************************************/ +void lctrCisRxPduFree(uint8_t *pBuf) +{ + /* Recover headroom, assume buffer starts at the beginning of the data PDU. */ + pBuf -= (LCTR_CIS_DATA_PDU_START_OFFSET + HCI_ISO_DL_MAX_LEN); + + WsfMsgFree(pBuf); +} + +/*************************************************************************************************/ +/*! + * \brief Enqueue a receive data PDU buffer. + * + * \param pBuf PDU data buffer to queue. + * \param eventCounter Event counter. + * \param cisHandle Connection handle. + */ +/*************************************************************************************************/ +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); + + /* Queue LE Data PDU. */ + WsfMsgEnq(&lmgrIsoCb.rxDataQ, cisHandle, pBuf); + WsfSetEvent(lmgrPersistCb.handlerId, (1 << LCTR_EVENT_CIS_RX_PENDING)); +} + +/*************************************************************************************************/ +/*! + * \brief Dequeue a receive data PDU buffer. + * + * \param pCisHandle Storage for connection handle. + * + * \return Pointer to the start of the PDU data buffer. + */ +/*************************************************************************************************/ +uint8_t *lctrCisRxDeq(uint16_t *pCisHandle) +{ + uint8_t *pBuf; + wsfHandlerId_t handlerId; + + if ((pBuf = WsfMsgDeq(&lmgrIsoCb.rxDataQ, &handlerId)) != NULL) + { + /* Return start of data PDU. */ + pBuf += LCTR_CIS_DATA_PDU_START_OFFSET; + + *pCisHandle = (uint16_t)handlerId; + } + + return pBuf; +} + +/*************************************************************************************************/ +/*! + * \brief Enqueue a receive data PDU buffer for a connection as a ISO message. + * + * \param pOutDataPathCtx Datapath output context. + * \param handle ISO handle. + * \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. + * + */ +/*************************************************************************************************/ +bool_t lctrIsoRxConnEnq(lctrOutDataPathCtx_t *pOutDataPathCtx, uint16_t handle, uint8_t *pBuf) +{ + switch (pOutDataPathCtx->id) + { + case LL_ISO_DATA_PATH_HCI: + WsfMsgEnq(&pOutDataPathCtx->cfg.hci.rxDataQ, handle, pBuf); + pOutDataPathCtx->cfg.hci.numRxPend++; + /* TODO optimize counter, accounting upon allocation. */ + lctrIsoDataRxDecAvailBuf(); + return TRUE; + + case LL_ISO_DATA_PATH_VS: + default: + return FALSE; + } +} + +/*************************************************************************************************/ +/*! + * \brief Dequeue a receive data PDU buffer for a connection as a ISO message. + * + * \param pOutCtx Output context. + * + * \return Pointer to the start of the ISO message. + * + * \note Returned pointer must be freed with WsfMsgFree(). + */ +/*************************************************************************************************/ +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. + * + * \param pOutCtx Output datapath context. + */ +/*************************************************************************************************/ +void lctrIsoOutDataPathSetup(lctrOutDataPathCtx_t *pOutCtx) +{ + switch (pOutCtx->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. */ + break; + + default: + /* No action. */ + break; + } +} + +/*************************************************************************************************/ +/*! + * \brief Clear a datapath context. + * + * \param pOutCtx Output datapath context. + */ +/*************************************************************************************************/ +void lctrIsoOutDataPathClear(lctrOutDataPathCtx_t *pOutCtx) +{ + 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); + lctrIsoDataRxIncAvailBuf(1); + } + break; + } + + case LL_ISO_DATA_PATH_VS: + /* No action. */ + break; + + default: + /* No action. */ + break; + } +} + +/*************************************************************************************************/ +/*! + * \brief Clear a ISOAL receive context. + * + * \param pRxCtx ISOAL receive context + * \param framing Framing scheme. + */ +/*************************************************************************************************/ +void lctrIsoalRxDataPathClear(lctrIsoalRxCtx_t *pRxCtx, uint8_t framing) +{ + uint8_t *pSduBuf; + uint8_t handlerId; + if (framing == LL_ISO_PDU_TYPE_UNFRAMED) + { + while ((pSduBuf = WsfMsgDeq(&pRxCtx->data.unframed.pendSduQ, &handlerId)) != NULL) + { + WsfMsgFree(pSduBuf); + } + } + else /* LL_ISO_PDU_TYPE_FRAMED */ + { + if (pRxCtx->pPendSduBuf) + { + WsfMsgFree(pRxCtx->pPendSduBuf); + pRxCtx->pPendSduBuf = NULL; + } + } + + pRxCtx->pduFlushed = FALSE; + pRxCtx->rxState = LL_ISO_SDU_STATE_NEW; +} + +/*************************************************************************************************/ +/*! + * \brief Generate transmit ISO test data. + * + * \param handle Connection handle. + * \param pldType Payload length type. + * \param maxSdu Max SDU length. + * \param pktCtr Packet counter. + * + * \return Pointer to an HCI ISO SDU. + * + * Initialization of ISO test data will allocate and fill a ISO SDU to accommodate any payload + * type. The LL will modify the length and payload (i.e. Packet Counter) as needed. + */ +/*************************************************************************************************/ +uint8_t *lctrGenerateIsoTestData(uint16_t handle, LlIsoPldType_t pldType, uint16_t maxSdu, uint32_t pktCtr) +{ + uint8_t *pSdu; + + if ((pSdu = lctrTxIsoDataPduAlloc()) == NULL) + { + LL_TRACE_WARN0("!!! Failed to generate a ISO Test Data SDU"); + return NULL; + } + + uint8_t *pBuf = pSdu; + uint16_t len; + + switch (pldType) + { + case LL_ISO_PLD_TYPE_VAR_LEN: + len = LlMathRandNum() % maxSdu; /* TODO Use portable mod routine */ + /* Ensure minimum SDU length includes mandatory payload. */ + len = WSF_MAX(len, sizeof(uint32_t)); + break; + + case LL_ISO_PLD_TYPE_MAX_LEN: + /* Ensure minimum SDU length includes mandatory payload. */ + len = WSF_MAX(maxSdu, sizeof(uint32_t)); + break; + + case LL_ISO_PLD_TYPE_ZERO_LEN: + len = 0; + break; + + default: + { + LL_TRACE_ERR1("Invalid value pldType=%u", pldType); + len = 0; + break; + } + } + + /* Pack ISO header. */ + lctrIsoHdr_t isoHdr; + + isoHdr.handle = handle; + isoHdr.pb = LCTR_PB_COMP; + isoHdr.tsFlag = 0; + isoHdr.len = len; + isoHdr.pktSn = 0; + isoHdr.sduLen = len; + isoHdr.ps = LCTR_PS_VALID; + + pBuf += lctrIsoPackHdr(pBuf, &isoHdr); + + if (len > 0) + { + /* Fill mandatory payload (do not advance pBuf). */ + UINT32_TO_BUF(pBuf, pktCtr); + + /* Fill VS payload (byte content is offset number). */ + for (unsigned int i = sizeof(uint32_t); i < len; i++) + { + pBuf[i] = i; + } + } + + return pSdu; +} + +/*************************************************************************************************/ +/*! + * \brief Validate received ISO test data. + * + * \param pPld Payload start buffer. + * \param actLen Length of payload + * \param pRxStats Rx statistics. + * \param pldType Payload length type. + * \param expMaxSdu Expected max SDU length. + * \param expPldCtr Expected payload counter. + */ +/*************************************************************************************************/ +void lctrValidateIsoTestData(uint8_t *pPld, uint8_t actLen, LlIsoTestCtrs_t *pRxStats, uint8_t pldType, uint16_t expMaxSdu, uint32_t expPldCtr) +{ + uint32_t actPldCtr; + + /* Parse transmitted payload counter. */ + switch (pldType) + { + case LL_ISO_PLD_TYPE_VAR_LEN: + case LL_ISO_PLD_TYPE_MAX_LEN: + BSTREAM_TO_UINT32(actPldCtr, pPld); + break; + case LL_ISO_PLD_TYPE_ZERO_LEN: + default: + actPldCtr = 0; + break; + } + + /* Validate received SDU. */ + switch (pldType) + { + case LL_ISO_PLD_TYPE_ZERO_LEN: + if (actLen != 0) + { + LL_TRACE_WARN1("lctrValidateIsoTestData: wrong length, actLen=%u expLen=0", actLen); + pRxStats->numFailed++; + } + else + { + pRxStats->numSuccess++; + } + break; + case LL_ISO_PLD_TYPE_VAR_LEN: + if ((actLen < sizeof(uint32_t)) || (actLen > expMaxSdu)) + { + LL_TRACE_WARN2("lctrValidateIsoTestData: wrong length, actLen=%u expLen=[0..%u]", actLen, expMaxSdu); + pRxStats->numFailed++; + } + else if (actPldCtr != expPldCtr) + { + LL_TRACE_WARN2("lctrValidateIsoTestData: wrong payload counter, actPldCtr[15:0]=%u expPldCtr[15:0]=%u", actPldCtr, expPldCtr); + pRxStats->numFailed++; + } + else + { + pRxStats->numSuccess++; + } + break; + case LL_ISO_PLD_TYPE_MAX_LEN: + if (actLen != expMaxSdu) + { + LL_TRACE_WARN2("lctrValidateIsoTestData: wrong length, actLen=%u expLen=%u", actLen, expMaxSdu); + pRxStats->numFailed++; + } + else if (actPldCtr != expPldCtr) + { + LL_TRACE_WARN2("lctrValidateIsoTestData: wrong payload counter, actPldCtr[15:0]=%u expPldCtr[15:0]=%u", actPldCtr, expPldCtr); + pRxStats->numFailed++; + } + else + { + pRxStats->numSuccess++; + } + break; + default: + LL_TRACE_WARN1("lctrValidateIsoTestData: invalid parameter, pldType=%u", pldType); + break; + } +} + +/*************************************************************************************************/ +/*! + * \brief Allocate a transmit ISO Data PDU buffer. + * + * \return Pointer to the start of the ISO Data PDU buffer, NULL if allocation failed. + */ +/*************************************************************************************************/ +uint8_t *lctrTxIsoDataPduAlloc(void) +{ + uint8_t *pPdu; + + const uint32_t allocLen = HCI_ISO_HDR_LEN + HCI_ISO_DL_MAX_LEN + pLctrRtCfg->maxIsoSduLen + BB_DATA_PDU_TAILROOM; + + /* 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); + } + + return pPdu; +} + +/*************************************************************************************************/ +/*! + * \brief Assemble framed PDU. + * + * \param pIsoalTxCtx Transmit ISOAL context. + * \param pPduBuf PDU buffer. + * \param maxPduLen Maximum PDU length. + * + * \return Total size of assembled PDU. + */ +/*************************************************************************************************/ +uint8_t lctrAssembleTxFramedPdu(lctrIsoalTxCtx_t *pIsoalTxCtx, uint8_t *pPduBuf, uint16_t maxPduLen) +{ + wsfQueue_t *pSduQ = &pIsoalTxCtx->pendingSduQ; + + uint8_t handlerId; /* Temp variable for the wsfMsg. */ + uint8_t totalTx = 0; + uint16_t remLen = maxPduLen; + lctrIsoSegHdr_t segHdr = { 0 }; + uint8_t segHdrLen = 0; + uint8_t *pFreeData = NULL; + + /* Set offset of pPduBuf */ + pPduBuf += HCI_ISO_HDR_LEN + HCI_ISO_DL_MIN_LEN; + + /*** Loop through and pack SDUs. ***/ + + while (remLen) + { + uint8_t *pSduBuf = WsfMsgPeek(pSduQ, &handlerId); + + /* The buffer is empty, process the completed PDU */ + if (pSduBuf == NULL) + { + break; + } + + lctrIsoHdr_t isoHdr; + + /*** Disassemble ISO packet. ***/ + + lctrIsoUnpackHdr(&isoHdr, pSduBuf); + + pSduBuf += LCTR_GET_ISO_DATA_HDR_LEN(&isoHdr); + segHdrLen = LL_DATA_HDR_LEN; + + /* If this is a segmented SDU, continue from the last segment. */ + if (pIsoalTxCtx->sduOffset) + { + /* Resume buffer at sduOffset. */ + pSduBuf += pIsoalTxCtx->sduOffset; + isoHdr.sduLen -= pIsoalTxCtx->sduOffset; + + /* Set continuation bit. */ + segHdr.sc = 1; + } + else + { + segHdr.sc = 0; + segHdrLen += LL_ISO_SEG_TO_LEN; + } + + /*** Compute segment parameters. ***/ + + /* There is enough room for the entire SDU. */ + if (remLen >= (isoHdr.sduLen + segHdrLen)) + { + segHdr.len = isoHdr.sduLen; + segHdr.cmplt = 1; + if (segHdr.sc == 0) + { + /* TODO: put in time offset. */ + segHdr.toffs = 0x1337; + } + + /* Reset pduOffset and update remaining length. */ + pIsoalTxCtx->sduOffset = 0; + remLen -= segHdr.len + segHdrLen; + + /* Pop off completed SDU. */ + pFreeData = WsfMsgDeq(pSduQ, &handlerId); + pIsoalTxCtx->pendQueueSize--; + pIsoalTxCtx->compSdu++; + } + else + { + /* If it cannot fit at least one effective (data) byte, finish packing here. */ + if (remLen < (segHdrLen + 1)) + { + break; + } + + segHdr.len = remLen - segHdrLen; + segHdr.cmplt = 0; + if (segHdr.sc == 0) + { + /* TODO: put in time offset. */ + segHdr.toffs = 0x1337; + } + + /* Save offset. */ + pIsoalTxCtx->sduOffset += segHdr.len; + remLen = 0; /* We filled as much as we can, no need to track it anymore. */ + } + + /*** Pack PDU ***/ + + /* Pack buffer with seg header */ + pPduBuf += lctrIsoPackSegHdr(pPduBuf, &segHdr); + + /* Pack data into buffer. */ + uint8_t sduDataLen = segHdr.len; + memcpy(pPduBuf, pSduBuf, sduDataLen); + pPduBuf += sduDataLen; + + /* Free buffer. */ + if (pFreeData) + { + WsfMsgFree(pFreeData); + pFreeData = NULL; + } + + totalTx += sduDataLen + segHdrLen; + } + + return totalTx; +} + +/*************************************************************************************************/ +/*! + * \brief Allocate a receive ISO SDU buffer. + * + * \return Pointer to the start of the ISO Data PDU buffer, NULL if allocation failed. + */ +/*************************************************************************************************/ +static uint8_t *lctrRxSduAlloc(void) +{ + uint8_t *pSdu; + + const uint32_t allocLen = HCI_ISO_HDR_LEN + HCI_ISO_DL_MAX_LEN + pLctrRtCfg->maxIsoSduLen + BB_DATA_PDU_TAILROOM; + + /* Use LL_ISO_PDU_MAX_LEN to ensure use of data buffers located in the large pool. */ + if ((pSdu = (uint8_t*)WsfMsgAlloc(allocLen)) != NULL) + { + lctrIsoDataRxDecAvailBuf(); + } + + return pSdu; +} + +/*************************************************************************************************/ +/*! + * \brief Queue the received SDU into the pending queue. + * + * \param pRxCtx ISOAL receive context. + * \param pSdu SDU buffer. + * \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) +{ + /* Save data for head packet. */ + /* pRxCtx->data.unframed.pendSduIsoHdr.ps = 0; */ /* Should be done in calling function. */ + pRxCtx->data.unframed.curLen += dataLen; + + WsfMsgEnq(&pRxCtx->data.unframed.pendSduQ, handle, pSdu); + + /* 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) + { + uint8_t *pHeadPkt; + uint8_t handlerId; + lctrIsoHdr_t isoHdr = {0}; + + pHeadPkt = WsfMsgPeek(&pRxCtx->data.unframed.pendSduQ, &handlerId); + WSF_ASSERT(pHeadPkt); + + lctrIsoUnpackHdr(&isoHdr, pHeadPkt); + isoHdr.pktSn = pRxCtx->packetSequence++; + 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); + + /* Clean up context */ + pRxCtx->data.unframed.curLen = 0; + pRxCtx->data.unframed.ps = 0; + return TRUE; + } + + return FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Assemble received framed SDU(s) from PDU. + * + * \param pIsoalRxCtx Receive ISOAL control block. + * \param pRxQueue Receive queue. + * \param handle CIS/BIS Handle. + * \param pIsoBuf ISO data buffer. + * \param len Length of data buffer. + * + * \return Total number of SDUs queued. + */ +/*************************************************************************************************/ +uint8_t lctrAssembleRxFramedSdu(lctrIsoalRxCtx_t *pIsoalRxCtx, wsfQueue_t *pRxQueue, + uint16_t handle, uint8_t *pIsoBuf, uint8_t len) +{ + uint8_t totalSduQueued = 0; + + /* Last PDU was flushed. SDU data is lost and will be flushed. */ + if (pIsoalRxCtx->pduFlushed) + { + if (pIsoalRxCtx->pPendSduBuf) + { + /* Flush SDU. */ + WsfMsgFree(pIsoalRxCtx->pPendSduBuf); + pIsoalRxCtx->pPendSduBuf = NULL; + } + pIsoalRxCtx->pduFlushed = FALSE; + return 0; + } + + uint8_t *pDataBuf = pIsoBuf + LL_DATA_HDR_LEN; + uint8_t *pSduBuf; + + uint8_t remLen = len; + + lctrIsoSegHdr_t segHdr = { 0 }; + + while (remLen > 0) + { + uint8_t hdrLen = lctrIsoUnpackSegHdr(&segHdr, pDataBuf); + pDataBuf += hdrLen; + + if (segHdr.sc == 0) + { + segHdr.len -= LL_ISO_SEG_TO_LEN; + } + + switch (pIsoalRxCtx->rxState) + { + case LL_ISO_SDU_STATE_NEW: + { + if ((pIsoalRxCtx->pPendSduBuf = lctrRxSduAlloc()) == NULL) + { + LL_TRACE_WARN1("Unable to allocate framed Rx buffer, handle=%u", handle); + continue; + } + + /* Move pointer to start of data buffer. */ + pIsoalRxCtx->rxSduOffset = LCTR_ISO_SDU_DATA_START_OFFSET; /* Start at the data buffer, save space for Dataload. */ + pSduBuf = pIsoalRxCtx->pPendSduBuf + pIsoalRxCtx->rxSduOffset; + + switch (segHdr.sc) + { + case HCI_ISOAL_SEG_HDR_SC_START: + pIsoalRxCtx->data.framed.timeOffset = segHdr.toffs; + break; + + case HCI_ISOAL_SEG_HDR_SC_CONT: + default: + LL_TRACE_WARN1("Missed start of segmentation; dropping packet, handle=%u", handle); + WsfMsgFree(pIsoalRxCtx->pPendSduBuf); + pIsoalRxCtx->pPendSduBuf = NULL; + pDataBuf += segHdr.len; + remLen -= hdrLen + segHdr.len; + continue; + } + break; + } + + case LL_ISO_SDU_STATE_CONT: + { + pSduBuf = pIsoalRxCtx->pPendSduBuf + pIsoalRxCtx->rxSduOffset; + + switch (segHdr.sc) + { + case HCI_ISOAL_SEG_HDR_SC_CONT: + break; + + case HCI_ISOAL_SEG_HDR_SC_START: + default: + LL_TRACE_WARN1("Expected continuation bit but got start bit; dropping packet, handle=%u", handle); + WsfMsgFree(pIsoalRxCtx->pPendSduBuf); + pIsoalRxCtx->pPendSduBuf = NULL; + pDataBuf += segHdr.len; + remLen -= hdrLen + segHdr.len; + pIsoalRxCtx->rxState = LL_ISO_SDU_STATE_NEW; + continue; + } + break; + } + + default: + LL_TRACE_WARN2("Unknown ISOAL state, handle=%u state=%u", handle, pIsoalRxCtx->rxState); + if (pIsoalRxCtx->pPendSduBuf) + { + WsfMsgFree(pIsoalRxCtx->pPendSduBuf); + pIsoalRxCtx->pPendSduBuf = NULL; + } + pDataBuf += segHdr.len; + remLen -= hdrLen + segHdr.len; + continue; + } + + memcpy(pSduBuf, pDataBuf, segHdr.len); + pDataBuf += segHdr.len; + pIsoalRxCtx->rxSduOffset += segHdr.len; + + /* SDU Complete, queue up SDU to host. */ + if (segHdr.cmplt) + { + lctrIsoHdr_t isoHdr = { 0 }; + isoHdr.handle = handle; + isoHdr.len = pIsoalRxCtx->rxSduOffset - (HCI_ISO_HDR_LEN + HCI_ISO_DL_MAX_LEN); + isoHdr.pktSn = pIsoalRxCtx->packetSequence++; + isoHdr.sduLen = isoHdr.len; + isoHdr.tsFlag = 1; + isoHdr.pb = LCTR_PB_COMP; + /* isoHdr.ps = LCTR_PS_VALID; */ /* Already done. */ + isoHdr.ts = pIsoalRxCtx->data.framed.timeOffset; /* TODO: Fill out timestamp based on anchor point */ + + uint8_t *pIsoHdrBuf = (pIsoalRxCtx->pPendSduBuf); + lctrIsoPackHdr(pIsoHdrBuf, &isoHdr); + + /* Queue SDU. */ + WsfMsgEnq(pRxQueue, handle, pIsoalRxCtx->pPendSduBuf); + /* lctrIsoDataRxDecAvailBuf(); */ /* Handled in lctrRxSduAlloc. */ + totalSduQueued++; + + pIsoalRxCtx->pPendSduBuf = NULL; + remLen -= hdrLen + segHdr.len; + pIsoalRxCtx->rxState = LL_ISO_SDU_STATE_NEW; + } + /* SDU Incomplete, save offset and return. */ + else + { + pIsoalRxCtx->rxState = LL_ISO_SDU_STATE_CONT; + return totalSduQueued; + } + } + + return totalSduQueued; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_master_phy.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_master_phy.c index 6df99ca042..34c2896a18 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_master_phy.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_master_phy.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller PHY features (master) implementation file. + * \file + * + * \brief Link layer controller PHY features (master) implementation file. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -29,8 +30,6 @@ /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for PHY features (master). - * - * \return None. */ /*************************************************************************************************/ void LctrMstPhyConnInit(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_past.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_past.c index 47eb399186..c130ea5ac3 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_past.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_past.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller periodic sync transfer implementation file. + * \file + * + * \brief Link layer controller periodic sync transfer implementation file. + * + * Copyright (c) 2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -203,8 +204,6 @@ uint8_t LctrSetPeriodicAdvSyncTransParams(uint16_t connHandle, uint8_t mode, uin /*! * \brief Initialize lctr subsystem for PAST(Periodic advertising sync transfer). * - * \return None. - * * This function initializes the lctr subsystem for PAST(Periodic advertising sync transfer). */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_pc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_pc.c new file mode 100644 index 0000000000..9d1514134a --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_pc.c @@ -0,0 +1,320 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller power control implementation 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. + */ +/*************************************************************************************************/ + +#include "lctr_int_conn.h" +#include "lmgr_api_conn.h" +#include "ll_api.h" +#include "wsf_assert.h" +#include "wsf_cs.h" +#include "wsf_math.h" +#include "wsf_msg.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include +#include "lctr_api_pc.h" +#include "lctr_int_pc.h" + +/*************************************************************************************************/ +/*! + * \brief Initialize power control resources. + */ +/*************************************************************************************************/ +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; + + /* Initialize state machines. */ + lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PC] = lctrLlcpExecutePclSm; + lctrMstLlcpSmTbl[LCTR_LLCP_SM_PC] = lctrLlcpExecutePclSm; + + /* Initialize function pointers. */ + lctrSendPowerChangeIndCback = lctrSendPowerChangeInd; + lctrNotifyPowerReportIndCback = lctrNotifyPowerReportInd; +} + +/*************************************************************************************************/ +/*! + * \brief Calculate path loss of a connection context. + * + * \param pCtx Connection context. + * + * \return Current path loss + */ +/*************************************************************************************************/ +static uint8_t lctrCalcPathLoss(lctrConnCtx_t *pCtx) +{ + int8_t txPower = pCtx->peerTxPower; + int8_t lastRssi = pCtx->rssi; + + return (uint8_t) (WSF_MAX(txPower, lastRssi) - WSF_MIN(txPower, lastRssi)); +} + +/*************************************************************************************************/ +/*! + * \brief Calculate the path loss zone of a connection context. + * + * \param pCtx Connection context. + * + * \return Path loss zone. + */ +/*************************************************************************************************/ +uint8_t lctrCalcPathLossZone(lctrConnCtx_t *pCtx) +{ + uint8_t pathLoss = lctrCalcPathLoss(pCtx); + uint8_t curZone = pCtx->pclMonitorParam.pathLoss.curZone; + + uint8_t highUpperBound = pCtx->pclMonitorParam.pathLoss.highThreshold + pCtx->pclMonitorParam.pathLoss.highHysteresis; + uint8_t highLowerBound = pCtx->pclMonitorParam.pathLoss.highThreshold - pCtx->pclMonitorParam.pathLoss.highHysteresis; + + uint8_t lowUpperBound = pCtx->pclMonitorParam.pathLoss.lowThreshold + pCtx->pclMonitorParam.pathLoss.lowHysteresis; + uint8_t lowLowerBound = pCtx->pclMonitorParam.pathLoss.lowThreshold - pCtx->pclMonitorParam.pathLoss.lowHysteresis; + + switch (curZone) + { + case LL_PATH_LOSS_ZONE_LOW: + { + if (pathLoss > highUpperBound) + { + return LL_PATH_LOSS_ZONE_HIGH; + } + else if (pathLoss > lowUpperBound) + { + return LL_PATH_LOSS_ZONE_MID; + } + else + { + return LL_PATH_LOSS_ZONE_LOW; + } + } + + case LL_PATH_LOSS_ZONE_MID: + { + if (pathLoss > highUpperBound) + { + return LL_PATH_LOSS_ZONE_HIGH; + } + else if (pathLoss < lowLowerBound) + { + return LL_PATH_LOSS_ZONE_LOW; + } + else + { + return LL_PATH_LOSS_ZONE_MID; + } + } + + case LL_PATH_LOSS_ZONE_HIGH: + { + if (pathLoss < lowLowerBound) + { + return LL_PATH_LOSS_ZONE_LOW; + } + else if (pathLoss < highLowerBound) + { + return LL_PATH_LOSS_ZONE_MID; + } + else + { + return LL_PATH_LOSS_ZONE_HIGH; + } + } + + default: + LL_TRACE_ERR1("lctrCalcPathLossZone: Path loss invalid zone: %d", curZone); + return LL_PATH_LOSS_ZONE_MID; + } +} + +/*************************************************************************************************/ +/*! + * \brief Set path loss reporting parameters + * + * \param handle Connection handle. + * \param highThresh High threshold. + * \param highHyst High hysteresis. + * \param lowThresh Low threshold. + * \param lowHyst Low hysteresis. + * \param minTime Minimum time spent to trigger event. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t lctrSetPathLossReportingParams(uint16_t handle, uint8_t highThresh, uint8_t highHyst, uint8_t lowThresh, uint8_t lowHyst, uint16_t minTime) +{ + lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(handle); + + memset(&pCtx->pclMonitorParam.pathLoss, 0, sizeof(pCtx->pclMonitorParam.pathLoss)); + pCtx->pclMonitorParam.pathLoss.highThreshold = highThresh; + pCtx->pclMonitorParam.pathLoss.highHysteresis = highHyst; + pCtx->pclMonitorParam.pathLoss.lowThreshold = lowThresh; + pCtx->pclMonitorParam.pathLoss.lowHysteresis = lowHyst; + pCtx->pclMonitorParam.pathLoss.minTimeSpent = minTime; + pCtx->pclMonitorParam.pathLoss.curZone = LL_PATH_LOSS_ZONE_MID; + + if ((pCtx->powerMonitorScheme == LCTR_PC_MONITOR_PATH_LOSS) && + (pCtx->monitoringState = LCTR_PC_MONITOR_ENABLED)) + { + pCtx->pclMonitorParam.pathLoss.curZone = lctrCalcPathLossZone(pCtx); + lctrNotifyHostPathLossRpt(pCtx); + } + else + { + pCtx->powerMonitorScheme = LCTR_PC_MONITOR_PATH_LOSS; + pCtx->monitoringState = LCTR_PC_MONITOR_READY; + } + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Set path loss enable. + * + * \param handle Connection handle. + * \param enable Enable. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t lctrSetPathLossReportingEnable(uint16_t handle, uint8_t enable) +{ + lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(handle); + if (pCtx->monitoringState != LCTR_PC_MONITOR_READY) + { + 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) + { + pCtx->pclMonitorParam.pathLoss.initialPathLossRead = TRUE; + pCtx->controllerInitRead = TRUE; + 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; + if ((pMsg = (lctrMsgPwrCtrlReq_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->hdr.handle = LCTR_GET_CONN_HANDLE(pCtx); + pMsg->hdr.dispId = LCTR_DISP_CONN; + pMsg->hdr.event = LCTR_CONN_MSG_API_PWR_CTRL_REQ; + pMsg->delta = 0; + pMsg->phy = reqPhy; + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } + else + { + LL_TRACE_WARN0("lctrSetPathLossReportingEnable: Failed to alloc power control read request."); + return LL_ERROR_CODE_MEM_CAP_EXCEEDED; + } + } + else + { + pCtx->pclMonitorParam.pathLoss.curZone = lctrCalcPathLossZone(pCtx); + lctrNotifyHostPathLossRpt(pCtx); + } + + pCtx->monitoringState = LCTR_PC_MONITOR_ENABLED; + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Notify the host of a path loss zone change event. + * + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +void lctrNotifyHostPathLossRpt(lctrConnCtx_t *pCtx) +{ + const uint16_t handle = LCTR_GET_CONN_HANDLE(pCtx); + uint8_t curPathLoss = lctrCalcPathLoss(pCtx); + + LlPathLossThresholdEvt_t evt = + { + .hdr = + { + .param = handle, + .event = LL_PATH_LOSS_REPORTING_IND, + .status = LL_SUCCESS + }, + + .connHandle = handle, + .curPathLoss = curPathLoss, + .zoneEntered = pCtx->pclMonitorParam.pathLoss.curZone, + }; + + LL_TRACE_INFO3("### LlEvent ### lctrNotifyHostPathLossRpt , handle=%u, zoneEntered=%d, curPathLoss=%d", handle, pCtx->pclMonitorParam.pathLoss.curZone, curPathLoss); + + LmgrSendEvent((LlEvt_t *)&evt); +} + +/*************************************************************************************************/ +/*! + * \brief Path loss monitoring action. + * + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +void lctrPathLossMonitorAct(lctrConnCtx_t *pCtx) +{ + /* If the first path loss zone has not been generated yet, skip monitoring. */ + if (pCtx->pclMonitorParam.pathLoss.initialPathLossRead == TRUE) + { + return; + } + + uint8_t newZone = lctrCalcPathLossZone(pCtx); + uint8_t curZone = pCtx->pclMonitorParam.pathLoss.curZone; + + if (newZone == curZone) + { + pCtx->pclMonitorParam.pathLoss.curTimeSpent = 0; + pCtx->pclMonitorParam.pathLoss.newZone = newZone; + return; + } + else if (newZone != pCtx->pclMonitorParam.pathLoss.newZone) + { + pCtx->pclMonitorParam.pathLoss.curTimeSpent = 0; + pCtx->pclMonitorParam.pathLoss.newZone = newZone; + return; + } + + /* Implies that the newZone is a consecutive event. */ + pCtx->pclMonitorParam.pathLoss.curTimeSpent++; + + if (pCtx->pclMonitorParam.pathLoss.curTimeSpent >= + pCtx->pclMonitorParam.pathLoss.minTimeSpent) + { + LL_TRACE_INFO2("lctrPathLossMonitorAct, New zone entered. newZone=%u, pathLoss=%u", newZone, lctrCalcPathLoss(pCtx)); + pCtx->pclMonitorParam.pathLoss.curTimeSpent = 0; + pCtx->pclMonitorParam.pathLoss.curZone = newZone; + + lctrNotifyHostPathLossRpt(pCtx); + } +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_priv.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_priv.c index 281f7319ad..3d139e14a5 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_priv.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_priv.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller privacy implementation file. + * \file + * + * \brief Link layer controller privacy implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -44,8 +45,6 @@ lctrPrivCtx_t lctrPriv; /*************************************************************************************************/ /*! * \brief Restart resolvable private address timer. - * - * \return None. */ /*************************************************************************************************/ static void lctrRestartResPrivAddrTimer(void) @@ -59,8 +58,6 @@ static void lctrRestartResPrivAddrTimer(void) * \brief Privacy message dispatcher. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void lctrPrivDisp(LctrPrivMsg_t *pMsg) @@ -107,8 +104,6 @@ static void lctrPrivDisp(LctrPrivMsg_t *pMsg) * \param peer TRUE if this is a peer RPA. * \param peerAddrType Peer identity address type. * \param peerIdentityAddr Peer identity address. - * - * \return None. */ /*************************************************************************************************/ static void lctrPrivPendAddrRes(uint64_t rpa, bool_t peer, uint8_t peerAddrType, uint64_t peerIdentityAddr) @@ -152,8 +147,6 @@ static void lctrPrivPendAddrRes(uint64_t rpa, bool_t peer, uint8_t peerAddrType, * \brief Set resolvable private address timeout. * * \param timeout Timeout in seconds. - * - * \return None. */ /*************************************************************************************************/ void LctrPrivSetResPrivAddrTimeout(uint32_t timeout) @@ -165,8 +158,6 @@ void LctrPrivSetResPrivAddrTimeout(uint32_t timeout) /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for privacy. - * - * \return None. */ /*************************************************************************************************/ void LctrPrivInit(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_sc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_sc.c index 7138c7a4e8..7a0f18aa04 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_sc.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_sc.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller secure connections implementation file. + * \file + * + * \brief Link layer controller secure connections implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -38,8 +39,6 @@ * \brief Baseband driver ECC service function. * * \param op Operation to service. - * - * \return None. */ /*************************************************************************************************/ static void lctrScBbDrvEcc(uint8_t op) @@ -84,8 +83,6 @@ static int lctrRng(uint8_t *pDest, unsigned size) * \param pDest Destination buffer. * \param pSrc Source buffer. * \param len Length of data, in octets. - * - * \return None. */ /*************************************************************************************************/ static void lctrReverseCopy(uint8_t *pDest, const uint8_t *pSrc, uint16_t len) @@ -103,8 +100,6 @@ static void lctrReverseCopy(uint8_t *pDest, const uint8_t *pSrc, uint16_t len) * * \param p Buffer. * \param len Length of data, in octets. - * - * \return None. */ /*************************************************************************************************/ static void lctrReverse(uint8_t *p, uint16_t len) @@ -125,8 +120,6 @@ static void lctrReverse(uint8_t *p, uint16_t len) /*************************************************************************************************/ /*! * \brief Start generating P-256 key pair. - * - * \return None. */ /*************************************************************************************************/ void lctrGenerateP256KeyPairStart(void) @@ -148,8 +141,6 @@ void lctrGenerateP256KeyPairStart(void) * \brief Start generating P-256 public key with a specified private key. * * \param pPrivKey Private key. - * - * \return None. */ /*************************************************************************************************/ void lctrGenerateP256PublicKeyStart(const uint8_t *pPrivKey) @@ -190,8 +181,6 @@ bool_t lctrGenerateP256KeyPairContinue(void) * * \param pPubKey Storage for public key. * \param pPrivKey Storage for private key. - * - * \return None. */ /*************************************************************************************************/ void lctrGenerateP256KeyPairComplete(uint8_t *pPubKey, uint8_t *pPrivKey) @@ -211,8 +200,6 @@ void lctrGenerateP256KeyPairComplete(uint8_t *pPubKey, uint8_t *pPrivKey) * * \param pPubKey Public key. * \param pPrivKey Private key. - * - * \return None. */ /*************************************************************************************************/ void lctrGenerateDhKeyStart(const uint8_t *pPubKey, const uint8_t *pPrivKey) @@ -255,8 +242,6 @@ bool_t lctrGenerateDhKeyContinue(void) * \brief Get results from generating Diffie-Hellman key. * * \param pDhKey Storage for Diffie-Hellman key. - * - * \return None. */ /*************************************************************************************************/ void lctrGenerateDhKeyComplete(uint8_t *pDhKey) @@ -302,8 +287,6 @@ bool_t lctrValidatePublicKey(const uint8_t *pPubKey, bool_t generateKey) * \brief Notify host of key generation. * * \param pPubKey Public key. - * - * \return None. */ /*************************************************************************************************/ static void lctrNotifyReadLocalP256PubKeyInd(const uint8_t *pPubKey) @@ -332,8 +315,6 @@ static void lctrNotifyReadLocalP256PubKeyInd(const uint8_t *pPubKey) * \brief Notify host of key generation. * * \param pDhKey Diffie-Hellman key. - * - * \return None. */ /*************************************************************************************************/ static void lctrNotifyGenerateDhKeyInd(const uint8_t *pDhKey) @@ -359,8 +340,6 @@ static void lctrNotifyGenerateDhKeyInd(const uint8_t *pDhKey) /*************************************************************************************************/ /*! * \brief P-256 key pair generation. - * - * \return None. */ /*************************************************************************************************/ static void lctrScGenerateP256KeyPairContinue(void) @@ -382,8 +361,6 @@ static void lctrScGenerateP256KeyPairContinue(void) /*************************************************************************************************/ /*! * \brief DH Key generation. - * - * \return None. */ /*************************************************************************************************/ static void lctrScGenerateDhKeyContinue(void) @@ -548,8 +525,6 @@ uint8_t LctrSetValidatePublicKeyMode(uint8_t validateMode) /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for secure connections. - * - * \return None. */ /*************************************************************************************************/ void LctrScInit(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_slave_phy.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_slave_phy.c index 3edbe1a454..fcb64785de 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_slave_phy.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_main_slave_phy.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller PHY features (slave) implementation file. + * \file + * + * \brief Link layer controller PHY features (slave) implementation file. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -29,8 +30,6 @@ /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for PHY features (slave). - * - * \return None. */ /*************************************************************************************************/ void LctrSlvPhyConnInit(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv.h index 4bbdf99bf7..286440d2d9 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller advertising channel packet interface file. + * \file + * + * \brief Link layer controller advertising channel packet interface file. + * + * Copyright (c) 2013-2017 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_ae.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_ae.h index bc7e23d05c..08acdd013c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_ae.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_ae.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller extended advertising channel packet interface file. + * \file + * + * \brief Link layer controller extended advertising channel packet interface file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ @@ -104,6 +105,9 @@ typedef struct uint16_t eventCounter; /*!< Event counter. */ } lctrSyncInfo_t; +/*! \brief Pack ACAD call signature. */ +typedef uint8_t (*lctrPackAcad_t)(lctrAdvSet_t *, uint8_t *); + /************************************************************************************************** Function Declarations **************************************************************************************************/ @@ -118,12 +122,15 @@ void lctrPackAuxPtr(lctrAdvSet_t const *pAdvSet, uint32_t offsUsec, uint8_t chId uint8_t lctrPackLegacyAdvPdu(lctrAdvSet_t *pAdvSet, uint8_t *pPduBuf); uint8_t lctrPackLegacyScanRspPdu(lctrAdvSet_t *pAdvSet, uint8_t *pPduBuf); uint8_t lctrPackSyncIndPdu(lctrAdvSet_t *pAdvSet, uint8_t *pPduBuf, lctrAdvDataBuf_t *pAdvData, bool_t isPeriodic); -uint8_t* lctrPackAcad(lctrAdvSet_t *pAdvSet, uint8_t commExtAdvPdu, uint8_t *pBuf, uint16_t *pRemLen, uint8_t acadId); +uint8_t lctrPackAcadChanMapUpd(lctrAdvSet_t *pAdvSet, uint8_t *pBuf); +uint8_t lctrPackAcadBigInfo(lctrAdvSet_t *pAdvSet, uint8_t *pBuf); /* Unpack */ uint8_t lctrUnpackExtAdvHeader(lctrExtAdvHdr_t *pPdu, uint8_t *pNewFlags, const uint8_t *pBuf); void lctrUnpackAuxPtr(lctrAuxPtr_t *pAuxPtr, const uint8_t *pBuf); void lctrUnpackSyncInfo(lctrSyncInfo_t *pSyncInfo, const uint8_t *pBuf); +void lctrUnpackAcadChanMapUpd(LctrAcadChanMapUpd_t *pChanMapUpd, const uint8_t *pBuf); +void lctrUnpackAcadBigInfo(LctrAcadBigInfo_t *pBigInfo, const uint8_t *pBuf, uint8_t len); #ifdef __cplusplus }; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_master_ae.c index 9b87a223b4..a076cfa07d 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave extended advertising operation builder implementation file. + * \file + * + * \brief Link layer controller slave extended advertising operation builder implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -99,19 +100,20 @@ uint8_t lctrUnpackExtAdvHeader(lctrExtAdvHdr_t *pPdu, uint8_t *pNewFlags, const { BSTREAM_TO_UINT8(pPdu->txPwr, pBuf); } - - if ((pPdu->extHdrLen + 1) > (pBuf - pStartBuf)) - { - pPdu->pAcad = pBuf; - pPdu->acadLen = (pPdu->extHdrLen + 1) - (pBuf - pStartBuf); - pBuf += pPdu->acadLen; - } - else - { - pPdu->pAcad = NULL; - pPdu->acadLen = 0; - } } + + if ((pPdu->extHdrLen + 1) > (pBuf - pStartBuf)) + { + pPdu->pAcad = pBuf; + pPdu->acadLen = (pPdu->extHdrLen + 1) - (pBuf - pStartBuf); + pBuf += pPdu->acadLen; + } + else + { + pPdu->pAcad = NULL; + pPdu->acadLen = 0; + } + return pBuf - pStartBuf; } @@ -121,8 +123,6 @@ uint8_t lctrUnpackExtAdvHeader(lctrExtAdvHdr_t *pPdu, uint8_t *pNewFlags, const * * \param pAuxPtr Unpacked AuxPtr data. * \param pBuf Packed AuxPtr data. - * - * \return None. */ /*************************************************************************************************/ void lctrUnpackAuxPtr(lctrAuxPtr_t *pAuxPtr, const uint8_t *pBuf) @@ -144,8 +144,6 @@ void lctrUnpackAuxPtr(lctrAuxPtr_t *pAuxPtr, const uint8_t *pBuf) * * \param pSyncInfo Sync info. * \param pBuf Buffer pointer to SyncInfo field. - * - * \return None. */ /*************************************************************************************************/ void lctrUnpackSyncInfo(lctrSyncInfo_t *pSyncInfo, const uint8_t *pBuf) @@ -155,7 +153,7 @@ void lctrUnpackSyncInfo(lctrSyncInfo_t *pSyncInfo, const uint8_t *pBuf) pSyncInfo->syncOffset = (field16 >> 0) & 0x1FFF; pSyncInfo->offsetUnits = (field16 >> 13) & 0x1; pSyncInfo->offsetAdjust = (field16 >> 14) & 0x1; - pBuf += 2; + pBuf += sizeof(uint16_t); BSTREAM_TO_UINT16(pSyncInfo->syncInter, pBuf); @@ -163,7 +161,7 @@ void lctrUnpackSyncInfo(lctrSyncInfo_t *pSyncInfo, const uint8_t *pBuf) BYTES_TO_UINT40(field64, pBuf); pSyncInfo->chanMap = (field64 >> 0) & LL_CHAN_DATA_ALL; pSyncInfo->sca = (field64 >> 37) & 0x07; - pBuf+=5; + pBuf += 5; BSTREAM_TO_UINT32(pSyncInfo->accAddr, pBuf); @@ -171,3 +169,76 @@ void lctrUnpackSyncInfo(lctrSyncInfo_t *pSyncInfo, const uint8_t *pBuf) BSTREAM_TO_UINT16(pSyncInfo->eventCounter, pBuf); } + +/*************************************************************************************************/ +/*! + * \brief Unpack Channel Map Update Indication. + * + * \param pChanMapUpd Unpacked Channel Map Update return buffer. + * \param pBuf Packed buffer pointer. + */ +/*************************************************************************************************/ +void lctrUnpackAcadChanMapUpd(LctrAcadChanMapUpd_t *pChanMapUpd, const uint8_t *pBuf) +{ + BSTREAM_TO_UINT40(pChanMapUpd->chanMask, pBuf); + BSTREAM_TO_UINT16(pChanMapUpd->instant, pBuf); +} + +/*************************************************************************************************/ +/*! + * \brief Unpack BIG Info. + * + * \param pBigInfo Unpacked BIG Info return buffer. + * \param pBuf Packed buffer pointer. + * \param len length of bigInfo. + */ +/*************************************************************************************************/ +void lctrUnpackAcadBigInfo(LctrAcadBigInfo_t *pBigInfo, const uint8_t *pBuf, uint8_t len) +{ + uint32_t field32; + uint64_t field64; + + BSTREAM_TO_UINT32(field32, pBuf); + pBigInfo->bigOffs = (field32 >> 0) & 0x3FFF; + pBigInfo->bigOffsUnits = (field32 >> 14) & 0x0001; + pBigInfo->isoInter = (field32 >> 15) & 0x0FFF; + pBigInfo->numBis = (field32 >> 27) & 0x001F; + BSTREAM_TO_UINT32(field32, pBuf); + pBigInfo->nse = (field32 >> 0) & 0x0001F; + pBigInfo->bn = (field32 >> 5) & 0x00007; + pBigInfo->subEvtInterUsec = (field32 >> 8) & 0xFFFFF; + pBigInfo->pto = (field32 >> 28) & 0x0000F; + BSTREAM_TO_UINT32(field32, pBuf); + pBigInfo->bisSpaceUsec = (field32 >> 0) & 0xFFFFF; + pBigInfo->irc = (field32 >> 20) & 0x0000F; + pBigInfo->maxPdu = (field32 >> 24) & 0x000FF; + pBuf++; /* RFU */ + BSTREAM_TO_UINT32(pBigInfo->seedAccAddr, pBuf); + BSTREAM_TO_UINT32(field32, pBuf); + pBigInfo->sduInterUsec = (field32 >> 0) & 0xFFFFF; + pBigInfo->maxSdu = (field32 >> 20) & 0x00FFF; + BSTREAM_TO_UINT16(pBigInfo->baseCrcInit, pBuf); + BSTREAM_TO_UINT40(field64, pBuf); + pBigInfo->chanMap = (field64 >> 0) & UINT64_C(0x1FFFFFFFFF); + pBigInfo->phy = (field64 >> 37) & 0x0007; + BSTREAM_TO_UINT40(field64, pBuf); + pBigInfo->bisPldCtr = (field64 >> 0) & UINT64_C(0x7FFFFFFFFF); + pBigInfo->framing = (field64 >> 39) & 0x0001; + + /* Convert BIG Info enumeration to PHY value. */ + pBigInfo->phy += 1; + + if (len > (LL_ACAD_BIG_INFO_UNENCRPT_LEN + LL_ACAD_LEN_FIELD_LEN)) + { + pBigInfo->encrypt = TRUE; + + memcpy(pBigInfo->giv, pBuf, LL_GIV_LEN); + pBuf += LL_GIV_LEN; + memcpy(pBigInfo->gskd, pBuf, LL_GSKD_LEN); + /* pBuf += LL_GSKD_LEN; */ + } + else + { + pBigInfo->encrypt = FALSE; + } +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_slave.c index 45d532aacf..f3067edaec 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave advertising channel packet implementation file. + * \file + * + * \brief Link layer controller slave advertising channel packet implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -25,7 +26,6 @@ #include "util/bstream.h" #include "wsf_trace.h" #include -#include /*************************************************************************************************/ /*! diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_slave_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_slave_ae.c index d0bef7b1cd..a93a841c7f 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_slave_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_adv_slave_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave extended advertising operation builder implementation file. + * \file + * + * \brief Link layer controller slave extended advertising operation builder implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -39,14 +40,23 @@ /*! \brief Assert minimum advertising payload length can contain a legacy length payload. */ WSF_CT_ASSERT(BB_ADV_PLD_MAX_LEN > (LL_EXT_ADV_HDR_MAX_LEN + LL_ADVBU_MAX_LEN)); +/************************************************************************************************** + Local Variables +**************************************************************************************************/ + +/*! \brief Packing lookup table; local use only. */ +static const lctrPackAcad_t lctrPackAcad[LCTR_ACAD_NUM_ID] = +{ + lctrPackAcadChanMapUpd, /*!< Channel map update. */ + lctrPackAcadBigInfo /*!< BIG Info. */ +}; + /*************************************************************************************************/ /*! * \brief Pack Sync info field. * * \param pAdvSet Advertising set. * \param pSyncInfo Packed SyncInfo field. - * - * \return None. */ /*************************************************************************************************/ static void lctrPackSyncInfo(lctrAdvSet_t *pAdvSet, uint8_t *pSyncInfo) @@ -59,18 +69,18 @@ static void lctrPackSyncInfo(lctrAdvSet_t *pAdvSet, uint8_t *pSyncInfo) BbOpDesc_t *pPerOp = &pAdvSet->perParam.perAdvBod; BbBleData_t *pBle = &pAdvSet->perParam.perBleData; - tempDue = pPerOp->due; + tempDue = pPerOp->dueUsec; while (TRUE) { /* If sync PDU is due in the future and at least MAFS apart, update offset. */ - if ((tempDue > pAuxOp->due) && ((BB_TICKS_TO_US(tempDue - pAuxOp->due)) > LL_BLE_MAFS_US)) + if (BbGetTargetTimeDelta(tempDue, pAuxOp->dueUsec) > LL_BLE_MAFS_US) { - offsUsec = BB_TICKS_TO_US(tempDue - pAuxOp->due); + offsUsec = BbGetTargetTimeDelta(tempDue, pAuxOp->dueUsec); break; } - tempDue += pAdvSet->perParam.perAdvInter; + tempDue += pAdvSet->perParam.perAdvInterUsec; } if (offsUsec < LL_30_USEC_OFFS_MAX_USEC) @@ -94,7 +104,7 @@ static void lctrPackSyncInfo(lctrAdvSet_t *pAdvSet, uint8_t *pSyncInfo) (offsUnits << 13) | /* Offset units. */ (offsAdjust << 14)); /* Offset adjust. */ UINT16_TO_BUF(&pSyncInfo[2], /* Interval. */ - LCTR_PER_INTER_TO_MS(BB_TICKS_TO_US(pAdvSet->perParam.perAdvInter))); + LCTR_PER_INTER_TO_MS(pAdvSet->perParam.perAdvInterUsec)); uint64_t temp = ((pAdvSet->perParam.perChanParam.chanMask & LL_CHAN_DATA_ALL) |/* Channel Map. */ ((uint64_t)lctrComputeSca() << 37)); /* SCA. */ @@ -118,7 +128,7 @@ static void lctrPackSyncInfo(lctrAdvSet_t *pAdvSet, uint8_t *pSyncInfo) * \param commExtAdvPdu Common extended advertising PDU type. * \param isPeriodic This header is part of periodic PDUs or not. * - * \return PDU header buffer length. + * \return Combined Adv and ExtAdv headers length. */ /*************************************************************************************************/ static uint8_t lctrPackExtAdvHeader(lctrAdvSet_t *pAdvSet, uint8_t manExtHdrFlags, uint8_t optExtHdrFlags, @@ -129,16 +139,8 @@ static uint8_t lctrPackExtAdvHeader(lctrAdvSet_t *pAdvSet, uint8_t manExtHdrFlag pPduHdr->len = 0; uint8_t *pAuxPtr = NULL; - uint8_t *pBuf = pPduBuf + LL_ADV_HDR_LEN + LCTR_EXT_HDR_CMN_LEN + LCTR_EXT_HDR_FLAG_LEN; - - /* Check if we need to look for Acads to pack later. */ - /* Future Acad may include PDUS: - * AUX_ADV_IND, AUX_SYNC_IND, AUX_SCAN_RSP */ - bool_t acadNeeded = FALSE; - if (commExtAdvPdu == LCTR_PDU_AUX_SYNC_IND) - { - acadNeeded = TRUE; - } + uint8_t *pExtHdrBuf = pPduBuf + LL_ADV_HDR_LEN + LCTR_EXT_HDR_CMN_LEN; + uint8_t *pBuf = pExtHdrBuf + LCTR_EXT_HDR_FLAG_LEN; /* Determine the superior PDU. */ if (commExtAdvPdu == LCTR_PDU_AUX_CHAIN_IND) @@ -271,45 +273,61 @@ static uint8_t lctrPackExtAdvHeader(lctrAdvSet_t *pAdvSet, uint8_t manExtHdrFlag UINT8_TO_BSTREAM(pBuf, (uint8_t)actTxPwr); } - /* Pack Acad. */ - if (acadNeeded) + /* ACAD assembly. */ + bool_t acadPresent = FALSE; + if (commExtAdvPdu == LCTR_PDU_AUX_SYNC_IND) { - for (uint8_t acadId = 0; acadId < LCTR_ACAD_NUM_ID; acadId++) + for (unsigned int acadId = 0; acadId < LCTR_ACAD_NUM_ID; acadId++) { - if (pAdvSet->acadParams[acadId].hdr.state != LCTR_ACAD_STATE_DISABLED) + if (pAdvSet->acadParams[acadId].hdr.state == LCTR_ACAD_STATE_ENABLED) { - pBuf = lctrPackAcad(pAdvSet, commExtAdvPdu, pBuf, &remDataLen, acadId); + uint8_t acadLen = LL_ACAD_OPCODE_LEN + LL_ACAD_LEN_FIELD_LEN + + pAdvSet->acadParams[acadId].hdr.len; + + uint8_t availExtHdrLen = LL_EXT_ADV_HDR_MAX_LEN - (pBuf - pExtHdrBuf); + + /* Only add ACAD if space available. */ + if (acadLen <= availExtHdrLen) + { + acadPresent = TRUE; + + /* Pack ACAD immediately after the Extended Header. */ + pBuf += lctrPackAcad[acadId](pAdvSet, pBuf); + } } } } + if (!extHdrFlags && !acadPresent) + { + /* Recover optional ExtHdrFlag field since it is not used. */ + pBuf = pExtHdrBuf; + } + + /* Assign AdvData to this PDU, defer buffer assembly to DMA gather. */ uint8_t advDataLen = 0; if (remDataLen) { const unsigned int maxAvailDataLen = LL_EXT_ADVB_MAX_LEN - (pBuf - pPduBuf); availDataLen = WSF_MIN(maxAvailDataLen, availDataLen); /* Limit to maximum packet size. */ advDataLen = WSF_MIN(remDataLen, availDataLen); /* Reduce to remaining data. */ + + /* Commit AdvData fragment to this PDU. */ pDataBuf->txOffs += advDataLen; } - if (extHdrFlags == 0) - { - /* Extended Header Flags only present if bits set. */ - pBuf = pPduBuf + LL_ADV_HDR_LEN + LCTR_EXT_HDR_CMN_LEN; - } - /* Pack Advertising Header now that Extended Advertising Header length is known. */ - uint16_t extHdrLen = pBuf - pPduBuf - LL_ADV_HDR_LEN - LCTR_EXT_HDR_CMN_LEN; - pPduHdr->len = pBuf - pPduBuf - LL_ADV_HDR_LEN + advDataLen; + uint16_t extHdrLen = pBuf - pExtHdrBuf; + pPduHdr->len = LCTR_EXT_HDR_CMN_LEN + extHdrLen + advDataLen; lctrPackAdvbPduHdr(pPduBuf, pPduHdr); - /* Pack Extended Advertising header. */ + /* Pack Extended Advertising header; unconditionally write even if unused. */ pPduBuf[LL_ADV_HDR_LEN + 0] = extHdrLen | /* Extended Header Length */ (advMode << 6); /* AdvMode */ pPduBuf[LL_ADV_HDR_LEN + 1] = extHdrFlags; /* Extended Header Flags */ - switch(commExtAdvPdu) + switch (commExtAdvPdu) { case LCTR_PDU_ADV_EXT_IND: pAdvSet->auxOffsUsec = 0; @@ -707,8 +725,6 @@ uint8_t lctrPackAuxConnRspPdu(lctrAdvSet_t *pAdvSet, uint8_t *pPduBuf, bool_t is * \param offsUsec Auxiliary offset in microseconds. * \param chIdx Channel index. * \param pAuxPtr Packed AuxPtr buffer. - * - * \return None. */ /*************************************************************************************************/ void lctrPackAuxPtr(lctrAdvSet_t const *pAdvSet, uint32_t offsUsec, uint8_t chIdx, uint8_t *pAuxPtr) @@ -925,44 +941,79 @@ uint8_t lctrPackSyncIndPdu(lctrAdvSet_t *pAdvSet, uint8_t *pPduBuf, lctrAdvDataB /*************************************************************************************************/ /*! - * \brief Pack acad field + * \brief Pack Channel Map Update ACAD. * * \param pAdvSet Advertising set. - * \param commExtAdvPdu Common ext adv pdu. * \param pBuf Packed data buffer. - * \param pRemLen Remaining length of ext adv header. - * \param acadId Acad Id. * - * \return Modified pBuf. + * \return Length of ACAD. */ /*************************************************************************************************/ -uint8_t* lctrPackAcad(lctrAdvSet_t *pAdvSet, uint8_t commExtAdvPdu, uint8_t *pBuf, uint16_t *pRemLen, uint8_t acadId) +uint8_t lctrPackAcadChanMapUpd(lctrAdvSet_t *pAdvSet, uint8_t *pBuf) { - switch(acadId) - { - case LCTR_ACAD_ID_CHAN_MAP_UPDATE: - { - uint8_t len = LL_ACAD_LEN_FIELD_LEN + LL_ACAD_UPDATE_CHANNEL_MAP_LEN; + const uint8_t len = LL_ACAD_LEN_FIELD_LEN + LL_ACAD_CHAN_MAP_UPD_LEN; - if ((commExtAdvPdu != LCTR_PDU_AUX_SYNC_IND) || - (len > *pRemLen)) - { - return pBuf; - } + LctrAcadChanMapUpd_t *pChanMapUpd = &pAdvSet->acadParams[LCTR_ACAD_ID_CHAN_MAP_UPDATE].chanMapUpdate; - lctrAcadChanMapUpd_t *pData = &pAdvSet->acadParams[acadId].chanMapUpdate; + /* Pack ACAD */ + UINT8_TO_BSTREAM (pBuf, LL_ACAD_CHAN_MAP_UPD_LEN); + UINT8_TO_BSTREAM (pBuf, LL_ACAD_OPCODE_CHAN_MAP_UPD); + UINT40_TO_BSTREAM(pBuf, pChanMapUpd->chanMask); + UINT16_TO_BSTREAM(pBuf, pChanMapUpd->instant); - /* Pack Acad */ - *pRemLen -= len; - UINT8_TO_BSTREAM(pBuf, LL_ACAD_UPDATE_CHANNEL_MAP_LEN); - UINT8_TO_BSTREAM(pBuf, LL_ACAD_OPCODE_CHANNEL_MAP_UPDATE); - - UINT40_TO_BSTREAM(pBuf, pData->chanMask); - UINT16_TO_BSTREAM(pBuf, pData->instant); - return pBuf; - } - - default: - return pBuf; - } + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Pack BIG Info ACAD. + * + * \param pAdvSet Advertising set. + * \param pBuf Packed data buffer. + * + * \return Length of ACAD. + */ +/*************************************************************************************************/ +uint8_t lctrPackAcadBigInfo(lctrAdvSet_t *pAdvSet, uint8_t *pBuf) +{ + LctrAcadBigInfo_t *pBigInfo = &pAdvSet->acadParams[LCTR_ACAD_ID_BIG_INFO].bigInfo; + + const uint8_t len = LL_ACAD_LEN_FIELD_LEN + LL_ACAD_OPCODE_LEN + pBigInfo->hdr.len; + + /* Convert PHY value to BIG Info enumeration. */ + uint8_t bigPhy = pBigInfo->phy - 1; + + /* Pack ACAD */ + UINT8_TO_BSTREAM (pBuf, pBigInfo->hdr.len + LL_ACAD_LEN_FIELD_LEN); + UINT8_TO_BSTREAM (pBuf, LL_ACAD_OPCODE_BIG_INFO); + + UINT32_TO_BSTREAM(pBuf, ((pBigInfo->bigOffs & 0x3FFF) << 0) | + ((pBigInfo->bigOffsUnits & 0x0001) << 14) | + ((pBigInfo->isoInter ) << 15) | + ((pBigInfo->numBis ) << 27)); + UINT32_TO_BSTREAM(pBuf, ((pBigInfo->nse ) << 0) | + ((pBigInfo->bn ) << 5) | + ((pBigInfo->subEvtInterUsec ) << 8) | + ((pBigInfo->pto ) << 28)); + UINT32_TO_BSTREAM(pBuf, ((pBigInfo->bisSpaceUsec ) << 0) | + ((pBigInfo->irc ) << 20) | + ((pBigInfo->maxPdu ) << 24)); + UINT8_TO_BSTREAM (pBuf, ((0 /* RFU */ ) << 0)); + UINT32_TO_BSTREAM(pBuf, ((pBigInfo->seedAccAddr ) << 0)); + UINT32_TO_BSTREAM(pBuf, ((pBigInfo->sduInterUsec ) << 0) | + ((pBigInfo->maxSdu ) << 20)); + UINT16_TO_BSTREAM(pBuf, ((pBigInfo->baseCrcInit ) << 0)); + UINT40_TO_BSTREAM(pBuf, ((pBigInfo->chanMap ) << 0) | + (((uint64_t)bigPhy ) << 37)); + UINT40_TO_BSTREAM(pBuf, ((pBigInfo->bisPldCtr & UINT64_C(0x7FFFFFFFFF)) << 0) | + ((pBigInfo->framing & UINT64_C(1)) << 39)); + if (pBigInfo->encrypt) + { + memcpy(pBuf, pBigInfo->giv, LL_GIV_LEN); + pBuf += LL_GIV_LEN; + memcpy(pBuf, pBigInfo->gskd, LL_GSKD_LEN); + pBuf += LL_GSKD_LEN; + } + + return len; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_bis.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_bis.c new file mode 100644 index 0000000000..404dacf6d1 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_bis.c @@ -0,0 +1,171 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller BIS packet implementation 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. + */ +/*************************************************************************************************/ + +#include "lctr_pdu_iso.h" +#include "util/bstream.h" +#include "hci_defs.h" +#include + +/*************************************************************************************************/ +/*! + * \brief Pack a BIS Data PDU header. + * + * \param pBuf Packed packet buffer. + * \param pHdr Unpacked PDU header. + * + * \return Header length. + */ +/*************************************************************************************************/ +uint8_t lctrBisPackDataPduHdr(uint8_t *pBuf, const lctrBisDataPduHdr_t *pHdr) +{ + const uint8_t len = LL_DATA_HDR_LEN; + + uint16_t hdr = 0; + + hdr |= (pHdr->llid ) << 0; + hdr |= (pHdr->cssn & 7) << 2; + hdr |= (pHdr->cstf ) << 5; + hdr |= (pHdr->len ) << 8; + UINT16_TO_BSTREAM(pBuf, hdr); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Pack a BIG Channel Map indication. + * + * \param pBuf Packed packet buffer. + * \param chanMap Channel map. + * \param instance Instance. + * + * \return Packet length. + */ +/*************************************************************************************************/ +uint8_t lctrBisPackBigChannelMapInd(uint8_t *pBuf, uint64_t chanMap, uint16_t instance) +{ + const uint8_t len = sizeof(uint8_t) + LL_BIG_CHAN_MAP_IND_PDU_LEN; + + UINT8_TO_BSTREAM (pBuf, LL_BIG_OPCODE_CHAN_MAP_IND); + UINT40_TO_BSTREAM(pBuf, chanMap); + UINT16_TO_BSTREAM(pBuf, instance); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Pack a BIG Terminate indication. + * + * \param pBuf Packed packet buffer. + * \param reason Reason code. + * \param instance Instance. + * + * \return Packet length. + */ +/*************************************************************************************************/ +uint8_t lctrBisPackBigTerminateInd(uint8_t *pBuf, uint8_t reason, uint16_t instance) +{ + const uint8_t len = sizeof(uint8_t) + LL_BIG_TERMINATE_IND_PDU_LEN; + + UINT8_TO_BSTREAM (pBuf, LL_BIG_OPCODE_BIG_TERM_IND); + UINT8_TO_BSTREAM (pBuf, reason); + UINT16_TO_BSTREAM(pBuf, instance); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Unpack a BIS Data PDU header. + * + * \param pHdr Unpacked header. + * \param pBuf Packed packet buffer. + * + * \return Header length. + */ +/*************************************************************************************************/ +uint8_t lctrBisUnpackDataPduHdr(lctrBisDataPduHdr_t *pHdr, const uint8_t *pBuf) +{ + const uint8_t len = LL_DATA_HDR_LEN; + + uint16_t hdr; + + BSTREAM_TO_UINT16(hdr, pBuf); + + pHdr->llid = (hdr >> 0) & 0x03; + pHdr->cssn = (hdr >> 2) & 0x07; + pHdr->cstf = (hdr >> 5) & 0x01; + pHdr->len = (hdr >> 8); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Unpack a BIG Channel Map indication. + * + * \param pChanMap Channel map return buffer. + * \param pInstance Instance return buffer. + * \param pBuf Packed packet buffer. + * + * \return PDU length. + */ +/*************************************************************************************************/ +uint8_t lctrBisUnpackBigChannelMapInd(uint64_t *pChanMap, uint16_t *pInstance, const uint8_t *pBuf) +{ + const uint8_t len = sizeof(uint8_t) + LL_BIG_CHAN_MAP_IND_PDU_LEN; + + uint64_t chanMap; + uint16_t instance; + + pBuf++; /* Opcode */ + BSTREAM_TO_UINT40(chanMap, pBuf); + BSTREAM_TO_UINT16(instance, pBuf); + + *pChanMap = chanMap; + *pInstance = instance; + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Unpack a BIG Terminate indication. + * + * \param pReason Channel map return buffer. + * \param pInstance Instance return buffer. + * \param pBuf Packed packet buffer. + * + * \return PDU length. + */ +/*************************************************************************************************/ +uint8_t lctrBisUnpackBigTerminateInd(uint8_t *pReason, uint16_t *pInstance, const uint8_t *pBuf) +{ + const uint8_t len = sizeof(uint8_t) + LL_BIG_TERMINATE_IND_PDU_LEN; + + pBuf++; /* Opcode */ + BSTREAM_TO_UINT8 (*pReason, pBuf); + BSTREAM_TO_UINT16(*pInstance, pBuf); + + return len; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_conn.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_conn.c index 701d0963e8..f44df7ffb0 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_conn.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_conn.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave data channel packet implementation file. + * \file + * + * \brief Link layer controller slave data channel packet implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,7 +28,6 @@ #include "hci_defs.h" #include "wsf_math.h" #include -#include /*************************************************************************************************/ /*! @@ -639,7 +639,7 @@ uint8_t lctrUnpackCisReqPdu(lctrCisReq_t *pPdu, const uint8_t *pBuf) BSTREAM_TO_UINT8 (pPdu->phySToM, pBuf); BSTREAM_TO_UINT16 (sduSizeMToS, pBuf); - pPdu->isoalPduType = (sduSizeMToS >> 15) & 0x01; + pPdu->framing = (sduSizeMToS >> 15) & 0x01; pPdu->sduSizeMToS = sduSizeMToS & 0x0FFF; BSTREAM_TO_UINT16 (pPdu->sduSizeSToM, pBuf); pPdu->sduSizeSToM &= 0x0FFF; @@ -648,8 +648,8 @@ uint8_t lctrUnpackCisReqPdu(lctrCisReq_t *pPdu, const uint8_t *pBuf) BSTREAM_TO_UINT24 (pPdu->sduIntervalSToM, pBuf); pPdu->sduIntervalSToM &= 0xFFFFF; - BSTREAM_TO_UINT8 (pPdu->plMToS, pBuf); - BSTREAM_TO_UINT8 (pPdu->plSToM, pBuf); + BSTREAM_TO_UINT16 (pPdu->plMToS, pBuf); + BSTREAM_TO_UINT16 (pPdu->plSToM, pBuf); BSTREAM_TO_UINT8 (pPdu->nse, pBuf); BSTREAM_TO_UINT24 (pPdu->subIntervUsec, pBuf); BSTREAM_TO_UINT8 (bn, pBuf); @@ -733,6 +733,73 @@ uint8_t lctrUnpackCisTermPdu(lctrCisTermInd_t *pPdu, const uint8_t *pBuf) return len; } +/*************************************************************************************************/ +/*! + * \brief Unpack a Power indication PDU. + * + * \param pPdu Power indication PDU. + * \param pBuf Packed packet buffer. + * + * \return PDU length. + */ +/*************************************************************************************************/ +static uint8_t lctrUnpackPwrChngIndPdu(lctrPwrChngInd_t *pPdu, const uint8_t *pBuf) +{ + const uint8_t len = LL_PWR_CHNG_IND_LEN; + + pBuf += 1; /* skip opcode */ + BSTREAM_TO_UINT8 (pPdu->phy, pBuf); + BSTREAM_TO_UINT8 (pPdu->limits, pBuf); + BSTREAM_TO_UINT8 (pPdu->delta, pBuf); + BSTREAM_TO_UINT8 (pPdu->txPower, pBuf); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Unpack a power control request PDU. + * + * \param pPdu Power indication PDU. + * \param pBuf Packed packet buffer. + * + * \return PDU length. + */ +/*************************************************************************************************/ +static uint8_t lctrUnpackPwrCtrlReqPdu(lctrPwrCtrlReq_t *pPdu, const uint8_t *pBuf) +{ + const uint8_t len = LL_PWR_CTRL_REQ_LEN; + + pBuf += 1; /* skip opcode */ + BSTREAM_TO_UINT8 (pPdu->phy, pBuf); + BSTREAM_TO_UINT8 (pPdu->delta, pBuf); + BSTREAM_TO_UINT8 (pPdu->txPower, pBuf); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Unpack a power control response PDU. + * + * \param pPdu Power indication PDU. + * \param pBuf Packed packet buffer. + * + * \return PDU length. + */ +/*************************************************************************************************/ +static uint8_t lctrUnpackPwrCtrlRspPdu(lctrPwrCtrlRsp_t *pPdu, const uint8_t *pBuf) +{ + const uint8_t len = LL_PWR_CTRL_RSP_LEN; + + pBuf += 1; /* skip opcode */ + BSTREAM_TO_UINT8 (pPdu->limits, pBuf); + BSTREAM_TO_UINT8 (pPdu->delta, pBuf); + BSTREAM_TO_UINT8 (pPdu->txPower, pBuf); + BSTREAM_TO_UINT8 (pPdu->apr, pBuf); + + return len; +} /*************************************************************************************************/ /*! * \brief Decode an LE-C channel buffer. @@ -984,6 +1051,36 @@ 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: + if ((lmgrCb.features & LL_FEAT_POWER_CHANGE_IND) == 0) + { + return LL_ERROR_CODE_UNKNOWN_LMP_PDU; + } + if (lctrUnpackPwrChngIndPdu(&pPdu->pld.pwrChngInd, pBuf) != pPdu->hdr.len) + { + return LL_ERROR_CODE_UNKNOWN_LMP_PDU; + } + break; + case LL_PDU_PWR_CTRL_REQ: + if ((lmgrCb.features & LL_FEAT_POWER_CONTROL_REQUEST) == 0) + { + return LL_ERROR_CODE_UNKNOWN_LMP_PDU; + } + if (lctrUnpackPwrCtrlReqPdu(&pPdu->pld.pwrCtrlReq, pBuf) != pPdu->hdr.len) + { + return LL_ERROR_CODE_UNKNOWN_LMP_PDU; + } + break; + case LL_PDU_PWR_CTRL_RSP: + if ((lmgrCb.features & LL_FEAT_POWER_CONTROL_REQUEST) == 0) + { + return LL_ERROR_CODE_UNKNOWN_LMP_PDU; + } + if (lctrUnpackPwrCtrlRspPdu(&pPdu->pld.pwrCtrlRsp, pBuf) != pPdu->hdr.len) + { + return LL_ERROR_CODE_UNKNOWN_LMP_PDU; + } + break; default: result = LL_ERROR_CODE_UNKNOWN_LMP_PDU; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_conn.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_conn.h index 904fd6a1c8..bb33c728df 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_conn.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_conn.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller data channel packet interface file. + * \file + * + * \brief Link layer controller data channel packet interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ @@ -209,13 +210,13 @@ typedef struct uint8_t cisId; /*!< CIS identifier. */ uint8_t phyMToS; /*!< Master to slave PHY. */ uint8_t phySToM; /*!< Slave to Master PHY. */ - uint8_t isoalPduType; /*!< ISOAL PDU type. */ + 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 */ - uint8_t plMToS; /*!< Master to slave payload. */ - uint8_t plSToM; /*!< Slave to master payload. */ + 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. */ @@ -254,6 +255,32 @@ typedef struct uint8_t reason; /*!< Reason for termination. */ } lctrCisTermInd_t; +/*! \brief Power control request PDU. */ +typedef struct +{ + uint8_t phy; /*!< PHY. */ + int8_t delta; /*!< Requested delta. */ + int8_t txPower; /*!< Local transmit power. */ +} lctrPwrCtrlReq_t; + +/*! \brief Power control RSP PDU. */ +typedef struct +{ + uint8_t limits; /*!< Limits field. */ + int8_t delta; /*!< Change in power. */ + int8_t txPower; /*!< Local txPower. */ + uint8_t apr; /*!< Acceptable power reduction. */ +} lctrPwrCtrlRsp_t; + +/*! \brief Power change indication PDU. */ +typedef struct +{ + uint8_t phy; /*!< PHY. */ + uint8_t limits; /*!< Limits field. */ + int8_t delta; /*!< Device txPower change. */ + int8_t txPower; /*!< Local txPower. */ +} lctrPwrChngInd_t; + /*! \brief Data channel control PDU. */ typedef struct { @@ -284,6 +311,9 @@ typedef struct lctrCisRsp_t cisRsp; /*!< CIS response. */ lctrCisInd_t cisInd; /*!< CIS indication. */ lctrCisTermInd_t cisTerm; /*!< CIS terminate indication. */ + lctrPwrCtrlReq_t pwrCtrlReq; /*!< Power control request. */ + lctrPwrCtrlRsp_t pwrCtrlRsp; /*!< Power control response. */ + lctrPwrChngInd_t pwrChngInd; /*!< Power change indication. */ } pld; /*!< Unpacked PDU payload. */ } lctrDataPdu_t; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_enc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_enc.c index a783156c09..42b18fa829 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_enc.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_enc.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master encryption packet implementation file. + * \file + * + * \brief Link layer controller master encryption packet implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_iso.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_iso.c new file mode 100644 index 0000000000..e2b8f33a47 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_iso.c @@ -0,0 +1,242 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller isochronous stream packet implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_pdu_iso.h" +#include "util/bstream.h" +#include "hci_defs.h" +#include + +/*************************************************************************************************/ +/*! + * \brief Unpack an ISO header. + * + * \param pHdr Unpacked packet header. + * \param pBuf Packed packet buffer. + * + * \return Header length. + */ +/*************************************************************************************************/ +uint8_t lctrIsoUnpackHdr(lctrIsoHdr_t *pHdr, const uint8_t *pBuf) +{ + uint8_t len = HCI_ISO_HDR_LEN + HCI_ISO_DL_MIN_LEN; + + uint16_t field16; + + BSTREAM_TO_UINT16(field16, pBuf); + pHdr->handle = (field16 >> 0) & 0x0FFF; + pHdr->pb = (field16 >> 12) & 0x03; + pHdr->tsFlag = (field16 >> 14) & 0x01; + + BSTREAM_TO_UINT16(pHdr->len, pBuf); + + 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); + + pHdr->sduLen = (field16 >> 0) & 0x0FFF; + pHdr->ps = (field16 >> 14) & 0x03; + + pHdr->pSdu = pBuf; + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Pack an ISO header. + * + * \param pBuf Packed packet buffer. + * \param pHdr Unpacked packet header. + * + * \return Header length. + */ +/*************************************************************************************************/ +uint8_t lctrIsoPackHdr(uint8_t *pBuf, const lctrIsoHdr_t *pHdr) +{ + const uint8_t len = HCI_ISO_HDR_LEN; + uint8_t dlLen = 0; + + uint16_t field16; + + field16 = (pHdr->handle & 0x0FFF) << 0; + field16 |= (pHdr->pb & 0x03) << 12; + field16 |= (pHdr->tsFlag & 0x01) << 14; + UINT16_TO_BSTREAM(pBuf, field16); + + uint8_t *pLen = pBuf; + pBuf += sizeof(uint16_t); + + switch (pHdr->pb) + { + case LCTR_PB_COMP: + case LCTR_PB_FIRST: + dlLen = HCI_ISO_DL_MIN_LEN; + if (pHdr->tsFlag) + { + UINT32_TO_BSTREAM(pBuf, pHdr->ts); + dlLen += HCI_ISO_TS_LEN; + } + + UINT16_TO_BSTREAM(pBuf, pHdr->pktSn); + + field16 = (pHdr->sduLen & 0x0FFF) << 0; + field16 |= (pHdr->ps & 0x03) << 14; + UINT16_TO_BSTREAM(pBuf, field16); + break; + + default: + break; + } + + /* Now that length is known, pack the length. */ + UINT16_TO_BSTREAM(pLen, pHdr->len + dlLen); + + return len + dlLen; +} + +/*************************************************************************************************/ +/*! + * \brief Pack a ISOAL Segmentation header. + * + * \param pBuf Packed packet buffer. + * \param pSegHdr Unpacked PDU header. + * + * \return Segmentation header length. + */ +/*************************************************************************************************/ +uint8_t lctrIsoPackSegHdr(uint8_t *pBuf, const lctrIsoSegHdr_t *pSegHdr) +{ + uint8_t len = LL_DATA_HDR_LEN; + + uint8_t flags = 0; + flags |= (pSegHdr->sc ) << 0; + flags |= (pSegHdr->cmplt) << 1; + UINT8_TO_BSTREAM(pBuf, flags); + + if (pSegHdr->sc == 0) + { + UINT8_TO_BSTREAM(pBuf, pSegHdr->len + LL_ISO_SEG_TO_LEN); + len += LL_ISO_SEG_TO_LEN; + UINT24_TO_BSTREAM(pBuf, pSegHdr->toffs); + } + else + { + UINT8_TO_BSTREAM(pBuf, pSegHdr->len); + } + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Pack a ISOAL Segmentation header. + * + * \param pBuf Packed packet buffer. + * \param pHdr Unpacked PDU header. + * + * \return Segmentation header length. + */ +/*************************************************************************************************/ +uint8_t lctrIsoUnpackSegHdr(lctrIsoSegHdr_t *pHdr, uint8_t *pBuf) +{ + uint8_t len = LL_DATA_HDR_LEN; + + uint8_t flags = 0; + BSTREAM_TO_UINT8(flags, pBuf); + pHdr->sc = (flags & LL_ISOAL_SEG_HDR_MASK_SC) >> 0; + pHdr->cmplt = (flags & LL_ISOAL_SEG_HDR_MASK_CMPLT) >> 1; + BSTREAM_TO_UINT8(pHdr->len, pBuf); + + if (pHdr->sc == 0) + { + len += LL_ISO_SEG_TO_LEN; + BSTREAM_TO_UINT24(pHdr->toffs, pBuf); + } + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Pack an CIS data channel PDU header. + * + * \param pBuf Packed packet buffer. + * \param pHdr Unpacked PDU header. + * + * \return Header length. + */ +/*************************************************************************************************/ +uint8_t lctrCisPackDataPduHdr(uint8_t *pBuf, const lctrCisDataPduHdr_t *pHdr) +{ + const uint8_t len = LL_DATA_HDR_LEN; + + uint16_t hdr = 0; + + hdr |= (pHdr->llid ) << 0; + hdr |= (pHdr->nesn & 1) << 2; + hdr |= (pHdr->sn & 1) << 3; + hdr |= (pHdr->cie & 1) << 4; + hdr |= (pHdr->np & 1) << 6; + hdr |= (pHdr->len ) << 8; + UINT16_TO_BSTREAM(pBuf, hdr); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Unpack a CIS data channel PDU header. + * + * \param pHdr Unpacked header. + * \param pBuf Packed packet buffer. + * + * \return Header length. + */ +/*************************************************************************************************/ +uint8_t lctrCisUnpackDataPduHdr(lctrCisDataPduHdr_t *pHdr, const uint8_t *pBuf) +{ + const uint8_t len = LL_DATA_HDR_LEN; + + uint16_t hdr; + + BSTREAM_TO_UINT16(hdr, pBuf); + + pHdr->llid = (hdr >> 0) & LL_DATA_HDR_LLID_MSK; + pHdr->nesn = (hdr >> 2) & 0x0001; + pHdr->sn = (hdr >> 3) & 0x0001; + pHdr->cie = (hdr >> 4) & 0x0001; + pHdr->np = (hdr >> 6) & 0x0001; + pHdr->len = (hdr >> 8) & LL_DATA_HDR_LEN_MSK; + + return len; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_iso.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_iso.h new file mode 100644 index 0000000000..3888a92ae8 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_pdu_iso.h @@ -0,0 +1,149 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller data channel packet interface file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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 LCTR_PDU_ISO_H +#define LCTR_PDU_ISO_H + +#include "wsf_types.h" +#include "wsf_queue.h" +#include "bb_ble_api.h" +#include "ll_defs.h" +#include "ll_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief Get length of ISO Header. */ +#define LCTR_GET_ISO_DATA_HDR_LEN(pIsoHdr) (HCI_ISO_HDR_LEN + (((pIsoHdr)->tsFlag) ? HCI_ISO_DL_MAX_LEN : HCI_ISO_DL_MIN_LEN)) + +/************************************************************************************************** + Constants +**************************************************************************************************/ + +/*! \brief Packet boundary flags. */ +typedef enum +{ + LCTR_PB_FIRST = 0, /*!< Data is the first fragment of a fragmented SDU. */ + LCTR_PB_CONT = 1, /*!< Data is a continuation fragment of a fragmented SDU. */ + LCTR_PB_COMP = 2, /*!< Data is a complete SDU. */ + LCTR_PB_LAST = 3 /*!< Data is the last fragment of a fragmented SDU. */ +} lctrPktBoundary_t; + +/*! \brief Packet status flags. */ +typedef enum +{ + LCTR_PS_VALID = 0, /*!< Data is received correctly. */ + LCTR_PS_INVALID = 1, /*!< Data with possible errors. */ + LCTR_PS_LOST = 2, /*!< Data with lost data. */ +} lctrPktStatus_t; + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief ISO header. */ +typedef struct +{ + /* ISO header */ + uint16_t handle; /*!< CIS or BIS handle. */ + lctrPktBoundary_t pb:8; /*!< Packet boundary flag. */ + bool_t tsFlag; /*!< Timestamp flag. */ + uint16_t len; /*!< Data length. */ + + /* ISO Data Load */ + uint32_t ts; /*!< Timestamp. */ + 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. */ +} lctrIsoHdr_t; + +/*! \brief ISO SDU descriptor. */ +typedef struct +{ + lctrIsoHdr_t hdr; /*!< ISO header. */ + uint32_t ts; /*!< Timestamp. */ + uint8_t data; /*!< Data. */ +} lctrSduDesc_t; + +/*! \brief ISO CIS PDU header. */ +typedef struct +{ + uint8_t llid; /*!< PDU type. */ + uint8_t nesn; /*!< Next Expected Sequence Number. */ + uint8_t sn; /*!< Sequence Number. */ + uint8_t cie; /*!< TRUE if stop next subevent. */ + uint8_t np; /*!< PDU type, whether a NULL PDU. */ + uint8_t len; /*!< Payload length. */ +} lctrCisDataPduHdr_t; + +/*! \brief ISO BIS PDU header. */ +typedef struct +{ + LlIsoLlid_t llid:8; /*!< PDU type. */ + uint8_t cssn; /*!< Control Subevent Sequence Number. */ + bool_t cstf; /*!< Control Subevent Submission Flag. */ + uint8_t len; /*!< Payload length. */ +} lctrBisDataPduHdr_t; + +/*! \brief ISOAL Segmentation Header. */ +typedef struct +{ + bool_t sc; /*!< Segment continuation flag. */ + bool_t cmplt; /*!< Segment complete flag. */ + uint8_t len; /*!< Payload length. */ + uint32_t toffs; /*!< Time offset. */ +} lctrIsoSegHdr_t; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/* Pack */ +uint8_t lctrIsoPackHdr(uint8_t *pBuf, const lctrIsoHdr_t *pHdr); +uint8_t lctrIsoPackSegHdr(uint8_t *pBuf, const lctrIsoSegHdr_t *pSegHdr); +uint8_t lctrIsoUnpackSegHdr(lctrIsoSegHdr_t *pHdr, uint8_t *pBuf); +uint8_t lctrCisPackDataPduHdr(uint8_t *pBuf, const lctrCisDataPduHdr_t *pHdr); +uint8_t lctrBisPackDataPduHdr(uint8_t *pBuf, const lctrBisDataPduHdr_t *pHdr); +uint8_t lctrBisPackBigChannelMapInd(uint8_t *pBuf, uint64_t chanMap, uint16_t instance); +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 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); +uint8_t lctrBisUnpackBigTerminateInd(uint8_t *pReason, uint16_t *pInstance, const uint8_t *pBuf); + +#ifdef __cplusplus +}; +#endif + +#endif /* LCTR_PDU_ISO_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_master.c index 266120a1b8..4bcd7da823 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master scan state machine implementation file. + * \file + * + * \brief Link layer controller master scan state machine implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -109,8 +110,6 @@ static const uint8_t lctrScanNextStateTbl[LCTR_SCAN_STATE_TOTAL][LCTR_SCAN_MSG_T * \brief Execute master scan state machine. * * \param event State machine event. - * - * \return None. */ /*************************************************************************************************/ void lctrMstScanExecuteSm(uint8_t event) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_master_ae.c index c7cd31185b..05008f5eb1 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master scan state machine implementation file. + * \file + * + * \brief Link layer controller master scan state machine implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -61,8 +62,8 @@ static const lctrActFn_t lctrExtScanActionTbl[LCTR_EXT_SCAN_STATE_TOTAL][LCTR_EX }, { /* LCTR_EXT_SCAN_STATE_SHUTDOWN */ NULL, /* LCTR_EXT_SCAN_MSG_RESET */ - lctrExtScanActDisallowScan, /* LCTR_EXT_SCAN_MSG_DISCOVER_ENABLE */ - lctrExtScanActDisallowScan, /* LCTR_EXT_SCAN_MSG_DISCOVER_DISABLE */ + lctrExtScanActHostEnable, /* LCTR_EXT_SCAN_MSG_DISCOVER_ENABLE */ + lctrExtScanHostDisable, /* LCTR_EXT_SCAN_MSG_DISCOVER_DISABLE */ lctrExtScanActScanTerm /* LCTR_EXT_SCAN_MSG_TERMINATE */ }, { /* LCTR_EXT_SCAN_STATE_RESET */ @@ -325,8 +326,6 @@ static const uint8_t lctrPerScanNextStateTbl[LCTR_PER_SCAN_STATE_TOTAL][LCTR_PER * * \param pExtScanCtx Extended scan context. * \param event State machine event. - * - * \return None. */ /*************************************************************************************************/ void lctrMstExtScanExecuteSm(lctrExtScanCtx_t *pExtScanCtx, uint8_t event) @@ -346,8 +345,6 @@ void lctrMstExtScanExecuteSm(lctrExtScanCtx_t *pExtScanCtx, uint8_t event) * \brief Execute master create sync state machine. * * \param event State machine event. - * - * \return None. */ /*************************************************************************************************/ void lctrMstCreateSyncExecuteSm(uint8_t event) @@ -367,8 +364,6 @@ void lctrMstCreateSyncExecuteSm(uint8_t event) * \brief Execute master transfer sync state machine. * * \param event State machine event. - * - * \return None. */ /*************************************************************************************************/ void lctrMstTransferSyncExecuteSm(uint8_t event) @@ -389,8 +384,6 @@ void lctrMstTransferSyncExecuteSm(uint8_t event) * * \param pPerScanCtx Periodic scanning context. * \param event State machine event. - * - * \return None. */ /*************************************************************************************************/ void lctrMstPerScanExecuteSm(lctrPerScanCtx_t *pPerScanCtx, uint8_t event) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_slave.c index b46d0b21c9..27ba51dc02 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave advertising state machine implementation file. + * \file + * + * \brief Link layer controller slave advertising state machine implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -116,8 +117,6 @@ static const uint8_t lctrAdvNextStateTbl[LCTR_ADV_STATE_TOTAL][LCTR_ADV_MSG_TOTA * \brief Execute slave advertising state machine. * * \param event State machine event. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvAdvExecuteSm(uint8_t event) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_slave_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_slave_ae.c index 7f92d70650..bda9c64e0d 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_slave_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_adv_slave_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave advertising state machine implementation file. + * \file + * + * \brief Link layer controller slave advertising state machine implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -36,7 +37,7 @@ typedef void (*lctrExtActFn_t)(lctrAdvSet_t *pAdvSet); /*! \brief Periodic action function call signature. */ typedef void (*lctrPerActFn_t)(lctrAdvSet_t *pAdvSet); -/*! \brief Periodic adv acad function call signature. */ +/*! \brief Periodic Adv ACAD function call signature. */ typedef void (*lctrAcadActFn_t)(lctrAdvSet_t *pAdvSet); /************************************************************************************************** @@ -175,16 +176,20 @@ static const uint8_t lctrPerAdvNextStateTbl[LCTR_PER_ADV_STATE_TOTAL][LCTR_PER_A } }; -/*! \brief Acad state machine action table */ +/*! \brief ACAD state machine action table */ static const lctrAcadActFn_t lctrAcadActionTbl[LCTR_ACAD_NUM_ID][LCTR_ACAD_COMM_MSG_TOTAL] = { { /* LCTR_ACAD_ID_CHAN_MAP_UPDATE */ lctrSlvAcadActChanMapUpdateStart, /* LCTR_ACAD_COMM_MSG_START */ lctrSlvAcadActChanMapUpdateFinish /* LCTR_ACAD_COMM_MSG_FINISH */ + }, + { /* LCTR_ACAD_ID_BIG_INFO */ + lctrSlvAcadActBigCreated, /* LCTR_ACAD_COMM_MSG_START */ + lctrSlvAcadActBigTerminated /* LCTR_ACAD_COMM_MSG_FINISH */ } }; -/*! \brief Acad state machine next state table. */ +/*! \brief ACAD state machine next state table. */ static const uint8_t lctrAcadNextStateTbl[LCTR_ACAD_STATE_TOTAL][LCTR_ACAD_COMM_MSG_TOTAL] = { { /* LCTR_ACAD_STATE_DISABLED */ @@ -204,8 +209,6 @@ static const uint8_t lctrAcadNextStateTbl[LCTR_ACAD_STATE_TOTAL][LCTR_ACAD_COMM_ * * \param pAdvSet Advertising set. * \param event State machine event. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvExtAdvExecuteSm(lctrAdvSet_t *pAdvSet, uint8_t event) @@ -226,8 +229,6 @@ void lctrSlvExtAdvExecuteSm(lctrAdvSet_t *pAdvSet, uint8_t event) * * \param pAdvSet Advertising set. * \param event State machine event. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvPeriodicAdvExecuteSm(lctrAdvSet_t *pAdvSet, uint8_t event) @@ -244,11 +245,11 @@ void lctrSlvPeriodicAdvExecuteSm(lctrAdvSet_t *pAdvSet, uint8_t event) /*************************************************************************************************/ /*! - * \brief Get common acad event from dispatcher message. + * \brief Get common ACAD event from dispatcher message. * * \param event State machine event. * - * \return None. + * \return Comment event ID. */ /*************************************************************************************************/ static uint8_t lctrSlvGetAcadCommEvt(uint8_t event) @@ -256,9 +257,11 @@ static uint8_t lctrSlvGetAcadCommEvt(uint8_t event) switch (event) { case LCTR_ACAD_MSG_CHAN_UPDATE: + case LCTR_ACAD_MSG_BIG_CREATED: return LCTR_ACAD_COMM_MSG_START; case LCTR_ACAD_MSG_CHAN_UPDATE_FINISH: + case LCTR_ACAD_MSG_BIG_TERMINATED: return LCTR_ACAD_COMM_MSG_FINISH; default: @@ -268,11 +271,11 @@ static uint8_t lctrSlvGetAcadCommEvt(uint8_t event) /*************************************************************************************************/ /*! - * \brief Get Acad id from dispatcher message. + * \brief Get ACAD ID from dispatcher message. * * \param event State machine event. * - * \return None. + * \return ACAD ID. */ /*************************************************************************************************/ static uint8_t lctrSlvGetAcadId(uint8_t event) @@ -283,6 +286,10 @@ static uint8_t lctrSlvGetAcadId(uint8_t event) case LCTR_ACAD_MSG_CHAN_UPDATE_FINISH: return LCTR_ACAD_ID_CHAN_MAP_UPDATE; + case LCTR_ACAD_MSG_BIG_CREATED: + case LCTR_ACAD_MSG_BIG_TERMINATED: + return LCTR_ACAD_ID_BIG_INFO; + default: return LCTR_ACAD_INVALID_ID; } @@ -302,11 +309,11 @@ void lctrSlvAcadExecuteSm(lctrAdvSet_t *pAdvSet, uint8_t event) { uint8_t acadId; - if ((event = lctrSlvGetAcadCommEvt(event)) == LCTR_ACAD_COMM_MSG_INVALID) + if ((acadId = lctrSlvGetAcadId(event)) == LCTR_ACAD_INVALID_ID) { return; } - if ((acadId = lctrSlvGetAcadId(event)) == LCTR_ACAD_INVALID_ID) + if ((event = lctrSlvGetAcadCommEvt(event)) == LCTR_ACAD_COMM_MSG_INVALID) { return; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_bis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_bis_master.c new file mode 100644 index 0000000000..aa0e79107c --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_bis_master.c @@ -0,0 +1,168 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller BIG state machine implementation 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. + */ +/*************************************************************************************************/ + +#include "lctr_int_bis_master.h" +#include "wsf_trace.h" + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief Extended action function call signature. */ +typedef void (*lctrMstBigActFn_t)(lctrBigCtx_t *pBigCtx); + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*! \brief BIG master state machine action table. */ +static const lctrMstBigActFn_t lctrMstBigActionTbl[LCTR_MST_BIG_STATE_TOTAL][LCTR_MST_BIG_MSG_TOTAL] = +{ + { /* LCTR_MST_BIG_STATE_DISABLED */ + NULL, /* LCTR_MST_BIG_MSG_RESET */ + lctrMstBigActStart, /* LCTR_MST_BIG_API_CREATE_SYNC */ + NULL, /* LCTR_MST_BIG_API_TERMINATE_SYNC */ + NULL, /* LCTR_MST_BIG_ACAD_BIG_INFO */ + NULL, /* LCTR_MST_BIG_PDU_TERM */ + NULL, /* LCTR_MST_BIG_INT_SYNC_TIMEOUT */ + NULL, /* LCTR_MST_BIG_INT_MIC_FAILED */ + NULL /* LCTR_MST_BIG_INT_TERMINATED_SYNC */ + }, + { /* LCTR_MST_BIG_STATE_SYNCING */ + lctrMstBigActShutdown, /* LCTR_MST_BIG_MSG_RESET */ + NULL, /* LCTR_MST_BIG_API_CREATE_SYNC */ + lctrMstBigActShutdown, /* LCTR_MST_BIG_API_TERMINATE_SYNC */ + lctrMstBigActBigSync, /* LCTR_MST_BIG_ACAD_BIG_INFO */ + NULL, /* LCTR_MST_BIG_PDU_TERM */ + NULL, /* LCTR_MST_BIG_INT_SYNC_TIMEOUT */ + NULL, /* LCTR_MST_BIG_INT_MIC_FAILED */ + NULL /* LCTR_MST_BIG_INT_TERMINATED_SYNC */ + }, + { /* LCTR_MST_BIG_STATE_SYNCED */ + lctrMstBigActShutdown, /* LCTR_MST_BIG_MSG_RESET */ + NULL, /* LCTR_MST_BIG_API_CREATE_SYNC */ + lctrMstBigActShutdown, /* LCTR_MST_BIG_API_TERMINATE_SYNC */ + NULL, /* LCTR_MST_BIG_ACAD_BIG_INFO */ + lctrMstBigActTerm, /* LCTR_MST_BIG_PDU_TERM */ + lctrMstBigActSyncLost, /* LCTR_MST_BIG_INT_SYNC_TIMEOUT */ + lctrMstBigActMicFailed, /* LCTR_MST_BIG_INT_MIC_FAILED */ + lctrMstBigActCleanup /* LCTR_MST_BIG_INT_TERMINATED_SYNC */ + }, + { /* LCTR_MST_BIG_STATE_SHUTDOWN */ + NULL, /* LCTR_MST_BIG_MSG_RESET */ + NULL, /* LCTR_MST_BIG_API_CREATE_SYNC */ + NULL, /* LCTR_MST_BIG_API_TERMINATE_SYNC */ + NULL, /* LCTR_MST_BIG_ACAD_BIG_INFO */ + NULL, /* LCTR_MST_BIG_PDU_TERM */ + NULL, /* LCTR_MST_BIG_INT_SYNC_TIMEOUT */ + NULL, /* LCTR_MST_BIG_INT_MIC_FAILED */ + lctrMstBigActCleanup /* LCTR_MST_BIG_INT_TERMINATED_SYNC */ + }, + { /* LCTR_EXT_ADV_STATE_RESET */ + NULL, /* LCTR_MST_BIG_MSG_RESET */ + NULL, /* LCTR_MST_BIG_API_CREATE_SYNC */ + NULL, /* LCTR_MST_BIG_API_TERMINATE_SYNC */ + NULL, /* LCTR_MST_BIG_ACAD_BIG_INFO */ + NULL, /* LCTR_MST_BIG_PDU_TERM */ + NULL, /* LCTR_MST_BIG_INT_SYNC_TIMEOUT */ + NULL, /* LCTR_MST_BIG_INT_MIC_FAILED */ + lctrMstBigActCleanup /* LCTR_MST_BIG_INT_TERMINATED_SYNC */ + } +}; + +/*! \brief BIG master state machine next state table. */ +static const uint8_t lctrMstBigNextStateTbl[LCTR_MST_BIG_STATE_TOTAL][LCTR_MST_BIG_MSG_TOTAL] = +{ + { /* LCTR_MST_BIG_STATE_DISABLED */ + LCTR_MST_BIG_STATE_DISABLED, /* LCTR_MST_BIG_MSG_RESET */ + LCTR_MST_BIG_STATE_SYNCING, /* LCTR_MST_BIG_API_CREATE_SYNC */ + LCTR_MST_BIG_STATE_DISABLED, /* LCTR_MST_BIG_API_TERMINATE_SYNC */ + LCTR_MST_BIG_STATE_DISABLED, /* LCTR_MST_BIG_ACAD_BIG_INFO */ + LCTR_MST_BIG_STATE_DISABLED, /* LCTR_MST_BIG_PDU_TERM */ + LCTR_MST_BIG_STATE_DISABLED, /* LCTR_MST_BIG_INT_SYNC_TIMEOUT */ + LCTR_MST_BIG_STATE_DISABLED, /* LCTR_MST_BIG_INT_MIC_FAILED */ + LCTR_MST_BIG_STATE_DISABLED /* LCTR_MST_BIG_INT_TERMINATED_SYNC */ + }, + { /* LCTR_MST_BIG_STATE_SYNCING */ + LCTR_MST_BIG_STATE_RESET, /* LCTR_MST_BIG_MSG_RESET */ + LCTR_MST_BIG_STATE_SYNCING, /* LCTR_MST_BIG_API_CREATE_SYNC */ + LCTR_MST_BIG_STATE_SHUTDOWN, /* LCTR_MST_BIG_API_TERMINATE_SYNC */ + LCTR_MST_BIG_STATE_SYNCED, /* LCTR_MST_BIG_ACAD_BIG_INFO */ + LCTR_MST_BIG_STATE_SYNCING, /* LCTR_MST_BIG_PDU_TERM */ + LCTR_MST_BIG_STATE_SYNCING, /* LCTR_MST_BIG_INT_SYNC_TIMEOUT */ + LCTR_MST_BIG_STATE_SHUTDOWN, /* LCTR_MST_BIG_INT_MIC_FAILED */ + LCTR_MST_BIG_STATE_SYNCING /* LCTR_MST_BIG_INT_TERMINATED_SYNC */ + }, + { /* LCTR_MST_BIG_STATE_SYNCED */ + LCTR_MST_BIG_STATE_RESET, /* LCTR_MST_BIG_MSG_RESET */ + LCTR_MST_BIG_STATE_SYNCED, /* LCTR_MST_BIG_API_CREATE_SYNC */ + LCTR_MST_BIG_STATE_SHUTDOWN, /* LCTR_MST_BIG_API_TERMINATE_SYNC */ + LCTR_MST_BIG_STATE_SYNCED, /* LCTR_MST_BIG_ACAD_BIG_INFO */ + LCTR_MST_BIG_STATE_SHUTDOWN, /* LCTR_MST_BIG_PDU_TERM */ + LCTR_MST_BIG_STATE_SHUTDOWN, /* LCTR_MST_BIG_INT_SYNC_TIMEOUT */ + LCTR_MST_BIG_STATE_SHUTDOWN, /* LCTR_MST_BIG_INT_MIC_FAILED */ + LCTR_MST_BIG_STATE_DISABLED /* LCTR_MST_BIG_INT_TERMINATED_SYNC */ + }, + { /* LCTR_MST_BIG_STATE_SHUTDOWN */ + LCTR_MST_BIG_STATE_RESET, /* LCTR_MST_BIG_MSG_RESET */ + LCTR_MST_BIG_STATE_SHUTDOWN, /* LCTR_MST_BIG_API_CREATE_SYNC */ + LCTR_MST_BIG_STATE_SHUTDOWN, /* LCTR_MST_BIG_API_TERMINATE_SYNC */ + LCTR_MST_BIG_STATE_SHUTDOWN, /* LCTR_MST_BIG_ACAD_BIG_INFO */ + LCTR_MST_BIG_STATE_SHUTDOWN, /* LCTR_MST_BIG_PDU_TERM */ + LCTR_MST_BIG_STATE_SHUTDOWN, /* LCTR_MST_BIG_INT_SYNC_TIMEOUT */ + LCTR_MST_BIG_STATE_SHUTDOWN, /* LCTR_MST_BIG_INT_MIC_FAILED */ + LCTR_MST_BIG_STATE_SHUTDOWN /* LCTR_MST_BIG_INT_TERMINATED_SYNC */ + }, + { /* LCTR_MST_BIG_STATE_RESET */ + LCTR_MST_BIG_STATE_RESET, /* LCTR_MST_BIG_MSG_RESET */ + LCTR_MST_BIG_STATE_RESET, /* LCTR_MST_BIG_API_CREATE_SYNC */ + LCTR_MST_BIG_STATE_RESET, /* LCTR_MST_BIG_API_TERMINATE_SYNC */ + LCTR_MST_BIG_STATE_RESET, /* LCTR_MST_BIG_ACAD_BIG_INFO */ + LCTR_MST_BIG_STATE_RESET, /* LCTR_MST_BIG_PDU_TERM */ + LCTR_MST_BIG_STATE_RESET, /* LCTR_MST_BIG_INT_SYNC_TIMEOUT */ + LCTR_MST_BIG_STATE_RESET, /* LCTR_MST_BIG_INT_MIC_FAILED */ + LCTR_MST_BIG_STATE_RESET /* LCTR_MST_BIG_INT_TERMINATED_SYNC */ + } +}; + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Execute BIG main state machine. + * + * \param pBigCtx BIG context. + * \param event State machine event. + *************************************************************************************************/ +void lctrMstBigExecuteSm(lctrBigCtx_t *pBigCtx, LctrMstBigMsg_t event) +{ + LL_TRACE_INFO3("lctrMstBigExecuteSm: bigHandle=%u, state=%u, event=%u", pBigCtx->handle, pBigCtx->state, event); + + if (lctrMstBigActionTbl[pBigCtx->state][event]) + { + lctrMstBigActionTbl[pBigCtx->state][event](pBigCtx); + } + + pBigCtx->state = lctrMstBigNextStateTbl[pBigCtx->state][event]; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_bis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_bis_slave.c new file mode 100644 index 0000000000..a4bd7a4ae1 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_bis_slave.c @@ -0,0 +1,129 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller BIG state machine implementation file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_bis_slave.h" +#include "sch_api.h" +#include "wsf_assert.h" +#include "wsf_trace.h" + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief Extended action function call signature. */ +typedef void (*lctrSlvBigActFn_t)(lctrBigCtx_t *pBigCtx); + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*! \brief BIS slave state machine action table. */ +static const lctrSlvBigActFn_t lctrSlvBigActionTbl[LCTR_SLV_BIG_STATE_TOTAL][LCTR_SLV_BIG_MSG_TOTAL] = +{ + { /* LCTR_SLV_BIG_STATE_DISABLED */ + NULL, /* LCTR_SLV_BIG_MSG_RESET */ + lctrSlvBigActStart, /* LCTR_SLV_BIG_MSG_CREATE_BIG */ + NULL, /* LCTR_SLV_BIG_MSG_CH_MAP_UPD */ + NULL, /* LCTR_SLV_BIG_MSG_TERMINATE_BIG */ + NULL /* LCTR_SLV_BIG_MSG_TERMINATED */ + }, + { /* LCTR_SLV_BIG_STATE_ENABLED */ + lctrSlvBigActShutdown, /* LCTR_SLV_BIG_MSG_RESET */ + NULL, /* LCTR_SLV_BIG_MSG_CREATE_BIG */ + lctrSlvBigActSendChMapUpd, /* LCTR_SLV_BIG_MSG_CH_MAP_UPD */ + lctrSlvBigActSendTerm, /* LCTR_SLV_BIG_MSG_TERMINATE_BIG */ + NULL /* LCTR_SLV_BIG_MSG_TERMINATED */ + }, + { /* LCTR_SLV_BIG_STATE_SHUTDOWN */ + NULL, /* LCTR_SLV_BIG_MSG_RESET */ + NULL, /* LCTR_SLV_BIG_MSG_CREATE_BIG */ + NULL, /* LCTR_SLV_BIG_MSG_CH_MAP_UPD */ + lctrSlvBigActSendTerm, /* LCTR_SLV_BIG_MSG_TERMINATE_BIG */ + lctrSlvBigActCleanup /* LCTR_SLV_BIG_MSG_TERMINATED */ + }, + { /* LCTR_EXT_ADV_STATE_RESET */ + NULL, /* LCTR_SLV_BIG_MSG_RESET */ + NULL, /* LCTR_SLV_BIG_MSG_CREATE_BIG */ + NULL, /* LCTR_SLV_BIG_MSG_CH_MAP_UPD */ + NULL, /* LCTR_SLV_BIG_MSG_TERMINATE_BIG */ + lctrSlvBigActCleanup /* LCTR_SLV_BIG_MSG_TERMINATED */ + } +}; + +/*! \brief BIS slave state machine next state table. */ +static const uint8_t lctrSlvBigNextStateTbl[LCTR_SLV_BIG_STATE_TOTAL][LCTR_SLV_BIG_MSG_TOTAL] = +{ + { /* LCTR_SLV_BIG_STATE_DISABLED */ + LCTR_SLV_BIG_STATE_DISABLED, /* LCTR_SLV_BIG_MSG_RESET */ + LCTR_SLV_BIG_STATE_ENABLED, /* LCTR_SLV_BIG_MSG_CREATE_BIG */ + LCTR_SLV_BIG_STATE_DISABLED, /* LCTR_SLV_BIG_MSG_CH_MAP_UPD */ + LCTR_SLV_BIG_STATE_DISABLED, /* LCTR_SLV_BIG_MSG_TERMINATE_BIG */ + LCTR_SLV_BIG_STATE_DISABLED /* LCTR_SLV_BIG_MSG_TERMINATED */ + }, + { /* LCTR_SLV_BIG_STATE_ENABLED */ + LCTR_SLV_BIG_STATE_RESET, /* LCTR_SLV_BIG_MSG_RESET */ + LCTR_SLV_BIG_STATE_ENABLED, /* LCTR_SLV_BIG_MSG_CREATE_BIG */ + LCTR_SLV_BIG_STATE_ENABLED, /* LCTR_SLV_BIG_MSG_CH_MAP_UPD */ + LCTR_SLV_BIG_STATE_SHUTDOWN, /* LCTR_SLV_BIG_MSG_TERMINATE_BIG */ + LCTR_SLV_BIG_STATE_DISABLED, /* LCTR_SLV_BIG_MSG_TERMINATED */ + }, + { /* LCTR_SLV_BIG_STATE_SHUTDOWN */ + LCTR_SLV_BIG_STATE_RESET, /* LCTR_SLV_BIG_MSG_RESET */ + LCTR_SLV_BIG_STATE_SHUTDOWN, /* LCTR_SLV_BIG_MSG_CREATE_BIG */ + LCTR_SLV_BIG_STATE_SHUTDOWN, /* LCTR_SLV_BIG_MSG_CH_MAP_UPD */ + LCTR_SLV_BIG_STATE_SHUTDOWN, /* LCTR_SLV_BIG_MSG_TERMINATE_BIG */ + LCTR_SLV_BIG_STATE_DISABLED /* LCTR_SLV_BIG_MSG_TERMINATED */ + }, + { /* LCTR_SLV_BIG_STATE_RESET */ + LCTR_SLV_BIG_STATE_RESET, /* LCTR_SLV_BIG_MSG_RESET */ + LCTR_SLV_BIG_STATE_RESET, /* LCTR_SLV_BIG_MSG_CREATE_BIG */ + LCTR_SLV_BIG_STATE_RESET, /* LCTR_SLV_BIG_MSG_CH_MAP_UPD */ + LCTR_SLV_BIG_STATE_RESET, /* LCTR_SLV_BIG_MSG_TERMINATE_BIG */ + LCTR_SLV_BIG_STATE_DISABLED /* LCTR_SLV_BIG_MSG_TERMINATED */ + } +}; + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Execute BIG main state machine. + * + * \param pBigCtx BIS context. + * \param event State machine event. + */ +/*************************************************************************************************/ +void lctrSlvBigExecuteSm(lctrBigCtx_t *pBigCtx, uint8_t event) +{ + LL_TRACE_INFO3("lctrSlvBigExecuteSm: bigHandle=%u, state=%u, event=%u", pBigCtx->handle, pBigCtx->state, event); + + if (lctrSlvBigActionTbl[pBigCtx->state][event]) + { + lctrSlvBigActionTbl[pBigCtx->state][event](pBigCtx); + } + + pBigCtx->state = lctrSlvBigNextStateTbl[pBigCtx->state][event]; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_cis.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_cis.c new file mode 100644 index 0000000000..6499914c51 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_cis.c @@ -0,0 +1,169 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller CIS main state machine implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_cis.h" +#include "lctr_api_conn.h" +#include "sch_api.h" +#include "wsf_assert.h" +#include "wsf_trace.h" + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Get remapped event. + * + * \param pCisCtx CIS Context. + * \param event Subsystem event. + * + * \return Procedure event ID. + */ +/*************************************************************************************************/ +static uint8_t lctrRemapEvent(lctrCisCtx_t *pCisCtx, uint8_t event) +{ + switch (event) + { + /*** Peer messages ***/ + + /*** Host messages ***/ + + case LCTR_CONN_MSG_API_DISCONNECT: + { + lctrCisStoreDisconnectReason(pCisCtx); + return LCTR_CIS_MSG_CIS_DISC; + } + + /*** Internal messages ***/ + case LCTR_CONN_TERM_SUP_TIMEOUT: + { + lctrCisStoreConnTimeoutTerminateReason(pCisCtx); + return LCTR_CIS_MSG_CIS_CONN_FAIL; + } + case LCTR_CIS_MSG_CIS_TERM_MIC_FAILED: + { + lctrCisStoreMicFailedTerminateReason(pCisCtx); + return LCTR_CIS_MSG_CIS_CONN_FAIL; + } + case LCTR_CIS_MSG_CIS_EST: + return LCTR_CIS_MSG_CIS_EST; + case LCTR_CIS_MSG_CIS_EST_FAIL: + return LCTR_CIS_MSG_CIS_EST_FAIL; + case LCTR_CIS_MSG_CIS_CLOSED: + return LCTR_CIS_MSG_CIS_CLOSED; + + default: + break; + } + return LCTR_CIS_MSG_INVALID; +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Execute CIS main state machine. + * + * \param pCisCtx CIS context. + * \param event State machine event. + *************************************************************************************************/ +void lctrCisExecuteSm(lctrCisCtx_t *pCisCtx, uint8_t event) +{ + if ((event = lctrRemapEvent(pCisCtx, event)) == LCTR_CIS_MSG_INVALID) + { + return; + } + + LL_TRACE_INFO3("lctrCisExecuteSm: handle=%d state=%u, event=%u", pCisCtx->cisHandle, pCisCtx->state, event); + + switch (pCisCtx->state) + { + case LCTR_CIS_STATE_IDLE: + switch (event) + { + case LCTR_CIS_MSG_CIS_EST: + lctrCisActCisEst(pCisCtx); + pCisCtx->state = LCTR_CIS_STATE_EST; + break; + case LCTR_CIS_MSG_CIS_EST_FAIL: + lctrCisActCisEstFail(pCisCtx); + pCisCtx->state = LCTR_CIS_STATE_IDLE; + break; + default: + LL_TRACE_INFO1("Invalid event in the LCTR_CIS_STATE_IDLE, event=%u", event); + break; + } + break; + + case LCTR_CIS_STATE_EST: + switch (event) + { + case LCTR_CIS_MSG_CIS_DISC: + lctrCisActDisc(pCisCtx); + pCisCtx->state = LCTR_CIS_STATE_SHUTDOWN; + break; + case LCTR_CIS_MSG_CIS_CONN_FAIL: + lctrCisActFail(pCisCtx); + pCisCtx->state = LCTR_CIS_STATE_IDLE; + break; + case LCTR_CIS_MSG_CIS_CLOSED: + lctrCisActClosed(pCisCtx); + pCisCtx->state = LCTR_CIS_STATE_IDLE; + break; + + default: + LL_TRACE_INFO1("Invalid event in the LCTR_CIS_STATE_EST, event=%u", event); + break; + } + break; + + case LCTR_CIS_STATE_SHUTDOWN: + switch (event) + { + case LCTR_CIS_MSG_CIS_CLOSED: + lctrCisActClosed(pCisCtx); + pCisCtx->state = LCTR_CIS_STATE_IDLE; + break; + + default: + LL_TRACE_INFO1("Invalid event in the LCTR_CIS_STATE_SHUTDOWN, event=%u", event); + break; + } + break; + + default: + break; + } +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_conn_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_conn_master.c index 9c48eff692..555b587def 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_conn_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_conn_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master connection state machine implementation file. + * \file + * + * \brief Link layer controller master connection state machine implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -36,8 +37,6 @@ * * \param pCtx Connection context. * \param event State machine event. - * - * \return None. */ /*************************************************************************************************/ void lctrMstConnExecuteSm(lctrConnCtx_t *pCtx, uint8_t event) @@ -128,8 +127,10 @@ void lctrMstConnExecuteSm(lctrConnCtx_t *pCtx, uint8_t event) { case LCTR_CONN_TERMINATED: LL_TRACE_INFO2("lctrMstConnExecuteSm: handle=%u, state=%u, event=TERMINATED", LCTR_GET_CONN_HANDLE(pCtx), pCtx->state); - SchRmRemove(LCTR_GET_CONN_HANDLE(pCtx)); lctrNotifyHostDisconnectInd(pCtx); + /* Fallthrough. */ + case LCTR_CONN_INIT_CANCELED: + SchRmRemove(LCTR_GET_CONN_HANDLE(pCtx)); lctrFreeConnCtx(pCtx); break; default: diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_conn_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_conn_slave.c index 683626b66c..6314ccb056 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_conn_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_conn_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller connection state machine implementation file. + * \file + * + * \brief Link layer controller connection state machine implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -26,6 +27,7 @@ #include "lctr_int_adv_slave.h" #include "lmgr_api_conn.h" #include "sch_api.h" +#include "sch_api_ble.h" #include "wsf_assert.h" #include "wsf_trace.h" @@ -35,8 +37,6 @@ * * \param pCtx Connection context. * \param event State machine event. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvConnExecuteSm(lctrConnCtx_t *pCtx, uint8_t event) @@ -129,7 +129,7 @@ void lctrSlvConnExecuteSm(lctrConnCtx_t *pCtx, uint8_t event) case LCTR_CONN_STATE_ESTABLISHED_STARTUP: LL_TRACE_INFO1("lctrSlvConnExecuteSm: state=ESTABLISHED_STARTUP, event=%u", event); - switch(event) + switch (event) { case LCTR_CONN_SLV_INIT_STARTUP_LLCP: pCtx->state = LCTR_CONN_STATE_ESTABLISHED_READY; @@ -216,8 +216,6 @@ void lctrSlvConnExecuteSm(lctrConnCtx_t *pCtx, uint8_t event) * * \param pCtx Connection context. * \param event State machine event. - * - * \return None. */ /*************************************************************************************************/ void lctrConnStatelessEventHandler(lctrConnCtx_t *pCtx, uint8_t event) @@ -226,6 +224,11 @@ void lctrConnStatelessEventHandler(lctrConnCtx_t *pCtx, uint8_t event) { case LCTR_CONN_TERMINATED: LL_TRACE_INFO2("lctrConnStatelessEventHandler: handle=%u, state=%u, event=TERMINATED", LCTR_GET_CONN_HANDLE(pCtx), pCtx->state); + if (pCtx->role == LL_ROLE_SLAVE) + { + SchTmRemove(LCTR_GET_CONN_HANDLE(pCtx)); + } + lctrNotifyHostDisconnectInd(pCtx); lctrFreeConnCtx(pCtx); break; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_init_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_init_master.c index 2f962e4439..a5c2be4029 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_init_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_init_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master initiate state machine implementation file. + * \file + * + * \brief Link layer controller master initiate state machine implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -100,8 +101,6 @@ static const uint8_t lctrInitNextStateTbl[LCTR_INIT_STATE_TOTAL][LCTR_INIT_MSG_T * \brief Execute master scan and initiate state machine. * * \param event State machine event. - * - * \return None. */ /*************************************************************************************************/ void lctrMstInitExecuteSm(uint8_t event) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_init_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_init_master_ae.c index 14cc356251..0e1ad283d7 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_init_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_init_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master initiate state machine implementation file. + * \file + * + * \brief Link layer controller master initiate state machine implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -102,8 +103,6 @@ static const uint8_t lctrExtInitNextStateTbl[LCTR_EXT_INIT_STATE_TOTAL][LCTR_EXT * * \param pExtInitCtx Extended scanning context. * \param event State machine event. - * - * \return None. */ /*************************************************************************************************/ void lctrMstExtInitExecuteSm(lctrExtScanCtx_t *pExtInitCtx, uint8_t event) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_cis.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_cis.c new file mode 100644 index 0000000000..b2a1a9a2ae --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_cis.c @@ -0,0 +1,328 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller CIS LLCP state machine implementation file shared by master + * and slave. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_cis_master.h" +#include "lctr_int_conn_master.h" +#include "lctr_int_conn.h" +#include "lmgr_api.h" +#include "wsf_assert.h" +#include "wsf_trace.h" +#include "util/bstream.h" + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief Action function call signature. */ +typedef void (*lctrActFn_t)(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*! \brief CIS termination state machine action table. */ +static const lctrActFn_t lctrCisTermActionTbl[LCTR_CIS_TERM_STATE_TOTAL][LCTR_CIS_TERM_EVENT_TOTAL] = +{ + { /* LCTR_CIS_TERM_STATE_IDLE */ + lctrCisLlcpActHostDisc, /* LCTR_CIS_TERM_EVENT_HOST_DISC */ + lctrCisLlcpActPeerDisc, /* LCTR_CIS_TERM_EVENT_PEER_DISC */ + lctrCisLlcpActIntHostDisc, /* LCTR_CIS_TERM_EVENT_INT_START_DISC */ + lctrCisLlcpActIntPeerDisc, /* LCTR_CIS_TERM_EVENT_INT_START_PEER_DISC */ + NULL /* LCTR_CIS_TERM_EVENT_CIS_TERM */ + }, + { /* LCTR_CIS_TERM_STATE_TERMINATING */ + NULL, /* LCTR_CIS_TERM_EVENT_HOST_DISC */ + NULL, /* LCTR_CIS_TERM_EVENT_PEER_DISC */ + NULL, /* LCTR_CIS_TERM_EVENT_INT_START_DISC */ + NULL, /* LCTR_CIS_TERM_EVENT_INT_START_PEER_DISC */ + lctrCisLlcpActCisTerm /* LCTR_CIS_TERM_EVENT_CIS_TERM */ + } +}; + +/*! \brief CIS termination state machine next state table. */ +static const uint8_t lctrCisTermNextStateTbl[LCTR_CIS_TERM_STATE_TOTAL][LCTR_CIS_TERM_EVENT_TOTAL] = +{ + { /* LCTR_CIS_TERM_STATE_IDLE */ + LCTR_CIS_TERM_STATE_TERMINATING, /* LCTR_CIS_TERM_EVENT_HOST_DISC */ + LCTR_CIS_TERM_STATE_TERMINATING, /* LCTR_CIS_TERM_EVENT_PEER_DISC */ + LCTR_CIS_TERM_STATE_TERMINATING, /* LCTR_CIS_TERM_EVENT_INT_START_DISC */ + LCTR_CIS_TERM_STATE_TERMINATING, /* LCTR_CIS_TERM_EVENT_INT_START_PEER_DISC */ + LCTR_CIS_TERM_STATE_IDLE /* LCTR_CIS_TERM_EVENT_CIS_TERM */ + }, + { /* LCTR_CIS_TERM_STATE_TERMINATING */ + LCTR_CIS_TERM_STATE_TERMINATING, /* LCTR_CIS_TERM_EVENT_HOST_DISC */ + LCTR_CIS_TERM_STATE_TERMINATING, /* LCTR_CIS_TERM_EVENT_PEER_DISC */ + LCTR_CIS_TERM_STATE_TERMINATING, /* LCTR_CIS_TERM_EVENT_INT_START_DISC */ + LCTR_CIS_TERM_STATE_TERMINATING, /* LCTR_CIS_TERM_EVENT_INT_START_PEER_DISC */ + LCTR_CIS_TERM_STATE_IDLE /* LCTR_CIS_TERM_EVENT_CIS_TERM */ + } +}; + + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief CIS executes termination action function. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + * \param event Event ID. + */ +/*************************************************************************************************/ +static inline void lctrExecTermAction(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx, uint8_t event) +{ + if (lctrCisTermActionTbl[pCisCtx->termState][event]) + { + lctrCisTermActionTbl[pCisCtx->termState][event](pCtx, pCisCtx); + } + + pCisCtx->termState = lctrCisTermNextStateTbl[pCisCtx->termState][event]; +} + +/*************************************************************************************************/ +/*! + * \brief Get remapped event. This function also updates the CIS handle for the LLCP. + * + * \param event Subsystem event. + * \param pCtx Connection context. + * + * \return Procedure event ID. + */ +/*************************************************************************************************/ +static uint8_t lctrRemapTermEvent(lctrConnCtx_t *pCtx, uint8_t event) +{ + switch (event) + { + /*** Peer messages ***/ + + case LCTR_CONN_MSG_RX_LLCP: + switch (lctrDataPdu.opcode) + { + case LL_PDU_CIS_TERM_IND: + { + lctrCisCtx_t *pCisCtx = lctrFindCisById(lctrDataPdu.pld.cisTerm.cigId, lctrDataPdu.pld.cisTerm.cisId); + pCtx->llcpCisHandle = pCisCtx->cisHandle; /* Update LLCP CIS handle for connection context from peer. */ + return LCTR_CIS_TERM_EVENT_PEER_DISC; + } + break; + + default: + break; + } + break; + + /*** Host messages ***/ + + case LCTR_CONN_MSG_API_DISCONNECT: + { + lctrCisCtx_t *pCisCtx; + + if ((pCisCtx = lctrFindCisByHandle(pLctrConnMsg->cisDisc.cisHandle)) != NULL) + { + pCtx->llcpCisHandle = pLctrConnMsg->cisDisc.cisHandle; /* Update LLCP CIS handle for connection context from host. */ + pLctrConnMsg->cisDisc.cisHandle = 0; + return LCTR_CIS_TERM_EVENT_HOST_DISC; + } + break; + } + /*** Internal messages ***/ + + case LCTR_CIS_TERM_EVENT_CIS_TERM: + return LCTR_CIS_TERM_EVENT_CIS_TERM; + + case LCTR_CONN_LLCP_START_PENDING: + if (pCtx->llcpPendMask & (1 << LCTR_PROC_CIS_TERM)) + { + pCtx->llcpPendMask &= ~(1 << LCTR_PROC_CIS_TERM); + return LCTR_CIS_TERM_EVENT_INT_START_DISC; + } + if (pCtx->llcpPendMask & (1 << LCTR_PROC_CIS_TERM_PEER)) + { + pCtx->llcpPendMask &= ~(1 << LCTR_PROC_CIS_TERM_PEER); + return LCTR_CIS_TERM_EVENT_INT_START_PEER_DISC; + } + break; + + default: + break; + } + return LCTR_CIS_TERM_EVENT_INVALID; +} + +/*************************************************************************************************/ +/*! + * \brief Resolve procedure collision. + * + * \param event Subsystem event. + * \param pCisCtx CIS context. + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +static void lctrResolveCollision(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx, uint8_t event) +{ + switch (event) + { + case LCTR_CIS_TERM_EVENT_PEER_DISC: + if ((pCtx->llcpActiveProc == LCTR_PROC_CMN_CH_MAP_UPD) || + (pCtx->llcpActiveProc == LCTR_PROC_CONN_UPD) || + (pCtx->llcpActiveProc == LCTR_PROC_PHY_UPD) || + (pCtx->llcpActiveProc == LCTR_PROC_CONN_PARAM)) + { + lctrSendRejectInd(pCtx, LL_ERROR_CODE_DIFFERENT_TRANSACTION_COLLISION, TRUE); + } + else + { + lctrCisStoreTerminateReason(pCisCtx); + pCtx->llcpPendMask |= 1 << LCTR_PROC_CIS_TERM_PEER; + LL_TRACE_INFO2("Pending CIS_TERM_IND=%u procedure: activeProc=%u", LCTR_PROC_CIS_TERM_PEER, pCtx->llcpActiveProc); + } + break; + + case LCTR_CIS_TERM_EVENT_HOST_DISC: + pCtx->llcpNotifyMask |= 1 << LCTR_PROC_CIS_TERM; + pCtx->llcpPendMask |= 1 << LCTR_PROC_CIS_TERM; + LL_TRACE_INFO2("Pending CIS_TERM_IND=%u procedure: activeProc=%u", LCTR_PROC_CIS_TERM, pCtx->llcpActiveProc); + break; + + default: + break; + } +} + +/*************************************************************************************************/ +/*! + * \brief Check if active procedure can be overridden with CIS termination procedure. + * + * \param pCtx Connection context. + * \param event Subsystem event. + * + * This routine will pend the active procedure and allow the phy update procedure to + * override it. + */ +/*************************************************************************************************/ +static void lctrCheckProcOverride(lctrConnCtx_t *pCtx, uint8_t event) +{ + switch (event) + { + case LCTR_CIS_TERM_EVENT_PEER_DISC: + /* Only the procedure without instant fields can be overridden. */ + switch (pCtx->llcpActiveProc) + { + case LCTR_PROC_CMN_VER_EXCH: + case LCTR_PROC_CMN_FEAT_EXCH: + case LCTR_PROC_CMN_DATA_LEN_UPD: + case LCTR_PROC_CMN_REQ_PEER_SCA: + pCtx->llcpPendMask |= 1 << pCtx->llcpActiveProc; + pCtx->llcpActiveProc = LCTR_PROC_CIS_TERM; + pCtx->llcpIsOverridden = TRUE; + break; + + default: + break; + } + break; + + default: + break; + } +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Execute CIS termination state machine. + * + * \param pCtx Connection context. + * \param event State machine event. + * + * \return TRUE if the event is handled by this state machine, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lctrLlcpExecuteCisTermSm(lctrConnCtx_t *pCtx, uint8_t event) +{ + if ((event = lctrRemapTermEvent(pCtx, event)) == LCTR_CIS_TERM_EVENT_INVALID) + { + return FALSE; + } + + lctrCisCtx_t *pCisCtx = lctrFindCisByHandle(pCtx->llcpCisHandle); + + WSF_ASSERT(pCisCtx != NULL) + + switch (pCtx->llcpState) + { + case LCTR_LLCP_STATE_IDLE: + LL_TRACE_INFO3("lctrLlcpExecuteCisTermSm: cis_handle=%u, llcpState=IDLE, termState=%u, event=%u", pCisCtx->cisHandle, pCisCtx->termState, event); + + lctrExecTermAction(pCtx, pCisCtx, event); + + if (pCisCtx->termState != LCTR_CIS_TERM_STATE_IDLE) + { + pCtx->llcpState = LCTR_LLCP_STATE_BUSY; + pCtx->llcpActiveProc = LCTR_PROC_CIS_TERM; + } + break; + + case LCTR_LLCP_STATE_BUSY: + LL_TRACE_INFO3("lctrLlcpExecuteCisTermSm: cis_handle=%u, llcpState=BUSY, termState=%u, event=%u", pCisCtx->cisHandle, pCisCtx->termState, event); + + lctrCheckProcOverride(pCtx, event); + + if (pCtx->llcpActiveProc == LCTR_PROC_CIS_TERM) + { + lctrExecTermAction(pCtx, pCisCtx, event); + + if (pCisCtx->termState == LCTR_CIS_TERM_STATE_IDLE) + { + lctrCisStopLlcpTimer(pCtx, pCisCtx); + pCtx->llcpState = LCTR_LLCP_STATE_IDLE; + pCtx->llcpActiveProc = LCTR_PROC_INVALID; + + lctrStartPendingLlcp(pCtx); + } + } + else + { + lctrResolveCollision(pCtx, pCisCtx, event); + } + break; + + default: + break; + } + + return TRUE; +} + diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_cis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_cis_master.c new file mode 100644 index 0000000000..1a62568038 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_cis_master.c @@ -0,0 +1,297 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller CIS LLCP master state machine implementation file. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_cis_master.h" +#include "lctr_int_conn_master.h" +#include "lctr_int_conn.h" +#include "lmgr_api.h" +#include "wsf_assert.h" +#include "wsf_trace.h" +#include "util/bstream.h" + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief Action function call signature. */ +typedef void (*lctrActFn_t)(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); + +/*! \brief CIS establishment procedure events. */ +enum +{ + LCTR_CIS_MST_EST_EVENT_HOST_CIS_REQ, /*!< Received host LL_CIS_REQ command. */ + LCTR_CIS_MST_EST_EVENT_PEER_CIS_RSP, /*!< Received peer LL_CIS_RSP. */ + LCTR_CIS_MST_EST_EVENT_PEER_REJECT, /*!< Received peer LL_REJECT_IND_EXT or LL_UNKNOWN_RSP. */ + LCTR_CIS_MST_EST_EVENT_RSP_TIMEOUT, /*!< Received internal response timeout. */ + LCTR_CIS_MST_EST_EVENT_LOCAL_REJECT, /*!< Received local rejection due to limited resources. */ + LCTR_CIS_MST_EST_EVENT_TOTAL, /*!< Total CIS events. */ + LCTR_CIS_MST_EST_EVENT_INVALID = 0xFF /*!< Invalid event. */ +}; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ +static void lctrMstCisLlcpActRejectCollision(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*! \brief CIS establishment state machine action table. */ +static const lctrActFn_t lctrMstCisEstActionTbl[LCTR_CIS_MST_EST_STATE_TOTAL][LCTR_CIS_MST_EST_EVENT_TOTAL] = +{ + { /* LCTR_CIS_MST_EST_STATE_IDLE */ + lctrMstCisLlcpActHostCisReq, /* LCTR_CIS_MST_EST_EVENT_HOST_CIS_REQ */ + lctrMstCisLlcpActRejectCollision, /* LCTR_CIS_MST_EST_EVENT_PEER_CIS_RSP */ /* Shall not happen */ + lctrMstCisLlcpActRejectCollision, /* LCTR_CIS_MST_EST_EVENT_PEER_REJECT */ /* Shall not happen */ + NULL, /* LCTR_CIS_MST_EST_EVENT_RSP_TIMEOUT */ /* Shall not happen */ + NULL, /* LCTR_CIS_MST_EST_EVENT_LOCAL_REJECT */ /* Shall not happen */ + }, + { /* LCTR_CIS_MST_EST_STATE_CIS_RSP */ + NULL, /* LCTR_CIS_MST_EST_EVENT_HOST_CIS_REQ */ + lctrMstCisLlcpActPeerCisRsp, /* LCTR_CIS_MST_EST_EVENT_PEER_CIS_RSP */ + lctrMstCisLlcpActPeerRej, /* LCTR_CIS_MST_EST_EVENT_PEER_REJECT */ + lctrMstCisLlcpActRspTimeout, /* LCTR_CIS_MST_EST_EVENT_RSP_TIMEOUT */ + lctrMstCisLlcpActLocalReject, /* LCTR_CIS_MST_EST_EVENT_LOCAL_REJECT */ + } +}; + +/*! \brief CIS establishment state machine next state table. */ +static const uint8_t lctrMstCisEstNextStateTbl[LCTR_CIS_MST_EST_STATE_TOTAL][LCTR_CIS_MST_EST_EVENT_TOTAL] = +{ + { /* LCTR_CIS_MST_EST_STATE_IDLE */ + LCTR_CIS_MST_EST_STATE_CIS_RSP, /* LCTR_CIS_MST_EST_EVENT_HOST_CIS_REQ */ + LCTR_CIS_MST_EST_STATE_IDLE, /* LCTR_CIS_MST_EST_EVENT_PEER_CIS_RSP */ + LCTR_CIS_MST_EST_STATE_IDLE, /* LCTR_CIS_MST_EST_EVENT_PEER_REJECT */ + LCTR_CIS_MST_EST_STATE_IDLE, /* LCTR_CIS_MST_EST_EVENT_RSP_TIMEOUT */ + LCTR_CIS_MST_EST_STATE_IDLE, /* LCTR_CIS_MST_EST_EVENT_LOCAL_REJECT */ + }, + { /* LCTR_CIS_MST_EST_STATE_CIS_RSP */ + LCTR_CIS_MST_EST_STATE_CIS_RSP, /* LCTR_CIS_MST_EST_EVENT_HOST_CIS_REQ */ + LCTR_CIS_MST_EST_STATE_IDLE, /* LCTR_CIS_MST_EST_EVENT_PEER_CIS_RSP */ + LCTR_CIS_MST_EST_STATE_IDLE, /* LCTR_CIS_MST_EST_EVENT_PEER_REJECT */ + LCTR_CIS_MST_EST_STATE_IDLE, /* LCTR_CIS_MST_EST_EVENT_RSP_TIMEOUT */ + LCTR_CIS_MST_EST_STATE_IDLE, /* LCTR_CIS_MST_EST_EVENT_LOCAL_REJECT */ + } +}; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Send peer LL_REJECT_IND_EXT due to pending operation. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static void lctrMstCisLlcpActRejectCollision(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + LL_TRACE_WARN1("Peer requested PHY while procedure pending, handle=%u", LCTR_GET_CONN_HANDLE(pCtx)); + lctrSendRejectInd(pCtx, LL_ERROR_CODE_LMP_ERR_TRANSACTION_COLLISION, TRUE); +} + +/*************************************************************************************************/ +/*! + * \brief Execute action function. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + * \param event Event ID. + */ +/*************************************************************************************************/ +static inline void lctrExecAction(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx, uint8_t event) +{ + if (lctrMstCisEstActionTbl[pCisCtx->estState][event]) + { + lctrMstCisEstActionTbl[pCisCtx->estState][event](pCtx, pCisCtx); + } + + pCisCtx->estState = lctrMstCisEstNextStateTbl[pCisCtx->estState][event]; +} + +/*************************************************************************************************/ +/*! + * \brief Get remapped event. This function also update the CIS handle for the LLCP. + * + * \param event Subsystem event. + * \param pCtx Connection context. + * + * \return Procedure event ID. + */ +/*************************************************************************************************/ +static uint8_t lctrRemapEvent(lctrConnCtx_t *pCtx, uint8_t event) +{ + switch (event) + { + /*** Peer messages ***/ + + case LCTR_CONN_MSG_RX_LLCP: + switch (lctrDataPdu.opcode) + { + case LL_PDU_CIS_RSP: + return LCTR_CIS_MST_EST_EVENT_PEER_CIS_RSP; + case LL_PDU_UNKNOWN_RSP: + if (lctrDataPdu.pld.unknownRsp.unknownType == LL_PDU_CIS_REQ) + { + return LCTR_CIS_MST_EST_EVENT_PEER_REJECT; + } + break; + case LL_PDU_REJECT_EXT_IND: + if (lctrDataPdu.pld.rejInd.opcode == LL_PDU_CIS_REQ) + { + return LCTR_CIS_MST_EST_EVENT_PEER_REJECT; + } + break; + break; + + default: + break; + } + break; + + /*** Host messages ***/ + + case LCTR_CONN_MSG_API_CIS_REQ: + pCtx->llcpCisHandle = pLctrConnMsg->createCis.cisHandle; /* Update LLCP CIS handle for connection context from host. */ + return LCTR_CIS_MST_EST_EVENT_HOST_CIS_REQ; + + /*** Internal messages ***/ + case LCTR_CONN_LLCP_START_PENDING: + if (pCtx->llcpPendMask & (1 << LCTR_PROC_CIS_EST)) + { + pCtx->llcpPendMask &= ~(1 << LCTR_PROC_CIS_EST); + return LCTR_CIS_MST_EST_EVENT_HOST_CIS_REQ; + } + break; + + case LCTR_CONN_TMR_CIS_LLCP_RSP_EXP: + return LCTR_CIS_MST_EST_EVENT_RSP_TIMEOUT; + + case LCTR_CONN_TERM_CIS_LOCAL_RESOURCE: + return LCTR_CIS_MST_EST_EVENT_LOCAL_REJECT; + + default: + break; + } + return LCTR_CIS_MST_EST_EVENT_INVALID; +} + +/*************************************************************************************************/ +/*! + * \brief Resolve procedure collision. + * + * \param event Subsystem event. + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +static void lctrResolveCollision(lctrConnCtx_t *pCtx, uint8_t event) +{ + switch (event) + { + case LCTR_CIS_MST_EST_EVENT_HOST_CIS_REQ: + pCtx->llcpNotifyMask |= 1 << LCTR_PROC_CIS_EST; + pCtx->llcpPendMask |= 1 << LCTR_PROC_CIS_EST; + LL_TRACE_INFO2("Pending CIS_REQ=%u procedure: activeProc=%u", LCTR_PROC_CIS_EST, pCtx->llcpActiveProc); + break; + + default: + break; + } +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Execute CIS master establishment LLCP state machine. + * + * \param pCtx Connection context. + * \param event State machine event. + * + * \return TRUE if the event is handled by this state machine, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lctrMstLlcpExecuteCisEstSm(lctrConnCtx_t *pCtx, uint8_t event) +{ + if ((event = lctrRemapEvent(pCtx, event)) == LCTR_CIS_MST_EST_EVENT_INVALID) + { + return FALSE; + } + + lctrCisCtx_t *pCisCtx = lctrFindCisByHandle(pCtx->llcpCisHandle); + WSF_ASSERT(pCisCtx != NULL) + + switch (pCtx->llcpState) + { + case LCTR_LLCP_STATE_IDLE: + LL_TRACE_INFO3("lctrMstLlcpExecuteCisEstSm: cis_handle=%u, llcpState=IDLE, estState=%u, event=%u", pCisCtx->cisHandle, pCisCtx->estState, event); + + lctrExecAction(pCtx, pCisCtx, event); + + if (pCisCtx->estState != LCTR_CIS_MST_EST_STATE_IDLE) + { + pCtx->llcpState = LCTR_LLCP_STATE_BUSY; + pCtx->llcpActiveProc = LCTR_PROC_CIS_EST; + } + break; + + case LCTR_LLCP_STATE_BUSY: + LL_TRACE_INFO3("lctrMstLlcpExecuteCisEstSm: cis_handle=%u, llcpState=BUSY, estState=%u, event=%u", pCisCtx->cisHandle, pCisCtx->estState, event); + + if (pCtx->llcpActiveProc == LCTR_PROC_CIS_EST) + { + lctrExecAction(pCtx, pCisCtx, event); + + if (pCisCtx->estState == LCTR_CIS_MST_EST_STATE_IDLE) + { + lctrCisStopLlcpTimer(pCtx, pCisCtx); + pCtx->llcpState = LCTR_LLCP_STATE_IDLE; + pCtx->llcpActiveProc = LCTR_PROC_INVALID; + + lctrStartPendingLlcp(pCtx); + } + } + else + { + lctrResolveCollision(pCtx, event); + } + + break; + + default: + break; + } + + return TRUE; +} + diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_cis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_cis_slave.c new file mode 100644 index 0000000000..30c7929433 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_cis_slave.c @@ -0,0 +1,382 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer controller CIS LLCP slave state machine implementation file. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_int_cis_slave.h" +#include "lctr_int_conn.h" +#include "lctr_int_conn_master.h" +#include "lctr_int_conn_slave.h" +#include "lmgr_api.h" +#include "wsf_assert.h" +#include "wsf_trace.h" +#include "util/bstream.h" + +/************************************************************************************************** + Data Types +**************************************************************************************************/ +/*! \brief Action function call signature. */ +typedef void (*lctrActFn_t)(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); + +/*! \brief Slave CIS establishment events. */ +enum +{ + LCTR_CIS_SLV_EST_EVENT_PEER_CIS_REQ, /*!< Received peer LL_CIS_REQ. */ + LCTR_CIS_SLV_EST_EVENT_INT_PEER_CIS_REQ, /*!< Received internal peer LL_CIS_REQ. */ + LCTR_CIS_SLV_EST_EVENT_HOST_REQ_ACCEPT, /*!< Received host LE CIS Request Accept command. */ + LCTR_CIS_SLV_EST_EVENT_HOST_REQ_REJECT, /*!< Received host LE CIS Request Reject command. */ + LCTR_CIS_SLV_EST_EVENT_PERR_CIS_IND, /*!< Received peer LL_CIS_IND. */ + LCTR_CIS_SLV_EST_EVENT_PEER_REJECT, /*!< Received peer LL_REJECT_IND_EXT or LL_UNKNOWN_RSP. */ + LCTR_CIS_SLV_EST_EVENT_TOTAL, /*!< Total CIS events. */ + LCTR_CIS_SLV_EST_EVENT_INVALID = 0xFF /*!< Invalid event. */ +}; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ +static void lctrSlvCisLlcpActRejectCollision(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx); + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*! \brief CIS establishment state machine action table. */ +static const lctrActFn_t lctrSlvCisEstActionTbl[LCTR_CIS_SLV_EST_STATE_TOTAL][LCTR_CIS_SLV_EST_EVENT_TOTAL] = +{ + { /* LCTR_CIS_SLV_EST_STATE_IDLE */ + lctrSlvCisLlcpActPeerCisReq, /* LCTR_CIS_SLV_EST_EVENT_PEER_CIS_REQ */ + lctrSlvCisLlcpActIntPeerCisReq, /* LCTR_CIS_SLV_EST_EVENT_INT_PEER_CIS_REQ */ + NULL, /* LCTR_CIS_SLV_EST_EVENT_HOST_REQ_ACCEPT */ + NULL, /* LCTR_CIS_SLV_EST_EVENT_HOST_REQ_REJECT */ + NULL, /* LCTR_CIS_SLV_EST_EVENT_PERR_CIS_IND */ + NULL /* LCTR_CIS_SLV_EST_EVENT_PEER_REJECT */ + }, + { /* LCTR_CIS_SLV_EST_STATE_HOST_REPLY */ + NULL, /* LCTR_CIS_SLV_EST_EVENT_PEER_CIS_REQ */ + lctrSlvCisLlcpActRejectCollision, /* LCTR_CIS_SLV_EST_EVENT_INT_PEER_CIS_REQ */ + lctrSlvCisLlcpActAcpCisReq, /* LCTR_CIS_SLV_EST_EVENT_HOST_REQ_ACCEPT */ + lctrSlvCisLlcpActRejCisReq, /* LCTR_CIS_SLV_EST_EVENT_HOST_REQ_REJECT */ + NULL, /* LCTR_CIS_SLV_EST_EVENT_PERR_CIS_IND */ + NULL /* LCTR_CIS_SLV_EST_EVENT_PEER_REJECT */ + }, + { /* LCTR_CIS_SLV_EST_STATE_CIS_IND */ + lctrSlvCisLlcpActRejectCollision, /* LCTR_CIS_SLV_EST_EVENT_PEER_CIS_REQ */ + NULL, /* LCTR_CIS_SLV_EST_EVENT_INT_PEER_CIS_REQ */ + NULL, /* LCTR_CIS_SLV_EST_EVENT_HOST_REQ_ACCEPT */ + NULL, /* LCTR_CIS_SLV_EST_EVENT_HOST_REQ_REJECT */ + lctrSlvCisLlcpActPeerCisInd, /* LCTR_CIS_SLV_EST_EVENT_PERR_CIS_IND */ + lctrSlvCisLlcpActPeerCisRej /* LCTR_CIS_SLV_EST_EVENT_PEER_REJECT */ + } +}; + +/*! \brief CIS establishment state machine next state table. */ +static const uint8_t lctrSlvCisEstNextStateTbl[LCTR_CIS_SLV_EST_STATE_TOTAL][LCTR_CIS_SLV_EST_EVENT_TOTAL] = +{ + { /* LCTR_CIS_SLV_EST_STATE_IDLE */ + LCTR_CIS_SLV_EST_STATE_HOST_REPLY, /* LCTR_CIS_SLV_EST_EVENT_PEER_CIS_REQ */ + LCTR_CIS_SLV_EST_STATE_HOST_REPLY, /* LCTR_CIS_SLV_EST_EVENT_INT_PEER_CIS_REQ */ + LCTR_CIS_SLV_EST_STATE_IDLE, /* LCTR_CIS_SLV_EST_EVENT_HOST_REQ_ACCEPT */ + LCTR_CIS_SLV_EST_STATE_IDLE, /* LCTR_CIS_SLV_EST_EVENT_HOST_REQ_REJECT */ + LCTR_CIS_SLV_EST_STATE_IDLE, /* LCTR_CIS_SLV_EST_EVENT_PERR_CIS_IND */ + LCTR_CIS_SLV_EST_STATE_IDLE /* LCTR_CIS_SLV_EST_EVENT_PEER_REJECT */ + }, + { /* LCTR_CIS_SLV_EST_STATE_HOST_REPLY */ + LCTR_CIS_SLV_EST_STATE_HOST_REPLY, /* LCTR_CIS_SLV_EST_EVENT_PEER_CIS_REQ */ + LCTR_CIS_SLV_EST_STATE_HOST_REPLY, /* LCTR_CIS_SLV_EST_EVENT_INT_PEER_CIS_REQ */ + LCTR_CIS_SLV_EST_STATE_CIS_IND, /* LCTR_CIS_SLV_EST_EVENT_HOST_REQ_ACCEPT */ + LCTR_CIS_SLV_EST_STATE_IDLE, /* LCTR_CIS_SLV_EST_EVENT_HOST_REQ_REJECT */ + LCTR_CIS_SLV_EST_STATE_HOST_REPLY, /* LCTR_CIS_SLV_EST_EVENT_PERR_CIS_IND */ + LCTR_CIS_SLV_EST_STATE_HOST_REPLY /* LCTR_CIS_SLV_EST_EVENT_PEER_REJECT */ + }, + { /* LCTR_CIS_SLV_EST_STATE_CIS_IND */ + LCTR_CIS_SLV_EST_STATE_CIS_IND, /* LCTR_CIS_SLV_EST_EVENT_PEER_CIS_REQ */ + LCTR_CIS_SLV_EST_STATE_CIS_IND, /* LCTR_CIS_SLV_EST_EVENT_INT_PEER_CIS_REQ */ + LCTR_CIS_SLV_EST_STATE_CIS_IND, /* LCTR_CIS_SLV_EST_EVENT_HOST_REQ_ACCEPT */ + LCTR_CIS_SLV_EST_STATE_CIS_IND, /* LCTR_CIS_SLV_EST_EVENT_HOST_REQ_REJECT */ + LCTR_CIS_SLV_EST_STATE_IDLE, /* LCTR_CIS_SLV_EST_EVENT_PERR_CIS_IND */ + LCTR_CIS_SLV_EST_STATE_IDLE /* LCTR_CIS_SLV_EST_EVENT_PEER_REJECT */ + } +}; + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ +/*************************************************************************************************/ +/*! + * \brief Send peer LL_REJECT_IND_EXT due to pending operation. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + */ +/*************************************************************************************************/ +static void lctrSlvCisLlcpActRejectCollision(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx) +{ + LL_TRACE_WARN1("Peer requested PHY while procedure pending, handle=%u", LCTR_GET_CONN_HANDLE(pCtx)); + lctrSendRejectInd(pCtx, LL_ERROR_CODE_LMP_ERR_TRANSACTION_COLLISION, TRUE); +} + +/*************************************************************************************************/ +/*! + * \brief Execute action function. + * + * \param pCtx Connection context. + * \param pCisCtx CIS context. + * \param event Event ID. + */ +/*************************************************************************************************/ +static inline void lctrExecAction(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx, uint8_t event) +{ + if (lctrSlvCisEstActionTbl[pCisCtx->estState][event]) + { + lctrSlvCisEstActionTbl[pCisCtx->estState][event](pCtx, pCisCtx); + } + + pCisCtx->estState = lctrSlvCisEstNextStateTbl[pCisCtx->estState][event]; +} + +/*************************************************************************************************/ +/*! + * \brief Get remapped event. This function also update the CIS handle for the LLCP. + * + * \param event Subsystem event. + * \param pCtx Connection context. + * + * \return Procedure event ID. + */ +/*************************************************************************************************/ +static uint8_t lctrRemapEvent(lctrConnCtx_t *pCtx, uint8_t event) +{ + switch (event) + { + /*** Peer messages ***/ + + case LCTR_CONN_MSG_RX_LLCP: + switch (lctrDataPdu.opcode) + { + case LL_PDU_CIS_REQ: + { + lctrCigCtx_t *pCigCtx; + if ((pCigCtx = lctrFindCigById(lctrDataPdu.pld.cisReq.cigId)) == NULL) + { + if ((pCigCtx = lctrAllocCigCtx(lctrDataPdu.pld.cisReq.cigId)) == NULL) + { + lctrSendRejectInd(pCtx, LL_ERROR_CODE_LIMIT_REACHED, TRUE); + LL_TRACE_WARN0("Not able to allocate a CIG context"); + break; + } + } + + lctrCisCtx_t *pCisCtx ; + if ((pCisCtx = lctrAllocCisCtx(pCigCtx)) == NULL) + { + lctrSendRejectInd(pCtx, LL_ERROR_CODE_LIMIT_REACHED, TRUE); + LL_TRACE_WARN0("Not able to allocate a CIS context"); + break; + } + pCisCtx->aclHandle = LCTR_GET_CONN_HANDLE(pCtx); /* Save the ACL handle. */ + pCisCtx->role = LL_ROLE_SLAVE; + pCtx->llcpCisHandle = pCisCtx->cisHandle; /* Update LLCP CIS handle for connection context from peer. */ + pCtx->checkCisTerm = lctrCheckForCisLinkTerm; + lctrCheckCisEstCisFn = lctrCheckIsCisEstCis; + return LCTR_CIS_SLV_EST_EVENT_PEER_CIS_REQ; + } + + case LL_PDU_CIS_IND: + return LCTR_CIS_SLV_EST_EVENT_PERR_CIS_IND; + + case LL_PDU_REJECT_EXT_IND: + { + if (lctrDataPdu.pld.rejInd.opcode == LL_PDU_CIS_RSP) + { + return LCTR_CIS_SLV_EST_EVENT_PEER_REJECT; + } + break; + } + + default: + break; + } + break; + + /*** Host messages ***/ + case LCTR_CONN_MSG_API_CIS_REQ_REJECT: + return LCTR_CIS_SLV_EST_EVENT_HOST_REQ_REJECT; + + case LCTR_CONN_MSG_API_CIS_REQ_ACCEPT: + return LCTR_CIS_SLV_EST_EVENT_HOST_REQ_ACCEPT; + + /*** Internal messages ***/ + case LCTR_CONN_LLCP_START_PENDING: + if (pCtx->llcpPendMask & (1 << LCTR_PROC_CIS_EST_PEER)) + { + pCtx->llcpPendMask &= ~(1 << LCTR_PROC_CIS_EST_PEER); + return LCTR_CIS_SLV_EST_EVENT_INT_PEER_CIS_REQ; + } + break; + default: + break; + } + return LCTR_CIS_SLV_EST_EVENT_INVALID; +} + +/*************************************************************************************************/ +/*! + * \brief Resolve procedure collision. + * + * \param event Subsystem event. + * \param pCisCtx CIS context. + * \param pCtx Connection context. + */ +/*************************************************************************************************/ +static void lctrResolveCollision(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx, uint8_t event) +{ + switch (event) + { + case LCTR_CIS_SLV_EST_EVENT_PEER_CIS_REQ: + if ((pCtx->llcpActiveProc == LCTR_PROC_CMN_CH_MAP_UPD) || + (pCtx->llcpActiveProc == LCTR_PROC_CONN_UPD) || + (pCtx->llcpActiveProc == LCTR_PROC_PHY_UPD) || + (pCtx->llcpActiveProc == LCTR_PROC_CONN_PARAM)) + { + lctrSendRejectInd(pCtx, LL_ERROR_CODE_DIFFERENT_TRANSACTION_COLLISION, TRUE); + } + else + { + lctrCisStorePeerCisReq(pCtx, pCisCtx); + pCtx->llcpPendMask |= 1 << LCTR_PROC_CIS_EST_PEER; + LL_TRACE_INFO2("Pending CIS_REQ=%u procedure: activeProc=%u", LCTR_PROC_CIS_EST_PEER, pCtx->llcpActiveProc); + } + break; + + default: + break; + } +} + +/*************************************************************************************************/ +/*! + * \brief Check if active procedure can be overridden with phy update procedure. + * + * \param pCtx Connection context. + * \param event Subsystem event. + * + * This routine will pend the active procedure and allow the phy update procedure to + * override it. + */ +/*************************************************************************************************/ +static void lctrCheckProcOverride(lctrConnCtx_t *pCtx, uint8_t event) +{ + switch (event) + { + case LCTR_CIS_SLV_EST_EVENT_PEER_CIS_REQ: + /* Only the procedure without instant fields can be overridden. */ + switch (pCtx->llcpActiveProc) + { + case LCTR_PROC_CMN_VER_EXCH: + case LCTR_PROC_CMN_FEAT_EXCH: + case LCTR_PROC_CMN_DATA_LEN_UPD: + case LCTR_PROC_CMN_REQ_PEER_SCA: + pCtx->llcpPendMask |= 1 << pCtx->llcpActiveProc; + pCtx->llcpActiveProc = LCTR_PROC_CIS_EST; + pCtx->llcpIsOverridden = TRUE; + break; + + default: + break; + } + break; + + default: + break; + } +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Execute slave CIS establishment LLCP state machine. + * + * \param pCtx Connection context. + * \param event State machine event. + * + * \return TRUE if the event is handled by this state machine, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lctrSlvLlcpExecuteCisEstSm(lctrConnCtx_t *pCtx, uint8_t event) +{ + if ((event = lctrRemapEvent(pCtx, event)) == LCTR_CIS_SLV_EST_EVENT_INVALID) + { + return FALSE; + } + + lctrCisCtx_t *pCisCtx = lctrFindCisByHandle(pCtx->llcpCisHandle); + WSF_ASSERT(pCisCtx != NULL) + + switch (pCtx->llcpState) + { + case LCTR_LLCP_STATE_IDLE: + LL_TRACE_INFO3("lctrSlvLlcpExecuteCisEstSm: handle=%u, llcpState=IDLE, estState=%u, event=%u", LCTR_GET_CONN_HANDLE(pCtx), pCisCtx->estState, event); + + lctrExecAction(pCtx, pCisCtx, event); + + if (pCisCtx->estState != LCTR_CIS_SLV_EST_STATE_IDLE) + { + pCtx->llcpState = LCTR_LLCP_STATE_BUSY; + pCtx->llcpActiveProc = LCTR_PROC_CIS_EST; + } + break; + + case LCTR_LLCP_STATE_BUSY: + LL_TRACE_INFO3("lctrSlvLlcpExecuteCisEstSm: handle=%u, llcpState=BUSY, estState=%u, event=%u", LCTR_GET_CONN_HANDLE(pCtx), pCisCtx->estState, event); + + lctrCheckProcOverride(pCtx, event); + + if (pCtx->llcpActiveProc == LCTR_PROC_CIS_EST) + { + lctrExecAction(pCtx, pCisCtx, event); + + if (pCisCtx->estState == LCTR_CIS_SLV_EST_STATE_IDLE) + { + lctrCisStopLlcpTimer(pCtx, pCisCtx); + pCtx->llcpState = LCTR_LLCP_STATE_IDLE; + pCtx->llcpActiveProc = LCTR_PROC_INVALID; + + lctrStartPendingLlcp(pCtx); + } + } + else + { + lctrResolveCollision(pCtx, pCisCtx, event); + } + + break; + + default: + break; + } + + return TRUE; +} + diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn.c index f697a267fe..54baacaf8f 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief LLCP state machine implementation file. + * \file + * + * \brief LLCP state machine implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -151,8 +152,6 @@ const lctrLlcpEh_t lctrCmnProcTbl[LCTR_PROC_CMN_TOTAL][LCTR_PROC_CMN_ACT_TOTAL] * \param pCtx Connection context. * \param proc Procedure ID. * \param act Action ID. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrExecAction(lctrConnCtx_t *pCtx, uint8_t proc, uint8_t act) @@ -556,8 +555,6 @@ static bool_t lctrFeatureAvail(lctrConnCtx_t *pCtx, uint8_t proc, uint8_t event) * * \param pCtx Connection context. * \param status Status. - * - * \return None. */ /*************************************************************************************************/ static void lctrNotifyHostReadRemoteFeatCnf(lctrConnCtx_t *pCtx, uint8_t status) @@ -591,8 +588,6 @@ static void lctrNotifyHostReadRemoteFeatCnf(lctrConnCtx_t *pCtx, uint8_t status) * * \param pCtx Connection context. * \param proc Completed procedure. - * - * \return None. */ /*************************************************************************************************/ static void lctrNotifyHostSuccess(lctrConnCtx_t *pCtx, uint8_t proc) @@ -629,8 +624,6 @@ static void lctrNotifyHostSuccess(lctrConnCtx_t *pCtx, uint8_t proc) * * \param pCtx Connection context. * \param proc Complete procedure. - * - * \return None. */ /*************************************************************************************************/ static void lctrNotifyHostReject(lctrConnCtx_t *pCtx, uint8_t proc) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn_master.c index 99f7716481..0f7f8ab60d 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master connection state machine implementation file. + * \file + * + * \brief Link layer controller master connection state machine implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -74,8 +75,6 @@ LctrLlcpHdlr_t lctrMstLlcpSmTbl[LCTR_LLCP_SM_TOTAL]; * \brief Action indirection for start connection update. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActStartConnUpd(lctrConnCtx_t *pCtx) @@ -109,8 +108,6 @@ static void lctrActStartConnUpd(lctrConnCtx_t *pCtx) * \brief Action indirection for received host connection update command. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActHostConnUpd(lctrConnCtx_t *pCtx) @@ -125,8 +122,6 @@ static void lctrActHostConnUpd(lctrConnCtx_t *pCtx) * \brief Action indirection for received host connection update command. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerConnParam(lctrConnCtx_t *pCtx) @@ -141,8 +136,6 @@ static void lctrActPeerConnParam(lctrConnCtx_t *pCtx) * \brief Action indirection for start connection parameter command. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActStartConnParam(lctrConnCtx_t *pCtx) @@ -156,8 +149,6 @@ static void lctrActStartConnParam(lctrConnCtx_t *pCtx) * \brief Action indirection for host reply command. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActHostReply(lctrConnCtx_t *pCtx) @@ -174,8 +165,6 @@ static void lctrActHostReply(lctrConnCtx_t *pCtx) * \brief Action indirection for received peer LL_CONN_PARAM_RSP. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerConnParamRsp(lctrConnCtx_t *pCtx) @@ -191,8 +180,6 @@ static void lctrActPeerConnParamRsp(lctrConnCtx_t *pCtx) * \brief Action indirection for skipping peer LL_CONN_PARAM_RSP. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActSkipConnParamRsp(lctrConnCtx_t *pCtx) @@ -206,8 +193,6 @@ static void lctrActSkipConnParamRsp(lctrConnCtx_t *pCtx) * \brief Notify host of connection update with disallowed status. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActConnUpdDisallow(lctrConnCtx_t *pCtx) @@ -221,8 +206,6 @@ static void lctrActConnUpdDisallow(lctrConnCtx_t *pCtx) * \brief Send peer LL_REJECT_IND due to pending operation. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActRejectCollision(lctrConnCtx_t *pCtx) @@ -236,8 +219,6 @@ static void lctrActRejectCollision(lctrConnCtx_t *pCtx) * \brief Notify host of local rejected connection parameter procedure. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActLocalRejectConnParam(lctrConnCtx_t *pCtx) @@ -379,8 +360,6 @@ static const uint8_t lctrMstConnUpdNextStateTbl[LCTR_CU_STATE_TOTAL][LCTR_CU_EVE * * \param pCtx Connection context. * \param event Event ID. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrExecAction(lctrConnCtx_t *pCtx, uint8_t event) @@ -499,8 +478,6 @@ static uint8_t lctrMstConnUpdRemapEvent(lctrConnCtx_t *pCtx, uint8_t event) * * \param event Subsystem event. * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrResolveCollision(lctrConnCtx_t *pCtx, uint8_t event) @@ -538,8 +515,6 @@ static void lctrResolveCollision(lctrConnCtx_t *pCtx, uint8_t event) * \param pCtx Connection context. * \param event Subsystem event. * - * \return None. - * * This routine will pend the active procedure and allow the connection update procedure to * override it. */ @@ -642,8 +617,6 @@ bool_t lctrMstLlcpExecuteConnUpdSm(lctrConnCtx_t *pCtx, uint8_t event) * * \param pCtx Connection context. * \param event State machine event. - * - * \return None. */ /*************************************************************************************************/ void lctrMstLlcpExecuteSm(lctrConnCtx_t *pCtx, uint8_t event) @@ -660,6 +633,7 @@ void lctrMstLlcpExecuteSm(lctrConnCtx_t *pCtx, uint8_t event) return; } break; + default: break; } @@ -670,6 +644,7 @@ void lctrMstLlcpExecuteSm(lctrConnCtx_t *pCtx, uint8_t 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/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn_slave.c index 328dae2065..4d0e7bbc6c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_conn_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave connection state machine implementation file. + * \file + * + * \brief Link layer controller slave connection state machine implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -68,8 +69,6 @@ LctrLlcpHdlr_t lctrSlvLlcpSmTbl[LCTR_LLCP_SM_TOTAL]; * \brief Action indirection for start connection update. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActStartConnUpd(lctrConnCtx_t *pCtx) @@ -92,8 +91,6 @@ static void lctrActStartConnUpd(lctrConnCtx_t *pCtx) * \brief Action indirection for received host connection update command. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActHostConnUpd(lctrConnCtx_t *pCtx) @@ -108,8 +105,6 @@ static void lctrActHostConnUpd(lctrConnCtx_t *pCtx) * \brief Action indirection for received host connection update command. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerConnParam(lctrConnCtx_t *pCtx) @@ -125,8 +120,6 @@ static void lctrActPeerConnParam(lctrConnCtx_t *pCtx) * \brief Action indirection for received host connection update command with collision. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerConnParamWithCollision(lctrConnCtx_t *pCtx) @@ -139,8 +132,6 @@ static void lctrActPeerConnParamWithCollision(lctrConnCtx_t *pCtx) * \brief Action indirection for received peer LL_CONN_IND. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerConnInd(lctrConnCtx_t *pCtx) @@ -154,8 +145,6 @@ static void lctrActPeerConnInd(lctrConnCtx_t *pCtx) * \brief Action indirection for host reply command. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActHostReply(lctrConnCtx_t *pCtx) @@ -170,8 +159,6 @@ static void lctrActHostReply(lctrConnCtx_t *pCtx) * \brief Action indirection for host negative reply command. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrActHostNegReply(lctrConnCtx_t *pCtx) @@ -186,8 +173,6 @@ void lctrActHostNegReply(lctrConnCtx_t *pCtx) * \brief Notify host of peer rejected connection parameter procedure. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrActPeerRejectConnParam(lctrConnCtx_t *pCtx) @@ -215,8 +200,6 @@ void lctrActPeerRejectConnParam(lctrConnCtx_t *pCtx) * \brief Notify host of connection update with success status. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrActNotifyHostConnUpdSuccess(lctrConnCtx_t *pCtx) @@ -233,8 +216,6 @@ void lctrActNotifyHostConnUpdSuccess(lctrConnCtx_t *pCtx) * \brief Notify host connection completed due to colliding connection parameter from peer. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActNotifyHostColliding(lctrConnCtx_t *pCtx) @@ -248,8 +229,6 @@ static void lctrActNotifyHostColliding(lctrConnCtx_t *pCtx) * \brief Notify host of connection update with disallowed status. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActConnUpdDisallow(lctrConnCtx_t *pCtx) @@ -263,8 +242,6 @@ static void lctrActConnUpdDisallow(lctrConnCtx_t *pCtx) * \brief Send peer LL_REJECT_IND due to pending operation. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActRejectCollision(lctrConnCtx_t *pCtx) @@ -373,8 +350,6 @@ static const uint8_t lctrSlvConnUpdNextStateTbl[LCTR_CU_STATE_TOTAL][LCTR_CU_EVE * * \param pCtx Connection context. * \param event Event ID. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrExecAction(lctrConnCtx_t *pCtx, uint8_t event) @@ -486,8 +461,6 @@ static uint8_t lctrSlvConnUpdRemapEvent(lctrConnCtx_t *pCtx, uint8_t event) * * \param event Subsystem event. * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrResolveCollision(lctrConnCtx_t *pCtx, uint8_t event) @@ -531,8 +504,6 @@ static void lctrResolveCollision(lctrConnCtx_t *pCtx, uint8_t event) * \param pCtx Connection context. * \param event Subsystem event. * - * \return None. - * * This routine will pend the active procedure and allow the connection update procedure to * override it. */ @@ -638,8 +609,6 @@ bool_t lctrSlvLlcpExecuteConnUpdSm(lctrConnCtx_t *pCtx, uint8_t event) * * \param pCtx Connection context. * \param event Control event. - * - * \return None. */ /*************************************************************************************************/ void lctrLlcpStatelessEventHandler(lctrConnCtx_t *pCtx, uint8_t event) @@ -681,8 +650,6 @@ void lctrLlcpStatelessEventHandler(lctrConnCtx_t *pCtx, uint8_t event) * * \param pCtx Connection context. * \param event State machine event. - * - * \return None. */ /*************************************************************************************************/ void lctrSlvLlcpExecuteSm(lctrConnCtx_t *pCtx, uint8_t event) @@ -698,6 +665,7 @@ void lctrSlvLlcpExecuteSm(lctrConnCtx_t *pCtx, uint8_t event) return; } break; + default: break; } @@ -708,7 +676,8 @@ void lctrSlvLlcpExecuteSm(lctrConnCtx_t *pCtx, uint8_t 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_CMN] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CMN](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/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_enc_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_enc_master.c index 0c2f6e370b..f61dbc80a2 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_enc_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_enc_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master encryption connection state machine implementation file. + * \file + * + * \brief Link layer controller master encryption connection state machine implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -74,8 +75,6 @@ enum * \brief Notify host of encryption change with disallowed status. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActEncChangeDisallow(lctrConnCtx_t *pCtx) @@ -89,8 +88,6 @@ static void lctrActEncChangeDisallow(lctrConnCtx_t *pCtx) * \brief Action indirection for received host start encryption command. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActStartEnc(lctrConnCtx_t *pCtx) @@ -104,8 +101,6 @@ static void lctrActStartEnc(lctrConnCtx_t *pCtx) * \brief Action Tx data queue flushed on encryption start. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActTxFlushedOnStart(lctrConnCtx_t *pCtx) @@ -121,8 +116,6 @@ static void lctrActTxFlushedOnStart(lctrConnCtx_t *pCtx) * \brief Action indirection for received peer LL_ENC_RSP. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerEncRsp(lctrConnCtx_t *pCtx) @@ -141,8 +134,6 @@ static void lctrActPeerEncRsp(lctrConnCtx_t *pCtx) * \brief Action indirection for received peer LL_START_ENC_REQ. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerStartEncReq(lctrConnCtx_t *pCtx) @@ -158,8 +149,6 @@ static void lctrActPeerStartEncReq(lctrConnCtx_t *pCtx) * \brief Action indirection for received peer LL_START_ENC_RSP. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerStartEncRsp(lctrConnCtx_t *pCtx) @@ -177,8 +166,6 @@ static void lctrActPeerStartEncRsp(lctrConnCtx_t *pCtx) * \brief Action indirection for received host refresh key. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActRefreshEncKey(lctrConnCtx_t *pCtx) @@ -194,8 +181,6 @@ static void lctrActRefreshEncKey(lctrConnCtx_t *pCtx) * \brief Action Tx data queue flushed on encryption restart. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActTxFlushedOnRestart(lctrConnCtx_t *pCtx) @@ -209,8 +194,6 @@ static void lctrActTxFlushedOnRestart(lctrConnCtx_t *pCtx) * \brief Action indirection for received peer LL_PAUSE_ENC_RSP. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerPauseEncRsp(lctrConnCtx_t *pCtx) @@ -228,8 +211,6 @@ static void lctrActPeerPauseEncRsp(lctrConnCtx_t *pCtx) * \brief Action indirection for received peer LL_REJECT_IND. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerEncReject(lctrConnCtx_t *pCtx) @@ -546,10 +527,10 @@ bool_t lctrMstExecuteEncryptSm(lctrConnCtx_t *pCtx, uint8_t event) { if (pCtx->pauseRxData == TRUE) /* During encryption start or encryption pause. */ { - switch(event) + switch (event) { case LCTR_CONN_MSG_RX_LLCP: - switch(lctrDataPdu.opcode) + switch (lctrDataPdu.opcode) { /* Allowed PDUs. */ case LL_PDU_TERMINATE_IND: diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_enc_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_enc_slave.c index c9d3df3ff2..e60fd8b1c2 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_enc_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_enc_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave encryption connection state machine implementation file. + * \file + * + * \brief Link layer controller slave encryption connection state machine implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -89,8 +90,6 @@ enum * \brief Action indirection for received peer LL_ENC_REQ. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerEncReq(lctrConnCtx_t *pCtx) @@ -105,8 +104,6 @@ static void lctrActPeerEncReq(lctrConnCtx_t *pCtx) * \brief Action Tx data queue flushed after a start encryption. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActTxFlushedOnStart(lctrConnCtx_t *pCtx) @@ -126,8 +123,6 @@ static void lctrActTxFlushedOnStart(lctrConnCtx_t *pCtx) * \brief Action indirection for received host LTK request reply HCI command. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActHostLtkReply(lctrConnCtx_t *pCtx) @@ -146,8 +141,6 @@ static void lctrActHostLtkReply(lctrConnCtx_t *pCtx) * \brief Action indirection for received host LTK request negative reply HCI command. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActHostLtkNegReply(lctrConnCtx_t *pCtx) @@ -177,8 +170,6 @@ static void lctrActHostLtkNegReply(lctrConnCtx_t *pCtx) * \brief Action indirection for received peer LL_START_ENC_RSP. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerStartEncRsp(lctrConnCtx_t *pCtx) @@ -198,8 +189,6 @@ static void lctrActPeerStartEncRsp(lctrConnCtx_t *pCtx) * \brief Action indirection for received peer LL_PAUSE_ENC_REQ. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerPauseEncReq(lctrConnCtx_t *pCtx) @@ -217,8 +206,6 @@ static void lctrActPeerPauseEncReq(lctrConnCtx_t *pCtx) * \brief Action Tx data queue flushed after a restart encryption. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActTxFlushedOnRestart(lctrConnCtx_t *pCtx) @@ -432,8 +419,6 @@ static uint8_t lctrSlvRemapEncryptEvent(lctrConnCtx_t *pCtx, uint8_t event) * \param pCtx Connection context. * \param event Subsystem event. * - * \return None. - * * This routine will pend the active procedure and allow the encryption procedure to override it. */ /*************************************************************************************************/ @@ -553,10 +538,10 @@ bool_t lctrSlvExecuteEncryptSm(lctrConnCtx_t *pCtx, uint8_t event) { if (pCtx->pauseRxData == TRUE) /* During encryption start or encryption pause. */ { - switch(event) + switch (event) { case LCTR_CONN_MSG_RX_LLCP: - switch(lctrDataPdu.opcode) + switch (lctrDataPdu.opcode) { /* Allowed PDUs. */ case LL_PDU_TERMINATE_IND: diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_master_phy.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_master_phy.c index 376caedc3b..a34367b94b 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_master_phy.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_master_phy.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller master PHY update state machine implementation file. + * \file + * + * \brief Link layer controller master PHY update state machine implementation file. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -106,8 +107,6 @@ static bool_t lctrPreferenceIsSymmetric(uint8_t peerTxPhys, uint8_t peerRxPhys) * \param rxPhys Preferred receiver PHYs. * \param peerTxPhys Peer's preferred transmitter PHYs. * \param peerRxPhys Peer'sreferred receiver PHYs. - * - * \return None. */ /*************************************************************************************************/ static void lctrSendPhyUpdate(lctrConnCtx_t *pCtx, uint8_t txPhys, uint8_t rxPhys, uint8_t peerTxPhys, uint8_t peerRxPhys) @@ -164,8 +163,6 @@ static void lctrSendPhyUpdate(lctrConnCtx_t *pCtx, uint8_t txPhys, uint8_t rxPhy * \brief Action indirection for start PHY update. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActStartPhyUpdatePeer(lctrConnCtx_t *pCtx) @@ -193,8 +190,6 @@ static void lctrActStartPhyUpdatePeer(lctrConnCtx_t *pCtx) * \brief Action indirection for received host PHY update command. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActHostPhyUpdate(lctrConnCtx_t *pCtx) @@ -209,8 +204,6 @@ static void lctrActHostPhyUpdate(lctrConnCtx_t *pCtx) * \brief Action indirection for received peer PHY request. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerPhyReq(lctrConnCtx_t *pCtx) @@ -224,8 +217,6 @@ static void lctrActPeerPhyReq(lctrConnCtx_t *pCtx) * \brief Action indirection for received peer PHY response. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerPhyRsp(lctrConnCtx_t *pCtx) @@ -239,8 +230,6 @@ static void lctrActPeerPhyRsp(lctrConnCtx_t *pCtx) * \brief Send peer LL_REJECT_IND due to pending operation. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActRejectCollision(lctrConnCtx_t *pCtx) @@ -254,8 +243,6 @@ static void lctrActRejectCollision(lctrConnCtx_t *pCtx) * \brief Notify host of PHY update with disallowed status. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPhyUpdateDisallow(lctrConnCtx_t *pCtx) @@ -384,8 +371,6 @@ static const uint8_t lctrMstPhyUpdateNextStateTbl[LCTR_PU_STATE_TOTAL][LCTR_PU_E * * \param pCtx Connection context. * \param event Event ID. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrExecAction(lctrConnCtx_t *pCtx, uint8_t event) @@ -492,8 +477,6 @@ static uint8_t lctrRemapEvent(lctrConnCtx_t *pCtx, uint8_t event) * * \param event Subsystem event. * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrResolveCollision(lctrConnCtx_t *pCtx, uint8_t event) @@ -534,8 +517,6 @@ static void lctrResolveCollision(lctrConnCtx_t *pCtx, uint8_t event) * \param pCtx Connection context. * \param event Subsystem event. * - * \return None. - * * This routine will pend the active procedure and allow the phy update procedure to * override it. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_pc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_pc.c new file mode 100644 index 0000000000..2fbb9dbe31 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_pc.c @@ -0,0 +1,546 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Power control LLCP state machine implementation 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. + */ +/*************************************************************************************************/ + +#include "lctr_int_conn.h" +#include "lctr_int_conn_slave.h" +#include "lmgr_api.h" +#include "lctr_int_pc.h" +#include "util/bstream.h" +#include "wsf_trace.h" + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief Power control LLCP types. */ +enum +{ + LCTR_PC_PROC_IND, /*!< Power Indication process. */ + LCTR_PC_PROC_CTRL, /*!< Power control process. */ + + LCTR_PC_PROC_TOTAL /*!< Total power control procedures. */ +}; + +/*! \brief Common 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. */ +}; + +/*! \brief Common 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. */ +}; + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*! \brief Common procedure state machine action table. */ +const lctrLlcpEh_t lctrPclProcTbl[LCTR_PC_PROC_TOTAL][LCTR_PROC_CMN_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 */ + }, + /* 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 */ + } +}; + +/*************************************************************************************************/ +/*! + * \brief Get power control state machine index from process ID + * + * \param proc Process ID. + * + * \return Index of power control state machine. + */ +/*************************************************************************************************/ +static uint8_t lctrGetPclProcSmIndex(uint8_t proc) +{ + if (proc == LCTR_PROC_PWR_IND) + { + return LCTR_PC_PROC_IND; + } + else if (proc == LCTR_PROC_PWR_CTRL) + { + return LCTR_PC_PROC_CTRL; + } + else + { + LL_TRACE_ERR1("lctrGetPclProcSmIndex, invalid proc=%d", proc); + return LCTR_PROC_INVALID; + } +} + +/*************************************************************************************************/ +/*! + * \brief Execute action function. + * + * \param pCtx Connection context. + * \param proc Procedure ID. + * \param act Action ID. + */ +/*************************************************************************************************/ +static inline void lctrExecAction(lctrConnCtx_t *pCtx, uint8_t proc, uint8_t act) +{ + uint8_t pclProc = lctrGetPclProcSmIndex(proc); + + if (lctrPclProcTbl[pclProc][act]) + { + lctrPclProcTbl[pclProc][act](pCtx); + } +} + +/*************************************************************************************************/ +/*! + * \brief Get power control LLCP procedure ID. + * + * \param pCtx Connection context. + * \param event Event. + * + * \return LLCP procedure event ID. + */ +/*************************************************************************************************/ +static uint8_t lctrGetPclProcId(lctrConnCtx_t *pCtx, uint8_t event) +{ + switch (event) + { + case LCTR_CONN_MSG_API_PWR_CTRL_REQ: + return LCTR_PROC_PWR_CTRL; + + case LCTR_CONN_MSG_RX_LLCP: + switch (lctrDataPdu.opcode) + { + case LL_PDU_PWR_CHNG_IND: + return LCTR_PROC_PWR_IND; + + case LL_PDU_PWR_CTRL_REQ: + case LL_PDU_PWR_CTRL_RSP: + return LCTR_PROC_PWR_CTRL; + + case LL_PDU_REJECT_IND: + case LL_PDU_REJECT_EXT_IND: + return pCtx->llcpActiveProc; + + default: + break; + } + + break; + + case LCTR_CONN_LLCP_START_PENDING: + if (pCtx->llcpPendMask & (1 << LCTR_PROC_PWR_IND)) + { + pCtx->llcpPendMask &= ~(1 << LCTR_PROC_PWR_IND); + return LCTR_PROC_PWR_IND; + } + if (pCtx->llcpPendMask & (1 << LCTR_PROC_PWR_CTRL)) + { + pCtx->llcpPendMask &= ~(1 << LCTR_PROC_PWR_CTRL); + return LCTR_PROC_PWR_CTRL; + } + break; + + default: + break; + } + + return LCTR_PROC_INVALID; +} + +/*************************************************************************************************/ +/*! + * \brief Get remapped common LLCP procedure event. + * + * \param pCtx Connection context. + * \param event Subsystem event. + * + * \return Common LLCP procedure action ID. + * + * This routine remaps events for the common LLCP procedure state machine for optimized + * compressed state tables. + */ +/*************************************************************************************************/ +static uint8_t lctrRemapCmnProcEvent(lctrConnCtx_t *pCtx, uint8_t event) +{ + switch (event) + { + case LCTR_CONN_MSG_API_PWR_CTRL_REQ: + return LCTR_PROC_CMN_EVT_HOST_START; + + case LCTR_CONN_MSG_RX_LLCP_UNKNOWN: + return LCTR_PROC_CMN_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; + + case LL_PDU_PWR_CHNG_IND: + return LCTR_PROC_CMN_EVT_RECV_IND; + + case LL_PDU_PWR_CTRL_RSP: + return LCTR_PROC_CMN_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; + + default: + return LCTR_PROC_CMN_EVT_INVALID; + } + + case LCTR_CONN_LLCP_START_PENDING: + if (pCtx->llcpIncompMask) + { + return LCTR_PROC_CMN_EVT_INT_INCOMP; + } + else + { + return LCTR_PROC_CMN_EVT_INT_START; + } + + default: + break; + } + + return LCTR_PROC_CMN_EVT_INVALID; +} + +/*************************************************************************************************/ +/*! + * \brief Check for feature availability. + * + * \param pCtx Connection context. + * \param proc Requesting procedure. + * \param event Event. + * + * \return TRUE if available, FALSE otherwise. + */ +/*************************************************************************************************/ +static bool_t lctrFeatureAvail(lctrConnCtx_t *pCtx, uint8_t proc, uint8_t event) +{ + bool_t result = TRUE; + + switch (proc) + { + case LCTR_PROC_PWR_IND: + if ((lmgrCb.features & LL_FEAT_POWER_CHANGE_IND) == 0) + { + LL_TRACE_WARN1("Requested LCTR_PROC_PWR_IND not available, FeatSet=0x%08x", lmgrCb.features); + result = FALSE; + } + break; + case LCTR_PROC_PWR_CTRL: + if ((lmgrCb.features & LL_FEAT_POWER_CONTROL_REQUEST) == 0) + { + LL_TRACE_WARN1("Requested LCTR_PROC_PWR_CTRL not available, FeatSet=0x%08x", lmgrCb.features); + result = FALSE; + } + break; + default: + break; + } + + return result; +} + +/*************************************************************************************************/ +/*! + * \brief Notify host of successful procedure. + * + * \param pCtx Connection context. + * \param proc Completed procedure. + */ +/*************************************************************************************************/ +static void lctrNotifyHostSuccess(lctrConnCtx_t *pCtx, uint8_t proc) +{ + if ((pCtx->llcpNotifyMask & (1 << proc)) == 0) + { + return; + } + + pCtx->llcpNotifyMask &= ~(1 << proc); + + switch (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); + pCtx->readRemoteTxPower = FALSE; + } + break; + default: + break; + } +} + +/*************************************************************************************************/ +/*! + * \brief Notify host of failed procedure. + * + * \param pCtx Connection context. + * \param proc Complete procedure. + */ +/*************************************************************************************************/ +static void lctrNotifyHostReject(lctrConnCtx_t *pCtx, uint8_t proc) +{ + if ((pCtx->llcpNotifyMask & (1 << proc)) == 0) + { + return; + } + + pCtx->llcpNotifyMask &= ~(1 << proc); +} + +/*************************************************************************************************/ +/*! + * \brief Execute common LLCP state machine. + * + * \param pCtx Connection context. + * \param event State machine event. + * + * \return TRUE if handled by this SM, FALSE otherwise. + */ +/*************************************************************************************************/ +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) + { + return FALSE; + } + + if ((proc = lctrGetPclProcId(pCtx, llEvent)) == LCTR_PROC_INVALID) + { + return FALSE; + } + + switch (pCtx->llcpState) + { + case LCTR_LLCP_STATE_IDLE: + LL_TRACE_INFO3("lctrLlcpExecutePclSm: handle=%u, proc=%u, state=IDLE, event=%u", LCTR_GET_CONN_HANDLE(pCtx), proc, event); + + switch (event) + { + case LCTR_PROC_CMN_EVT_HOST_START: + pCtx->llcpNotifyMask |= 1 << proc; + lctrExecAction(pCtx, proc, LCTR_PROC_CMN_ACT_API_PARAM); + /* Fallthrough */ + case LCTR_PROC_CMN_EVT_INT_START: + if (lctrFeatureAvail(pCtx, proc, event)) + { + lctrExecAction(pCtx, proc, LCTR_PROC_CMN_ACT_SEND_REQ); + lctrStartLlcpTimer(pCtx); + pCtx->llcpActiveProc = proc; + pCtx->cmnState = LCTR_CMN_STATE_BUSY; + pCtx->llcpState = LCTR_LLCP_STATE_BUSY; + } + else + { + lctrNotifyHostReject(pCtx, proc); + } + break; + + case LCTR_PROC_CMN_EVT_INT_INCOMP: + case LCTR_PROC_CMN_EVT_RECV_IND: + case LCTR_PROC_CMN_EVT_RECV_REQ: + if (lctrFeatureAvail(pCtx, proc, event)) + { + if (event != LCTR_PROC_CMN_EVT_INT_INCOMP) + { + lctrExecAction(pCtx, proc, LCTR_PROC_CMN_ACT_RECV_REQ); + } + + if (lctrPclProcTbl[lctrGetPclProcSmIndex(proc)][LCTR_PROC_CMN_ACT_SEND_RSP]) + { + /* Procedure completes; no transition to BUSY. */ + lctrPclProcTbl[lctrGetPclProcSmIndex(proc)][LCTR_PROC_CMN_ACT_SEND_RSP](pCtx); + } + else + { + /* No response; procedure completes at CE instant. */ + pCtx->llcpActiveProc = proc; + pCtx->llcpInstantComp = FALSE; + pCtx->cmnState = LCTR_CMN_STATE_BUSY; + pCtx->llcpState = LCTR_LLCP_STATE_BUSY; + } + } + else + { + lctrSendRejectInd(pCtx, LL_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE, FALSE); + } + break; + + case LCTR_PROC_CMN_EVT_RECV_RSP: + case LCTR_PROC_CMN_EVT_PROC_COMP: + case LCTR_PROC_CMN_EVT_REJECT: + default: + /* No action required. */ + break; + } + break; + + case LCTR_LLCP_STATE_BUSY: + LL_TRACE_INFO3("lctrLlcpExecutePclSm: handle=%u, proc=%u, state=BUSY, event=%u", LCTR_GET_CONN_HANDLE(pCtx), proc, event); + + switch (event) + { + case LCTR_PROC_CMN_EVT_HOST_START: + case LCTR_PROC_CMN_EVT_INT_START: + if (lctrFeatureAvail(pCtx, proc, event)) + { + if (event == LCTR_PROC_CMN_EVT_HOST_START) + { + pCtx->llcpNotifyMask |= 1 << proc; + } + + if (pCtx->llcpActiveProc != proc) + { + LL_TRACE_INFO1("Pending procedure in progress: activeProc=%u", pCtx->llcpActiveProc); + pCtx->llcpPendMask |= 1 << proc; + } + if (event == LCTR_PROC_CMN_EVT_HOST_START) + { + lctrExecAction(pCtx, proc, LCTR_PROC_CMN_ACT_API_PARAM); + } + } + else + { + lctrNotifyHostReject(pCtx, proc); + } + break; + + case LCTR_PROC_CMN_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); + pCtx->llcpIncompMask |= 1 << proc; + } + break; + } + /* Fallthrough */ + case LCTR_PROC_CMN_EVT_RECV_RSP: + if (proc == pCtx->llcpActiveProc) + { + /* Incoming procedure matches the active one. */ + lctrExecAction(pCtx, proc, LCTR_PROC_CMN_ACT_RECV_RSP); + } + else if (pCtx->llcpPendMask & (1 << proc)) + { + /* Incoming procedure matches one of the pended one. */ + pCtx->llcpPendMask &= ~(1 << proc); + if (pCtx->llcpIsOverridden == TRUE) + { + pCtx->llcpIsOverridden = FALSE; + } + lctrExecAction(pCtx, proc, LCTR_PROC_CMN_ACT_RECV_RSP); + lctrNotifyHostSuccess(pCtx, proc); + break; + } + else + { + LL_TRACE_ERR1("Unexpected response packet, expected llcpActiveProc=%u", pCtx->llcpActiveProc); + 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) + { + lctrNotifyHostReject(pCtx, proc); + } + else + { + lctrNotifyHostSuccess(pCtx, proc); + } + + lctrStopLlcpTimer(pCtx); + + pCtx->llcpActiveProc = LCTR_PROC_INVALID; + pCtx->cmnState = LCTR_CMN_STATE_IDLE; + pCtx->llcpState = LCTR_LLCP_STATE_IDLE; + + lctrStartPendingLlcp(pCtx); + break; + + case LCTR_PROC_CMN_EVT_RECV_REQ: + LL_TRACE_WARN1("Procedure collision; pending incomplete request, activeProc=%u", pCtx->llcpActiveProc); + lctrExecAction(pCtx, proc, LCTR_PROC_CMN_ACT_RECV_REQ); + if (lctrFeatureAvail(pCtx, proc, event)) + { + lctrPclProcTbl[lctrGetPclProcSmIndex(proc)][LCTR_PROC_CMN_ACT_SEND_RSP](pCtx); + } + else + { + lctrSendRejectInd(pCtx, LL_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE, FALSE); + } + break; + + default: + /* No action. */ + break; + } + break; + + default: + break; + } + + return TRUE; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_slave_phy.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_slave_phy.c index 0febf04960..a4fc42e106 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_slave_phy.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lctr/lctr_sm_llcp_slave_phy.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer controller slave PHY update state machine implementation file. + * \file + * + * \brief Link layer controller slave PHY update state machine implementation file. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -83,8 +84,6 @@ void lctrActFlushArq(lctrConnCtx_t *pCtx); * \brief Update effective data packet time after PHY update procedure completes and notify host. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrUpdateDataTime(lctrConnCtx_t *pCtx) @@ -97,26 +96,26 @@ 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), pCtx->effDataPdu.maxTxTime); + 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), pCtx->effDataPdu.maxTxTime); + maxTxTime = WSF_MIN(LL_DATA_LEN_TO_TIME_2M(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), pCtx->effDataPdu.maxTxTime); + maxTxTime = WSF_MIN(LL_DATA_LEN_TO_TIME_CODED_S8(pCtx->effDataPdu.maxTxLen, TRUE), pCtx->effDataPdu.maxTxTime); break; } switch (pCtx->bleData.chan.rxPhy) { case BB_PHY_BLE_1M: - maxRxTime = WSF_MIN(LL_DATA_LEN_TO_TIME_1M(pCtx->effDataPdu.maxRxLen), pCtx->effDataPdu.maxRxTime); + 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), pCtx->effDataPdu.maxRxTime); + maxRxTime = WSF_MIN(LL_DATA_LEN_TO_TIME_2M(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), pCtx->effDataPdu.maxRxTime); + maxRxTime = WSF_MIN(LL_DATA_LEN_TO_TIME_CODED_S8(pCtx->effDataPdu.maxRxLen, TRUE), pCtx->effDataPdu.maxRxTime); break; } @@ -163,8 +162,6 @@ static void lctrUpdateDataTime(lctrConnCtx_t *pCtx) * \brief Notify host of peer rejected PHY request. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrActPeerRejectPhyReq(lctrConnCtx_t *pCtx) @@ -197,8 +194,6 @@ void lctrActPeerRejectPhyReq(lctrConnCtx_t *pCtx) * \brief Notify host of connection update with no change. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrActNotifyHostPhyUpdateNoChange(lctrConnCtx_t *pCtx) @@ -223,8 +218,6 @@ void lctrActNotifyHostPhyUpdateNoChange(lctrConnCtx_t *pCtx) * \brief Notify host of connection update with success status. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrActNotifyHostPhyUpdateSuccess(lctrConnCtx_t *pCtx) @@ -300,8 +293,6 @@ uint8_t lctrSuppPhys(void) * \param pTxPhys Preferred transmitter PHYs. * \param pRxPhys Preferred receiver PHYs. * \param peerPhys Peer preferred PHYs. - * - * \return None. */ /*************************************************************************************************/ static void lctrAdjustPhyPreference(lctrConnCtx_t *pCtx, uint8_t allPhys, uint8_t *pTxPhys, uint8_t *pRxPhys, uint8_t peerPhys) @@ -355,8 +346,6 @@ static void lctrAdjustPhyPreference(lctrConnCtx_t *pCtx, uint8_t allPhys, uint8_ * \brief Action indirection for start PHY update. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrActStartPhyUpdate(lctrConnCtx_t *pCtx) @@ -400,8 +389,6 @@ void lctrActStartPhyUpdate(lctrConnCtx_t *pCtx) * \brief Action indirection for flushing ARQ. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ void lctrActFlushArq(lctrConnCtx_t *pCtx) @@ -419,8 +406,6 @@ void lctrActFlushArq(lctrConnCtx_t *pCtx) * \brief Action indirection for received host PHY update command. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActHostPhyUpdate(lctrConnCtx_t *pCtx) @@ -435,8 +420,6 @@ static void lctrActHostPhyUpdate(lctrConnCtx_t *pCtx) * \brief Action indirection for start PHY response. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActStartPhyRsp(lctrConnCtx_t *pCtx) @@ -460,8 +443,6 @@ static void lctrActStartPhyRsp(lctrConnCtx_t *pCtx) * \brief Action indirection for received peer PHY request. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerPhyReq(lctrConnCtx_t *pCtx) @@ -475,8 +456,6 @@ static void lctrActPeerPhyReq(lctrConnCtx_t *pCtx) * \brief Action indirection for received peer PHY update request. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerPhyUpdateReq(lctrConnCtx_t *pCtx) @@ -500,8 +479,6 @@ static void lctrActPeerPhyUpdateReq(lctrConnCtx_t *pCtx) * \brief Action indirection for received peer PHY request. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPeerPhyReqWithCollision(lctrConnCtx_t *pCtx) @@ -514,8 +491,6 @@ static void lctrActPeerPhyReqWithCollision(lctrConnCtx_t *pCtx) * \brief Notify host of PHY update with disallowed status. * * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrActPhyUpdateDisallow(lctrConnCtx_t *pCtx) @@ -652,8 +627,6 @@ static const uint8_t lctrSlvPhyUpdateNextStateTbl[LCTR_PU_STATE_TOTAL][LCTR_PU_E * * \param pCtx Connection context. * \param event Event ID. - * - * \return None. */ /*************************************************************************************************/ static inline void lctrExecAction(lctrConnCtx_t *pCtx, uint8_t event) @@ -760,8 +733,6 @@ static uint8_t lctrRemapEvent(lctrConnCtx_t *pCtx, uint8_t event) * * \param event Subsystem event. * \param pCtx Connection context. - * - * \return None. */ /*************************************************************************************************/ static void lctrResolveCollision(lctrConnCtx_t *pCtx, uint8_t event) @@ -801,8 +772,6 @@ static void lctrResolveCollision(lctrConnCtx_t *pCtx, uint8_t event) * \param pCtx Connection context. * \param event Subsystem event. * - * \return None. - * * This routine will pend the active procedure and allow the phy update procedure to * override it. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd.c index 950b64cafc..0f20089845 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief HCI command module implementation file. + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -63,7 +64,7 @@ static uint8_t lhciUnpackSetEventMaskCmd(uint64_t *pEvtMsk, const uint8_t *pBuf) * \return Packet length. */ /*************************************************************************************************/ -static uint8_t lhciPackReadBufSizeEvt(uint8_t *pBuf, uint8_t status, uint16_t pktLen, uint16_t numPkts) +static uint8_t lhciPackReadBufSizeEvt(uint8_t *pBuf, uint8_t status, uint16_t pktLen, uint8_t numPkts) { const uint8_t len = LHCI_LEN_LE_READ_BUF_SIZE_EVT; @@ -121,7 +122,7 @@ static uint8_t lhciPackLocalSupCmds(uint8_t *pBuf, uint8_t status) memset(pBuf, 0, len); UINT8_TO_BSTREAM (pBuf, status); - memcpy(pBuf, LmgrReadHciSupCmd(), HCI_SUP_CMD_LEN); + memcpy(pBuf, lhciPersistCb.supCmds, HCI_SUP_CMD_LEN); return len; } @@ -152,8 +153,6 @@ static uint8_t lhciPackLocalSupFeat(uint8_t *pBuf, uint8_t status) * * \param pCmdHdr Command HCI header. * \param status Status value. - * - * \return None. */ /*************************************************************************************************/ void lhciSendCmdStatusEvt(LhciHdr_t *pCmdHdr, uint8_t status) @@ -176,8 +175,6 @@ void lhciSendCmdStatusEvt(LhciHdr_t *pCmdHdr, uint8_t status) * \param pCmdHdr Command HCI header. * \param status Status value. * \param paramLen Parameter length of the command status event. - * - * \return None. */ /*************************************************************************************************/ static void lhciCommonSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen) @@ -205,6 +202,7 @@ static void lhciCommonSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t case HCI_OPCODE_LE_WRITE_RF_PATH_COMP: case HCI_OPCODE_NOP: case HCI_OPCODE_LE_MODIFY_SLEEP_CLK_ACC: + case HCI_OPCODE_LE_SET_HOST_FEATURE: lhciPackCmdCompleteEvtStatus(pBuf, status); break; @@ -384,6 +382,10 @@ bool_t lhciCommonDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) case HCI_OPCODE_LE_READ_TX_POWER: paramLen = LHCI_LEN_LE_READ_SUP_TX_POWER; break; + case HCI_OPCODE_LE_SET_HOST_FEATURE: + status = LlSetHostFeatures(*pBuf, *(pBuf + 1)); + paramLen = LHCI_LEN_LE_SET_HOST_FEATURE; + break; case HCI_OPCODE_LE_WRITE_RF_PATH_COMP: { int16_t txPathComp; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_master.c index f97fa3cd5a..614875253f 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief HCI command module implementation file. + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -59,8 +60,6 @@ static uint8_t lhciUnpackSetScanParamCmd(LlScanParam_t *pCmd, const uint8_t *pBu * \param pCmdHdr Command HCI header. * \param status Status value. * \param paramLen Parameter length of the command status event. - * - * \return None. */ /*************************************************************************************************/ static void lhciMstScanSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_master_ae.c index 6bf8d73919..382e6f1a4c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief HCI command module implementation file. + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -52,8 +53,6 @@ typedef struct * * \param pCmd Unpacked command structure. * \param pBuf Packed packet buffer. - * - * \return None. */ /*************************************************************************************************/ static void lhciUnpackSetExtScanParamCmd(lhciSetExtScanParamCmd_t *pCmd, const uint8_t *pBuf) @@ -86,8 +85,6 @@ static void lhciUnpackSetExtScanParamCmd(lhciSetExtScanParamCmd_t *pCmd, const u * \param pCmdHdr Command HCI header. * \param status Status value. * \param paramLen Parameter length of the command status event. - * - * \return None. */ /*************************************************************************************************/ static void lhciMstAeSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen) @@ -191,7 +188,17 @@ bool_t lhciMstExtScanDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) BSTREAM_TO_UINT16(cmd.skip, pBuf); BSTREAM_TO_UINT16(cmd.syncTimeOut, pBuf); pBuf++; /* Sync_CTE_Type (Unused) */ - status = LlPeriodicAdvCreateSync(&cmd); + + if (((cmd.options >> 1) & 0x01) && + ((lhciPersistCb.supCmds[40] & HCI_SUP_LE_SET_PER_ADV_RCV_ENABLE) == 0)) + { + status = LL_ERROR_CODE_CONN_FAILED_TO_ESTABLISH; + } + else + { + status = LlPeriodicAdvCreateSync(&cmd); + } + paramLen = LHCI_LEN_CMD_STATUS_EVT; break; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_priv.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_priv.c index 7712a95c42..27dcc6d82b 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_priv.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_priv.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief HCI command module implementation file. + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -57,8 +58,6 @@ static uint8_t lhciPackReadResListSizeEvt(uint8_t *pBuf, uint8_t status, uint16_ * \param pCmdHdr Command HCI header. * \param status Status value. * \param paramLen Parameter length of the command status event. - * - * \return None. */ /*************************************************************************************************/ static void lhciPrivAdvSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_slave.c index 8506dae9a9..384854aa83 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief HCI command module implementation file. + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -80,8 +81,6 @@ static uint8_t lhciUnpackSetAdvParamCmd(lhciSetAdvParamCmd_t *pCmd, const uint8_ * \param pCmdHdr Command HCI header. * \param status Status value. * \param paramLen Parameter length of the command status event. - * - * \return None. */ /*************************************************************************************************/ static void lhciSlvAdvSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_slave_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_slave_ae.c index c3a0ff8693..527853b718 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_slave_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_adv_slave_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief HCI command module implementation file. + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -36,8 +37,6 @@ * \param status Status value. * \param paramLen Parameter length of the command status event. * \param handle Advertising handle. - * - * \return None. */ /*************************************************************************************************/ static void lhciSlvExtAdvSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen, uint8_t handle) @@ -238,7 +237,7 @@ bool_t lhciSlvExtAdvDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) uint8_t enable; BSTREAM_TO_UINT8(enable, pBuf); BSTREAM_TO_UINT8(handle, pBuf); - LlSetPeriodicAdvEnable(handle, enable); + LlSetPeriodicAdvEnable(enable, handle); /* Send command complete once LL finishes processing the command. */ return TRUE; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_bis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_bis_master.c new file mode 100644 index 0000000000..ac7995b6c4 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_bis_master.c @@ -0,0 +1,90 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 "lhci_int.h" +#include "ll_api.h" +#include "util/bstream.h" +#include "wsf_math.h" +#include + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Decode an HCI command packet. + * + * \param pHdr Decoded packet header. + * \param pBuf Packed HCI packet buffer. + * + * \return TRUE if opcode handled, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lhciMstBisDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) +{ + uint8_t status = HCI_SUCCESS; + uint8_t paramLen = 0; + + switch (pHdr->opCode) + { + case HCI_OPCODE_LE_BIG_CREATE_SYNC: + { + LlBigCreateSync_t param; + + BSTREAM_TO_UINT8(param.bigHandle, pBuf); + BSTREAM_TO_UINT16(param.syncHandle, pBuf); + BSTREAM_TO_UINT8(param.encrypt, pBuf); + memcpy(param.bcstCode, pBuf, sizeof(param.bcstCode)); + pBuf += 16; + BSTREAM_TO_UINT8(param.mse, pBuf); + BSTREAM_TO_UINT16(param.bigSyncTimeout, pBuf); + BSTREAM_TO_UINT8(param.numBis, pBuf); + memcpy(param.bis, pBuf, WSF_MIN(param.numBis, sizeof(param.bis))); + + status = LlBigCreateSync(¶m); + paramLen = LHCI_LEN_CMD_STATUS_EVT; + break; + } + case HCI_OPCODE_LE_BIG_TERMINATE_SYNC: + { + uint8_t bigHandle; + + BSTREAM_TO_UINT8(bigHandle, pBuf); + + LlBigTerminateSync(bigHandle); + break; + } + + default: + return FALSE; /* exit dispatcher routine */ + } + + if (paramLen == LHCI_LEN_CMD_STATUS_EVT) + { + lhciSendCmdStatusEvt(pHdr, status); + } + + return TRUE; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_bis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_bis_slave.c new file mode 100644 index 0000000000..440d5b3028 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_bis_slave.c @@ -0,0 +1,121 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 "lhci_int.h" +#include "hci_defs.h" +#include "ll_api.h" +#include "util/bstream.h" +#include + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Decode an HCI command packet. + * + * \param pHdr Decoded packet header. + * \param pBuf Packed HCI packet buffer. + * + * \return TRUE if opcode handled, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lhciSlvBisDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) +{ + uint8_t status = HCI_SUCCESS; + uint8_t paramLen = 0; + + switch (pHdr->opCode) + { + case HCI_OPCODE_LE_CREATE_BIG: + { + LlCreateBig_t param; + + BSTREAM_TO_UINT8 (param.bigHandle, pBuf); + BSTREAM_TO_UINT8 (param.advHandle, pBuf); + BSTREAM_TO_UINT8 (param.numBis, pBuf); + BSTREAM_TO_UINT24(param.sduInterUsec, pBuf); + BSTREAM_TO_UINT16(param.maxSdu, pBuf); + BSTREAM_TO_UINT16(param.mtlMs, pBuf); + BSTREAM_TO_UINT8 (param.rtn, pBuf); + BSTREAM_TO_UINT8 (param.phys, pBuf); + BSTREAM_TO_UINT8 (param.packing, pBuf); + BSTREAM_TO_UINT8 (param.framing, pBuf); + BSTREAM_TO_UINT8 (param.encrypt, pBuf); + memcpy(param.bcstCode, pBuf, sizeof(param.bcstCode)); + + status = LlCreateBig(¶m); + paramLen = LHCI_LEN_CMD_STATUS_EVT; + break; + } + case HCI_OPCODE_LE_CREATE_BIG_TEST: + { + LlCreateBigTest_t param; + + BSTREAM_TO_UINT8 (param.bigHandle, pBuf); + BSTREAM_TO_UINT8 (param.advHandle, pBuf); + BSTREAM_TO_UINT8 (param.numBis, pBuf); + BSTREAM_TO_UINT24(param.sduInterUsec, pBuf); + BSTREAM_TO_UINT16(param.isoInter, pBuf); + BSTREAM_TO_UINT8 (param.nse, pBuf); + BSTREAM_TO_UINT16(param.maxSdu, pBuf); + BSTREAM_TO_UINT16(param.maxPdu, pBuf); + BSTREAM_TO_UINT8 (param.phys, pBuf); + BSTREAM_TO_UINT8 (param.packing, pBuf); + BSTREAM_TO_UINT8 (param.framing, pBuf); + BSTREAM_TO_UINT8 (param.bn, pBuf); + BSTREAM_TO_UINT8 (param.irc, pBuf); + BSTREAM_TO_UINT8 (param.pto, pBuf); + BSTREAM_TO_UINT8 (param.encrypt, pBuf); + memcpy(param.bcstCode, pBuf, sizeof(param.bcstCode)); + + status = LlCreateBigTest(¶m); + paramLen = LHCI_LEN_CMD_STATUS_EVT; + break; + } + case HCI_OPCODE_LE_TERMINATE_BIG: + { + uint8_t bigHandle; + uint8_t reason; + + BSTREAM_TO_UINT8(bigHandle, pBuf); + BSTREAM_TO_UINT8(reason, pBuf); + + status = LlTerminateBig(bigHandle, reason); + paramLen = LHCI_LEN_CMD_STATUS_EVT; + break; + } + + default: + return FALSE; /* exit dispatcher routine */ + } + + if (paramLen == LHCI_LEN_CMD_STATUS_EVT) + { + lhciSendCmdStatusEvt(pHdr, status); + } + + return TRUE; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_cis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_cis_master.c new file mode 100644 index 0000000000..8126506cc0 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_cis_master.c @@ -0,0 +1,308 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "lhci_int.h" +#include "hci_defs.h" +#include "ll_api.h" +#include "ll_defs.h" +#include "wsf_msg.h" +#include "wsf_math.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +uint8_t numCis; /*!< Number of CIS. */ +uint8_t cigID; /*!< Number of CIS. */ +uint16_t cisHandles[LL_MAX_CIS] = {0}; /*!< CIS Handle list. */ + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Pack a set CIG parameters event. + * + * \param pBuf Packed packet buffer. + * \param status Status code. + * \param numHandles Number of cis handles. + * \param pCisHandles Handle numbers. + */ +/*************************************************************************************************/ +static void lhciPackSetCigParamsEvt(uint8_t *pBuf, uint8_t status, uint8_t numHandles, uint16_t *pCisHandles) +{ + UINT8_TO_BSTREAM (pBuf, status); + UINT8_TO_BSTREAM (pBuf, cigID); + UINT8_TO_BSTREAM (pBuf, numHandles); + + for (unsigned int i = 0; i < numHandles; i++) + { + UINT16_TO_BSTREAM (pBuf, pCisHandles[i]); + } + + return; +} + +/*************************************************************************************************/ +/*! + * \brief Pack a remove CIG event. + * + * \param pBuf Packed packet buffer. + * \param status Status code. + * + * \return Packet length. + */ +/*************************************************************************************************/ +static uint8_t lhciPackRemoveCigEvt(uint8_t *pBuf, uint8_t status) +{ + const uint8_t len = LHCI_LEN_LE_REMOVE_CIG; + + UINT8_TO_BSTREAM (pBuf, status); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Build and send a command complete event packet. + * + * \param pCmdHdr Command HCI header. + * \param status Status value. + * \param paramLen Parameter length of the command status event. + */ +/*************************************************************************************************/ +static void lhciCisMstSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen) +{ + uint8_t *pBuf; + uint8_t *pEvtBuf; + + if ((pEvtBuf = lhciAllocCmdCmplEvt(paramLen, pCmdHdr->opCode)) == NULL) + { + return; + } + pBuf = pEvtBuf; + + switch (pCmdHdr->opCode) + { + /* --- command completion with status only parameter --- */ + + case HCI_OPCODE_LE_SET_CIG_PARAMS: + case HCI_OPCODE_LE_SET_CIG_PARAMS_TEST: + { + lhciPackSetCigParamsEvt(pBuf, status, numCis, cisHandles); + break; + } + case HCI_OPCODE_LE_REMOVE_CIG: + { + lhciPackRemoveCigEvt(pBuf, status); + break; + } + /* --- default --- */ + + default: + break; + } + + lhciSendCmdCmplEvt(pEvtBuf); +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Decode an HCI command packet. + * + * \param pHdr Decoded packet header. + * \param pBuf Packed HCI packet buffer. + * + * \return TRUE if opcode handled, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lhciMstCisDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) +{ + uint8_t status = HCI_SUCCESS; + uint8_t paramLen = 0; + const uint8_t MAX_CIS_COUNT = 16; + + switch (pHdr->opCode) + { + case HCI_OPCODE_LE_SET_CIG_PARAMS: + { + uint8_t cigId; + uint32_t sduIntervalMToS = 0; + uint32_t sduIntervalSToM = 0; + uint8_t sca; + uint8_t packing; + uint8_t framing; + uint16_t transLatMToS; + uint16_t transLatSToM; + + BSTREAM_TO_UINT8(cigId, pBuf); + BSTREAM_TO_UINT24(sduIntervalMToS, pBuf); + BSTREAM_TO_UINT24(sduIntervalSToM, pBuf); + BSTREAM_TO_UINT8(sca, pBuf); + BSTREAM_TO_UINT8(packing, pBuf); + BSTREAM_TO_UINT8(framing, pBuf); + BSTREAM_TO_UINT16(transLatMToS, pBuf); + BSTREAM_TO_UINT16(transLatSToM, pBuf); + BSTREAM_TO_UINT8(numCis, pBuf); + + LlCisCigParams_t cigParam; + + LlCisCisParams_t cisParam[MAX_CIS_COUNT]; + + for (unsigned int i = 0; i < WSF_MIN(numCis, MAX_CIS_COUNT); i++) + { + BSTREAM_TO_UINT8(cisParam[i].cisId, pBuf); + BSTREAM_TO_UINT16(cisParam[i].sduSizeMToS, pBuf); + BSTREAM_TO_UINT16(cisParam[i].sduSizeSToM, pBuf); + BSTREAM_TO_UINT8(cisParam[i].phyMToS, pBuf); + BSTREAM_TO_UINT8(cisParam[i].phySToM, pBuf); + BSTREAM_TO_UINT8(cisParam[i].rteMToS, pBuf); + BSTREAM_TO_UINT8(cisParam[i].rteSToM, pBuf); + } + + cigParam.cigId = cigId; + cigParam.sduIntervalMToS = sduIntervalMToS; + cigParam.sduIntervalSToM = sduIntervalSToM; + cigParam.sca = sca; + cigParam.packing = packing; + cigParam.framing = framing; + cigParam.transLatMToS = transLatMToS; + cigParam.transLatSToM = transLatSToM; + cigParam.numCis = numCis; + cigParam.pCisParam = &cisParam[0]; + + status = LlSetCigParams(&cigParam, cisHandles); + paramLen = 3 + numCis * 2; + break; + } + case HCI_OPCODE_LE_SET_CIG_PARAMS_TEST: + { + uint8_t cigId; + uint32_t sduIntervalMToS = 0; + uint32_t sduIntervalSToM = 0; + uint8_t ftMToS; + uint8_t ftSToM; + uint16_t isoInterval; + uint8_t sca; + uint8_t packing; + uint8_t framing; + + BSTREAM_TO_UINT8(cigId, pBuf); + BSTREAM_TO_UINT24(sduIntervalMToS, pBuf); + BSTREAM_TO_UINT24(sduIntervalSToM, pBuf); + BSTREAM_TO_UINT8(ftMToS, pBuf); + BSTREAM_TO_UINT8(ftSToM, pBuf); + BSTREAM_TO_UINT16(isoInterval, pBuf); + BSTREAM_TO_UINT8(sca, pBuf); + BSTREAM_TO_UINT8(packing, pBuf); + BSTREAM_TO_UINT8(framing, pBuf); + BSTREAM_TO_UINT8(numCis, pBuf); + + LlCisCigParamsTest_t cigParam; + + LlCisCigCisParamsTest_t cisParam[LL_MAX_CIS]; + + for (unsigned int i = 0; i < WSF_MIN(numCis, LL_MAX_CIS); i++) + { + BSTREAM_TO_UINT8(cisParam[i].cisId, pBuf); + BSTREAM_TO_UINT8(cisParam[i].nse, pBuf); + BSTREAM_TO_UINT16(cisParam[i].sduSizeMToS, pBuf); + BSTREAM_TO_UINT16(cisParam[i].sduSizeSToM, pBuf); + BSTREAM_TO_UINT16(cisParam[i].pduSizeMToS, pBuf); + BSTREAM_TO_UINT16(cisParam[i].pduSizeSToM, pBuf); + BSTREAM_TO_UINT8(cisParam[i].phyMToS, pBuf); + BSTREAM_TO_UINT8(cisParam[i].phySToM, pBuf); + BSTREAM_TO_UINT8(cisParam[i].bnMToS, pBuf); + BSTREAM_TO_UINT8(cisParam[i].bnSToM, pBuf); + } + + cigParam.cigId = cigId; + cigParam.sduIntervalMToS = sduIntervalMToS; + cigParam.sduIntervalSToM = sduIntervalSToM; + cigParam.ftMToS = ftMToS; + cigParam.ftSToM = ftSToM; + cigParam.isoInterval = isoInterval; + cigParam.sca = sca; + cigParam.packing = packing; + cigParam.framing = framing; + cigParam.numCis = numCis; + cigParam.pCisParam = &cisParam[0]; + + status = LlSetCigParamsTest(&cigParam, cisHandles); + paramLen = 3 + numCis * 2; + break; + } + case HCI_OPCODE_LE_CREATE_CIS: + { + BSTREAM_TO_UINT8(numCis, pBuf); + LlCisCreateCisParams_t createCisParam; + uint16_t aclHandle[LL_MAX_CIS]; + uint16_t cisHandle[LL_MAX_CIS]; + + for (unsigned int i = 0; i < WSF_MIN(numCis, LL_MAX_CIS); i++) + { + BSTREAM_TO_UINT16 (cisHandle[i], pBuf); + BSTREAM_TO_UINT16 (aclHandle[i], pBuf); + } + createCisParam.pCisHandle = &cisHandle[0]; + createCisParam.pAclHandle = &aclHandle[0]; + status = LlCreateCis(numCis, &createCisParam); + paramLen = LHCI_LEN_CMD_STATUS_EVT; + break; + } + case HCI_OPCODE_LE_REMOVE_CIG: + { + uint8_t cigId; + + BSTREAM_TO_UINT8(cigId, pBuf); + status = LlRemoveCig(cigId); + + paramLen = LHCI_LEN_LE_REMOVE_CIG; + + break; + } + + default: + return FALSE; /* exit dispatcher routine */ + } + + if (paramLen == LHCI_LEN_CMD_STATUS_EVT) + { + lhciSendCmdStatusEvt(pHdr, status); + } + else if (paramLen > 0) + { + lhciCisMstSendCmdCmplEvt(pHdr, status, paramLen); + } + + return TRUE; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_cis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_cis_slave.c new file mode 100644 index 0000000000..86ae732934 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_cis_slave.c @@ -0,0 +1,138 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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 "lhci_int.h" +#include "hci_defs.h" +#include "ll_api.h" +#include "ll_defs.h" +#include "wsf_msg.h" +#include "wsf_math.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Build and send a command complete event packet. + * + * \param pCmdHdr Command HCI header. + * \param status Status value. + * \param paramLen Parameter length of the command status event. + * \param handle Handle. + */ +/*************************************************************************************************/ +static void lhciCisSlvSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen, uint16_t handle) +{ + uint8_t *pBuf; + uint8_t *pEvtBuf; + + if ((pEvtBuf = lhciAllocCmdCmplEvt(paramLen, pCmdHdr->opCode)) == NULL) + { + return; + } + pBuf = pEvtBuf; + + switch (pCmdHdr->opCode) + { + /* --- command completion with status only parameter --- */ + case HCI_OPCODE_LE_ACCEPT_CIS_REQ: + { + break; + } + case HCI_OPCODE_LE_REJECT_CIS_REQ: + { + lhciPackCmdCompleteEvtStatus(pBuf, status); + break; + } + /* --- default --- */ + + default: + break; + } + + lhciSendCmdCmplEvt(pEvtBuf); +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Decode an HCI command packet. + * + * \param pHdr Decoded packet header. + * \param pBuf Packed HCI packet buffer. + * + * \return TRUE if opcode handled, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lhciSlvCisDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) +{ + uint8_t status = HCI_SUCCESS; + uint8_t paramLen = 0; + uint16_t handle = 0; + + switch (pHdr->opCode) + { + case HCI_OPCODE_LE_ACCEPT_CIS_REQ: + { + uint16_t cisHandle; + + BSTREAM_TO_UINT16(cisHandle, pBuf); + status = LlAcceptCisReq(cisHandle); + paramLen = LHCI_LEN_CMD_STATUS_EVT; + break; + } + + case HCI_OPCODE_LE_REJECT_CIS_REQ: + { + uint16_t cisHandle; + uint8_t reason; + + BSTREAM_TO_UINT16(cisHandle, pBuf); + BSTREAM_TO_UINT8(reason, pBuf); + status = LlRejectCisReq(cisHandle, reason); + paramLen = LHCI_LEN_LE_REJECT_CIS_REQ; + break; + } + default: + return FALSE; /* exit dispatcher routine */ + } + + if (paramLen == LHCI_LEN_CMD_STATUS_EVT) + { + lhciSendCmdStatusEvt(pHdr, status); + } + else if (paramLen > 0) + { + lhciCisSlvSendCmdCmplEvt(pHdr, status, paramLen, handle); + } + + return TRUE; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_conn.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_conn.c index 21334737fd..b2ad1ac383 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_conn.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_conn.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief HCI command module implementation file. + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -68,7 +69,7 @@ uint8_t lhciUnpackConnSpec(LlConnSpec_t *pConnSpec, const uint8_t *pBuf) /*************************************************************************************************/ static uint8_t lhciPackReadPwrLevel(uint8_t *pBuf, uint8_t status, uint16_t handle, int8_t level) { - const uint8_t len = LHCI_LEN_READ_LOCAL_VER_EVT; + const uint8_t len = LHCI_LEN_READ_PWR_LVL_EVT; UINT8_TO_BSTREAM (pBuf, status); UINT16_TO_BSTREAM(pBuf, handle); @@ -86,8 +87,6 @@ static uint8_t lhciPackReadPwrLevel(uint8_t *pBuf, uint8_t status, uint16_t hand * \param paramLen Parameter length of the command status event. * \param pParam Parameter buffer. * \param handle Connection handle. - * - * \return None. */ /*************************************************************************************************/ void lhciConnSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen, uint8_t *pParam, uint16_t handle) @@ -107,7 +106,6 @@ void lhciConnSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen case HCI_OPCODE_LE_WRITE_DEF_DATA_LEN: case HCI_OPCODE_LE_SET_PER_ADV_RCV_ENABLE: - case HCI_OPCODE_LE_SET_PAST_PARAM: case HCI_OPCODE_LE_SET_DEFAULT_PAST_PARAM: lhciPackCmdCompleteEvtStatus(pBuf, status); break; @@ -119,6 +117,7 @@ void lhciConnSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen case HCI_OPCODE_LE_SET_DATA_LEN: case HCI_OPCODE_LE_PER_ADV_SYNC_TRANSFER: case HCI_OPCODE_LE_PER_ADV_SET_INFO_TRANSFER: + case HCI_OPCODE_LE_SET_PAST_PARAM: pBuf += lhciPackCmdCompleteEvtStatus(pBuf, status); UINT16_TO_BSTREAM(pBuf, handle); break; @@ -162,6 +161,7 @@ void lhciConnSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen lhciPackReadPwrLevel(pBuf, status, handle, level); break; } + case HCI_OPCODE_READ_RSSI: { int8_t rssi; @@ -355,8 +355,6 @@ bool_t lhciConnDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) * \param handle Connection handle. * \param pktLen Packet length. * \param numPkts Number of packets. - * - * \return None. */ /*************************************************************************************************/ void lhciGenerateAcl(uint16_t handle, uint16_t pktLen, uint8_t numPkts) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_conn_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_conn_master.c index 8073b4b518..adeb5a0836 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_conn_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_conn_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief HCI command module implementation file. + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -37,8 +38,6 @@ * \param pCmdHdr Command HCI header. * \param status Status value. * \param paramLen Parameter length of the command status event. - * - * \return None. */ /*************************************************************************************************/ static void lhciMstConnSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_conn_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_conn_master_ae.c index 76fd5ea96b..0da42e76d9 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_conn_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_conn_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief HCI command module implementation file. + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -41,7 +42,7 @@ * \param connSpec Unpacked connection specification table indexed by PHY. * \param pBuf Packed packet buffer. * - * \return None. + * \return Bytes unpacked. */ /*************************************************************************************************/ static uint8_t lhciUnpackExtInitParam(LlExtInitParam_t *pInitParam, LlExtInitScanParam_t initScanParam[], LlConnSpec_t connSpec[], const uint8_t *pBuf) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_conn_priv.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_conn_priv.c index 45484d76e2..f391b2bd1b 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_conn_priv.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_conn_priv.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief HCI command module implementation file. + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -58,8 +59,6 @@ static uint8_t lhciPackReadResAddrEvt(uint8_t *pBuf, uint8_t status, const uint8 * \param status Status value. * \param paramLen Parameter length of the command status event. * \param pParam Pointer to parameters. - * - * \return None. */ /*************************************************************************************************/ static void lhciPrivConnSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen, uint8_t *pParam) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_enc_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_enc_master.c index 40974ae476..df01189e21 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_enc_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_enc_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief HCI command module implementation file. + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_enc_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_enc_slave.c index 6f2a1722cb..78772050db 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_enc_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_enc_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief HCI command module implementation file. + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -103,8 +104,6 @@ static uint8_t lhciPackReadAuthPayloadTimeoutEvt(uint8_t *pBuf, uint8_t status, * \param paramLen Parameter length of the command status event. * \param pParam Parameter buffer. * \param handle Connection handle. - * - * \return None. */ /*************************************************************************************************/ static void lhciSlvEncSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen, uint8_t *pParam, uint16_t handle) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_iso.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_iso.c new file mode 100644 index 0000000000..0073a37187 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_iso.c @@ -0,0 +1,587 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "lhci_int.h" +#include "hci_defs.h" +#include "ll_api.h" +#include "ll_defs.h" +#include "pal_codec.h" +#include "wsf_msg.h" +#include "wsf_math.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +#define LHCI_MAX_CODEC 5 /*!< Maximum number of codecs to read from audio subsystem. */ + +/************************************************************************************************** + Type Definitions +**************************************************************************************************/ + +/*! \brief ISO return parameters. */ +typedef union +{ + struct + { + uint32_t minDly; /*!< Minimum controller delay. */ + uint32_t maxDly; /*!< Maximum controller delay. */ + } ctrDly; /*!< Read local supported controller delay return parameters. */ +} lhciIsoReturnParam_t; + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Pack a read ISO buffer size event packet. + * + * \param pBuf Packed packet buffer. + * \param status Completion status. + * \param aclPktLen ACL data packet length. + * \param aclNumPkts Number of controller ACL data packet buffers. + * \param isoBufSize ISO data packet length. + * \param numIsoPkts Number of controller ISO data packet buffers. + * + * \return Packet length. + */ +/*************************************************************************************************/ +static uint8_t lhciPackReadBufSizeV2Evt(uint8_t *pBuf, uint8_t status, uint16_t aclPktLen, uint8_t aclNumPkts, + uint16_t isoBufSize, uint8_t numIsoPkts) +{ + const uint8_t len = LHCI_LEN_LE_READ_BUF_SIZE_V2; + + UINT8_TO_BSTREAM (pBuf, status); + UINT16_TO_BSTREAM(pBuf, aclPktLen); + UINT8_TO_BSTREAM (pBuf, aclNumPkts); + UINT16_TO_BSTREAM(pBuf, isoBufSize); + UINT8_TO_BSTREAM (pBuf, numIsoPkts); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Pack a read ISO buffer size event packet. + * + * \param pBuf Packed packet buffer. + * \param status Completion status. + * \param handle Connection handle. + * \param pktSn Packet sequence number. + * \param ts Timestamp. + * \param timeOffs Time offset. + * + * \return Packet length. + */ +/*************************************************************************************************/ +static uint8_t lhciPackReadIsoTxSyncEvt(uint8_t *pBuf, uint8_t status, uint16_t handle, uint16_t pktSn, + uint32_t ts, uint32_t timeOffs) +{ + const uint8_t len = LHCI_LEN_LE_READ_TX_SYNC; + + UINT8_TO_BSTREAM (pBuf, status); + UINT16_TO_BSTREAM(pBuf, handle); + UINT16_TO_BSTREAM(pBuf, pktSn); + UINT32_TO_BSTREAM(pBuf, ts); + UINT24_TO_BSTREAM(pBuf, timeOffs); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Pack a read ISO test counter command complete event packet. + * + * \param pBuf Packed packet buffer. + * \param status Completion status. + * \param handle Connection handle. + * \param pCtr ISO test counters. + * + * \return Packet length. + */ +/*************************************************************************************************/ +static uint8_t lhciPackIsoReadTestCounters(uint8_t *pBuf, uint8_t status, uint16_t handle, LlIsoTestCtrs_t *pCtr) +{ + const uint8_t len = LHCI_LEN_LE_ISO_READ_TEST_COUNTER; + + UINT8_TO_BSTREAM (pBuf, status); + UINT16_TO_BSTREAM(pBuf, handle); + UINT32_TO_BSTREAM(pBuf, pCtr->numSuccess); + UINT32_TO_BSTREAM(pBuf, pCtr->numMissed); + UINT32_TO_BSTREAM(pBuf, pCtr->numFailed); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Pack a read ISO link quality command complete event packet. + * + * \param pBuf Packed packet buffer. + * \param status Completion status. + * \param handle Connection handle. + * \param LinkQualStats Link quality stats. + * + * \return Packet length. + */ +/*************************************************************************************************/ +static uint8_t lhciPackReadIsoLinkQuality(uint8_t *pBuf, uint8_t status, uint16_t handle, LlIsoLinkQual_t LinkQualStats) +{ + const uint8_t len = LHCI_LEN_LE_READ_ISO_LINK_QUAL; + + UINT8_TO_BSTREAM (pBuf, status); + UINT16_TO_BSTREAM(pBuf, handle); + UINT32_TO_BSTREAM(pBuf, LinkQualStats.txUnAckPkt); + UINT32_TO_BSTREAM(pBuf, LinkQualStats.txFlushedPkt); + UINT32_TO_BSTREAM(pBuf, LinkQualStats.txLastSubEventPkt); + UINT32_TO_BSTREAM(pBuf, LinkQualStats.retransmitPkt); + UINT32_TO_BSTREAM(pBuf, LinkQualStats.crcErrPkt); + UINT32_TO_BSTREAM(pBuf, LinkQualStats.rxUnreceivedPkt); + UINT32_TO_BSTREAM(pBuf, LinkQualStats.duplicatePkt); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Pack setup data path event packet. + * + * \param pBuf Packed packet buffer. + * \param status Completion status. + * \param handle Connection handle. + * + * \return Packet length. + */ +/*************************************************************************************************/ +static uint8_t lhciPackSetupDataPathEvt(uint8_t *pBuf, uint8_t status, uint16_t handle) +{ + const uint8_t len = LHCI_LEN_LE_SETUP_ISO_DATA_PATH; + + UINT8_TO_BSTREAM(pBuf, status); + UINT16_TO_BSTREAM(pBuf, handle); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Pack remove data path event packet. + * + * \param pBuf Packed packet buffer. + * \param status Completion status. + * \param handle Connection handle. + * + * \return Packet length. + */ +/*************************************************************************************************/ +static uint8_t lhciPackRemoveDataPathEvt(uint8_t *pBuf, uint8_t status, uint16_t handle) +{ + const uint8_t len = LHCI_LEN_LE_REMOVE_ISO_DATA_PATH; + + UINT8_TO_BSTREAM(pBuf, status); + UINT16_TO_BSTREAM(pBuf, handle); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Pack read local supported codecs event packet. + * + * \param pBuf Packed packet buffer. + * \param status Completion status. + * \param numStd Number of standard codecs. + * \param stdCodecs Table of standard codec info. + * \param numVs Number of vendor specific codecs. + * \param vsCodecs Table of vendor specific codec info. + * + * \return Packet length. + */ +/*************************************************************************************************/ +static uint8_t lhciPackReadLocalSupportedCodecs(uint8_t *pBuf, uint8_t status, + uint8_t numStd, AudioStdCodecInfo_t stdCodecs[], + uint8_t numVs, AudioVsCodecInfo_t vsCodecs[]) +{ + uint8_t len = LHCI_LEN_READ_LOCAL_SUP_CODECS; + + UINT8_TO_BSTREAM(pBuf, status); + UINT8_TO_BSTREAM(pBuf, numStd); + + for (size_t i = 0; i < numStd; i++) + { + UINT8_TO_BSTREAM(pBuf, stdCodecs[i].codecId); + UINT8_TO_BSTREAM(pBuf, LL_CODEC_TRANS_CIS_BIT | LL_CODEC_TRANS_BIS_BIT); + len += sizeof(uint8_t) + sizeof(uint8_t); + } + + UINT8_TO_BSTREAM(pBuf, numVs); + + for (size_t i = 0; i < numVs; i++) + { + UINT16_TO_BSTREAM(pBuf, vsCodecs[i].compId); + UINT16_TO_BSTREAM(pBuf, vsCodecs[i].codecId); + UINT8_TO_BSTREAM(pBuf, LL_CODEC_TRANS_CIS_BIT | LL_CODEC_TRANS_BIS_BIT); + len += sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint8_t); + } + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Build and send a command complete event packet. + * + * \param pCmdHdr Command HCI header. + * \param status Status value. + * \param paramLen Parameter length of the command status event. + * \param handle Connection handle. + * \param pRet Return parameters. + */ +/*************************************************************************************************/ +static void lhciIsoSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen, uint16_t handle, const lhciIsoReturnParam_t *pRet) +{ + uint8_t *pBuf; + uint8_t *pEvtBuf; + + if ((pEvtBuf = lhciAllocCmdCmplEvt(paramLen, pCmdHdr->opCode)) == NULL) + { + return; + } + pBuf = pEvtBuf; + + switch (pCmdHdr->opCode) + { + case HCI_OPCODE_LE_READ_BUF_SIZE_V2: + { + lhciPackReadBufSizeV2Evt(pBuf, status, LlGetAclMaxSize(), LlGetAclTxBufs(), + LlGetIsoMaxBufSize(), LlGetIsoTxBufs()); + break; + } + case HCI_OPCODE_LE_READ_ISO_TX_SYNC: + { + uint16_t pktSn; + uint32_t ts; + uint32_t timeOffs; + + status = LlReadIsoTxSync(handle, &pktSn, &ts, &timeOffs); + lhciPackReadIsoTxSyncEvt(pBuf, status, handle, pktSn, ts, timeOffs); + break; + } + case HCI_OPCODE_LE_REMOVE_ISO_DATA_PATH: + { + lhciPackRemoveDataPathEvt(pBuf, status, handle); + break; + } + case HCI_OPCODE_LE_SETUP_ISO_DATA_PATH: + { + lhciPackSetupDataPathEvt(pBuf, status, handle); + break; + } + case HCI_OPCODE_LE_ISO_READ_TEST_COUNTERS: + { + LlIsoTestCtrs_t ctr; + + status = LlIsoReadTestCounter(handle, &ctr); + + lhciPackIsoReadTestCounters(pBuf, status, handle, &ctr); + break; + } + case HCI_OPCODE_LE_ISO_TEST_END: + { + LlIsoTestCtrs_t ctr; + status = LlIsoTestEnd(handle, &ctr); + + if (status == LL_SUCCESS) + { + lhciIsoCb.isoRxTest = FALSE; + } + + /* ISO Test End command complete event is identical to ISO Read Test Counters. */ + lhciPackIsoReadTestCounters(pBuf, status, handle, &ctr); + break; + } + case HCI_OPCODE_LE_READ_ISO_LINK_QUAL: + { + LlIsoLinkQual_t qualStats; + status = LlReadIsoLinkQual(handle, &qualStats); + lhciPackReadIsoLinkQuality(pBuf, status, handle, qualStats); + break; + } + case HCI_OPCODE_READ_LOCAL_SUP_CODECS: + { + uint8_t numStdCodecs = LHCI_MAX_CODEC; + AudioStdCodecInfo_t stdCodecs[LHCI_MAX_CODEC]; + uint8_t numVsCodecs = LHCI_MAX_CODEC; + AudioVsCodecInfo_t vsCodecs[LHCI_MAX_CODEC]; + + PalCodecReadLocalSupportedCodecs(&numStdCodecs, stdCodecs, + &numVsCodecs, vsCodecs); + + paramLen = lhciPackReadLocalSupportedCodecs(pBuf, status, + numStdCodecs, stdCodecs, + numVsCodecs, vsCodecs); + + /* Re-pack the event header now that the actual length is known. */ + lhciPackEvtHdr(pEvtBuf - (HCI_EVT_HDR_LEN + HCI_LEN_CMD_CMPL), HCI_CMD_CMPL_EVT, HCI_LEN_CMD_CMPL + paramLen); + break; + } + case HCI_OPCODE_READ_LOCAL_SUP_CODEC_CAP: + { + UINT8_TO_BSTREAM(pBuf, status); + UINT8_TO_BSTREAM(pBuf, 0); /* Num_Codec_Capabilities */ + break; + } + case HCI_OPCODE_READ_LOCAL_SUP_CONTROLLER_DLY: + { + UINT8_TO_BSTREAM (pBuf, status); + UINT24_TO_BSTREAM(pBuf, pRet->ctrDly.minDly); /* Min_Controller_Delay */ + UINT24_TO_BSTREAM(pBuf, pRet->ctrDly.maxDly); /* Max_Controller_Delay */ + break; + } + + /* --- command completion with status only parameter --- */ + + case HCI_OPCODE_LE_ISO_TX_TEST: + case HCI_OPCODE_LE_ISO_RX_TEST: + case HCI_OPCODE_CONFIG_DATA_PATH: + { + LhciPackCmdCompleteEvtStatus(pBuf, status); + break; + } + + /* --- default --- */ + + default: + break; + } + + lhciSendCmdCmplEvt(pEvtBuf); +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Decode an HCI command packet. + * + * \param pHdr Decoded packet header. + * \param pBuf Packed HCI packet buffer. + * + * \return TRUE if opcode handled, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lhciIsoDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) +{ +#if LHCI_ENABLE_VS + if (lhciIsoVsStdDecodeCmdPkt(pHdr, pBuf)) + { + return TRUE; + } +#endif + + uint8_t status = HCI_SUCCESS; + uint8_t paramLen = 0; + uint16_t handle = 0; + lhciIsoReturnParam_t ret; + + switch (pHdr->opCode) + { + case HCI_OPCODE_LE_READ_BUF_SIZE_V2: + { + paramLen = LHCI_LEN_LE_READ_BUF_SIZE_V2; + break; + } + case HCI_OPCODE_LE_READ_ISO_TX_SYNC: + { + BSTREAM_TO_UINT16(handle, pBuf); + + paramLen = LHCI_LEN_LE_READ_TX_SYNC; + break; + } + case HCI_OPCODE_LE_ISO_TX_TEST: + { + uint8_t pldType; + + BSTREAM_TO_UINT16(handle, pBuf); + BSTREAM_TO_UINT8 (pldType, pBuf); + + status = LlIsoTxTest(handle, pldType); + paramLen = LHCI_LEN_LE_ISO_TX_TEST; + break; + } + case HCI_OPCODE_LE_ISO_RX_TEST: + { + uint8_t pldType; + + BSTREAM_TO_UINT16(handle, pBuf); + BSTREAM_TO_UINT8 (pldType, pBuf); + + status = LlIsoRxTest(handle, pldType); + paramLen = LHCI_LEN_LE_ISO_RX_TEST; + + if (status == LL_SUCCESS) + { + lhciIsoCb.isoRxTest = TRUE; + } + break; + } + case HCI_OPCODE_LE_ISO_READ_TEST_COUNTERS: + { + BSTREAM_TO_UINT16(handle, pBuf); + paramLen = LHCI_LEN_LE_ISO_READ_TEST_COUNTER; + break; + } + case HCI_OPCODE_LE_ISO_TEST_END: + { + BSTREAM_TO_UINT16(handle, pBuf); + paramLen = LHCI_LEN_LE_ISO_TEST_END; + break; + } + case HCI_OPCODE_LE_READ_ISO_LINK_QUAL: + { + BSTREAM_TO_UINT16(handle, pBuf); + paramLen = LHCI_LEN_LE_READ_ISO_LINK_QUAL; + break; + } + case HCI_OPCODE_LE_SETUP_ISO_DATA_PATH: + { + LlIsoSetupDataPath_t param; + + BSTREAM_TO_UINT16(param.handle, pBuf); + BSTREAM_TO_UINT8 (param.dpDir, pBuf); + BSTREAM_TO_UINT8 (param.dpId, pBuf); + BSTREAM_TO_UINT8 (param.codecFormat, pBuf); + BSTREAM_TO_UINT16(param.codecCompId, pBuf); + BSTREAM_TO_UINT16(param.codecId, pBuf); + BSTREAM_TO_UINT24(param.ctrDly, pBuf); + BSTREAM_TO_UINT8 (param.codecConfigLen, pBuf); + param.pCodecConfig = pBuf; + status = LlSetupIsoDataPath(¶m); + handle = param.handle; + paramLen = LHCI_LEN_LE_SETUP_ISO_DATA_PATH; + break; + } + case HCI_OPCODE_LE_REMOVE_ISO_DATA_PATH: + { + uint8_t dpDir; + BSTREAM_TO_UINT16(handle, pBuf); + BSTREAM_TO_UINT8 (dpDir, pBuf); + status = LlRemoveIsoDataPath(handle, dpDir); + paramLen = LHCI_LEN_LE_REMOVE_ISO_DATA_PATH; + break; + } + 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; + } + paramLen = LHCI_LEN_CONFIG_DATA_PATH; + break; + } + case HCI_OPCODE_READ_LOCAL_SUP_CODECS: + { + /* Reserve maximum buffer size, re-pack length once size is known. */ + paramLen = LHCI_LEN_READ_LOCAL_SUP_CODECS + + (LHCI_MAX_CODEC * 2) + /* Max standard codecs */ + (LHCI_MAX_CODEC * 5); /* Max VS codecs */ + break; + } + case HCI_OPCODE_READ_LOCAL_SUP_CODEC_CAP: + { + uint8_t codingFmt; + uint16_t compId; + uint16_t vsCodecId; + uint8_t transType; + uint8_t dir; + BSTREAM_TO_UINT8 (codingFmt, pBuf); + BSTREAM_TO_UINT16(compId, pBuf); + BSTREAM_TO_UINT16(vsCodecId, pBuf); + BSTREAM_TO_UINT8 (transType, pBuf); + BSTREAM_TO_UINT8 (dir, pBuf); + + if (PalCodecReadLocalSupportedCodecCapabilities(codingFmt, compId, vsCodecId, dir)) + { + if ((transType & (LL_CODEC_TRANS_CIS_BIT | LL_CODEC_TRANS_BIS_BIT)) == 0) + { + status = HCI_ERR_INVALID_PARAM; + } + } + else + { + status = HCI_ERR_INVALID_PARAM; + } + + paramLen = LHCI_LEN_READ_LOCAL_SUP_CODEC_CAP; + break; + } + case HCI_OPCODE_READ_LOCAL_SUP_CONTROLLER_DLY: + { + uint8_t codingFmt; + uint16_t compId; + uint16_t vsCodecId; + uint8_t transType; + uint8_t dir; + BSTREAM_TO_UINT8 (codingFmt, pBuf); + BSTREAM_TO_UINT16(compId, pBuf); + BSTREAM_TO_UINT16(vsCodecId, pBuf); + BSTREAM_TO_UINT8 (transType, pBuf); + BSTREAM_TO_UINT8 (dir, pBuf); + ret.ctrDly.minDly = ret.ctrDly.maxDly = 0; + if (PalCodecReadLocalSupportedControllerDelay(codingFmt, compId, vsCodecId, dir, + &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; + } + paramLen = LHCI_LEN_READ_LOCAL_SUP_CONTROLLER_DLY; + break; + } + default: + return FALSE; /* exit dispatcher routine */ + } + + if (paramLen > 0) + { + lhciIsoSendCmdCmplEvt(pHdr, status, paramLen, handle, &ret); + } + + return TRUE; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_past.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_past.c index 853533ff42..6523399001 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_past.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_past.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief HCI command module implementation file. + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_pc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_pc.c new file mode 100644 index 0000000000..e557b2930a --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_pc.c @@ -0,0 +1,215 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief HCI command module implementation 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. + */ +/*************************************************************************************************/ + +#include "lhci_int.h" +#include "hci_defs.h" +#include "ll_api.h" +#include "ll_defs.h" +#include "wsf_msg.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include + +/*************************************************************************************************/ +/*! + * \brief Pack a read enhanced Tx power level or RSSI event packet. + * + * \param pBuf Packed packet buffer. + * \param status Completion status. + * \param handle Connection handle. + * \param curPwr Current Tx power level. + * \param maxPwr Maximum Tx power level. + * \param phy PHY read. + * + * \return Packet length. + */ +/*************************************************************************************************/ +static uint8_t lhciPackEnhancedReadPwrLevel(uint8_t *pBuf, uint8_t status, uint16_t handle, int8_t curPwr, int8_t maxPwr, uint8_t phy) +{ + const uint8_t len = LHCI_LEN_LE_READ_ENH_TX_POWER_EVT; + + UINT8_TO_BSTREAM (pBuf, status); + UINT16_TO_BSTREAM(pBuf, handle); + UINT8_TO_BSTREAM (pBuf, phy); + UINT8_TO_BSTREAM (pBuf, curPwr); + UINT8_TO_BSTREAM (pBuf, maxPwr); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Build and send a command complete event packet. + * + * \param pCmdHdr Command HCI header. + * \param status Status value. + * \param paramLen Parameter length of the command status event. + * \param pParam Parameter buffer. + * \param handle Connection handle. + */ +/*************************************************************************************************/ +void lhciPclSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen, uint8_t *pParam, uint16_t handle) +{ + uint8_t *pBuf; + uint8_t *pEvtBuf; + + if ((pEvtBuf = lhciAllocCmdCmplEvt(paramLen, pCmdHdr->opCode)) == NULL) + { + return; + } + pBuf = pEvtBuf; + + switch (pCmdHdr->opCode) + { + /* --- command completion with status and connHandle parameters --- */ + + case HCI_OPCODE_LE_SET_TX_POWER_REPORT_ENABLE: + case HCI_OPCODE_LE_SET_PATH_LOSS_REPORTING_PARAMS: + case HCI_OPCODE_LE_SET_PATH_LOSS_REPORTING_ENABLE: + pBuf += lhciPackCmdCompleteEvtStatus(pBuf, status); + UINT16_TO_BSTREAM(pBuf, handle); + break; + + /* --- status --- */ + case HCI_OPCODE_LE_READ_ENHANCED_TX_POWER: + { + int8_t curPwr = 0; + int8_t maxPwr = 0; + uint8_t phy; + BSTREAM_TO_UINT8(phy, pParam); + status = LlGetEnhTxPowerLevel(handle, phy, &curPwr, &maxPwr); + lhciPackEnhancedReadPwrLevel(pBuf, status, handle, curPwr, maxPwr, phy); + break; + } + + /* --- default --- */ + + default: + break; + } + + lhciSendCmdCmplEvt(pEvtBuf); +} + +/*************************************************************************************************/ +/*! + * \brief Decode an HCI command packet. + * + * \param pHdr Decoded packet header. + * \param pBuf Packed HCI packet buffer. + * + * Command processing is organized by urgency then by frequency of command calls during normal + * operation. The following grouping is used: + * - connection control + * - connection status + * - local device management + * - remote device management + * - default + * + * \return TRUE if opcode handled, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lhciPclDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) +{ + uint8_t status = HCI_SUCCESS; + uint8_t paramLen = 0; + uint8_t *pParam = NULL; + uint16_t handle = 0; + + switch (pHdr->opCode) + { + /* --- connection status --- */ + + case HCI_OPCODE_LE_READ_ENHANCED_TX_POWER: + BSTREAM_TO_UINT16(handle, pBuf); + paramLen = LHCI_LEN_LE_READ_ENH_TX_POWER_EVT; + pParam = pBuf; + break; + + + /* --- remote device management --- */ + case HCI_OPCODE_LE_READ_REMOTE_TX_POWER: + { + uint8_t phy; + BSTREAM_TO_UINT16(handle, pBuf); + BSTREAM_TO_UINT8 (phy, pBuf); + status = LlPowerCtrlReq(handle, 0, phy); + paramLen = LHCI_LEN_CMD_STATUS_EVT; + break; + } + case HCI_OPCODE_LE_SET_TX_POWER_REPORT_ENABLE: + { + uint8_t enableLocal; + uint8_t enableRemote; + BSTREAM_TO_UINT16(handle, pBuf); + BSTREAM_TO_UINT8 (enableLocal, pBuf); + BSTREAM_TO_UINT8 (enableRemote, pBuf); + status = LlSetTxPowerReporting(handle, enableLocal, enableRemote); + paramLen = LHCI_LEN_LE_SET_TX_POWER_REPORT_EVT; + break; + } + case HCI_OPCODE_LE_SET_PATH_LOSS_REPORTING_PARAMS: + { + int8_t highThreshold; + int8_t highHysteresis; + int8_t lowThreshold; + int8_t lowHysteresis; + uint16_t minTimeSpent; + + BSTREAM_TO_UINT16(handle, pBuf); + BSTREAM_TO_INT8 (highThreshold, pBuf); + BSTREAM_TO_INT8 (highHysteresis, pBuf); + BSTREAM_TO_INT8 (lowThreshold, pBuf); + BSTREAM_TO_INT8 (lowHysteresis, pBuf); + BSTREAM_TO_UINT16(minTimeSpent, pBuf); + status = LlSetPathLossReportingParams(handle, highThreshold, highHysteresis, lowThreshold, lowHysteresis, minTimeSpent); + paramLen = LHCI_LEN_LE_SET_PATH_LOSS_REPORTING_PARAMS; + break; + } + case HCI_OPCODE_LE_SET_PATH_LOSS_REPORTING_ENABLE: + { + uint8_t enable; + + BSTREAM_TO_UINT16(handle, pBuf); + BSTREAM_TO_INT8 (enable, pBuf); + status = LlSetPathLossReportingEnable(handle, enable); + paramLen = LHCI_LEN_LE_SET_PATH_LOSS_REPORTING_ENABLE; + break; + } + + /* --- default --- */ + + default: + return FALSE; /* exit dispatcher routine */ + } + + if (paramLen == LHCI_LEN_CMD_STATUS_EVT) + { + lhciSendCmdStatusEvt(pHdr, status); + } + else + { + lhciPclSendCmdCmplEvt(pHdr, status, paramLen, pParam, handle); + } + + return TRUE; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_phy.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_phy.c index 50715e7220..ddaed05ad9 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_phy.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_phy.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief HCI command module implementation file. + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -63,8 +64,6 @@ static uint8_t lhciPackReadPhyEvt(uint8_t *pBuf, uint8_t status, uint16_t handle * \param status Status value. * \param paramLen Parameter length of the command status event. * \param handle Connection handle. - * - * \return None. */ /*************************************************************************************************/ static void lhciPhySendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen, uint16_t handle) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_sc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_sc.c index 449176283a..b20620129f 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_sc.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_sc.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief HCI command module implementation file. + * \file + * + * \brief HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs.c index afe91ec9fe..b63fc09961 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Arm Ltd. vendor specific HCI command module implementation file. + * \file + * + * \brief Arm Ltd. vendor specific HCI command module implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,6 +28,7 @@ #include "ll_api.h" #include "pal_sys.h" #include "sch_api.h" +#include "bb_ble_sniffer_api.h" #include "wsf_assert.h" #include "wsf_buf.h" #include "wsf_cs.h" @@ -49,12 +51,12 @@ /*! \brief Get System Statistics command complete event length. */ /* stackWatermark(uint16_t) + palSysAssertCount(uint16_t) + - * freeMem (uint32_t) + usedMem(uint32_t) + - * connMax(uint16_t) + connCtxSize(uint16_t) + csWatermarkUsec(uint16_t) + llHandlerWatermarkUsec(uint16_t) + schHandlerWatermarkUsec(uint16_t) + lhciHandlerWatermarkUsec(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) + 2 * sizeof(uint32_t) + 6 * sizeof(uint16_t) + 2 * sizeof(uint16_t) + 10 * 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)) /************************************************************************************************** Functions @@ -62,7 +64,7 @@ /*************************************************************************************************/ /*! - * \brief Decode Cordio common vendor specific HCI command packet. + * \brief Decode Packetcraft common vendor specific HCI command packet. * * \param pHdr Unpacked command header. * \param pBuf Packed HCI packet buffer. @@ -97,12 +99,26 @@ bool_t lhciCommonVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) bool_t enable; uint64_t mask; BSTREAM_TO_UINT64(mask, pBuf); + BSTREAM_TO_UINT8 (enable, pBuf); - enable = !!(mask & ((uint64_t)LHCI_VS_EVT_MASK_SCAN_REPORT_EVT) << LHCI_BYTE_TO_BITS(0)); - LlScanReportEnable(enable); + if (mask & ((uint64_t)LHCI_VS_EVT_MASK_SCAN_REPORT_EVT) << LHCI_BYTE_TO_BITS(0)) + { + LlScanReportEnable(enable); + } + + if (mask & ((uint64_t)LHCI_VS_EVT_MASK_DIAG_TRACE_EVT) << LHCI_BYTE_TO_BITS(0)) + { + LL_TRACE_ENABLE(enable); + } + +#if (BT_VER >= LL_VER_BT_CORE_SPEC_5_2) + /* TODO: Use function pointer to allow run time configuration of supported versions. */ + if (mask & ((uint64_t)LHCI_VS_EVT_MASK_ISO_EVENT_CMPL_EVT) << LHCI_BYTE_TO_BITS(0)) + { + LlIsoEventCompleteEnable(enable); + } +#endif - enable = !!(mask & ((uint64_t)LHCI_VS_EVT_MASK_DIAG_TRACE_EVT) << LHCI_BYTE_TO_BITS(0)); - LL_TRACE_ENABLE(enable); break; } case LHCI_OPCODE_VS_SET_TX_TEST_ERR_PATT: @@ -113,16 +129,13 @@ bool_t lhciCommonVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) status = LlSetTxTestErrorPattern(pattern); break; } - case LHCI_OPCODE_VS_SET_HCI_SUP_CMD: - { - uint8_t byte, bit; - bool_t enable; - BSTREAM_TO_UINT8(byte, pBuf); - BSTREAM_TO_UINT8(bit, pBuf); - BSTREAM_TO_UINT8(enable, pBuf); - status = LlSetHciSupCmd(byte, bit, enable); - break; - } + case LHCI_OPCODE_VS_SET_SNIFFER_ENABLE: +#if (BB_SNIFFER_ENABLED == TRUE) + status = BbBleInitSniffer(pBuf[0], pBuf[1]); +#else + status = HCI_ERR_UNKNOWN_CMD; +#endif + break; case LHCI_OPCODE_VS_SET_BD_ADDR: LlSetBdAddr(pBuf); @@ -176,7 +189,7 @@ bool_t lhciCommonVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) case LHCI_OPCODE_VS_SET_BD_ADDR: case LHCI_OPCODE_VS_GET_RAND_ADDR: case LHCI_OPCODE_VS_SET_TX_TEST_ERR_PATT: - case LHCI_OPCODE_VS_SET_HCI_SUP_CMD: + case LHCI_OPCODE_VS_SET_SNIFFER_ENABLE: /* no action */ break; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_adv_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_adv_master.c index 68e4b760ad..52bb2940e3 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_adv_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_adv_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Arm Ltd. vendor specific HCI command module implementation file. + * \file + * + * \brief Arm Ltd. vendor specific HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_adv_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_adv_master_ae.c index 7dfb006c2f..fd35ccaa41 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_adv_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_adv_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Arm Ltd. vendor specific HCI command module implementation file. + * \file + * + * \brief Arm Ltd. vendor specific HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_adv_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_adv_slave.c index eb35126598..6532955b22 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_adv_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_adv_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Arm Ltd. vendor specific HCI command module implementation file. + * \file + * + * \brief Arm Ltd. vendor specific HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_adv_slave_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_adv_slave_ae.c index ee08da829d..66cf6cfdb1 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_adv_slave_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_adv_slave_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Arm Ltd. vendor specific HCI command module implementation file. + * \file + * + * \brief Arm Ltd. vendor specific HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_conn.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_conn.c index 598c87396a..e362abb5c1 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_conn.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_conn.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Arm Ltd. vendor specific HCI command module implementation file. + * \file + * + * \brief Arm Ltd. vendor specific HCI command module implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ @@ -87,13 +88,26 @@ bool_t lhciConnVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) status = LlSetConnOpFlags(handle, flags, enable); break; } + case LHCI_OPCODE_VS_SET_CONN_TX_PWR: { uint16_t handle; int8_t level; BSTREAM_TO_UINT16(handle, pBuf); BSTREAM_TO_UINT8 (level, pBuf); - status = LlSetTxPowerLevel(handle, level); + status = LlSetAllPhyTxPowerLevel(handle, level); + break; + } + + case LHCI_OPCODE_VS_SET_CONN_PHY_TX_PWR: + { + uint16_t handle; + int8_t level; + uint8_t phy; + BSTREAM_TO_UINT16(handle, pBuf); + BSTREAM_TO_UINT8 (level, pBuf); + BSTREAM_TO_UINT8 (phy, pBuf); + status = LlSetPhyTxPowerLevel(handle, level, phy); break; } @@ -155,6 +169,7 @@ bool_t lhciConnVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) break; case LHCI_OPCODE_VS_SET_CONN_TX_PWR: + case LHCI_OPCODE_VS_SET_CONN_PHY_TX_PWR: /* no action */ break; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_conn_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_conn_master.c index c3dc808561..3cd8929f5b 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_conn_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_conn_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Arm Ltd. vendor specific HCI command module implementation file. + * \file + * + * \brief Arm Ltd. vendor specific HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_enc_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_enc_slave.c index 9c53df2916..e22e5697c0 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_enc_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_enc_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Arm Ltd. vendor specific HCI command module implementation file. + * \file + * + * \brief Arm Ltd. vendor specific HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_ext.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_ext.c deleted file mode 100644 index c9ced2ed7a..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_ext.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (c) 2019 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. - */ - -/*************************************************************************************************/ -/*! - * \file - * \brief Extended vendor specific HCI command module implementation file. - */ -/*************************************************************************************************/ - -#include "lhci_api.h" - -/*************************************************************************************************/ -/*! - * \brief Decode extended vendor specific HCI command packet. - * - * \param pHdr Unpacked command header. - * \param pBuf Packed HCI packet buffer. - * - * Command processing for vendor specific commands. - * - * \return TRUE if opcode handled, FALSE otherwise. - */ -/*************************************************************************************************/ -bool_t lhciVsExtDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) -{ - return FALSE; -} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_iso.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_iso.c new file mode 100644 index 0000000000..90731fb38c --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_iso.c @@ -0,0 +1,164 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Arm Ltd. vendor specific HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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 "lhci_int.h" +#include "hci_defs.h" +#include "bb_ble_api.h" +#include "ll_api.h" +#include "wsf_msg.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include + +/*! \brief Control block for ISO generation. */ +lhciIsoCb_t lhciIsoCb; + +/*************************************************************************************************/ +/*! + * \brief Decode Arm Ltd. connection vendor specific HCI command packet. + * + * \param pHdr Unpacked command header. + * \param pBuf Packed HCI packet buffer. + * + * Command processing for vendor specific commands. + * + * \return TRUE if opcode handled, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lhciIsoVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf) +{ + uint8_t status = HCI_SUCCESS; + uint8_t evtParamLen = 1; /* default is status field only */ + + /* Decode and consume command packet. */ + switch (pHdr->opCode) + { + /* --- ISO --- */ + + case LHCI_OPCODE_VS_GET_ISO_TEST_REPORT: + evtParamLen += sizeof(uint32_t) * 4; + break; + case LHCI_OPCODE_VS_ENA_ISO_SINK: + lhciIsoCb.recvIsoSink = pBuf[0]; + break; + case LHCI_OPCODE_VS_ENA_AUTO_GEN_ISO: + BSTREAM_TO_UINT16(lhciIsoCb.genPktLen, pBuf); + break; + case LHCI_OPCODE_VS_GENERATE_ISO: + { + uint16_t handle; + uint16_t pktLen; + uint8_t numPkts; + + BSTREAM_TO_UINT16(handle, pBuf); + BSTREAM_TO_UINT16(pktLen, pBuf); + numPkts = *pBuf++; + + lhciGenerateIso(handle, pktLen, numPkts); + break; + } + case LHCI_OPCODE_VS_GET_CIS_STATS: + evtParamLen += sizeof(BbBleDataPktStats_t); + break; + + /* --- default --- */ + + default: + return FALSE; /* exit dispatcher routine */ + } + + uint8_t *pEvtBuf; + + /* Encode and send command complete event packet. */ + if ((pEvtBuf = lhciAllocCmdCmplEvt(evtParamLen, pHdr->opCode)) != NULL) + { + pBuf = pEvtBuf; + pBuf += lhciPackCmdCompleteEvtStatus(pBuf, status); + + switch (pHdr->opCode) + { + case LHCI_OPCODE_VS_GET_ISO_TEST_REPORT: + UINT32_TO_BSTREAM(pBuf, lhciIsoCb.recvIsoPktCnt); + UINT32_TO_BSTREAM(pBuf, lhciIsoCb.recvIsoOctetCnt); + UINT32_TO_BSTREAM(pBuf, lhciIsoCb.genPktCnt); + UINT32_TO_BSTREAM(pBuf, lhciIsoCb.genOctetCnt); + break; + + case LHCI_OPCODE_VS_GET_CIS_STATS: + { + BbBleDataPktStats_t stats; + BbBleGetCisStats(&stats); + memcpy(pBuf, (uint8_t *)&stats, sizeof(stats)); + break; + } + + /* --- default --- */ + + default: + break; + } + + lhciSendCmdCmplEvt(pEvtBuf); + } + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Generate ISO packets. + * + * \param handle Connection handle. + * \param pktLen Packet length. + * \param numPkts Number of packets. + */ +/*************************************************************************************************/ +void lhciGenerateIso(uint16_t handle, uint16_t pktLen, uint8_t numPkts) +{ + if (lhciIsoCb.genEnaFlag) + { + /* Prevent re-entrance. */ + return; + } + + lhciIsoCb.genEnaFlag = TRUE; + + while (numPkts--) + { + uint8_t *pIsoBuf; + if ((pIsoBuf = (uint8_t*)WsfMsgAlloc(LL_ISO_PDU_MAX_LEN)) == NULL) + { + break; + } + + uint8_t *pBuf = pIsoBuf; + UINT16_TO_BSTREAM(pBuf, handle & 0xFFF); /* BTS=0 and BF=0 */ + UINT16_TO_BSTREAM(pBuf, pktLen); + memset(pBuf, lhciIsoCb.genPldCnt++, pktLen); + + LlSendIsoData(pIsoBuf); + } + + lhciIsoCb.genEnaFlag = FALSE; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_sc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_sc.c index 27f831592f..9af929cf78 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_sc.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_cmd_vs_sc.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Arm Ltd. vendor specific HCI command module implementation file. + * \file + * + * \brief Arm Ltd. vendor specific HCI command module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt.c index 41358ad291..d613ba1f07 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief LL HCI event module implementation file. + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -108,8 +109,6 @@ bool_t lhciLlEvtHandler(LlEvt_t *pEvt) WSF_ASSERT(lhciEvtTbl[LHCI_MSG_ADV]); /* proper init guarantees this handler exists. */ - LL_TRACE_INFO1("Encoding LL event=%u", pEvt->hdr.event); - /* Standard event handlers. */ do { @@ -165,8 +164,6 @@ bool_t lhciLlEvtHandler(LlEvt_t *pEvt) * \brief Send an HCI event and service the event queue. * * \param pBuf Buffer containing HCI event to send or NULL to service the queue. - * - * \return None. */ /*************************************************************************************************/ void LhciSendEvent(uint8_t *pBuf) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_adv_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_adv_master.c index 1dcd483302..a2d53fb0ca 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_adv_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_adv_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief LL HCI event module implementation file. + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_adv_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_adv_master_ae.c index e5304111ba..6635361340 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_adv_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_adv_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief LL HCI event module implementation file. + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -99,8 +100,6 @@ static uint8_t *lhciAllocPerAdvRptEvt(uint8_t evtCode, uint8_t paramLen) * \param pEvt Extended advertising report indication data. * \param pFragStart Start of fragmentation buffer. * \param fragLen Length of fragment. - * - * \return None. */ /*************************************************************************************************/ static void lhciPackExtAdvRptEvt(uint8_t *pBuf, const LlExtAdvReportInd_t *pEvt, @@ -142,8 +141,6 @@ static void lhciPackExtAdvRptEvt(uint8_t *pBuf, const LlExtAdvReportInd_t *pEvt, * \param pEvt Periodic advertising report indication data. * \param pFragStart Start of fragmentation buffer. * \param fragLen Length of fragment. - * - * \return None. */ /*************************************************************************************************/ static void lhciPackPerAdvRptEvt(uint8_t *pBuf, const LlPerAdvReportInd_t *pEvt, @@ -187,8 +184,6 @@ static void lhciPackPerAdvRptEvt(uint8_t *pBuf, const LlPerAdvReportInd_t *pEvt, * * \param pBuf Packed packet buffer. * \param pEvt Periodic advertising sync established event confirmation. - * - * \return None. */ /*************************************************************************************************/ static void lhciPackPerAdvSyncEstdEvt(uint8_t *pBuf, const LlPerAdvSyncEstdCnf_t *pEvt) @@ -210,8 +205,6 @@ static void lhciPackPerAdvSyncEstdEvt(uint8_t *pBuf, const LlPerAdvSyncEstdCnf_t * * \param pBuf Packed packet buffer. * \param pEvt Periodic advertising sync lost event confirmation. - * - * \return None. */ /*************************************************************************************************/ static void lhciPackPerAdvSyncLostEvt(uint8_t *pBuf, const LlPerAdvSyncLostInd_t *pEvt) @@ -226,8 +219,6 @@ static void lhciPackPerAdvSyncLostEvt(uint8_t *pBuf, const LlPerAdvSyncLostInd_t * * \param pBuf Packed packet buffer. * \param pEvt Periodic advertising sync transfer received event indication. - * - * \return None. */ /*************************************************************************************************/ static void lhciPackPerSyncTrsfRcvdEvt(uint8_t *pBuf, const LlPerSyncTrsfRcvdInd_t *pEvt) @@ -272,7 +263,7 @@ bool_t lhciMstExtScanEncodeEvtPkt(LlEvt_t *pEvt) if ((lhciCb.numAdvReport + num_buffers) > pLctrRtCfg->maxAdvReports) { - LL_TRACE_WARN0("LL_EXT_ADV_REPORT_IND, discarded, not enough advRport buffers available."); + LL_TRACE_WARN0("LL_EXT_ADV_REPORT_IND, discarded, not enough advRport buffers available"); break; } @@ -293,7 +284,7 @@ bool_t lhciMstExtScanEncodeEvtPkt(LlEvt_t *pEvt) /* Drop remaining fragments. */ remDataLen = 0; - LL_TRACE_WARN0("LL_EXT_ADV_REPORT_IND, truncated, not enough advRport buffers."); + LL_TRACE_WARN0("LL_EXT_ADV_REPORT_IND, truncated, not enough advRport buffers"); } else { @@ -366,7 +357,7 @@ bool_t lhciMstExtScanEncodeEvtPkt(LlEvt_t *pEvt) if ((lhciCb.numAdvReport + num_buffers) > pLctrRtCfg->maxAdvReports) { - LL_TRACE_WARN0("LL_PER_ADV_REPORT_IND, discarded, not enough advRport buffers available."); + LL_TRACE_WARN0("LL_PER_ADV_REPORT_IND, discarded, not enough advRport buffers available"); break; } @@ -386,7 +377,7 @@ bool_t lhciMstExtScanEncodeEvtPkt(LlEvt_t *pEvt) /* Drop remaining fragments. */ remDataLen = 0; - LL_TRACE_WARN0("LL_PER_ADV_REPORT_IND, truncated, not enough advRport buffers."); + LL_TRACE_WARN0("LL_PER_ADV_REPORT_IND, truncated, not enough advRport buffers"); } else { diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_adv_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_adv_slave.c index e9c422f9c6..6d83d42212 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_adv_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_adv_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief LL HCI event module implementation file. + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_adv_slave_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_adv_slave_ae.c index cb639890eb..17f3b8c002 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_adv_slave_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_adv_slave_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief LL HCI event module implementation file. + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -32,8 +33,6 @@ * * \param pBuf Packed packet buffer. * \param pEvt Advertising set terminated indication data. - * - * \return None. */ /*************************************************************************************************/ static void lhciPackAdvSetTermEvt(uint8_t *pBuf, const LlAdvSetTermInd_t *pEvt) @@ -51,8 +50,6 @@ static void lhciPackAdvSetTermEvt(uint8_t *pBuf, const LlAdvSetTermInd_t *pEvt) * * \param pBuf Packed packet buffer. * \param pEvt Scan request received indication data. - * - * \return None. */ /*************************************************************************************************/ static void lhciPackScanReqRcvdEvt(uint8_t *pBuf, const LlScanReqRcvdInd_t *pEvt) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_bis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_bis_master.c new file mode 100644 index 0000000000..f5e41fed74 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_bis_master.c @@ -0,0 +1,183 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 "lhci_int.h" +#include "ll_api.h" +#include "util/bstream.h" + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Pack a BIG Terminate Sync command complete packet. + * + * \param pBuf Packed packet buffer. + * \param pEvt BIG terminate event data. + */ +/*************************************************************************************************/ +static void lhciPackCmdCompleteBigTerminateSync(uint8_t *pBuf, const LlBigTermSyncCnf_t *pEvt) +{ + UINT8_TO_BSTREAM(pBuf, pEvt->status); + UINT8_TO_BSTREAM(pBuf, pEvt->bigHandle); +} + +/*************************************************************************************************/ +/*! + * \brief Pack a BIG create BIG Sync Established event packet. + * + * \param pBuf Packed packet buffer. + * \param pEvt BIG Sync Established event data. + */ +/*************************************************************************************************/ +static void lhciPackBigSyncEstEvt(uint8_t *pBuf, const LlBigSyncEstInd_t *pEvt) +{ + UINT8_TO_BSTREAM (pBuf, HCI_LE_BIG_SYNC_EST_EVT); + UINT8_TO_BSTREAM (pBuf, pEvt->status); + UINT8_TO_BSTREAM (pBuf, pEvt->bigHandle); + UINT24_TO_BSTREAM(pBuf, pEvt->transLatUsec); + UINT8_TO_BSTREAM (pBuf, pEvt->nse); + UINT8_TO_BSTREAM (pBuf, pEvt->bn); + UINT8_TO_BSTREAM (pBuf, pEvt->pto); + UINT8_TO_BSTREAM (pBuf, pEvt->irc); + UINT16_TO_BSTREAM(pBuf, pEvt->maxPdu); + UINT16_TO_BSTREAM(pBuf, pEvt->isoInterval); + UINT8_TO_BSTREAM (pBuf, pEvt->numBis); + for (unsigned int i = 0; i < pEvt->numBis; i++) + { + UINT16_TO_BSTREAM(pBuf, pEvt->bisHandle[i]); + } +} + +/*************************************************************************************************/ +/*! + * \brief Pack a BIG Sync Lost event packet. + * + * \param pBuf Packed packet buffer. + * \param pEvt Terminate BIG Complete event data. + */ +/*************************************************************************************************/ +static void lhciPackBigSyncLostEvt(uint8_t *pBuf, const LlBigSyncLostInd_t *pEvt) +{ + UINT8_TO_BSTREAM(pBuf, HCI_LE_BIG_SYNC_LOST_EVT); + UINT8_TO_BSTREAM(pBuf, pEvt->bigHandle); + UINT8_TO_BSTREAM(pBuf, pEvt->reason); +} + +/*************************************************************************************************/ +/*! + * \brief Pack a BIG Sync Lost event packet. + * + * \param pBuf Packed packet buffer. + * \param pEvt Terminate BIG Complete event data. + */ +/*************************************************************************************************/ +static void lhciPackBigBigInfoAdvReportEvt(uint8_t *pBuf, const LlBigInfoAdvRptInd_t *pEvt) +{ + UINT8_TO_BSTREAM (pBuf, HCI_LE_BIG_INFO_ADV_REPORT_EVT); + UINT16_TO_BSTREAM(pBuf, pEvt->syncHandle); + UINT8_TO_BSTREAM (pBuf, pEvt->numBis); + UINT8_TO_BSTREAM (pBuf, pEvt->nse); + UINT16_TO_BSTREAM(pBuf, pEvt->isoInterv); + UINT8_TO_BSTREAM (pBuf, pEvt->bn); + UINT8_TO_BSTREAM (pBuf, pEvt->pto); + UINT8_TO_BSTREAM (pBuf, pEvt->irc); + UINT16_TO_BSTREAM(pBuf, pEvt->maxPdu); + UINT24_TO_BSTREAM(pBuf, pEvt->sduInterv); + UINT16_TO_BSTREAM(pBuf, pEvt->maxSdu); + UINT8_TO_BSTREAM (pBuf, pEvt->phy); + UINT8_TO_BSTREAM (pBuf, pEvt->framing); + UINT8_TO_BSTREAM (pBuf, pEvt->encrypt); +} + +/*************************************************************************************************/ +/*! + * \brief LL BIS master event handler. + * + * \param pEvt Buffer containing LL event. + * + * \return TRUE if event handled, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lhciMstBisEncodeEvtPkt(LlEvt_t *pEvt) +{ + uint8_t *pEvtBuf = NULL; + + switch (pEvt->hdr.event) + { + case LL_BIG_TERM_SYNC_CNF: + if ((pEvtBuf = lhciAllocEvt(HCI_CMD_CMPL_EVT, HCI_LEN_CMD_CMPL + LHCI_LEN_LE_BIG_TERMINATE_SYNC)) != NULL) + { + uint8_t *pBuf = pEvtBuf; + pBuf += LhciPackCmdCompleteEvt(pBuf, HCI_OPCODE_LE_BIG_TERMINATE_SYNC); + lhciPackCmdCompleteBigTerminateSync(pBuf, &pEvt->bigTermSyncCnf); + } + break; + + case LL_BIG_SYNC_EST_IND: + if ((lhciCb.leEvtMsk & ((uint64_t)(HCI_EVT_MASK_LE_BIG_SYNC_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_BIG_SYNC_EST(pEvt->bigSyncEstInd.numBis))) != NULL) + { + lhciPackBigSyncEstEvt(pEvtBuf, &pEvt->bigSyncEstInd); + } + } + break; + + case LL_BIG_SYNC_LOST_IND: + if ((lhciCb.leEvtMsk & ((uint64_t)(HCI_EVT_MASK_LE_BIG_SYNC_LOST_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_BIG_SYNC_LOST)) != NULL) + { + lhciPackBigSyncLostEvt(pEvtBuf, &pEvt->bigSyncLostInd); + } + } + break; + + case LL_BIG_INFO_ADV_REPORT_IND: + 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) + { + lhciPackBigBigInfoAdvReportEvt(pEvtBuf, &pEvt->bigInfoInd); + } + } + break; + + default: + break; + } + + if (pEvtBuf) + { + lhciSendEvt(pEvtBuf); + return TRUE; + } + + return FALSE; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_bis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_bis_slave.c new file mode 100644 index 0000000000..0aef969937 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_bis_slave.c @@ -0,0 +1,129 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 "lhci_int.h" +#include "ll_api.h" +#include "util/bstream.h" + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Pack a BIS create BIG complete event packet. + * + * \param pBuf Packed packet buffer. + * \param pEvt Generate BIS create BIG complete data. + */ +/*************************************************************************************************/ +static void lhciPackCreateBigCnfEvt(uint8_t *pBuf, const LlCreateBigCnf_t *pEvt) +{ + UINT8_TO_BSTREAM (pBuf, HCI_LE_CREATE_BIG_CMPL_EVT); + UINT8_TO_BSTREAM (pBuf, pEvt->status); + UINT8_TO_BSTREAM (pBuf, pEvt->bigHandle); + UINT24_TO_BSTREAM(pBuf, pEvt->syncDelayUsec); + UINT24_TO_BSTREAM(pBuf, pEvt->transLatUsec); + UINT8_TO_BSTREAM (pBuf, pEvt->phy); + UINT8_TO_BSTREAM (pBuf, pEvt->nse); + UINT8_TO_BSTREAM (pBuf, pEvt->bn); + UINT8_TO_BSTREAM (pBuf, pEvt->pto); + UINT8_TO_BSTREAM (pBuf, pEvt->irc); + UINT16_TO_BSTREAM(pBuf, pEvt->maxPdu); + UINT16_TO_BSTREAM(pBuf, pEvt->isoInterval); + UINT8_TO_BSTREAM (pBuf, pEvt->numBis); + for (unsigned int i = 0; i < pEvt->numBis; i++) + { + UINT16_TO_BSTREAM(pBuf, pEvt->bisHandle[i]); + } +} + +/*************************************************************************************************/ +/*! + * \brief Pack a BIS terminate BIG complete event packet. + * + * \param pBuf Packed packet buffer. + * \param pEvt Generate BIS create BIG complete data. + */ +/*************************************************************************************************/ +static void lhciPackTerminateBigCnfEvt(uint8_t *pBuf, const LlTerminateBigInd_t *pEvt) +{ + UINT8_TO_BSTREAM(pBuf, HCI_LE_TERMINATE_BIG_CMPL_EVT); + UINT8_TO_BSTREAM(pBuf, pEvt->bigHandle); + UINT8_TO_BSTREAM(pBuf, pEvt->reason); +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief LL BIS slave event handler. + * + * \param pEvt Buffer containing LL event. + * + * \return TRUE if event handled, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lhciSlvBigEncodeEvtPkt(LlEvt_t *pEvt) +{ + uint8_t *pEvtBuf = NULL; + + switch (pEvt->hdr.event) + { + case LL_CREATE_BIG_CNF: + if ((lhciCb.leEvtMsk & ((uint64_t)(HCI_EVT_MASK_LE_CREATE_BIG_CMPL_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_CREATE_BIG_CMPL(pEvt->createBigCnf.numBis))) != NULL) + { + lhciPackCreateBigCnfEvt(pEvtBuf, &pEvt->createBigCnf); + } + } + break; + + case LL_TERM_BIG_IND: + if ((lhciCb.leEvtMsk & ((uint64_t)(HCI_EVT_MASK_LE_TERMINATE_BIG_CMPL_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_TERMINATE_BIG_CMPL)) != NULL) + { + lhciPackTerminateBigCnfEvt(pEvtBuf, &pEvt->termBigInd); + } + } + break; + + default: + break; + } + + if (pEvtBuf) + { + lhciSendEvt(pEvtBuf); + return TRUE; + } + + return FALSE; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_cis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_cis_master.c new file mode 100644 index 0000000000..953d007225 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_cis_master.c @@ -0,0 +1,115 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2016-2019 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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 "lhci_int.h" +#include "chci_api.h" +#include "hci_defs.h" +#include "wsf_msg.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include + +/************************************************************************************************** + 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 +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief LL CIS master event handler. + * + * \param pEvt Buffer containing LL event. + * + * \return TRUE if event handled, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lhciMstCisEncodeEvtPkt(LlEvt_t *pEvt) +{ + uint8_t *pEvtBuf = NULL; + + switch (pEvt->hdr.event) + { + 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; + } + + if (pEvtBuf) + { + lhciSendEvt(pEvtBuf); + return TRUE; + } + + return FALSE; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_cis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_cis_slave.c new file mode 100644 index 0000000000..45cb477000 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_cis_slave.c @@ -0,0 +1,101 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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 "lhci_int.h" +#include "lctr_api_cis_slave.h" +#include "hci_defs.h" +#include "ll_api.h" +#include "wsf_msg.h" +#include "wsf_os.h" +#include "util/bstream.h" + +/************************************************************************************************** + Local Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Pack a CIS request event packet. + * + * \param pBuf Packed packet buffer. + * \param pEvt Generate CIS request data. + * + * \return Packet length. + */ +/*************************************************************************************************/ +static uint8_t lhciPackCisReqEvt(uint8_t *pBuf, const LlCisReqInd_t *pEvt) +{ + const uint8_t len = HCI_LEN_LE_CIS_REQ; + + UINT8_TO_BSTREAM (pBuf, HCI_LE_CIS_REQ_EVT); + UINT16_TO_BSTREAM (pBuf, pEvt->aclHandle); + UINT16_TO_BSTREAM(pBuf, pEvt->cisHandle); + UINT8_TO_BSTREAM (pBuf, pEvt->cigId); + UINT8_TO_BSTREAM (pBuf, pEvt->cisId); + + return len; +} + +/************************************************************************************************** + External Functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief LL CIS slave event handler. + * + * \param pEvt Buffer containing LL event. + * + * \return TRUE if event handled, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lhciSlvCisEncodeEvtPkt(LlEvt_t *pEvt) +{ + uint8_t *pEvtBuf = NULL; + + switch (pEvt->hdr.event) + { + case LL_CIS_REQ_IND: + if ((lhciCb.leEvtMsk & ((uint64_t)(HCI_EVT_MASK_LE_CIS_REQ_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_REQ)) != NULL) + { + lhciPackCisReqEvt(pEvtBuf, &pEvt->cisReqInd); + } + } + break; + + default: + break; + } + + if (pEvtBuf) + { + lhciSendEvt(pEvtBuf); + return TRUE; + } + + return FALSE; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn.c index 94d7167223..8929c53ac2 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief LL HCI event module implementation file. + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -39,14 +40,13 @@ * \return Packet length. */ /*************************************************************************************************/ -static uint8_t lhciPackNumCompPktsEvt(uint8_t *pBuf, uint16_t connHandle, uint8_t numPkts) +static uint8_t lhciPackNumCompPktsEvt(uint8_t *pBuf, uint16_t connHandle, uint16_t numPkts) { - const uint8_t len = HCI_LEN_NUM_CMPL_PKTS; - uint16_t numPkts_u16 = numPkts; + const uint8_t len = HCI_LEN_NUM_CMPL_PKTS(1); UINT8_TO_BSTREAM (pBuf, 1); UINT16_TO_BSTREAM(pBuf, connHandle); - UINT16_TO_BSTREAM(pBuf, numPkts_u16); + UINT16_TO_BSTREAM(pBuf, numPkts); return len; } @@ -251,14 +251,60 @@ static uint8_t lhciPackReqPeerScaCompleteEvt(uint8_t *pBuf, const LlPeerScaCnf_t return len; } +/*************************************************************************************************/ +/*! + * \brief Power report event handler. + * + * \param pBuf Packed packet buffer. + * \param pEvt Power report indication data. + * + * \return Packet length. + */ +/*************************************************************************************************/ +static uint8_t lhciPackPowerReportEvt(uint8_t *pBuf, const LlPowerReportInd_t *pEvt) +{ + const uint8_t len = HCI_LEN_LE_POWER_REPORT; + + UINT8_TO_BSTREAM (pBuf, HCI_LE_POWER_REPORT_EVT); + UINT8_TO_BSTREAM (pBuf, pEvt->status) + UINT16_TO_BSTREAM(pBuf, pEvt->connHandle); + UINT8_TO_BSTREAM (pBuf, pEvt->reason); + UINT8_TO_BSTREAM (pBuf, pEvt->phy); + UINT8_TO_BSTREAM (pBuf, pEvt->txPower); + UINT8_TO_BSTREAM (pBuf, pEvt->txPowerLimits); + UINT8_TO_BSTREAM (pBuf, pEvt->delta); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Path loss event handler. + * + * \param pBuf Packed packet buffer. + * \param pEvt Path loss event data. + * + * \return Packet length. + */ +/*************************************************************************************************/ +static uint8_t lhciPackPathLossEvt(uint8_t *pBuf, const LlPathLossThresholdEvt_t *pEvt) +{ + const uint8_t len = HCI_LEN_LE_PATH_LOSS_ZONE; + + UINT8_TO_BSTREAM (pBuf, HCI_LE_PATH_LOSS_REPORT_EVT); + UINT16_TO_BSTREAM(pBuf, pEvt->connHandle); + UINT8_TO_BSTREAM (pBuf, pEvt->curPathLoss); + UINT8_TO_BSTREAM (pBuf, pEvt->zoneEntered); + + return len; +} + /*************************************************************************************************/ /*! * \brief LL ACL send complete event handler. * * \param handle Connection handle. * \param numBufs Number of buffers. - * - * \return None. */ /*************************************************************************************************/ void lhciAclSendComplete(uint16_t handle, uint8_t numBufs) @@ -267,7 +313,7 @@ void lhciAclSendComplete(uint16_t handle, uint8_t numBufs) { uint8_t *pEvtBuf; - if ((pEvtBuf = lhciAllocEvt(HCI_NUM_CMPL_PKTS_EVT, HCI_LEN_NUM_CMPL_PKTS)) != NULL) + if ((pEvtBuf = lhciAllocEvt(HCI_NUM_CMPL_PKTS_EVT, HCI_LEN_NUM_CMPL_PKTS(1))) != NULL) { lhciPackNumCompPktsEvt(pEvtBuf, handle, numBufs); lhciSendEvt(pEvtBuf); @@ -336,8 +382,6 @@ uint8_t *lhciRecvAcl(void) * * \param handle Connection handle. * \param numBufs Number of buffers. - * - * \return None. */ /*************************************************************************************************/ void lhciAclRecvPending(uint16_t handle, uint8_t numBufs) @@ -451,6 +495,26 @@ bool_t lhciConnEncodeEvtPkt(LlEvt_t *pEvt) } } break; + case LL_TX_POWER_REPORTING_IND: + if ((lhciCb.leEvtMsk & ((uint64_t)(HCI_EVT_MASK_LE_TX_POWER_REPORT_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_POWER_REPORT)) != NULL) + { + lhciPackPowerReportEvt(pEvtBuf, &pEvt->powerRptInd); + } + } + break; + case LL_PATH_LOSS_REPORTING_IND: + if ((lhciCb.leEvtMsk & ((uint64_t)(HCI_EVT_MASK_LE_PATH_LOSS_REPORT_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_PATH_LOSS_ZONE)) != NULL) + { + lhciPackPathLossEvt(pEvtBuf, &pEvt->pathLossEvt); + } + } + break; default: break; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn_cs2.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn_cs2.c index 632db665ee..1423cd17c0 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn_cs2.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn_cs2.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief LL HCI event module implementation file. + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn_master.c index 2f920b0145..8217178c98 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief LL HCI event module implementation file. + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn_priv.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn_priv.c index 3c76ec5fb7..22841e4753 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn_priv.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_conn_priv.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief LL HCI event module implementation file. + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_enc_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_enc_master.c index e568b36724..2031d5c210 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_enc_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_enc_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief LL HCI event module implementation file. + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_enc_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_enc_slave.c index 5cfdd10705..15336b9e03 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_enc_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_enc_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief LL HCI event module implementation file. + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_iso.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_iso.c new file mode 100644 index 0000000000..24011075e7 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_iso.c @@ -0,0 +1,203 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "lhci_int.h" +#include "chci_api.h" +#include "hci_defs.h" +#include "wsf_msg.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include + +/*************************************************************************************************/ +/*! + * \brief Pack a number of completed packets event packet. + * + * \param pBuf Packed packet buffer. + * \param numHandles Number of handles. + * \param pHandle Array of CIS or BIS handle. + * \param pNumPkts Array of number of completed packets. + * + * \return Packet length. + */ +/*************************************************************************************************/ +static uint8_t lhciPackNumCompPktsEvt(uint8_t *pBuf, uint8_t numHandles, uint16_t *pHandle, uint16_t *pNumPkts) +{ + const uint8_t len = HCI_LEN_NUM_CMPL_PKTS(numHandles); + + UINT8_TO_BSTREAM (pBuf, numHandles); + + for (unsigned int i = 0; i < numHandles; i++) + { + UINT16_TO_BSTREAM(pBuf, pHandle[i]); + UINT16_TO_BSTREAM(pBuf, pNumPkts[i]); + } + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Free the received ISO data for test Rx. + * + * \param pIsoData ISO data buffer. + */ +/*************************************************************************************************/ +static void lhciFreeRcvdIsoData(uint8_t *pIsoData) +{ + WsfMsgFree(pIsoData); + LlRecvIsoDataComplete(1); +} + +/*************************************************************************************************/ +/*! + * \brief LL ISO send complete event handler. + * + * \param numHandles Number of handles. + * \param pHandle Array of CIS or BIS handle. + * \param pNumPkts Array of number of completed packets. + */ +/*************************************************************************************************/ +void lhciIsoSendComplete(uint8_t numHandles, uint16_t *pHandle, uint16_t *pNumPkts) +{ + uint8_t *pEvtBuf; + + if ((pEvtBuf = lhciAllocEvt(HCI_NUM_CMPL_PKTS_EVT, HCI_LEN_NUM_CMPL_PKTS(numHandles))) != NULL) + { + lhciPackNumCompPktsEvt(pEvtBuf, numHandles, pHandle, pNumPkts); + + lhciSendEvt(pEvtBuf); + } +} + +/*************************************************************************************************/ +/*! + * \brief Sink LL ACL. + * + * \param pBuf Buffer to sink. + * + * \return TRUE if buffer sink. + */ +/*************************************************************************************************/ +static bool_t lhciSinkIso(uint8_t *pBuf) +{ + if (lhciIsoCb.recvIsoSink) + { + uint8_t len; + + len = pBuf[2]; + lhciIsoCb.recvIsoPktCnt++; + lhciIsoCb.recvIsoOctetCnt += len; + + WsfMsgFree(pBuf); + LlRecvIsoDataComplete(1); + return TRUE; + } + return FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Receive LL ISO. + * + * \return Pointer to buffer for transport. + */ +/*************************************************************************************************/ +uint8_t *lhciRecvIso(void) +{ + uint8_t *pIsoData; + + if ((pIsoData = LlRecvIsoData()) != NULL) + { + if (!lhciSinkIso(pIsoData)) + { + return pIsoData; + } + } + + return NULL; +} + +/*************************************************************************************************/ +/*! + * \brief LL ISO receive pending event handler. + * + * \param numHandles Number of handles. + * \param pHandle Array of CIS or BIS handle. + * \param pNumPkts Array of number of pending packets. + */ +/*************************************************************************************************/ +void lhciIsoRecvPending(uint8_t numHandles, uint16_t *pHandle, uint16_t *pNumPkts) +{ + uint8_t *pIsoData; + + if (lhciIsoCb.isoRxTest == TRUE) + { + if ((pIsoData = LlRecvIsoData()) != NULL) + { + lhciFreeRcvdIsoData(pIsoData); + return; + } + } + else + { + if (lhciIsoCb.recvIsoSink && ((pIsoData = LlRecvIsoData()) != NULL)) + { + lhciSinkIso(pIsoData); + return; + } + } + + ChciTrNeedsService(CHCI_TR_PROT_BLE); +} + +/*************************************************************************************************/ +/*! + * \brief LL ISO event handler. + * + * \param pEvt Buffer containing LL event. + * + * \return TRUE if event handled, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lhciIsoEncodeEvtPkt(LlEvt_t *pEvt) +{ + uint8_t *pEvtBuf = NULL; + + switch (pEvt->hdr.event) + { + + default: + break; + } + + if (pEvtBuf) + { + lhciSendEvt(pEvtBuf); + return TRUE; + } + + return FALSE; +} + diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_pc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_pc.c new file mode 100644 index 0000000000..3c4c5c5709 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_pc.c @@ -0,0 +1,124 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2019 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 "lhci_int.h" +#include "chci_api.h" +#include "hci_defs.h" +#include "wsf_msg.h" +#include "util/bstream.h" +#include + +/*************************************************************************************************/ +/*! + * \brief Power report event handler. + * + * \param pBuf Packed packet buffer. + * \param pEvt Power report indication data. + * + * \return Packet length. + */ +/*************************************************************************************************/ +static uint8_t lhciPackPowerReportEvt(uint8_t *pBuf, const LlPowerReportInd_t *pEvt) +{ + const uint8_t len = HCI_LEN_LE_POWER_REPORT; + + UINT8_TO_BSTREAM (pBuf, HCI_LE_POWER_REPORT_EVT); + UINT8_TO_BSTREAM (pBuf, pEvt->status) + UINT16_TO_BSTREAM(pBuf, pEvt->connHandle); + UINT8_TO_BSTREAM (pBuf, pEvt->reason); + UINT8_TO_BSTREAM (pBuf, pEvt->phy); + UINT8_TO_BSTREAM (pBuf, pEvt->txPower); + UINT8_TO_BSTREAM (pBuf, pEvt->txPowerLimits); + UINT8_TO_BSTREAM (pBuf, pEvt->delta); + + return len; +} + +/*************************************************************************************************/ +/*! + * \brief Path loss event handler. + * + * \param pBuf Packed packet buffer. + * \param pEvt Path loss event data. + * + * \return Packet length. + */ +/*************************************************************************************************/ +static uint8_t lhciPackPathLossEvt(uint8_t *pBuf, const LlPathLossThresholdEvt_t *pEvt) +{ + const uint8_t len = HCI_LEN_LE_PATH_LOSS_ZONE; + + UINT8_TO_BSTREAM (pBuf, HCI_LE_PATH_LOSS_REPORT_EVT); + UINT16_TO_BSTREAM(pBuf, pEvt->connHandle); + UINT8_TO_BSTREAM (pBuf, pEvt->curPathLoss); + UINT8_TO_BSTREAM (pBuf, pEvt->zoneEntered); + + return len; +} +/*************************************************************************************************/ +/*! + * \brief LL connection event handler. + * + * \param pEvt Buffer containing LL event. + * + * \return TRUE if event handled, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t lhciPclEncodeEvtPkt(LlEvt_t *pEvt) +{ + uint8_t *pEvtBuf = NULL; + + switch (pEvt->hdr.event) + { + case LL_TX_POWER_REPORTING_IND: + if ((lhciCb.leEvtMsk & ((uint64_t)(HCI_EVT_MASK_LE_TX_POWER_REPORT_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_POWER_REPORT)) != NULL) + { + lhciPackPowerReportEvt(pEvtBuf, &pEvt->powerRptInd); + } + } + break; + case LL_PATH_LOSS_REPORTING_IND: + if ((lhciCb.leEvtMsk & ((uint64_t)(HCI_EVT_MASK_LE_PATH_LOSS_REPORT_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_PATH_LOSS_ZONE)) != NULL) + { + lhciPackPathLossEvt(pEvtBuf, &pEvt->pathLossEvt); + } + } + break; + + default: + break; + } + + if (pEvtBuf) + { + lhciSendEvt(pEvtBuf); + return TRUE; + } + + return FALSE; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_phy.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_phy.c index fff4ba59a5..5ef331bcce 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_phy.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_phy.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief LL HCI event module implementation file. + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_sc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_sc.c index b6901db08d..e0cd3987c3 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_sc.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_sc.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief LL HCI event module implementation file. + * \file + * + * \brief LL HCI event module implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_vs.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_vs.c index 733542406c..95a3369991 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_vs.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_evt_vs.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Vendor specific HCI event module implementation file. + * \file + * + * \brief Vendor specific HCI event module implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -25,7 +26,9 @@ #include "hci_defs.h" #include "wsf_msg.h" #include "util/bstream.h" +#include "bb_ble_api_op.h" #include +#include "bb_ble_sniffer_api.h" /************************************************************************************************** Macros @@ -33,10 +36,127 @@ /* Note: Arm Ltd. vendor specific subevent code is 0xFFF0-0xFFFF. */ -#define LHCI_OPCODE_VS_SUBEVT_TRACE_MSG 0xFFF0 /*!< Trace message event. */ -#define LHCI_OPCODE_VS_SUBEVT_SCAN_REPORT 0xFFF1 /*!< Scan report event. */ +#define LHCI_OPCODE_VS_SUBEVT_TRACE_MSG 0xFFF0 /*!< Trace message event. */ +#define LHCI_OPCODE_VS_SUBEVT_SCAN_REPORT 0xFFF1 /*!< Scan report event. */ +#define LHCI_OPCODE_VS_SUBEVT_PACKET_REPORT 0xFFF2 /*!< Packet report event from sniffer. */ +#define LHCI_OPCODE_VS_SUBEVT_ISO_EVT_CMPL 0xFFF3 /*!< ISO Event complete event. */ #define LHCI_LEN_VS_SUBEVT_SCAN_REPORT 13 /*!< Scan report event length. */ +#define LHCI_LEN_VS_SUBEVT_ISO_EVT_CMPL 8 /*!< ISO Event complete length. */ + +#if (BB_SNIFFER_ENABLED == TRUE) +/*************************************************************************************************/ +/*! + * \brief Send a packet report event. + * + * \param pBuf Message. + * + * \return TRUE if successful, FALSE otherwise. + */ +/*************************************************************************************************/ +static bool_t LhciVsEncodeSnifferPktEvtPkt(BbBleSnifferPkt_t *pPktData) +{ + uint8_t *pEvtBuf; + uint8_t *pPkt = lhciAllocEvt(HCI_VENDOR_SPEC_EVT, LHCI_LEN_VS_EVT + BB_SNIFFER_MAX_PKT_SIZE); + + if (pPkt == NULL) + { + return FALSE; + } + + pEvtBuf = pPkt; + pEvtBuf += lhciPackVsEvt(pEvtBuf, LHCI_OPCODE_VS_SUBEVT_PACKET_REPORT); + + /* Pack metadata. */ + BbBleSnifferMeta_t meta = pPktData->pktType.meta; + UINT8_TO_BSTREAM(pEvtBuf, meta.type); + UINT8_TO_BSTREAM(pEvtBuf, meta.status); + UINT8_TO_BSTREAM(pEvtBuf, meta.state); + UINT32_TO_BSTREAM(pEvtBuf, meta.timeStamp); + UINT8_TO_BSTREAM(pEvtBuf, meta.rssi); + + /* Pack channelization metadata. */ + PalBbBleChan_t chan = meta.chan; + UINT8_TO_BSTREAM(pEvtBuf, chan.opType); + UINT8_TO_BSTREAM(pEvtBuf, chan.chanIdx); + UINT8_TO_BSTREAM(pEvtBuf, chan.txPower); + UINT32_TO_BSTREAM(pEvtBuf, chan.accAddr); + UINT24_TO_BSTREAM(pEvtBuf, chan.crcInit); + UINT8_TO_BSTREAM(pEvtBuf, chan.txPhy); + UINT8_TO_BSTREAM(pEvtBuf, chan.rxPhy); + UINT8_TO_BSTREAM(pEvtBuf, chan.initTxPhyOptions); + UINT8_TO_BSTREAM(pEvtBuf, chan.tifsTxPhyOptions); + UINT8_TO_BSTREAM(pEvtBuf, chan.peerTxStableModIdx); + UINT8_TO_BSTREAM(pEvtBuf, chan.peerRxStableModIdx); + + /* Pack data based on packet. */ + switch (chan.opType) + { + case BB_BLE_OP_MST_ADV_EVENT: + case BB_BLE_OP_SLV_ADV_EVENT: + case BB_BLE_OP_MST_AUX_ADV_EVENT: + case BB_BLE_OP_SLV_AUX_ADV_EVENT: + case BB_BLE_OP_MST_PER_SCAN_EVENT: + case BB_BLE_OP_SLV_PER_ADV_EVENT: + memcpy(pEvtBuf, pPktData->pktType.advPkt.hdr, LL_ADV_HDR_LEN); + break; + + case BB_BLE_OP_MST_CONN_EVENT: + case BB_BLE_OP_SLV_CONN_EVENT: + memcpy(pEvtBuf, pPktData->pktType.dataPkt.hdr, LL_DATA_HDR_MAX_LEN); + break; + + default: + break; + } + + lhciSendEvt(pPkt); + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Handle a received packet. + * + * \return TRUE if packets still remain. FALSE if not. + */ +/*************************************************************************************************/ +bool_t LhciSnifferHandler(void) +{ + BbBleSnifferHciCtx_t * pHci = &bbSnifferCtx.outputCtx.hci; + if ((bbSnifferCtx.enabled == FALSE) || + (pHci->bufIdx == 0)) + { + return FALSE; + } + + BbBleSnifferPkt_t * pPktData = &pHci->pktBuf[--pHci->bufIdx]; + LhciVsEncodeSnifferPktEvtPkt(pPktData); + + return pHci->bufIdx == 0; +} +#endif + +/*************************************************************************************************/ +/*! + * \brief Pack a scan report packet. + * + * \param pBuf Packed packet buffer. + * \param pEvt Scan report data. + * + * \return Packet length. + */ +/*************************************************************************************************/ +static uint8_t lhciVsPackScanReportEvt(uint8_t *pBuf, const LlScanReportInd_t *pEvt) +{ + const uint8_t len = LHCI_LEN_VS_SUBEVT_SCAN_REPORT; + + UINT8_TO_BSTREAM(pBuf, pEvt->peerAddrType); + BDA64_TO_BSTREAM(pBuf, pEvt->peerAddr); + BDA64_TO_BSTREAM(pBuf, pEvt->peerRpa); + + return len; +} /*************************************************************************************************/ /*! @@ -86,27 +206,6 @@ bool_t LhciVsEncodeTraceMsgEvtPkt(const uint8_t *pBuf, uint32_t len) return TRUE; } -/*************************************************************************************************/ -/*! - * \brief Pack a scan report packet. - * - * \param pBuf Packed packet buffer. - * \param pEvt Scan report data. - * - * \return Packet length. - */ -/*************************************************************************************************/ -static uint8_t lhciVsPackScanReportEvt(uint8_t *pBuf, const LlScanReportInd_t *pEvt) -{ - const uint8_t len = LHCI_LEN_VS_SUBEVT_SCAN_REPORT; - - UINT8_TO_BSTREAM(pBuf, pEvt->peerAddrType); - BDA64_TO_BSTREAM(pBuf, pEvt->peerAddr); - BDA64_TO_BSTREAM(pBuf, pEvt->peerRpa); - - return len; -} - /*************************************************************************************************/ /*! * \brief LL slave VS event handler. @@ -132,6 +231,18 @@ bool_t lhciSlvVsStdEncodeEvtPkt(LlEvt_t *pEvt) } break; + case LL_ISO_EVT_CMPL_IND: + /* No need to check the event mask; LL should not generate this event without the event masked. */ + if ((pEvtBuf = lhciAllocEvt(HCI_VENDOR_SPEC_EVT, LHCI_LEN_VS_EVT + LHCI_LEN_VS_SUBEVT_ISO_EVT_CMPL)) != NULL) + { + uint8_t *pBuf = pEvtBuf; + pBuf += LhciPackVsEvt(pBuf, LHCI_OPCODE_VS_SUBEVT_ISO_EVT_CMPL); + UINT8_TO_BSTREAM(pBuf, pEvt->isoEvtCmplInd.handle); + pBuf += 3; /* padding */ + UINT32_TO_BSTREAM(pBuf, pEvt->isoEvtCmplInd.evtCtr); + } + break; + default: break; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init.c index 78e8087f3c..2bd21d6de3 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -31,8 +32,6 @@ * * \param handlerId WSF handler ID. * - * \return None. - * * This function initializes the LL HCI subsystem. It is typically called once upon system * initialization. */ @@ -56,8 +55,6 @@ void LhciHandlerInit(wsfHandlerId_t handlerId) * \brief Initialize VS extended command decoder. * * \param decodeCmd Command decoder. - * - * \return None. */ /*************************************************************************************************/ void LhciVsExtInit(lhciCmdHandler_t decodeCmd) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_master.c index d9ff608a09..d5a1052e48 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,8 +28,6 @@ /*! * \brief Initialize LL HCI subsystem for master mode. * - * \return None. - * * This function initializes the LL HCI subsystem for master commands. It is typically called * once upon system initialization. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_master_ae.c index 41b544f4db..d982c18077 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -28,8 +29,6 @@ /*! * \brief Initialize LL HCI subsystem for master mode. * - * \return None. - * * This function initializes the LL HCI subsystem for master commands. It is typically called * once upon system initialization. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_priv.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_priv.c index 118f4c8a0b..9faea59fc9 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_priv.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_priv.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,8 +28,6 @@ /*! * \brief Initialize LL HCI subsystem for privacy. * - * \return None. - * * This function initializes the LL HCI subsystem for LE Privacy 1.2. It is typically * called once upon system initialization. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_slave.c index 014e57cd9d..ecf4c8a84e 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,8 +28,6 @@ /*! * \brief Initialize LL HCI subsystem for slave mode. * - * \return None. - * * This function initializes the LL HCI subsystem for slave commands. It is typically called * once upon system initialization. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_slave_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_slave_ae.c index 78e9952a03..7852308e22 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_slave_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_adv_slave_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,8 +28,6 @@ /*! * \brief Initialize LL HCI subsystem for slave mode. * - * \return None. - * * This function initializes the LL HCI subsystem for slave commands. It is typically called * once upon system initialization. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_bis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_bis_master.c new file mode 100644 index 0000000000..bace6fdd09 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_bis_master.c @@ -0,0 +1,40 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 "lhci_int.h" +#include + +/*************************************************************************************************/ +/*! + * \brief Initialize LL HCI subsystem for BIS slave mode. + * + * This function initializes the LL HCI subsystem for BIS slave commands. It is typically called + * once upon system initialization. + */ +/*************************************************************************************************/ +void LhciBisMasterInit(void) +{ + lhciCmdTbl[LHCI_MSG_BIS_MST] = lhciMstBisDecodeCmdPkt; + lhciEvtTbl[LHCI_MSG_BIS_MST] = lhciMstBisEncodeEvtPkt; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_bis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_bis_slave.c new file mode 100644 index 0000000000..f9521c8f4e --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_bis_slave.c @@ -0,0 +1,40 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 "lhci_int.h" +#include + +/*************************************************************************************************/ +/*! + * \brief Initialize LL HCI subsystem for BIS slave mode. + * + * This function initializes the LL HCI subsystem for BIS slave commands. It is typically called + * once upon system initialization. + */ +/*************************************************************************************************/ +void LhciBisSlaveInit(void) +{ + lhciCmdTbl[LHCI_MSG_BIS_SLV] = lhciSlvBisDecodeCmdPkt; + lhciEvtTbl[LHCI_MSG_BIS_SLV] = lhciSlvBigEncodeEvtPkt; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_cis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_cis_master.c new file mode 100644 index 0000000000..1b1e529d62 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_cis_master.c @@ -0,0 +1,40 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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 "lhci_int.h" +#include + +/*************************************************************************************************/ +/*! + * \brief Initialize LL HCI subsystem for CIS master mode. + * + * This function initializes the LL HCI subsystem for CIS master commands. It is typically called + * once upon system initialization. + */ +/*************************************************************************************************/ +void LhciCisMasterInit(void) +{ + lhciCmdTbl[LHCI_MSG_CIS_MST] = lhciMstCisDecodeCmdPkt; + lhciEvtTbl[LHCI_MSG_CIS_MST] = lhciMstCisEncodeEvtPkt; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_cis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_cis_slave.c new file mode 100644 index 0000000000..c33329c2c1 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_cis_slave.c @@ -0,0 +1,40 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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 "lhci_int.h" +#include + +/*************************************************************************************************/ +/*! + * \brief Initialize LL HCI subsystem for CIS slave mode. + * + * This function initializes the LL HCI subsystem for CIS slave commands. It is typically called + * once upon system initialization. + */ +/*************************************************************************************************/ +void LhciCisSlaveInit(void) +{ + lhciCmdTbl[LHCI_MSG_CIS_SLV] = lhciSlvCisDecodeCmdPkt; + lhciEvtTbl[LHCI_MSG_CIS_SLV] = lhciSlvCisEncodeEvtPkt; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn.c index 1213ada0d2..3bad47d051 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,8 +28,6 @@ /*! * \brief Initialize LL HCI subsystem for connections. * - * \return None. - * * This function initializes the LL HCI subsystem for ACL data exchanges. It is typically * called once upon system initialization. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn_cs2.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn_cs2.c index 4e9f26adfc..7175a0d17e 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn_cs2.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn_cs2.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,8 +28,6 @@ /*! * \brief Initialize LL HCI subsystem for channel selection 2. * - * \return None. - * * This function initializes the LL HCI subsystem for channel selection 2.. It is typically * called once upon system initialization. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn_master.c index 9647e002d7..f09b3faa0a 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,8 +28,6 @@ /*! * \brief Initialize LL HCI subsystem for master connections. * - * \return None. - * * This function initializes the LL HCI subsystem for ACL data exchanges. It is typically * called once upon system initialization. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn_master_ae.c index bdbdd46eb3..add8aacd91 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,8 +28,6 @@ /*! * \brief Initialize LL HCI subsystem for master connections. * - * \return None. - * * This function initializes the LL HCI subsystem for ACL data exchanges. It is typically * called once upon system initialization. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn_priv.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn_priv.c index 7aed705f28..28d6da4715 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn_priv.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_conn_priv.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,8 +28,6 @@ /*! * \brief Initialize LL HCI subsystem for privacy (connections). * - * \return None. - * * This function initializes the LL HCI subsystem for LE Privacy 1.2. It is typically * called once upon system initialization. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_enc_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_enc_master.c index fa02e5a296..c88bbdb811 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_enc_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_enc_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,8 +28,6 @@ /*! * \brief Initialize LL HCI subsystem for master encryption mode. * - * \return None. - * * This function initializes the LL HCI subsystem for master commands. It is typically called * once upon system initialization. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_enc_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_enc_slave.c index 16fe852ab4..e37b6f9659 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_enc_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_enc_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,8 +28,6 @@ /*! * \brief Initialize LL HCI subsystem for slave encryption mode. * - * \return None. - * * This function initializes the LL HCI subsystem for slave encryption commands. It is typically * called once upon system initialization. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_iso.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_iso.c new file mode 100644 index 0000000000..6d4ee337ff --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_iso.c @@ -0,0 +1,69 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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 "lhci_int.h" +#include "chci_api.h" +#include + +/*************************************************************************************************/ +/*! + * \brief Initialize LL HCI handler including ISO feature. + * + * \param handlerId WSF handler ID. + * + * This function initializes the LL HCI subsystem. It is typically called once upon system + * initialization. + */ +/*************************************************************************************************/ +void LhciIsoHandlerInit(wsfHandlerId_t handlerId) +{ + ChciTrSetCbacks(CHCI_TR_PROT_BLE, lhciRecv, lhciSendComplete, lhciService); + ChciTrSetSendHwErrorCback(lhciSendHwError); + + memset(&lhciPersistCb, 0, sizeof(lhciPersistCb)); + lhciPersistCb.handlerId = handlerId; + memset(&lhciCb, 0, sizeof(lhciCb)); + + LlEvtRegister(lhciLlEvtHandler); + + lhciReset(); +} + +/*************************************************************************************************/ +/*! + * \brief Initialize LL HCI subsystem for isochornous. + * + * This function initializes the LL HCI subsystem for ISO data exchanges. It is typically + * called once upon system initialization. + */ +/*************************************************************************************************/ +void LhciIsoInit(void) +{ + LlIsoRegister(lhciIsoSendComplete, lhciIsoRecvPending); + + lhciServiceIso = lhciRecvIso; + + lhciCmdTbl[LHCI_MSG_ISO] = lhciIsoDecodeCmdPkt; + lhciEvtTbl[LHCI_MSG_ISO] = lhciIsoEncodeEvtPkt; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_past.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_past.c index 760b729943..f6cac4cf5d 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_past.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_past.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -28,8 +29,6 @@ /*! * \brief Initialize LL HCI subsystem for PAST(Periodic advertising sync transfer) features. * - * \return None. - * * This function initializes the LL HCI subsystem for PAST features commands. It is * typically called once upon system initialization. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_pc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_pc.c new file mode 100644 index 0000000000..d365a9d2db --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_pc.c @@ -0,0 +1,38 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation 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. + */ +/*************************************************************************************************/ + +#include "lhci_int.h" +#include "lhci_api.h" + +/*************************************************************************************************/ +/*! + * \brief Initialize LL HCI subsystem for Power control. + */ +/*************************************************************************************************/ +void LhciPowerControlInit(void) +{ + if (!lhciCmdTbl[LHCI_MSG_PC]) + { + lhciCmdTbl[LHCI_MSG_PC] = lhciPclDecodeCmdPkt; + lhciEvtTbl[LHCI_MSG_PC] = lhciPclEncodeEvtPkt; + } +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_phy.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_phy.c index fbf9677710..b266a779f8 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_phy.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_phy.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,8 +28,6 @@ /*! * \brief Initialize LL HCI subsystem for PHY features. * - * \return None. - * * This function initializes the LL HCI subsystem for PHY features commands. It is * typically called once upon system initialization. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_sc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_sc.c index 5defba4d40..93f8792275 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_sc.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_init_sc.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,8 +28,6 @@ /*! * \brief Initialize LL HCI subsystem for secure connections. * - * \return None. - * * This function initializes the LL HCI subsystem for secure connections commands. It is * typically called once upon system initialization. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_int.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_int.h index 7efadec410..f0f91165e0 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_int.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_int.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief LL HCI main module interface file. + * \file + * + * \brief LL HCI main module interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -137,18 +138,31 @@ extern "C" { #define LHCI_LEN_LE_SET_PER_ADV_RCV_ENABLE 1 /*!< LE set periodic advertising receive enable command complete event length. */ #define LHCI_LEN_LE_PER_ADV_SYNC_TRANSFER 3 /*!< LE periodic advertising sync transfer command complete event length. */ #define LHCI_LEN_LE_PER_ADV_SET_INFO_TRANSFER 3 /*!< LE periodic advertising set info transfer command complete event length. */ -#define LHCI_LEN_LE_SET_PAST_PARAM 1 /*!< LE set periodic advertising sync transfer parameters command complete event length. */ +#define LHCI_LEN_LE_SET_PAST_PARAM 3 /*!< LE set periodic advertising sync transfer parameters command complete event length. */ #define LHCI_LEN_LE_SET_DEFAULT_PAST_PARAM 1 /*!< LE set default periodic advertising sync transfer parameters command complete event length. */ #define LHCI_LEN_LE_MODIFY_SCA_EVT 1 /*!< LE Modify sleep clock accuracy event length. */ -/* New in version Milan */ -#define LHCI_LEN_LE_READ_ISO_BUF_SIZE 4 /*!< LE read ISO buffer size command complete event length. */ +/* 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_REJECT_CIS_REQ 1 /*!< LE reject CIS request. */ -#define LHCI_LEN_LE_SETUP_ISO_DATA_PATH 1 /*!< LE setup ISO data path. */ -#define LHCI_LEN_LE_REMOVE_ISO_DATA_PATH 1 /*!< LE remove ISO data path. */ +#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. */ +#define LHCI_LEN_LE_REMOVE_ISO_DATA_PATH 3 /*!< LE remove ISO data path. */ #define LHCI_LEN_LE_ISO_TX_TEST 1 /*!< LE ISO Tx Test. */ #define LHCI_LEN_LE_ISO_RX_TEST 1 /*!< LE ISO Rx Test. */ -#define LHCI_LEN_LE_ISO_READ_TEST_COUNTER 13 /*!< LE ISO read test counter. */ +#define LHCI_LEN_LE_ISO_READ_TEST_COUNTER 15 /*!< LE ISO read test counter. */ +#define LHCI_LEN_LE_ISO_TEST_END 15 /*!< LE ISO test end. */ +#define LHCI_LEN_LE_SET_HOST_FEATURE 1 /*!< LE Set Host Feature. */ +#define LHCI_LEN_LE_READ_ISO_LINK_QUAL 31 /*!< LE Read ISO link quality. */ +#define LHCI_LEN_LE_READ_ENH_TX_POWER_EVT 6 /*!< LE Read enhanced TX power. */ +#define LHCI_LEN_LE_SET_TX_POWER_REPORT_EVT 3 /*!< LE Set transmit power reporting enable event. */ +#define LHCI_LEN_LE_SET_PATH_LOSS_REPORTING_PARAMS 3 /*!< LE Set path loss reporting parameters event. */ +#define LHCI_LEN_LE_SET_PATH_LOSS_REPORTING_ENABLE 3 /*!< LE Set path loss reporting enable event. */ +#define LHCI_LEN_CONFIG_DATA_PATH 1 /*!< Configure data path. */ +#define LHCI_LEN_READ_LOCAL_SUP_CODECS 3 /*!< Read local supported codecs. */ +#define LHCI_LEN_READ_LOCAL_SUP_CODEC_CAP 2 /*!< Read local supported codec configuration. */ +#define LHCI_LEN_READ_LOCAL_SUP_CONTROLLER_DLY 7 /*!< Read local supported controller delay. */ /*! \brief Mandatory event mask. */ #define LHCI_DEF_EVT_MASK UINT64_C(0x00001FFFFFFFFFFF); @@ -173,7 +187,7 @@ extern "C" { /*! \brief Indicate command status event shall be returned. */ #define LHCI_LEN_CMD_STATUS_EVT 0xFF -/* Cordio vendor specific OCF range is 0x3C0-0x3FF */ +/* Packetcraft vendor specific OCF range is 0x3C0-0x3FF */ #define LHCI_OPCODE_VS_SET_SCAN_CH_MAP HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3E0) /*!< Set Scan Channel Map opcode. */ #define LHCI_OPCODE_VS_SET_EVENT_MASK HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3E1) /*!< Set Vendor Specific Event Mask opcode. */ #define LHCI_OPCODE_VS_SET_RSRC_MGR_MODE HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3E2) /*!< DEPRECATED. */ @@ -184,7 +198,7 @@ extern "C" { #define LHCI_OPCODE_VS_SET_CONN_OP_FLAGS HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3E7) /*!< Set Connection Operational Flags opcode. */ #define LHCI_OPCODE_VS_SET_P256_PRIV_KEY HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3E8) /*!< Set P-256 Private Key opcode. */ #define LHCI_OPCODE_VS_GET_PER_CHAN_MAP HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3DE) /*!< Get channel map of periodic scan/adv. */ -#define LHCI_OPCODE_VS_SET_HCI_SUP_CMD HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3DF) /*!< Set Hci supported commands. */ +#define LHCI_OPCODE_VS_SET_HCI_SUP_CMD HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3DF) /*!< DEPRECATED. */ #define LHCI_OPCODE_VS_GET_ACL_TEST_REPORT HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3E9) /*!< Get ACL Test Report opcode. */ #define LHCI_OPCODE_VS_SET_LOCAL_MIN_USED_CHAN HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3EA) /*!< Set local minimum number of used channels. */ #define LHCI_OPCODE_VS_GET_PEER_MIN_USED_CHAN HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3EB) /*!< Get peer minimum number of used channels. */ @@ -200,6 +214,7 @@ extern "C" { #define LHCI_OPCODE_VS_SET_CHAN_MAP HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3F8) /*!< Set Channel Map opcode. */ #define LHCI_OPCODE_VS_SET_DIAG_MODE HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3F9) /*!< Set Diagnostic Mode opcode. */ +#define LHCI_OPCODE_VS_SET_SNIFFER_ENABLE HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3CD) /*!< Enable sniffer packet forwarding. */ #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. */ @@ -224,11 +239,13 @@ extern "C" { #define LHCI_OPCODE_VS_GET_AUX_SCAN_STATS HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3DB) /*!< Get Auxiliary Scanning Statistics opcode. */ #define LHCI_OPCODE_VS_GET_PER_SCAN_STATS HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3DC) /*!< Get Periodic Scanning Statistics opcode. */ +#define LHCI_OPCODE_VS_SET_CONN_PHY_TX_PWR HCI_OPCODE(HCI_OGF_VENDOR_SPEC, 0x3DD) /*!< Set Connection Phy Tx Power opcode. */ /* Vendor specific event masks. */ #define LHCI_VS_EVT_MASK_SCAN_REPORT_EVT 0x01 /*!< (Byte 0) VS event bit, scan report. */ #define LHCI_VS_EVT_MASK_DIAG_TRACE_EVT 0x02 /*!< (Byte 0) VS event bit, diagnostic tracing. */ +#define LHCI_VS_EVT_MASK_ISO_EVENT_CMPL_EVT 0x04 /*!< (Byte 0) VS event bit, ISO event complete. */ /************************************************************************************************** Data Types @@ -252,7 +269,10 @@ enum LHCI_MSG_PAST, /*!< Periodic advertising sync transfer command handler type. */ LHCI_MSG_CIS_MST, /*!< Connected isochronous stream master features command handler type. */ LHCI_MSG_CIS_SLV, /*!< Connected isochronous stream slave features command handler type. */ + LHCI_MSG_BIS_MST, /*!< Broadcast isochronous stream master features command handler type. */ + LHCI_MSG_BIS_SLV, /*!< Broadcast isochronous stream slave features command handler type. */ LHCI_MSG_ISO, /*!< Isochronous features command handler type. */ + LHCI_MSG_PC, /*!< Power control handler type. */ LHCI_MSG_VS_EXT, /*!< Extended vendor specific command handler type. */ LHCI_MSG_TESTER, /*!< Tester vendor specific command handler type. */ LHCI_MSG_TOTAL /*!< Total number of command handlers. */ @@ -287,6 +307,9 @@ typedef struct wsfQueue_t evtQ; /*!< Event queue. */ wsfQueue_t isoQ; /*!< ISO queue. */ bool_t evtTrPending; /*!< Event transport in progress. */ + + uint8_t supCmds[HCI_SUP_CMD_LEN]; + /*!< Supported HCI commands bit mask. */ } lhciPersistCb_t; /*! \brief Control block of the LL HCI subsystem (cleared with resets). */ @@ -295,6 +318,7 @@ 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. */ @@ -308,23 +332,24 @@ typedef struct uint32_t genPktCnt; /*!< Generate ACL packet count. */ uint32_t genOctetCnt; /*!< Generate ACL octet count. */ - bool_t recvIsoSink; /*!< Receive ISO sink. */ - uint32_t recvIsoPktCnt; /*!< Receive ISO packet count. */ - uint32_t recvIsoOctetCnt; /*!< Receive Iso octet count. */ - bool_t isoGenEnaFlag; /*!< Generate ISO enable flag. */ - uint8_t isoGenPldCnt; /*!< Generate ISO packet fill value. */ - uint16_t isoGenPktLen; /*!< Generate ISO packet length (0 to disable). */ - uint32_t isoGenPktCnt; /*!< Generate ISO packet count. */ - uint32_t isoGenOctetCnt; /*!< Generate ISO octet count. */ - - bool_t isoTxTest; /*!< TRUE if ISO Tx test is enabled. */ - bool_t isoRxTest; /*!< TRUE if ISO Rx test is enabled. */ - uint8_t isoTxTestPlLen; /*!< ISO Tx test payload length. */ - uint8_t isoRxTestPlLen; /*!< ISO Rx test payload length. */ - uint8_t numAdvReport; /*!< Number of pending advertising reports. */ } lhciCb_t; +/*! \brief Control block for ISO data generator. */ +typedef struct +{ + bool_t recvIsoSink; /*!< Receive ISO sink. */ + uint32_t recvIsoPktCnt; /*!< Receive ISO packet count. */ + uint32_t recvIsoOctetCnt; /*!< Receive ISO octet count. */ + bool_t genEnaFlag; /*!< Generate ISO enable flag. */ + uint8_t genPldCnt; /*!< Generate ISO packet fill value. */ + uint16_t genPktLen; /*!< Generate ISO packet length (0 to disable). */ + uint32_t genPktCnt; /*!< Generate ISO packet count. */ + uint32_t genOctetCnt; /*!< Generate ISO octet count. */ + + bool_t isoRxTest; /*!< TRUE if ISO Rx test is enabled. */ +} lhciIsoCb_t; + /************************************************************************************************** Global Variables **************************************************************************************************/ @@ -347,6 +372,9 @@ extern lhciPersistCb_t lhciPersistCb; /* Control block */ extern lhciCb_t lhciCb; +/* Control block for ISO data generation. */ +extern lhciIsoCb_t lhciIsoCb; + /* Handler duration watermark in microseconds. */ extern uint16_t lhciHandlerWatermarkUsec; @@ -361,7 +389,6 @@ void lhciReset(void); void lhciRecv(uint8_t type, uint8_t *pBuf); void lhciSendComplete(uint8_t type, uint8_t *pBuf); bool_t lhciService(uint8_t *pType, uint16_t *pLen, uint8_t **pBuf); -void lhciSendIsoComplete(uint8_t type, uint8_t *pBuf); void lhciSendHwError(uint8_t code); /* Handlers */ @@ -371,9 +398,9 @@ uint8_t *lhciRecvAcl(void); void lhciAclRecvPending(uint16_t handle, uint8_t numBufs); void lhciGenerateAcl(uint16_t handle, uint16_t pktLen, uint8_t numPkts); -void lhciIsoSendComplete(uint16_t handle, uint8_t numBufs); +void lhciIsoSendComplete(uint8_t numHandles, uint16_t *pHandle, uint16_t *pNumPkts); uint8_t *lhciRecvIso(void); -void lhciIsoRecvPending(uint16_t handle, uint8_t numBufs); +void lhciIsoRecvPending(uint8_t numHandles, uint16_t *pHandle, uint16_t *pNumPkts); void lhciGenerateIso(uint16_t handle, uint16_t pktLen, uint8_t numPkts); /* Command parser */ @@ -394,7 +421,10 @@ bool_t lhciPhyDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf); bool_t lhciPastDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf); bool_t lhciMstCisDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf); bool_t lhciSlvCisDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf); +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 lhciCommonVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf); bool_t lhciConnVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf); @@ -424,7 +454,10 @@ bool_t lhciScEncodeEvtPkt(LlEvt_t *pEvt); bool_t lhciPhyEncodeEvtPkt(LlEvt_t *pEvt); bool_t lhciMstCisEncodeEvtPkt(LlEvt_t *pEvt); bool_t lhciSlvCisEncodeEvtPkt(LlEvt_t *pEvt); +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 lhciSlvVsStdEncodeEvtPkt(LlEvt_t *pEvt); @@ -433,6 +466,7 @@ bool_t lhciSlvVsStdEncodeEvtPkt(LlEvt_t *pEvt); uint8_t *lhciAllocEvt(uint8_t evtCode, uint8_t paramLen); uint8_t *lhciAllocCmdCmplEvt(uint8_t paramLen, uint16_t opCode); void lhciConnSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen, uint8_t *pParam, uint16_t handle); +void lhciPclSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen, uint8_t *pParam, uint16_t handle); /* Command packet. */ uint8_t lhciUnpackConnSpec(LlConnSpec_t *pConnSpec, const uint8_t *pBuf); @@ -543,8 +577,6 @@ static inline uint8_t lhciPackVsEvt(uint8_t *pBuf, uint16_t vsEvtCode) * \brief Send an event. * * \param pEvtBuf Buffer containing event. - * - * \return None. */ /*************************************************************************************************/ static inline void lhciSendEvt(uint8_t *pEvtBuf) @@ -557,8 +589,6 @@ static inline void lhciSendEvt(uint8_t *pEvtBuf) * \brief Send a command complete event. * * \param pEvtBuf Buffer containing command complete event. - * - * \return None. */ /*************************************************************************************************/ static inline void lhciSendCmdCmplEvt(uint8_t *pEvtBuf) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_main.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_main.c index 5a1bf4f762..aa22316670 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_main.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_main.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -83,8 +84,6 @@ static inline uint8_t lhciUnpackHdr(LhciHdr_t *pHdr, const uint8_t *pBuf) * * \param event WSF event. * \param pMsg WSF message. - * - * \return None. */ /*************************************************************************************************/ void LhciHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) @@ -93,7 +92,11 @@ void LhciHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) uint32_t startTime; uint32_t endTime; - startTimeValid = PalBbGetTimestamp(&startTime); + startTimeValid = PalBbGetTimestamp(NULL); + if (startTimeValid) + { + startTime = PalBbGetCurrentTime(); + } if (event & LHCI_EVT_ACL_RCVD) { @@ -149,6 +152,11 @@ void LhciHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) { lhciPersistCb.evtTrPending = FALSE; ChciTrNeedsService(CHCI_TR_PROT_BLE); + + if (lhciCb.evtCompCback) + { + lhciCb.evtCompCback(); + } } if (event & LHCI_EVT_HW_ERR) @@ -165,9 +173,10 @@ void LhciHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) } if (startTimeValid && - PalBbGetTimestamp(&endTime)) + PalBbGetTimestamp(NULL)) { - uint32_t durUsec = BB_TICKS_TO_US(endTime - startTime); + endTime = PalBbGetCurrentTime(); + uint32_t durUsec = BbGetTargetTimeDelta(endTime, startTime); if (lhciHandlerWatermarkUsec < durUsec) { lhciHandlerWatermarkUsec = durUsec; @@ -181,15 +190,18 @@ void LhciHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) * * \param type Type of message. * \param pBuf Pointer to received message. - * - * \return None. */ /*************************************************************************************************/ void lhciRecv(uint8_t type, uint8_t *pBuf) { switch (type) { - case CHCI_TR_TYPE_DATA: + case CHCI_TR_TYPE_ISO: + WsfMsgEnq(&lhciPersistCb.isoQ, 0, pBuf); + WsfSetEvent(lhciPersistCb.handlerId, LHCI_EVT_ISO_RCVD); + break; + + case CHCI_TR_TYPE_ACL: WsfMsgEnq(&lhciPersistCb.aclQ, 0, pBuf); WsfSetEvent(lhciPersistCb.handlerId, LHCI_EVT_ACL_RCVD); break; @@ -199,11 +211,6 @@ void lhciRecv(uint8_t type, uint8_t *pBuf) WsfSetEvent(lhciPersistCb.handlerId, LHCI_EVT_CMD_RCVD); break; - case CHCI_TR_TYPE_ISO: - WsfMsgEnq(&lhciPersistCb.isoQ, 0, pBuf); - WsfSetEvent(lhciPersistCb.handlerId, LHCI_EVT_ISO_RCVD); - break; - default: WsfMsgFree(pBuf); break; @@ -216,8 +223,6 @@ void lhciRecv(uint8_t type, uint8_t *pBuf) * * \param type Type of message. * \param pBuf Pointer to transmitted message. - * - * \return None. */ /*************************************************************************************************/ void lhciSendComplete(uint8_t type, uint8_t *pBuf) @@ -245,11 +250,19 @@ void lhciSendComplete(uint8_t type, uint8_t *pBuf) WsfMsgFree(pBuf); break; - case CHCI_TR_TYPE_DATA: + case CHCI_TR_TYPE_ACL: WsfMsgFree(pBuf); LlRecvAclDataComplete(1); break; +#if (BT_VER >= LL_VER_BT_CORE_SPEC_5_2) + /* TODO: Use function pointer to allow run time configuration of supported versions. */ + case CHCI_TR_TYPE_ISO: + WsfMsgFree(pBuf); + LlRecvIsoDataComplete(1); + break; +#endif + default: break; } @@ -294,14 +307,13 @@ bool_t lhciService(uint8_t *pType, uint16_t *pLen, uint8_t **pBuf) /* Additionally check if ISO data needs servicing. */ if ((pBufTemp = lhciServiceIso()) != NULL) { + BYTES_TO_UINT16(len, &pBufTemp[2]); + len += HCI_ISO_HDR_LEN; - len = pBufTemp[2] + HCI_ISO_HDR_LEN; lhciPersistCb.evtTrPending = TRUE; - *pType = CHCI_TR_TYPE_ISO; *pLen = len; *pBuf = pBufTemp; - return TRUE; } } @@ -315,7 +327,7 @@ bool_t lhciService(uint8_t *pType, uint16_t *pLen, uint8_t **pBuf) len += HCI_ACL_HDR_LEN; lhciPersistCb.evtTrPending = TRUE; - *pType = CHCI_TR_TYPE_DATA; + *pType = CHCI_TR_TYPE_ACL; *pLen = len; *pBuf = pBufTemp; return TRUE; @@ -332,8 +344,6 @@ bool_t lhciService(uint8_t *pType, uint16_t *pLen, uint8_t **pBuf) * \brief Signal transport hardware error. * * \param code Error code. - * - * \return None. */ /*************************************************************************************************/ void lhciSendHwError(uint8_t code) @@ -346,8 +356,6 @@ void lhciSendHwError(uint8_t code) /*! * \brief Reset HCI state. * - * \return None. - * * This function is called at the end of a HCI reset. */ /*************************************************************************************************/ @@ -364,12 +372,12 @@ void lhciReset(void) /*! * \brief Set default Hci supported cmds. * - * \return None. + * \param pBuf Buffer to set supported commands. * * This function is called at reset by lmgr. */ /*************************************************************************************************/ -void LhciSetDefaultHciSupCmd(uint8_t *pBuf) +static void LhciSetDefaultHciSupCmd(uint8_t *pBuf) { pBuf[5] = HCI_SUP_SET_EVENT_MASK | /* mandatory */ HCI_SUP_RESET; /* mandatory */ @@ -390,6 +398,8 @@ 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[44] = HCI_SUP_LE_SET_HOST_FEATURE; /* v5.2 */ + pBuf[45] = HCI_SUP_LE_TRANSMITTER_TEST_V4; /* v5.2 */ pBuf[38] = HCI_SUP_LE_READ_TX_POWER; /* mandatory (5.0) */ if (lhciCmdTbl[LHCI_MSG_CONN]) @@ -531,24 +541,82 @@ void LhciSetDefaultHciSupCmd(uint8_t *pBuf) if (lhciCmdTbl[LHCI_MSG_CIS_MST]) { - pBuf[42] |= HCI_SUP_LE_READ_BUF_SIZE_V2 | /* Isochronous stream master */ - HCI_SUP_LE_SET_CIG_PARAM | /* Isochronous stream master */ - HCI_SUP_LE_CREATE_CIS | /* Isochronous stream master */ - HCI_SUP_LE_REMOVE_CIG; /* Isochronous stream master */ - - pBuf[44] |= HCI_SUP_LE_SETUP_ISO_DATA_PATH | /* Isochronous stream master */ - HCI_SUP_LE_REMOVE_ISO_DATA_PATH | /* Isochronous stream master */ - HCI_SUP_LE_REQ_PEER_SCA; /* Isochronous stream master */ + pBuf[41] |= HCI_SUP_LE_SET_CIG_PARAM; /* ISO CIS master */ + pBuf[42] |= HCI_SUP_LE_SET_CIG_PARAM_TEST | /* ISO CIS master */ + HCI_SUP_LE_CREATE_CIS | /* ISO CIS master */ + HCI_SUP_LE_REMOVE_CIG; /* ISO CIS master */ } if (lhciCmdTbl[LHCI_MSG_CIS_SLV]) { - pBuf[42] |= HCI_SUP_LE_READ_BUF_SIZE_V2 | /* Isochronous stream master */ - HCI_SUP_LE_ACCEPT_CIS_REQ | /* Isochronous stream master */ - HCI_SUP_LE_REJECT_CIS_REQ; /* Isochronous stream master */ + pBuf[42] |= HCI_SUP_LE_ACCEPT_CIS_REQ | /* ISO CIS slave */ + HCI_SUP_LE_REJECT_CIS_REQ; /* ISO CIS slave */ + } - pBuf[44] |= HCI_SUP_LE_SETUP_ISO_DATA_PATH | /* Isochronous stream master */ - HCI_SUP_LE_REMOVE_ISO_DATA_PATH | /* Isochronous stream master */ - HCI_SUP_LE_REQ_PEER_SCA; /* Isochronous stream master */ + if (lhciCmdTbl[LHCI_MSG_BIS_MST]) + { + pBuf[43] |= HCI_SUP_LE_BIG_CREATE_SYNC | /* ISO BIS master */ + HCI_SUP_LE_BIG_TERMINATE_SYNC; /* ISO BIS master */ + } + + if (lhciCmdTbl[LHCI_MSG_BIS_SLV]) + { + pBuf[42] |= HCI_SUP_LE_CREATE_BIG | /* ISO BIS slave */ + HCI_SUP_LE_CREATE_BIG_TEST | /* ISO BIS slave */ + HCI_SUP_LE_TERMINATE_BIG; /* ISO BIS slave */ + } + + if (lhciCmdTbl[LHCI_MSG_ISO]) + { + 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 */ + HCI_SUP_LE_REMOVE_ISO_DATA_PATH | /* ISO */ + HCI_SUP_LE_REQ_PEER_SCA; /* ISO */ + + pBuf[43] |= HCI_SUP_LE_ISO_TRANSMIT_TEST | /* ISO */ + HCI_SUP_LE_ISO_RECEIVE_TEST | /* ISO */ + HCI_SUP_LE_ISO_READ_TEST_COUNTERS; /* ISO */ + pBuf[44] |= HCI_SUP_LE_ISO_TEST_END | /* ISO */ + HCI_SUP_LE_READ_ISO_LINK_QUALITY; /* ISO */ + + pBuf[45] |= HCI_SUP_READ_LOCAL_SUP_CODECS_V2 | /* ISO */ + HCI_SUP_READ_LOCAL_SUP_CODEC_CAP | /* ISO */ + HCI_SUP_READ_LOCAL_SUP_CTR_DLY | /* ISO */ + HCI_SUP_CONFIG_DATA_PATH; /* ISO */ + } + + if (lhciCmdTbl[LHCI_MSG_PC]) + { + pBuf[44] |= HCI_SUP_LE_ENH_READ_TX_POWER_LEVEL | /* LEPC */ + HCI_SUP_LE_READ_REMOTE_TX_POWER_LEVEL | /* LEPC */ + HCI_SUP_LE_SET_PATH_LOSS_REPORT_PARAM | /* LEPC */ + HCI_SUP_LE_SET_PATH_LOSS_REPORT_PARAM | /* LEPC */ + HCI_SUP_LE_SET_PATH_LOSS_REPORT_ENABLE | /* LEPC */ + HCI_SUP_LE_SET_TX_POWER_REPORT_ENABLE; /* LEPC */ } } + +/*************************************************************************************************/ +/*! + * \brief Finalize HCI initialization. + * + * Called after all specific initializers. + */ +/*************************************************************************************************/ +void LhciInitFinalize(void) +{ + LhciSetDefaultHciSupCmd(lhciPersistCb.supCmds); +} + +/*************************************************************************************************/ +/*! + * \brief Register an event complete callback. + * + * \param compCback Event completion callback. + */ +/*************************************************************************************************/ +void LhciRegisterSendTrCompleteHandler(lhciCompHandler_t compCback) +{ + lhciCb.evtCompCback = compCback; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_main_iso.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_main_iso.c new file mode 100644 index 0000000000..a5e2bfec05 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lhci/lhci_main_iso.c @@ -0,0 +1,62 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) Host Controller Interface (HCI) initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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 "lhci_int.h" +#include "chci_api.h" +#include "hci_defs.h" +#include "ll_api.h" +#include "bb_api.h" +#include "pal_bb.h" +#include "wsf_assert.h" +#include "wsf_msg.h" +#include "util/bstream.h" +#include + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief LL HCI message dispatch handler. + * + * \param event WSF event. + * \param pMsg WSF message. + */ +/*************************************************************************************************/ +void LhciIsoHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) +{ + if (event & LHCI_EVT_ISO_RCVD) + { + uint8_t *pIsoBuf; + wsfHandlerId_t handlerId; + + while ((pIsoBuf = WsfMsgDeq(&lhciPersistCb.isoQ, &handlerId)) != NULL) + { + LlSendIsoData(pIsoBuf); + } + } + + LhciHandler(event, pMsg); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init.c index 88d0504ff6..fd9479ae50 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) slave initialization implementation file. + * \file + * + * \brief Link layer (LL) slave initialization implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -46,8 +47,6 @@ static uint16_t llHandlerWatermarkUsec = 0; * * \param pCfg Pointer to runtime configuration parameters. * - * \return None. - * * This function returns default value for the LL subsystem's runtime configurations. */ /*************************************************************************************************/ @@ -57,7 +56,7 @@ void LlGetDefaultRunTimeCfg(LlRtCfg_t *pCfg) const LlRtCfg_t defCfg = { /* Device */ - .compId = LL_COMP_ID_ARM, + .compId = HCI_ID_PACKETCRAFT, .implRev = LL_VER_NUM >> 16, .btVer = LL_VER_BT_CORE_SPEC_4_2, /* Advertiser */ @@ -80,10 +79,13 @@ void LlGetDefaultRunTimeCfg(LlRtCfg_t *pCfg) /* ISO */ .numIsoTxBuf = 0, .numIsoRxBuf = 0, - .maxIsoBufLen = 0, + .maxIsoSduLen = 0, .maxIsoPduLen = 0, + .maxCig = 0, .maxCis = 0, /* Disable CIS. */ - .subEvtSpaceDelay = 0, + .cisSubEvtSpaceDelay= 0, + .maxBig = 0, + .maxBis = 0, /* DTM */ .dtmRxSyncMs = 10000, /* PHY */ @@ -102,8 +104,6 @@ void LlGetDefaultRunTimeCfg(LlRtCfg_t *pCfg) * * \param pCfg Pointer to runtime configuration parameters (data must be static). * - * \return None. - * * This function initializes the LL subsystem's runtime configuration. * * \note This routine must be called only once before any other initialization routines. @@ -133,8 +133,6 @@ void LlInitRunTimeCfg(const LlRtCfg_t *pCfg) * * \param handlerId WSF handler ID. * - * \return None. - * * This function initializes the LL subsystem. It is called once upon system initialization. * It must be called before any other function in the LL API is called. */ @@ -169,7 +167,7 @@ void LlHandlerInit(wsfHandlerId_t handlerId) LlTestInit(); - LL_TRACE_INFO1(" opModeFlags = 0x%08x", lmgrCb.opModeFlags); + LL_TRACE_INFO1(" opModeFlags = 0x%08x", lmgrCb.opModeFlags); } /*************************************************************************************************/ @@ -178,8 +176,6 @@ void LlHandlerInit(wsfHandlerId_t handlerId) * * \param event WSF event. * \param pMsg WSF message. - * - * \return None. */ /*************************************************************************************************/ void LlHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) @@ -188,7 +184,11 @@ void LlHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) uint32_t startTime; uint32_t endTime; - startTimeValid = PalBbGetTimestamp(&startTime); + startTimeValid = PalBbGetTimestamp(NULL); + if (startTimeValid) + { + startTime = PalBbGetCurrentTime(); + } if (event != 0) { @@ -208,9 +208,10 @@ void LlHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) } if (startTimeValid && - PalBbGetTimestamp(&endTime)) + PalBbGetTimestamp(NULL)) { - uint32_t durUsec = BB_TICKS_TO_US(endTime - startTime); + endTime = PalBbGetCurrentTime(); + uint32_t durUsec = BbGetTargetTimeDelta(endTime, startTime); if (llHandlerWatermarkUsec < durUsec) { llHandlerWatermarkUsec = durUsec; @@ -223,8 +224,6 @@ void LlHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) /*! * \brief Reset LL subsystem. * - * \return None. - * * Reset the LL subsystem. All active connections are closed and all radio procedures such as * scanning or advertising are terminated. */ @@ -252,8 +251,6 @@ void LlReset(void) * * \param evtCback Client callback function. * - * \return None. - * * This function is called by a client to register for LL events. */ /*************************************************************************************************/ @@ -314,8 +311,8 @@ void LlGetConnContextSize(uint8_t *pMaxConn, uint16_t *pConnCtxSize) /*! * \brief Get extended scanner context size. * - * \param pMaxPerScan Buffer to return the maximum number of extended scanners. - * \param pPerScanCtxSize Buffer to return the size in bytes of the extended scanner context. + * \param pMaxExtScan Buffer to return the maximum number of extended scanners. + * \param pExtScanCtxSize Buffer to return the size in bytes of the extended scanner context. * * Return the advertising set context sizes. */ @@ -331,8 +328,8 @@ void LlGetExtScanContextSize(uint8_t *pMaxExtScan, uint16_t *pExtScanCtxSize) /*! * \brief Get extended initiator context size. * - * \param pMaxPerScan Buffer to return the maximum number of extended initiators. - * \param pPerScanCtxSize Buffer to return the size in bytes of the extended initiator context. + * \param pMaxExtInit Buffer to return the maximum number of extended initiators. + * \param pExtInitCtxSize Buffer to return the size in bytes of the extended initiator context. * * Return the advertising set context sizes. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_adv_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_adv_master.c index f2d3d26d75..ea93c8ada9 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_adv_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_adv_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) master initialization implementation file. + * \file + * + * \brief Link layer (LL) master initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -30,8 +31,6 @@ /*! * \brief Initialize LL subsystem for operation as an scanning master. * - * \return None. - * * This function initializes the LL subsystem for use as an scanning master. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_adv_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_adv_master_ae.c index 977eceb219..2ede064632 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_adv_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_adv_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) master initialization implementation file. + * \file + * + * \brief Link layer (LL) master initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -53,8 +54,6 @@ uint16_t LlInitExtScanMem(uint8_t *pFreeMem, uint32_t freeMemSize) /*! * \brief Initialize LL subsystem for operation as an scanning master. * - * \return None. - * * This function initializes the LL subsystem for use as an scanning master. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_adv_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_adv_slave.c index 36ad002331..cab593267c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_adv_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_adv_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) slave initialization implementation file. + * \file + * + * \brief Link layer (LL) slave initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -30,8 +31,6 @@ /*! * \brief Initialize LL subsystem for operation as an advertising slave. * - * \return None. - * * This function initializes the LL subsystem for use as an advertising slave. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_adv_slave_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_adv_slave_ae.c index bb575a63ca..9aa264f78b 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_adv_slave_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_adv_slave_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) slave initialization implementation file. + * \file + * + * \brief Link layer (LL) slave initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -59,8 +60,6 @@ uint16_t LlInitExtAdvMem(uint8_t *pFreeMem, uint32_t freeMemSize) /*! * \brief Initialize LL subsystem for operation for extended advertising slave. * - * \return None. - * * This function initializes the LL subsystem for use as an extended advertising slave. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_bis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_bis_master.c new file mode 100644 index 0000000000..d88f596601 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_bis_master.c @@ -0,0 +1,42 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) slave initialization implementation file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_api_bis_master.h" +#include "lmgr_api_iso.h" +#include "wsf_assert.h" + +/*************************************************************************************************/ +/*! + * \brief Initialize LL subsystem for operation for slave broadcast isochronous stream. + * + * This function initializes the LL subsystem for use as a slave broadcast isochronous stream. + */ +/*************************************************************************************************/ +void LlBisMasterInit(void) +{ + WSF_ASSERT(pLctrRtCfg); /* Runtime configuration must be available. */ + + LmgrIsoInit(); + LctrMstBisInit(); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_bis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_bis_slave.c new file mode 100644 index 0000000000..d92480e179 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_bis_slave.c @@ -0,0 +1,71 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) slave initialization implementation file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_api_bis_slave.h" +#include "lmgr_api_iso.h" +#include "wsf_assert.h" + +/*************************************************************************************************/ +/*! + * \brief Initialize memory for BIS. + * + * \param pFreeMem Pointer to free memory. + * \param freeMemSize Size of pFreeMem. + * + * \return Amount of free memory consumed. + * + * This function allocates memory for BIS slave. + * + * \note This routine must be called after LlInitRunTimeCfg() but only once before any + * other initialization routines. + */ +/*************************************************************************************************/ +uint16_t LlInitBisMem(uint8_t *pFreeMem, uint32_t freeMemSize) +{ + WSF_ASSERT(pLctrRtCfg); + WSF_ASSERT(pFreeMem); + + uint16_t bytesUsed = 0; + +#if (LL_MAX_BIG > 0) + bytesUsed = LctrInitBisMem(pFreeMem, freeMemSize); +#endif + + return bytesUsed; +} + +/*************************************************************************************************/ +/*! + * \brief Initialize LL subsystem for operation for slave broadcast isochronous stream. + * + * This function initializes the LL subsystem for use as a slave broadcast isochronous stream. + */ +/*************************************************************************************************/ +void LlBisSlaveInit(void) +{ + WSF_ASSERT(pLctrRtCfg); /* Runtime configuration must be available. */ + + LmgrIsoInit(); + LctrSlvBisInit(); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_cis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_cis_master.c new file mode 100644 index 0000000000..293c02ada6 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_cis_master.c @@ -0,0 +1,45 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) master initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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 "lmgr_api_iso.h" +#include "ll_api.h" +#include "lmgr_api_cis_master.h" +#include "lctr_api_cis_master.h" +#include "wsf_assert.h" + +/*************************************************************************************************/ +/*! + * \brief Initialize LL subsystem for operation for master connected isochronous stream. + * + * This function initializes the LL subsystem for use as a master connected isochronous stream. + */ +/*************************************************************************************************/ +void LlCisMasterInit(void) +{ + WSF_ASSERT(pLctrRtCfg); /* Runtime configuration must be available. */ + + LmgrIsoInit(); + LmgrMstCisInit(); + LctrMstCisInit(); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_cis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_cis_slave.c new file mode 100644 index 0000000000..c7c8aac7ae --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_cis_slave.c @@ -0,0 +1,73 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) slave initialization implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "ll_api.h" +#include "lctr_api_cis_slave.h" +#include "lctr_api_cis.h" +#include "lmgr_api_iso.h" +#include "wsf_assert.h" + +/*************************************************************************************************/ +/*! + * \brief Initialize memory for CIS. + * + * \param pFreeMem Pointer to free memory. + * \param freeMemSize Size of pFreeMem. + * + * \return Amount of free memory consumed. + * + * This function allocates memory for CIS slave. + * + * \note This routine must be called after LlInitRunTimeCfg() but only once before any + * other initialization routines. + */ +/*************************************************************************************************/ +uint16_t LlInitCisMem(uint8_t *pFreeMem, uint32_t freeMemSize) +{ + WSF_ASSERT(pLctrRtCfg); + WSF_ASSERT(pFreeMem); + + uint16_t bytesUsed = 0; + +#if (LL_MAX_CIS > 0) + bytesUsed = LctrInitCisMem(pFreeMem, freeMemSize); +#endif + + return bytesUsed; +} + +/*************************************************************************************************/ +/*! + * \brief Initialize LL subsystem for operation for slave connected isochronous stream. + * + * This function initializes the LL subsystem for use as a slave connected isochronous stream. + */ +/*************************************************************************************************/ +void LlCisSlaveInit(void) +{ + WSF_ASSERT(pLctrRtCfg); /* Runtime configuration must be available. */ + + LmgrIsoInit(); + LctrCisSlvInit(); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_conn_cs2.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_conn_cs2.c index 4c67082597..86d5df4b61 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_conn_cs2.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_conn_cs2.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) channel selection 2 initialization implementation file. + * \file + * + * \brief Link layer (LL) channel selection 2 initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -27,8 +28,6 @@ /*! * \brief Initialize LL subsystem for secure connections. * - * \return None. - * * This function initializes the LL subsystem for secure connections. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_conn_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_conn_master.c index 2cc3faf85d..807845a1a4 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_conn_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_conn_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) master initialization implementation file. + * \file + * + * \brief Link layer (LL) master initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -31,8 +32,6 @@ /*! * \brief Initialize LL subsystem for operation as a connectable master. * - * \return None. - * * This function initializes the LL subsystem for use as an advertising and connectable master. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_conn_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_conn_slave.c index a6da257b91..4138a4da43 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_conn_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_conn_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) slave initialization implementation file. + * \file + * + * \brief Link layer (LL) slave initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -60,8 +61,6 @@ uint16_t LlInitConnMem(uint8_t *pFreeMem, uint32_t freeMemSize) /*! * \brief Initialize LL subsystem for operation as a connectable slave. * - * \return None. - * * This function initializes the LL subsystem for use as an advertising and connectable slave. */ /*************************************************************************************************/ @@ -80,8 +79,6 @@ void LlConnSlaveInit(void) * \param sendCompCback Client ACL send complete callback function. * \param recvPendCback Client ACL receive pending callback function. * - * \return None. - * * This function is called by a client to register for ACL data. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_enc_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_enc_master.c index 6e6498a292..6316bbac74 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_enc_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_enc_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) encryptable master initialization implementation file. + * \file + * + * \brief Link layer (LL) encryptable master initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -31,8 +32,6 @@ /*! * \brief Initialize LL subsystem for operation as a encryptable connectable master. * - * \return None. - * * This function initializes the LL subsystem for use as an advertising and encryptable * connectable master. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_enc_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_enc_slave.c index e02dc1b628..2d70ac8a22 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_enc_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_enc_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) encryptable slave initialization implementation file. + * \file + * + * \brief Link layer (LL) encryptable slave initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -31,8 +32,6 @@ /*! * \brief Initialize LL subsystem for operation as a encryptable connectable slave. * - * \return None. - * * This function initializes the LL subsystem for use as an advertising and encryptable * connectable slave. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_init_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_init_master.c index f5f0e7db1d..633251a2d9 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_init_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_init_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) master initialization implementation file. + * \file + * + * \brief Link layer (LL) master initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -29,8 +30,6 @@ /*! * \brief Initialize LL subsystem for operation as an initiating master. * - * \return None. - * * This function initializes the LL subsystem for use as an initiating master. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_init_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_init_master_ae.c index e30a98883d..1d01bcacf5 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_init_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_init_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) master initialization implementation file. + * \file + * + * \brief Link layer (LL) master initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -29,8 +30,6 @@ /*! * \brief Initialize LL subsystem for operation as an initiating master. * - * \return None. - * * This function initializes the LL subsystem for use as an initiating master. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_iso.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_iso.c new file mode 100644 index 0000000000..2a8f3ddaa3 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_iso.c @@ -0,0 +1,70 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) slave initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_api_iso.h" +#include "lmgr_api.h" +#include "lctr_api.h" +#include "wsf_assert.h" + +/*************************************************************************************************/ +/*! + * \brief Register ISO handler. + * + * \param sendIsoCompCback Client ISO send complete callback function. + * \param recvIsoPendCback Client ISO receive pending callback function. + * + * This function is called by a client to register for ACL data. + */ +/*************************************************************************************************/ +void LlIsoRegister(llIsoCback_t sendIsoCompCback, llIsoCback_t recvIsoPendCback) +{ + lmgrPersistCb.sendIsoCompCback = sendIsoCompCback; + lmgrPersistCb.recvIsoPendCback = recvIsoPendCback; +} + +/*************************************************************************************************/ +/*! + * \brief Initialize memory for ISO. + * + * \param pFreeMem Pointer to free memory. + * \param freeMemSize Size of pFreeMem. + * + * \return Amount of free memory consumed. + * + * This function allocates memory for CIS slave. + * + * \note This routine must be called after LlInitRunTimeCfg() but only once before any + * other initialization routines. + */ +/*************************************************************************************************/ +uint16_t LlInitIsoMem(uint8_t *pFreeMem, uint32_t freeMemSize) +{ + WSF_ASSERT(pLctrRtCfg); + WSF_ASSERT(pFreeMem); + + uint16_t bytesUsed = 0; + + bytesUsed = LctrInitIsoMem(pFreeMem, freeMemSize); + + return bytesUsed; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_master_phy.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_master_phy.c index 76d08b2727..5d173d9e2d 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_master_phy.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_master_phy.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) PHY features initialization implementation file. + * \file + * + * \brief Link layer (LL) PHY features initialization implementation file. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -29,8 +30,6 @@ /*! * \brief Initialize LL subsystem for PHY features (master). * - * \return None. - * * This function initializes the LL subsystem for master PHY features. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_past.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_past.c index 94a75312cb..119554dfba 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_past.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_past.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) master initialization implementation file. + * \file + * + * \brief Link layer (LL) master initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -29,8 +30,6 @@ /*! * \brief Initialize LL subsystem for PAST(Periodic advertising sync transfer). * - * \return None. - * * This function initializes the LL subsystem for PAST(Periodic advertising sync transfer). */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_pc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_pc.c new file mode 100644 index 0000000000..2b31cc085b --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_pc.c @@ -0,0 +1,39 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) power control initialization implementation 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. + */ +/*************************************************************************************************/ + +#include "lctr_api_pc.h" +#include "ll_api.h" +#include "lhci_api.h" +#include "wsf_assert.h" + +/*************************************************************************************************/ +/*! + * \brief Initialize LL subsystem for operation for power control. + * + * This function initializes the LL subsystem for power control. + */ +/*************************************************************************************************/ +void LlPowerControlInit(void) +{ + LhciPowerControlInit(); + LctrPowerControlInit(); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_priv.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_priv.c index 5e61d3b6e2..aa55be5a07 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_priv.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_priv.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) privacy initialization implementation file. + * \file + * + * \brief Link layer (LL) privacy initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -29,8 +30,6 @@ /*! * \brief Initialize LL subsystem for operation as an advertising slave. * - * \return None. - * * This function initializes the LL subsystem for use as an advertising slave. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_sc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_sc.c index 115551f3c9..ba881f75a6 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_sc.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_sc.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) secure connections initialization implementation file. + * \file + * + * \brief Link layer (LL) secure connections initialization implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -30,8 +31,6 @@ /*! * \brief Initialize LL subsystem for secure connections. * - * \return None. - * * This function initializes the LL subsystem for secure connections. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_slave_phy.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_slave_phy.c index 0532e929be..0cbf0d2b61 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_slave_phy.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_init_slave_phy.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) PHY features initialization implementation file. + * \file + * + * \brief Link layer (LL) PHY features initialization implementation file. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -29,8 +30,6 @@ /*! * \brief Initialize LL subsystem for PHY features (slave). * - * \return None. - * * This function initializes the LL subsystem for slave PHY features. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main.c index 9e1e2feb82..284369d985 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) slave parameter interface implementation file. + * \file + * + * \brief Link layer (LL) slave parameter interface implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -50,8 +51,8 @@ /*! \brief Check if periodic adv is enabled (ae functionality). */ LctrIsPerAdvEnabledFn_t LctrPerAdvEnabled; /*!< Lctr Per Adv Enabled check function (defined if AE supported). */ -/*! \brief Check if periodic adv is enabled (ae functionality). */ -LctrIsPerAdvEnabledFn_t LctrPerAdvEnabled; /*!< Lctr Per Adv Enabled check function (defined if AE supported). */ +/*! \brief Update the channel map for CIS. */ +LctrUpdateCisChanMapFn_t LctrUpdateCisChanMapFn; /*!< Lctr Per Adv Enabled check function (defined if AE supported). */ /*! \brief Check is Ext Scan is enabled (ae functionality). */ LctrExtCheckFn_t LctrMstExtScanEnabled; @@ -65,8 +66,6 @@ LctrExtCheckFn_t LctrMstExtInitEnabled; * * \param pAddr Bluetooth device address. * - * \return None. - * * Set the BD address to be used by LL. */ /*************************************************************************************************/ @@ -86,8 +85,6 @@ void LlSetBdAddr(const uint8_t *pAddr) * * \param pAddr Bluetooth device address. * - * \return None. - * * Get the BD address currently used by LL or all zeros if address is not set. */ /*************************************************************************************************/ @@ -230,8 +227,6 @@ uint8_t LlGetRandAddr(uint8_t *pAddr) * \param pCompId Company ID. * \param pBtVer Bluetooth version. * \param pImplRev Implementation revision. - * - * \return None. */ /*************************************************************************************************/ void LlGetVersion(uint16_t *pCompId, uint8_t *pBtVer, uint16_t *pImplRev) @@ -249,8 +244,6 @@ void LlGetVersion(uint16_t *pCompId, uint8_t *pBtVer, uint16_t *pImplRev) * * \param pStates Supported states bitmask. * - * \return None. - * * Return the states supported by the LL. */ /*************************************************************************************************/ @@ -269,8 +262,6 @@ void LlGetSupStates(uint8_t *pStates) * * \param pFeatures Supported features bitmask. * - * \return None. - * * Return the LE features supported by the LL. */ /*************************************************************************************************/ @@ -352,6 +343,7 @@ uint8_t LlSetOpFlags(uint32_t flags, bool_t enable) 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; @@ -517,6 +509,38 @@ uint8_t LlRemoveDeviceFromWhitelist(uint8_t addrType, bdAddr_t pAddr) return LL_SUCCESS; } +/*************************************************************************************************/ +/*! + * \brief Set host feature. + * + * \param bitNum Bit position in the FeatureSet. + * \param bitVal Enable or disable feature. + * + * \return Status error code. + * + * Set or clear a bit in the feature controlled by the Host in the Link Layer FeatureSet + * stored in the Controller. + */ +/*************************************************************************************************/ +uint8_t LlSetHostFeatures(uint8_t bitNum, bool_t bitVal) +{ + LL_TRACE_INFO2("### LlApi ### LlSetHostFeatures, Bit=%d Value=%d", bitNum, bitVal); + + if ((LL_HOST_CONTROLLED_FEAT & (UINT64_C(1) << bitNum)) == 0) + { + return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; + } + + if (lmgrCb.numConnEnabled) + { + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + lmgrCb.features = (lmgrCb.features & ~(UINT64_C(1) << bitNum)) | (((uint64_t) bitVal) << bitNum); + + return LL_SUCCESS; +} + /*************************************************************************************************/ /*! * \brief Get random number. @@ -547,8 +571,6 @@ uint8_t LlGetRandNum(uint8_t *pRandNum) * \param pMinTxPwr Return buffer for minimum transmit power. * \param pMaxTxPwr Return buffer for maximum transmit power. * - * \return None. - * * Read the minimum and maximum transmit powers supported by the LL. */ /*************************************************************************************************/ @@ -566,8 +588,6 @@ void LlReadSupTxPower(int8_t *pMinTxPwr, int8_t *pMaxTxPwr) * \param pTxPathComp Return buffer for RF transmit path compensation value. * \param pRxPathComp Return buffer for RF receive path compensation value. * - * \return None. - * * Read the RF Path Compensation Values parameter used in the Tx Power Level and RSSI calculation. */ /*************************************************************************************************/ @@ -617,9 +637,7 @@ uint8_t LlWriteRfPathComp(int16_t txPathComp, int16_t rxPathComp) /*************************************************************************************************/ uint8_t LlSetChannelClass(const uint8_t *pChanMap) { - lctrChanMapUpdate_t *pMsg; uint64_t chanMap; - uint16_t handle; LL_TRACE_INFO0("### LlApi ### LlSetChannelClass"); @@ -632,70 +650,5 @@ uint8_t LlSetChannelClass(const uint8_t *pChanMap) return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; } - lmgrCb.chanClass = chanMap; - - /* Update for connections */ - for (handle = 0; handle < pLctrRtCfg->maxConn; handle++) - { - if ((LctrIsConnHandleEnabled(handle)) && - (LctrGetRole(handle) == LL_ROLE_MASTER)) - { - if (LctrIsProcActPended(handle, LCTR_CONN_MSG_API_CHAN_MAP_UPDATE) == TRUE) - { - return 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); - } - } - } - - /* If periodic advertising is not included, return here. */ - if (LctrPerAdvEnabled) - { - /* Update for periodic adv sets */ - for(uint8_t perAdvHandle = 0; perAdvHandle < pLctrRtCfg->maxAdvSets; perAdvHandle++) - { - if (LctrPerAdvEnabled(perAdvHandle) == TRUE) - { - if ((pMsg = (lctrChanMapUpdate_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) - { - pMsg->hdr.handle = (uint16_t) perAdvHandle; - pMsg->hdr.dispId = LCTR_DISP_ACAD; - pMsg->hdr.event = LCTR_ACAD_MSG_CHAN_UPDATE; - pMsg->chanMap = chanMap; - - WsfMsgSend(lmgrPersistCb.handlerId, pMsg); - } - } - } - } - - return LL_SUCCESS; -} - -/*************************************************************************************************/ -/*! - * \brief Set Hci supported command - * - * \param byte Byte location of command - * \param bit Bit location of command - * \param enable Enable or disable command - * - * \return Status error code - * - */ -/*************************************************************************************************/ -uint8_t LlSetHciSupCmd(uint8_t byte, uint8_t bit, bool_t enable) -{ - lmgrCb.hciSupCommands[byte] = ((lmgrCb.hciSupCommands[byte] & ~(1 << bit)) | ((uint8_t) enable << bit)); - return LL_SUCCESS; + return LctrSetChannelClass(chanMap); } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_master.c index fa64d7114b..2469c29e85 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) master parameter interface implementation file. + * \file + * + * \brief Link layer (LL) master parameter interface implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -130,8 +131,6 @@ uint8_t LlSetScanParam(const LlScanParam_t *pParam) * \param enable Set to TRUE to enable scanning, FALSE to disable scanning. * \param filterDup Set to TRUE to filter duplicates. * - * \return None. - * * Enable or disable scanning. This function is only used when operating in master role. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_master_ae.c index d600883cce..8d0aa0eed5 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) master control interface implementation file. + * \file + * + * \brief Link layer (LL) master control interface implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -159,8 +160,6 @@ uint8_t LlSetExtScanParam(uint8_t ownAddrType, uint8_t scanFiltPolicy, uint8_t s * \param duration Duration. * \param period Period. * - * \return None. - * * Enable or disable extended scanning. */ /*************************************************************************************************/ @@ -190,23 +189,31 @@ void LlExtScanEnable(uint8_t enable, uint8_t filterDup, uint16_t duration, uint1 } if ((LL_API_PARAM_CHECK == 1) && - ((enable != 0) && - ((filterDup > filterDupMax) || - ((perMs > 0) && (durMs == 0)) || /* Minimum Duration is 1. */ - ((perMs > 0) && (perMs <= durMs))))) /* Ensure Period > Duration. */ + (enable == TRUE)) { - lmgrCb.extScanEnaDelayCnt = 1; - LmgrSendExtScanEnableCnf(LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS); - return; - } + if (filterDup > filterDupMax) + { + lmgrCb.extScanEnaDelayCnt = 1; + LmgrSendExtScanEnableCnf(LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS); + return; + } - if ((LL_API_PARAM_CHECK == 1) && - ((enable != 0) && - ((filterDup == LL_SCAN_FILTER_DUP_ENABLE_PERIODIC) && ((duration == 0) || (period == 0))))) - { - lmgrCb.extScanEnaDelayCnt = 1; - LmgrSendExtScanEnableCnf(LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS); - return; + if ((filterDup == LL_SCAN_FILTER_DUP_ENABLE_PERIODIC) && + ((perMs == 0) || (durMs == 0))) + { + lmgrCb.extScanEnaDelayCnt = 1; + LmgrSendExtScanEnableCnf(LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS); + return; + } + + /* Ensure period > duration. */ + if (((perMs != 0) && (durMs != 0)) && + (durMs >= perMs)) + { + lmgrCb.extScanEnaDelayCnt = 1; + LmgrSendExtScanEnableCnf(LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS); + return; + } } if ((LL_API_PARAM_CHECK == 1) && @@ -277,12 +284,6 @@ uint8_t LlPeriodicAdvCreateSync(const LlPerAdvCreateSyncCmd_t *pParam) return LL_ERROR_CODE_MEM_CAP_EXCEEDED; } - /* If reporting is initially disabled and controller does not support LE_Set_Per_Adv_Rcv_En cmd, return error. */ - if (((pParam->options >> 1) & 0x01) && !(lmgrCb.hciSupCommands[40] & HCI_SUP_LE_SET_PER_ADV_RCV_ENABLE)) - { - return LL_ERROR_CODE_CONN_FAILED_TO_ESTABLISH; - } - lctrPerCreateSyncMsg_t *pMsg; if ((pMsg = WsfMsgAlloc(sizeof(*pMsg))) != NULL) @@ -359,6 +360,7 @@ uint8_t LlPeriodicAdvTerminateSync(uint16_t syncHandle) LL_TRACE_WARN0("Legacy Advertising/Scanning operation enabled; extended commands not available"); return LL_ERROR_CODE_CMD_DISALLOWED; } + if ((LL_API_PARAM_CHECK == 1) && syncHandle > LL_SYNC_MAX_HANDLE) { @@ -426,6 +428,12 @@ uint8_t LlAddDeviceToPeriodicAdvList(const LlDevicePerAdvList_t *pParam) } uint64_t addr = BstreamToBda64(pParam->pAdvAddr); + + if (BbBlePeriodicListCheckAddr(pParam->advAddrType, addr, pParam->advSID)) + { + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + if (!BbBlePeriodicListAdd(pParam->advAddrType, addr, pParam->advSID)) { return LL_ERROR_CODE_MEM_CAP_EXCEEDED; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_slave.c index b9e0dbe25c..f00155c520 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) slave parameter interface implementation file. + * \file + * + * \brief Link layer (LL) slave parameter interface implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -42,8 +43,6 @@ * * \param advTxPwr Advertising transmit power level. * - * \return None. - * * Set the advertising transmit power. */ /*************************************************************************************************/ @@ -151,8 +150,8 @@ uint8_t LlSetAdvParam(uint16_t advIntervalMin, uint16_t advIntervalMax, uint8_t pMsg->hdr.dispId = LCTR_DISP_ADV; pMsg->hdr.event = LCTR_ADV_MSG_PARAM_UPD; - pMsg->param.advInterMin = BB_BLE_TO_BB_TICKS(advIntervalMin); - pMsg->param.advInterMax = BB_BLE_TO_BB_TICKS(advIntervalMax); + pMsg->param.advInterMinUsec = BB_BLE_TO_US(advIntervalMin); + pMsg->param.advInterMaxUsec = BB_BLE_TO_US(advIntervalMax); pMsg->param.advType = advType; pMsg->param.ownAddrType = ownAddrType; pMsg->param.peerAddrType = peerAddrType; @@ -251,8 +250,6 @@ uint8_t LlSetScanRespData(uint8_t len, const uint8_t *pData) * * \param enable Set to TRUE to enable advertising, FALSE to disable advertising. * - * \return None. - * * Enable or disable advertising. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_slave_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_slave_ae.c index 4b238a4d6f..b644cad744 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_slave_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_adv_slave_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) master control interface implementation file. + * \file + * + * \brief Link layer (LL) master control interface implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -61,12 +62,12 @@ uint8_t LlSetAdvSetRandAddr(uint8_t handle, const uint8_t *pAddr) return LctrSetExtAdvSetRandAddr(handle, pAddr); } - /*************************************************************************************************/ /*! * \brief Read periodic channel map for slave or master * - * \param pBuf Packed packet buffer. + * \param handle handle. + * \param isAdv Handle is an advertiser. * * \return Channel map, packed into a 64bit int * @@ -125,7 +126,7 @@ uint8_t LlSetExtAdvParam(uint8_t handle, LlExtAdvParam_t *pExtAdvParam) LL_ADV_EVT_PROP_CONN_ADV_BIT; /* Maximum extended advertising interval is half the maximum BB clock rollover time. */ - const uint32_t bbDurMaxUsec = BB_TICKS_TO_US(UINT64_C(1) << 31); + const uint32_t bbDurMaxUsec = (BbGetBbTimerBoundaryUs() >> 1) + 1; const uint32_t validAdvInterMax = WSF_MIN(LL_MATH_DIV_625(bbDurMaxUsec), 0xFFFFFF); LL_TRACE_INFO2("### LlApi ### LlSetExtAdvParam, handle=%u, advEventProp=0x%04x", handle, pExtAdvParam->advEventProp); @@ -195,8 +196,6 @@ uint8_t LlSetExtAdvParam(uint8_t handle, LlExtAdvParam_t *pExtAdvParam) LL_TRACE_WARN1("Unsupported PHY, handle=%u", handle); return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; } - pExtAdvParam->priAdvInterMin = BB_BLE_TO_BB_TICKS(pExtAdvParam->priAdvInterMin); - pExtAdvParam->priAdvInterMax = BB_BLE_TO_BB_TICKS(pExtAdvParam->priAdvInterMax); return LctrSetExtAdvParam(handle, pExtAdvParam); } @@ -289,8 +288,6 @@ uint8_t LlSetExtScanRespData(uint8_t handle, uint8_t op, uint8_t fragPref, uint8 * \param numAdvSets Number of elements in enaParam[]. * \param enaParam Enable parameter table. * - * \return None. - * * Enable or disable extended advertising. */ /*************************************************************************************************/ @@ -298,8 +295,11 @@ void LlExtAdvEnable(uint8_t enable, uint8_t numAdvSets, LlExtAdvEnableParam_t en { LL_TRACE_INFO2("### LlApi ### LlExtAdvEnable: enable=%u, numAdvSets=%u", enable, numAdvSets); - /* Non-overlapping enable requests. */ - WSF_ASSERT(lmgrCb.extAdvEnaDelayCnt == 0); + if (lmgrCb.extAdvEnaDelayCnt != 0) + { + LL_TRACE_WARN0("Overlapped enable request"); + LmgrSendExtAdvEnableCnf(0, LL_ERROR_CODE_CMD_DISALLOWED); + } lmgrCb.advSetEnaStatus = LL_SUCCESS; @@ -574,15 +574,13 @@ uint8_t LlSetPeriodicAdvData(uint8_t handle, uint8_t op, uint8_t len, const uint /*! * \brief Set periodic advertising enable. * - * \param enable Set to TRUE to enable advertising, FALSE to disable advertising. * \param handle Advertising handle. - * - * \return None. + * \param enable Set to TRUE to enable advertising, FALSE to disable advertising. * * Enable or disable periodic advertising. */ /*************************************************************************************************/ -void LlSetPeriodicAdvEnable(uint8_t handle, uint8_t enable) +void LlSetPeriodicAdvEnable(uint8_t enable, uint8_t handle) { LL_TRACE_INFO2("### LlApi ### LlSetPeriodicAdvEnable: enable=%u, handle=%u", enable, handle); @@ -692,8 +690,6 @@ uint8_t LlSetExtAdvTxPhyOptions(uint8_t handle, uint8_t priPhyOpts, uint8_t secP * * \param phyOptions PHY options. * - * \return None. - * * Set the default TX PHY options for extended adv slave primary and secondary channel. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_bis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_bis_master.c new file mode 100644 index 0000000000..5488377306 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_bis_master.c @@ -0,0 +1,128 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) master control interface implementation file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_api_bis_master.h" +#include "wsf_math.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include + +/************************************************************************************************** + Internal functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Check if the create BIG parameters are valid or not. + * + * \param pParam Create BIG test parameters. + * + * \return True if parameter is valid, False otherwise. + */ +/*************************************************************************************************/ +static bool_t LlIsBigCreateSyncParamsValid(LlBigCreateSync_t *pParam) +{ + const uint8_t MAX_BIG_HANDLE = 0xEF; + const uint16_t MAX_SYNC_HANDLE = 0x0EFF; + const uint8_t MAX_ENCRYPTION = 0x01; + const uint8_t MAX_MSE = 0x1F; + const uint16_t MIN_BIG_SYNC_TIMEOUT = 0x000A; + const uint16_t MAX_BIG_SYNC_TIMEOUT = 0x4000; + const uint8_t MIN_BIS = LL_MIN_BIS; + const uint8_t MAX_BIS = 0x1F; + + if (pParam->bigHandle > MAX_BIG_HANDLE) + { + LL_TRACE_WARN1("bigHandle=%u out of range", pParam->bigHandle); + return FALSE; + } + if (pParam->syncHandle > MAX_SYNC_HANDLE) + { + LL_TRACE_WARN1("syncHandle=%u out of range", pParam->syncHandle); + return FALSE; + } + if (pParam->encrypt > MAX_ENCRYPTION) + { + LL_TRACE_WARN1("encrypt=%u out of range", pParam->encrypt); + return FALSE; + } + if (pParam->mse > MAX_MSE) + { + LL_TRACE_WARN1("mse=%u out of range", pParam->mse); + return FALSE; + } + if ((pParam->bigSyncTimeout < MIN_BIG_SYNC_TIMEOUT) || (pParam->bigSyncTimeout > MAX_BIG_SYNC_TIMEOUT)) + { + LL_TRACE_WARN1("bigSyncTimeout=%u out of range", pParam->bigSyncTimeout); + return FALSE; + } + if ((pParam->numBis < MIN_BIS) || (pParam->numBis > MAX_BIS)) + { + LL_TRACE_WARN1("numBis=%u out of range", pParam->numBis); + return FALSE; + } + + return TRUE; +} + +/************************************************************************************************** + External functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \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) +{ + LL_TRACE_INFO2("### LlApi ### LlBigCreateSync bigHandle=%u syncHandle=%u", pCreateSync->bigHandle, pCreateSync->syncHandle); + + if ((LL_API_PARAM_CHECK == 1) && + (LlIsBigCreateSyncParamsValid(pCreateSync) == FALSE)) + { + return LL_ERROR_CODE_PARAM_OUT_OF_MANDATORY_RANGE; + } + + return LctrMstBigCreateSync(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) +{ + LL_TRACE_INFO1("### LlApi ### LlBigTerminateSync bigHandle=%u", bigHandle); + + LctrMstBigTerminateSync(bigHandle); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_bis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_bis_slave.c new file mode 100644 index 0000000000..c52252815e --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_bis_slave.c @@ -0,0 +1,355 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) slave control interface implementation file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 "lctr_api_bis_slave.h" +#include "lctr_api_adv_slave_ae.h" +#include "wsf_trace.h" +#include + +/************************************************************************************************** + Internal functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \brief Check if the create BIG parameters are valid or not. + * + * \param pParam Create BIG command parameters. + * + * \return TRUE if parameter is valid, FALSE otherwise. + */ +/*************************************************************************************************/ +static bool_t LlIsBigParamsValid(LlCreateBig_t *pParam) +{ + const uint8_t MAX_BIG_HANDLE = 0xEF; + const uint8_t MAX_ADV_HANDLE = 0xEF; + const uint8_t MIN_NUM_BIS = 0x01; + const uint8_t MAX_NUM_BIS = 0x1F; + const uint32_t MIN_SDU_INTERVAL = 0x00100; + const uint32_t MAX_SDU_INTERVAL = 0xFFFFF; + const uint16_t MAX_SDU = 0x0FFF; + const uint16_t MAX_TRANSPORT_LATENCY = 0x0FA0; + const uint8_t MAX_RTN = 0x0F; + const uint8_t MIN_PHY = 0x01; + const uint8_t MAX_PACKING = 0x01; + const uint8_t MAX_FRAMING = 0x01; + const uint8_t MAX_ENCRYPTION = 0x01; + + if (pParam->bigHandle > MAX_BIG_HANDLE) + { + LL_TRACE_WARN1("bigHandle=%u out of range", pParam->bigHandle); + return FALSE; + } + if (pParam->advHandle > MAX_ADV_HANDLE) + { + LL_TRACE_WARN1("advHandle=%u out of range", pParam->advHandle); + return FALSE; + } + if ((pParam->numBis < MIN_NUM_BIS) || (pParam->numBis > MAX_NUM_BIS)) + { + LL_TRACE_WARN1("numBis=%u out of range", pParam->numBis); + return FALSE; + } + if ((pParam->sduInterUsec < MIN_SDU_INTERVAL) || (pParam->sduInterUsec > MAX_SDU_INTERVAL)) + { + LL_TRACE_WARN1("sduIntervUsec=%u out of range", pParam->sduInterUsec); + return FALSE; + } + if (pParam->maxSdu > MAX_SDU) + { + LL_TRACE_WARN1("maxSdu=%u value out of range", pParam->maxSdu); + return FALSE; + } + if (pParam->mtlMs > MAX_TRANSPORT_LATENCY) + { + LL_TRACE_WARN1("mtl=%u value out of range", pParam->mtlMs); + return FALSE; + } + if (pParam->rtn > MAX_RTN) + { + LL_TRACE_WARN1("rtn=%u value out of range", pParam->rtn); + return FALSE; + } + if (pParam->phys < MIN_PHY) + { + LL_TRACE_WARN1("phy=0x%02x value out of range", pParam->phys); + return FALSE; + } + if (pParam->packing > MAX_PACKING) + { + LL_TRACE_WARN1("packing=%u value out of range", pParam->packing); + return FALSE; + } + if (pParam->framing > MAX_FRAMING) + { + LL_TRACE_WARN1("framing=%u value out of range", pParam->framing); + return FALSE; + } + if (pParam->encrypt > MAX_ENCRYPTION) + { + LL_TRACE_WARN1("encryption=%u value out of range", pParam->encrypt); + return FALSE; + } + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Check if the create BIG test parameters are valid or not. + * + * \param pParam Create BIG test parameters. + * + * \return True if parameter is valid, False otherwise. + */ +/*************************************************************************************************/ +static bool_t LlIsBigTestParamsValid(LlCreateBigTest_t *pParam) +{ + const uint8_t MAX_BIG_HANDLE = 0xEF; + const uint8_t MAX_ADV_HANDLE = 0xEF; + const uint8_t MIN_NUM_BIS = 0x01; + const uint8_t MAX_NUM_BIS = 0x1F; + const uint32_t MIN_SDU_INTERVAL = 0x00100; + const uint32_t MAX_SDU_INTERVAL = 0xFFFFF; + const uint16_t MIN_ISO_INTERVAL = 0x0004; + const uint16_t MAX_ISO_INTERVAL = 0x0C80; + const uint8_t MIN_NUM_NSE = 0x01; + const uint8_t MAX_NUM_NSE = 0x1F; + const uint16_t MAX_SDU = 0x0FFF; + const uint8_t MIN_PDU = 0x01; + const uint8_t MAX_PDU = 0xFB; + const uint8_t MIN_PHY = 0x01; + const uint8_t MAX_PACKING = 0x01; + const uint8_t MAX_FRAMING = 0x01; + const uint8_t MIN_BN = 0x01; + const uint8_t MAX_BN = 0x07; + const uint8_t MIN_IRC = 0x01; + const uint8_t MAX_IRC = 0x0F; + const uint8_t MAX_PTO = 0x0F; + const uint8_t MAX_ENCRYPTION = 0x01; + + if (pParam->bigHandle > MAX_BIG_HANDLE) + { + LL_TRACE_WARN1("bigHandle=%u out of range", pParam->bigHandle); + return FALSE; + } + if (pParam->advHandle > MAX_ADV_HANDLE) + { + LL_TRACE_WARN1("advHandle=%u out of range", pParam->advHandle); + return FALSE; + } + if ((pParam->numBis < MIN_NUM_BIS) || (pParam->numBis > MAX_NUM_BIS)) + { + LL_TRACE_WARN1("numBis=%u out of range", pParam->numBis); + return FALSE; + } + if ((pParam->sduInterUsec < MIN_SDU_INTERVAL) || (pParam->sduInterUsec > MAX_SDU_INTERVAL)) + { + LL_TRACE_WARN1("sduInterval=%u out of range", pParam->sduInterUsec); + return FALSE; + } + if ((pParam->isoInter < MIN_ISO_INTERVAL) || (pParam->isoInter > MAX_ISO_INTERVAL)) + { + LL_TRACE_WARN1("isoInterval=%u out of range", pParam->isoInter); + return FALSE; + } + if ((pParam->nse < MIN_NUM_NSE) || (pParam->nse > MAX_NUM_NSE)) + { + LL_TRACE_WARN1("NSE=%u out of range", pParam->nse); + return FALSE; + } + if (pParam->maxSdu > MAX_SDU) + { + LL_TRACE_WARN1("maxSdu=%u out of range", pParam->maxSdu); + return FALSE; + } + if ((pParam->maxPdu < MIN_PDU) || (pParam->maxPdu > MAX_PDU)) + { + LL_TRACE_WARN1("maxPdu=%u out of range", pParam->maxPdu); + return FALSE; + } + if (pParam->phys < MIN_PHY) + { + LL_TRACE_WARN1("phy=0x%02x out of range", pParam->phys); + return FALSE; + } + if (pParam->packing > MAX_PACKING) + { + LL_TRACE_WARN1("packing=%u out of range", pParam->packing); + return FALSE; + } + if (pParam->framing > MAX_FRAMING) + { + LL_TRACE_WARN1("framing=%u out of range", pParam->framing); + return FALSE; + } + if ((pParam->bn < MIN_BN) || (pParam->bn > MAX_BN)) + { + LL_TRACE_WARN1("BN=%u out of range", pParam->bn); + return FALSE; + } + if ((pParam->irc < MIN_IRC) || (pParam->irc > MAX_IRC)) + { + LL_TRACE_WARN1("IRC=%u out of range", pParam->irc); + return FALSE; + } + if (pParam->pto > MAX_PTO) + { + LL_TRACE_WARN1("PTO=%u out of range", pParam->pto); + return FALSE; + } + if (pParam->encrypt > MAX_ENCRYPTION) + { + LL_TRACE_WARN1("encrypt=%u out of range", pParam->encrypt); + return FALSE; + } + + if ((pParam->framing == LL_ISO_PDU_TYPE_UNFRAMED) && + (((pParam->isoInter * 1250) % pParam->sduInterUsec) > 0)) + { + LL_TRACE_WARN0("Unframed PDUs must have ISO_Interval that are multiples of the SDU_Interval"); + return FALSE; + } + + return TRUE; +} + +/************************************************************************************************** + External functions +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \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) +{ + LL_TRACE_INFO2("### LlApi ### LlCreateBig bigHandle=%u advHandle=%u", pCreateBig->bigHandle, pCreateBig->advHandle); + + if ((LL_API_PARAM_CHECK == 1) && + (LlIsBigParamsValid(pCreateBig) == FALSE)) + { + return LL_ERROR_CODE_PARAM_OUT_OF_MANDATORY_RANGE; + } + + if ((LL_API_PARAM_CHECK == 1) && + (LctrIsPerAdvEnabled(pCreateBig->advHandle) == FALSE)) + { + LL_TRACE_WARN1("Periodic advertiser not found, advHandle=%u", pCreateBig->advHandle); + return LL_ERROR_CODE_UNKNOWN_ADV_ID; + } + + uint8_t supPhyMask = LL_PHYS_LE_1M_BIT | + (pLctrRtCfg->phy2mSup ? LL_PHYS_LE_2M_BIT : 0) | + (pLctrRtCfg->phyCodedSup ? LL_PHYS_LE_CODED_BIT : 0); + + if ((LL_API_PARAM_CHECK == 1) && + (pCreateBig->phys & (~supPhyMask))) + { + LL_TRACE_WARN1("Unknown PHY bits, phys=%u", pCreateBig->phys); + return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; + } + + return LctrSlvBisCreateBig(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 parameters. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlCreateBigTest(LlCreateBigTest_t *pCreateBigTest) +{ + uint8_t status = LL_SUCCESS; + + LL_TRACE_INFO2("### LlApi ### LlCreateBigTest bigHandle=%u advHandle=%u", pCreateBigTest->bigHandle, pCreateBigTest->advHandle); + + if ((LL_API_PARAM_CHECK == 1) && + (LlIsBigTestParamsValid(pCreateBigTest) == FALSE)) + { + return LL_ERROR_CODE_PARAM_OUT_OF_MANDATORY_RANGE; + } + + if ((LL_API_PARAM_CHECK == 1) && + (pCreateBigTest->nse < (pCreateBigTest->irc * pCreateBigTest->bn))) + { + LL_TRACE_WARN0("NSE not less than 'IRC * BN'"); + return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; + } + + if ((LL_API_PARAM_CHECK == 1) && + (LctrIsPerAdvEnabled(pCreateBigTest->advHandle) == FALSE)) + { + LL_TRACE_WARN1("Periodic advertiser not found, advHandle=%u", pCreateBigTest->advHandle); + return LL_ERROR_CODE_UNKNOWN_ADV_ID; + } + + uint8_t supPhyMask = LL_PHYS_LE_1M_BIT | + (pLctrRtCfg->phy2mSup ? LL_PHYS_LE_2M_BIT : 0) | + (pLctrRtCfg->phyCodedSup ? LL_PHYS_LE_CODED_BIT : 0); + + if ((LL_API_PARAM_CHECK == 1) && + (pCreateBigTest->phys & (~supPhyMask))) + { + LL_TRACE_WARN1("Unknown PHY bits, phys=%u", pCreateBigTest->phys); + return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; + } + + status = LctrSlvBisCreateBigTest(pCreateBigTest); + + return status; +} + +/*************************************************************************************************/ +/*! + * \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) +{ + uint8_t status = LL_SUCCESS; + + LL_TRACE_INFO2("### LlApi ### LlTerminateBig bigHandle=%u advHandle=%u", bigHandle, reason); + + status = LctrSlvBisTerminateBig(bigHandle, reason); + + return status; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_cis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_cis_master.c new file mode 100644 index 0000000000..ee19329f82 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_cis_master.c @@ -0,0 +1,500 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) master control interface implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "ll_api.h" +#if (LL_ENABLE_TESTER) +#include "ll_tester_api.h" +#endif +#include "lmgr_api.h" +#include "lmgr_api_cis_master.h" +#include "lctr_api_cis_master.h" +#include "lctr_api_conn.h" +#include "util/bstream.h" +#include "wsf_assert.h" +#include "wsf_msg.h" +#include "wsf_trace.h" +#include + +/*************************************************************************************************/ +/*! + * \brief Check if the CIG parameters are valid or not. + * + * \param pCigParam Set CIG parameters. + * + * \return True if parameter is valid, False otherwise. + */ +/*************************************************************************************************/ +static bool_t LlIsCigParamsValid(LlCisCigParams_t *pCigParam) +{ + const uint8_t MAX_CIG_ID = 0xEF; + const uint32_t MIN_SDU_INTERVAL = 0x000FF; + const uint32_t MAX_SDU_INTERVAL = 0xFFFFF; + const uint8_t MAX_SCA = 0x07; + const uint8_t MAX_PACKING = 0x01; + const uint8_t MAX_FRAMING = 0x01; + const uint16_t MIN_TRANS_LATENCY = 0x0005; + const uint16_t MAX_TRANS_LATENCY = 0x0FA0; + const uint8_t MIN_NUM_CIS = 0x01; + 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) + { + return FALSE; + } + if (pCigParam->sduIntervalMToS != pCigParam->sduIntervalSToM) + { + /* For now, sduIntervalMToS shall be equal to the sduIntervalMToS */ + LL_TRACE_INFO0("LlIsCigParamsValid sduIntervalMToS != sduIntervalSToM"); + return FALSE; + } + if ((pCigParam->sduIntervalMToS < MIN_SDU_INTERVAL) || (pCigParam->sduIntervalMToS > MAX_SDU_INTERVAL)) + { + LL_TRACE_INFO0("LlIsCigParamsValid Invalid sduIntervalMToS"); + return FALSE; + } + if ((pCigParam->sduIntervalSToM < MIN_SDU_INTERVAL) || (pCigParam->sduIntervalSToM > MAX_SDU_INTERVAL)) + { + LL_TRACE_INFO0("LlIsCigParamsValid Invalid sduIntervalSToM"); + return FALSE; + } + if (pCigParam->sca > MAX_SCA) + { + LL_TRACE_INFO0("LlIsCigParamsValid Invalid sca"); + return FALSE; + } + if (pCigParam->packing > MAX_PACKING) + { + LL_TRACE_INFO0("LlIsCigParamsValid Invalid packing"); + return FALSE; + } + if (pCigParam->framing > MAX_FRAMING) + { + LL_TRACE_INFO0("LlIsCigParamsValid Invalid framing"); + return FALSE; + } + if ((pCigParam->transLatMToS < MIN_TRANS_LATENCY) || (pCigParam->transLatMToS > MAX_TRANS_LATENCY)) + { + LL_TRACE_INFO0("LlIsCigParamsValid Invalid transLatMToS"); + return FALSE; + } + if ((pCigParam->transLatSToM < MIN_TRANS_LATENCY) || (pCigParam->transLatSToM > MAX_TRANS_LATENCY)) + { + LL_TRACE_INFO0("LlIsCigParamsValid Invalid transLatSToM"); + return FALSE; + } + if ((pCigParam->numCis < MIN_NUM_CIS) || (pCigParam->numCis > MAX_NUM_CIS)) + { + LL_TRACE_INFO0("LlIsCigParamsValid Invalid numCis"); + return FALSE; + } + + for (unsigned int i = 0; i < pCigParam->numCis; i++) + { + LlCisCisParams_t *pCisParam = &pCigParam->pCisParam[i]; + + if (pCisParam->cisId > MAX_CIS_ID) + { + LL_TRACE_INFO0("LlIsCigParamsValid Invalid cisId"); + return FALSE; + } + if (pCisParam->sduSizeMToS > MAX_SDU_SIZE) + { + LL_TRACE_INFO0("LlIsCigParamsValid Invalid sduSizeMToS"); + return FALSE; + } + if (pCisParam->sduSizeSToM > MAX_SDU_SIZE) + { + LL_TRACE_INFO0("LlIsCigParamsValid Invalid sduSizeSToM"); + return FALSE; + } + if ((pCisParam->phyMToS < MIN_PHY) || (pCisParam->phyMToS > MAX_PHY)) + { + LL_TRACE_INFO0("LlIsCigParamsValid Invalid phyMToS"); + return FALSE; + } + if ((pCisParam->phySToM < MIN_PHY) || (pCisParam->phySToM > MAX_PHY)) + { + LL_TRACE_INFO0("LlIsCigParamsValid Invalid phySToM"); + return FALSE; + } + if (pCisParam->rteMToS > MAX_RTE) + { + LL_TRACE_INFO0("LlIsCigParamsValid Invalid rteMToS"); + return FALSE; + } + if (pCisParam->rteSToM > MAX_RTE) + { + LL_TRACE_INFO0("LlIsCigParamsValid Invalid rteSToM"); + return FALSE; + } + } + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Validate all CIS PHY parameters. + * + * \param pCigParam CIG parameters. + * + * \return True if all PHY are valid, false otherwise. + */ +/*************************************************************************************************/ +static bool_t LlIsCigPhyParamsValid(LlCisCigParams_t *pCigParam) +{ + for (unsigned int i = 0; i < pCigParam->numCis; i++) + { + LlCisCisParams_t *pCisParam = &pCigParam->pCisParam[i]; + + if (!llValidatePhySupport(pCisParam->phyMToS, pCisParam->phySToM)) + { + return FALSE; + } + + + if (BB_SYM_PHY_REQ && + (pCisParam->phyMToS != pCisParam->phySToM)) + { + return FALSE; + } + } + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Check if the CIG test parameters are valid or not. + * + * \param pSetCigParamTest Set CIG parameters. + * + * \return True if parameter is valid, False otherwise. + */ +/*************************************************************************************************/ +static bool_t LlIsCigTestParamsValid(LlCisCigParamsTest_t *pSetCigParamTest) +{ + /* All the values below are in the valid range. */ + const uint8_t MAX_CIG_ID = 0xEF; + const uint32_t MIN_SDU_INTERVAL = 0x000FF; + const uint32_t MAX_SDU_INTERVAL = 0xFFFFF; + const uint8_t MAX_SCA = 0x07; + const uint8_t MAX_PACKING = 0x01; + const uint8_t MAX_FRAMING = 0x01; + const uint8_t MIN_FT = 0x01; + const uint8_t MAX_FT = 0x1F; + const uint16_t MIN_ISO_INTERVAL = 0x0004; + const uint16_t MAX_ISO_INTERVAL = 0x0C80; + const uint8_t MIN_NUM_CIS = 0x01; + const uint8_t MAX_NUM_CIS = 0x10; + 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) + { + return FALSE; + } + if ((pSetCigParamTest->sduIntervalMToS < MIN_SDU_INTERVAL) || (pSetCigParamTest->sduIntervalMToS > MAX_SDU_INTERVAL)) + { + return FALSE; + } + if ((pSetCigParamTest->sduIntervalSToM < MIN_SDU_INTERVAL) || (pSetCigParamTest->sduIntervalSToM > MAX_SDU_INTERVAL)) + { + return FALSE; + } + if ((pSetCigParamTest->ftMToS < MIN_FT) || (pSetCigParamTest->ftMToS > MAX_FT)) + { + return FALSE; + } + if ((pSetCigParamTest->ftSToM < MIN_FT) || (pSetCigParamTest->ftSToM > MAX_FT)) + { + return FALSE; + } + if ((pSetCigParamTest->isoInterval < MIN_ISO_INTERVAL) || (pSetCigParamTest->isoInterval > MAX_ISO_INTERVAL)) + { + return FALSE; + } + if (pSetCigParamTest->sca > MAX_SCA) + { + return FALSE; + } + if (pSetCigParamTest->packing > MAX_PACKING) + { + return FALSE; + } + if (pSetCigParamTest->framing > MAX_FRAMING) + { + return FALSE; + } + if ((pSetCigParamTest->numCis < MIN_NUM_CIS) || (pSetCigParamTest->numCis > MAX_NUM_CIS)) + { + return FALSE; + } + + for (unsigned int i = 0; i < pSetCigParamTest->numCis; i++) + { + LlCisCigCisParamsTest_t *pCisParam = &pSetCigParamTest->pCisParam[i]; + + if (pCisParam->cisId > MAX_CIS_ID) + { + return FALSE; + } + if (pCisParam->sduSizeMToS > MAX_SDU_SIZE) + { + return FALSE; + } + if (pCisParam->sduSizeSToM > MAX_SDU_SIZE) + { + return FALSE; + } + if (pCisParam->pduSizeMToS > MAX_PDU_SIZE) + { + return FALSE; + } + if (pCisParam->pduSizeSToM > MAX_PDU_SIZE) + { + return FALSE; + } + if ((pCisParam->phyMToS < MIN_PHY) || (pCisParam->phyMToS > MAX_PHY)) + { + return FALSE; + } + if ((pCisParam->phySToM < MIN_PHY) || (pCisParam->phySToM > MAX_PHY)) + { + return FALSE; + } + if (pCisParam->bnMToS > MAX_BN) + { + return FALSE; + } + if (pCisParam->bnSToM > MAX_BN) + { + return FALSE; + } + } + + + if (pSetCigParamTest->pCisParam->bnMToS > pSetCigParamTest->pCisParam->nse || + pSetCigParamTest->pCisParam->bnSToM > pSetCigParamTest->pCisParam->nse) + { + return FALSE; + } + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Validate all test cis param PHYs. + * + * \param pSetCigParamTest CIG parameters. + * + * \return True if all PHY are valid, false otherwise. + */ +/*************************************************************************************************/ +static bool_t LlIsCigPhyTestParamsValid(LlCisCigParamsTest_t *pSetCigParamTest) +{ + for (unsigned int i = 0; i < pSetCigParamTest->numCis; i++) + { + LlCisCigCisParamsTest_t *pCisParam = &pSetCigParamTest->pCisParam[i]; + + if (!llValidatePhySupport(pCisParam->phyMToS, pCisParam->phySToM)) + { + return FALSE; + } + + if (BB_SYM_PHY_REQ && + (pCisParam->phyMToS != pCisParam->phySToM)) + { + return FALSE; + } + } + + return TRUE; +} + +/*************************************************************************************************/ +/*! + * \brief Used by a master host to set the parameters of all connected isochronous streams associated with a connected isochronous group in the controller. + * + * \param pCigParam CIG parameters. + * \param pCisHandles Return buffer for the connected isochronous stream handles. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlSetCigParams(LlCisCigParams_t *pCigParam, uint16_t *pCisHandles) +{ + uint8_t status = LL_SUCCESS; + + LL_TRACE_INFO1("### LlApi ### LlSetCigParams numCis=%d", 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); + + if ((LL_API_PARAM_CHECK == 1) && + (LlIsCigParamsValid(pCigParam) == FALSE)) + { + LL_TRACE_INFO0("### LlApi ### LlSetCigParams Invalid Parameters"); + return LL_ERROR_CODE_PARAM_OUT_OF_MANDATORY_RANGE; + } + + if ((LL_API_PARAM_CHECK == 1) && + (LlIsCigPhyParamsValid(pCigParam) == FALSE)) + { + LL_TRACE_INFO0("### LlApi ### LlSetCigParams Invalid PHY: Not supported by controller"); + return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; + } + + status = LctrSetCigParam(pCigParam, pCisHandles); + + /* Add the check If the Host attempts to set Connected Isochronous Stream parameters that exceed the maximum supported Connected Isochronous Stream parameters in the Controller, the Controller shall return the error code Unsupported Feature or Parameter Value (0x11).*/ + + return status; +} + +/*************************************************************************************************/ +/*! + * \brief Used by a master Host to set the parameters of all connected isochronous streams + * associated with a connected isochronous group in the controller for testing purpose. + * + * \param pSetCigParamTest CIG test parameters. + * \param pCisHandles Return buffer for the connected isochronous stream handles. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlSetCigParamsTest(LlCisCigParamsTest_t *pSetCigParamTest, uint16_t *pCisHandles) +{ + uint8_t status = LL_SUCCESS; + + LL_TRACE_INFO1("### LlApi ### LlSetCigParamsTest numCis=%d", pSetCigParamTest->numCis); + + memset(pCisHandles, 0, pSetCigParamTest->numCis * sizeof(uint16_t)); + + if ((LL_API_PARAM_CHECK == 1) && + (LlIsCigTestParamsValid(pSetCigParamTest) == FALSE)) + { + LL_TRACE_INFO0("### LlApi ### LlSetCigParamsTest Invalid Parameters"); + return LL_ERROR_CODE_PARAM_OUT_OF_MANDATORY_RANGE; + } + + if ((LL_API_PARAM_CHECK == 1) && + (LlIsCigPhyTestParamsValid(pSetCigParamTest) == FALSE)) + { + LL_TRACE_INFO0("### LlApi ### LlSetCigParams Invalid PHY: Not supported by controller"); + return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; + } + + status = LctrSetCigParamTest(pSetCigParamTest, pCisHandles); + + return status; +} + +/*************************************************************************************************/ +/*! + * \brief Used by the master host to establish one or more connected isochronous streams. + * + * \param numCis Number of connected isochronous streams. + * \param pCreateCisParam Parameters for create connected isochronous stream. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlCreateCis(uint8_t numCis, LlCisCreateCisParams_t *pCreateCisParam) +{ + uint8_t status = LL_SUCCESS; + + LL_TRACE_INFO1("### LlApi ### LlCreateCis numCis=%d", numCis); + + if ((lmgrCb.features & LL_FEAT_ISO_HOST_SUPPORT) == 0) + { + LL_TRACE_INFO0("### LlApi ### LlCreateCis ISO host support bit is not enabled"); + return LL_ERROR_CODE_CMD_DISALLOWED; + } + + if ((LL_API_PARAM_CHECK == 1)) + { + for (unsigned int i = 0; i < numCis; i++) + { + if ((pCreateCisParam->pAclHandle[i] >= pLctrRtCfg->maxConn) || + !LctrIsConnHandleEnabled(pCreateCisParam->pAclHandle[i])) + { + return LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + + if (LctrGetRole(pCreateCisParam->pAclHandle[i]) != LL_ROLE_MASTER) + { + return LL_ERROR_CODE_CMD_DISALLOWED; + } + } + } + status = LctrCreateCis(numCis, pCreateCisParam); + + return status; +} + +/*************************************************************************************************/ +/*! + * \brief Removes all the connected isochronous streams which have been set up. + * + * \param cigId Identifier of the connected isochronous group. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlRemoveCig(uint8_t cigId) +{ + uint8_t status = LL_SUCCESS; + + LL_TRACE_INFO1("### LlApi ### LlRemoveCig CIG_ID=%d", cigId); + + status = LctrRemoveCig(cigId); + + return status; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_cis_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_cis_slave.c new file mode 100644 index 0000000000..18573d27eb --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_cis_slave.c @@ -0,0 +1,75 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) master control interface implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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 "ll_api.h" +#include "lmgr_api.h" +#include "lctr_api_cis_slave.h" +#include "util/bstream.h" +#include "wsf_assert.h" +#include "wsf_msg.h" +#include "wsf_trace.h" +#include + +/*************************************************************************************************/ +/*! + * \brief Used by the slave host to inform the controller to accept the request for the + * connected isochronous stream. + * + * \param cisHandle Handle of the connected isochronous stream. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlAcceptCisReq(uint16_t cisHandle) +{ + uint8_t status = LL_SUCCESS; + + LL_TRACE_INFO1("### LlApi ### LlAcceptCisReq cisHandle=%d", cisHandle); + + status = LctrAcceptCisReq(cisHandle); + + return status; +} + +/*************************************************************************************************/ +/*! + * \brief Used by the slave host to inform the controller to reject the request for the + * connected isochronous stream. + * + * \param cisHandle Handle of the connected isochronous stream. + * \param reason Indicate the reason for rejecting the request. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlRejectCisReq(uint16_t cisHandle, uint8_t reason) +{ + uint8_t status = LL_SUCCESS; + + LL_TRACE_INFO2("### LlApi ### LlRejectCisReq cisHandle=%d reason=%d", cisHandle, reason); + + status = LctrRejectCisReq(cisHandle, reason); + + return status; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn.c index 2bef004cd4..9be7e7904e 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) slave parameter interface implementation file. + * \file + * + * \brief Link layer (LL) connection interface implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -26,6 +27,7 @@ #include "lmgr_api.h" #include "lmgr_api_conn.h" #include "bb_ble_api.h" +#include "pal_radio.h" #include "wsf_assert.h" #include "wsf_cs.h" #include "wsf_math.h" @@ -128,17 +130,61 @@ uint8_t LlGetTxPowerLevel(uint16_t handle, uint8_t type, int8_t *pLevel) /*************************************************************************************************/ /*! - * \brief Set connection's TX power level. + * \brief Get connection's enhanced TX power level and max txPower. + * + * \param handle Connection handle. + * \param phy PHY. + * \param pCurPwr Current transmit power level. + * \param pMaxPwr Max power level. + * + * \return Status error code. + * + */ +/*************************************************************************************************/ +uint8_t LlGetEnhTxPowerLevel(uint16_t handle, uint8_t phy, int8_t *pCurPwr, int8_t *pMaxPwr) +{ + uint8_t result = LL_SUCCESS; + + WSF_CS_INIT(cs); + WSF_CS_ENTER(cs); + + if ((LL_API_PARAM_CHECK == 1) && + ((handle >= pLctrRtCfg->maxConn) || + !LctrIsConnHandleEnabled(handle))) + { + result = LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + else if ((phy <= LL_PHY_NONE) || (phy > LL_PC_PHY_TOTAL)) + { + result = LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; + } + else + { + int8_t minPwr; /* Used for getting max power only .*/ + PalRadioGetSupTxPower(&minPwr, pMaxPwr); + *pCurPwr = PalRadioGetActualTxPower(LctrGetPhyTxPowerLevel(handle, phy), FALSE); + } + + WSF_CS_EXIT(cs); + + LL_TRACE_INFO3("### LlApi ### LlGetEnhancedTxPowerLevel, handle=%u, phy=%u, curPower=%d", handle, phy, *pCurPwr); + + return result; +} + +/*************************************************************************************************/ +/*! + * \brief Set connection's TX power level (All PHYs). * * \param handle Connection handle. * \param level Transmit power level. * * \return Status error code. * - * Set the TX power of a connection. + * Set the TX power of a connection (All PHYs). */ /*************************************************************************************************/ -uint8_t LlSetTxPowerLevel(uint16_t handle, int8_t level) +uint8_t LlSetAllPhyTxPowerLevel(uint16_t handle, int8_t level) { uint8_t result = LL_SUCCESS; @@ -163,6 +209,47 @@ uint8_t LlSetTxPowerLevel(uint16_t handle, int8_t level) return result; } +/*************************************************************************************************/ +/*! + * \brief Set connection's TX power level for a PHY. + * + * \param handle Connection handle. + * \param level Transmit power level. + * + * \return Status error code. + * + * Set the TX power of a connection for a PHY. + */ +/*************************************************************************************************/ +uint8_t LlSetPhyTxPowerLevel(uint16_t handle, int8_t level, uint8_t phy) +{ + uint8_t result = LL_SUCCESS; + + LL_TRACE_INFO3("### LlApi ### LlSetPhyTxPowerLevel, handle=%u, level=%d, phy=%u", handle, level, phy); + + WSF_CS_INIT(cs); + WSF_CS_ENTER(cs); + + if ((LL_API_PARAM_CHECK == 1) && + ((handle >= pLctrRtCfg->maxConn) || + !LctrIsConnHandleEnabled(handle))) + { + result = LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + else if (phy > LL_PC_PHY_TOTAL) + { + result = LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + else + { + LctrSetPhyTxPowerLevel(handle, level, phy); + } + + WSF_CS_EXIT(cs); + + return result; +} + /*************************************************************************************************/ /*! * \brief Get connection's channel map. @@ -268,7 +355,7 @@ uint8_t LlDisconnect(uint16_t handle, uint8_t reason) LL_TRACE_INFO2("### LlApi ### LlDisconnect, handle=%u, reason=%u", handle, reason); if ((LL_API_PARAM_CHECK == 1) && - (handle >= (pLctrRtCfg->maxConn + pLctrRtCfg->maxCis * pLctrRtCfg->maxCig))) + (handle >= (LCTR_MAX_HANDLE_INDEX))) { return LL_ERROR_CODE_UNKNOWN_CONN_ID; } @@ -441,7 +528,7 @@ uint8_t LlRemoteConnParamReqReply(uint16_t handle, const LlConnSpec_t *pConnSpec * \param handle Connection handle. * \param reason Reason code. * - * \return None. + * \return Status error code. * * Negative reply to a connection parameter request. */ @@ -585,8 +672,6 @@ uint8_t LlSetDataLen(uint16_t handle, uint16_t txLen, uint16_t txTime) * \param pMaxTxLen Maximum number of payload bytes for a Data PDU * \param pMaxTxTime Maximum microseconds for a Data PDU * - * \return None. - * * Suggested length and microseconds that the local Controller should use to transmit a * single Link Layer Data Channel PDU. */ @@ -650,8 +735,6 @@ uint8_t LlWriteDefaultDataLen(uint16_t maxTxLen, uint16_t maxTxTime) * \param pMaxRxLen Maximum number of payload bytes for a Rx Data PDU * \param pMaxRxTime Maximum microseconds for a Rx Data PDU * - * \return None. - * * Read the Controller's maximum supported payload octets and packet duration times for * transmission and reception. */ @@ -664,7 +747,7 @@ void LlReadMaximumDataLen(uint16_t *pMaxTxLen, uint16_t *pMaxTxTime, uint16_t *p WSF_ASSERT(pMaxTxTime); *pMaxTxLen = WSF_MIN(pLctrRtCfg->maxAclLen, LCTR_MAX_DATA_LEN_MAX); - *pMaxTxTime = LL_DATA_LEN_TO_TIME_1M(*pMaxTxLen); + *pMaxTxTime = LL_DATA_LEN_TO_TIME_1M(*pMaxTxLen, TRUE); *pMaxRxLen = *pMaxTxLen; *pMaxRxTime = *pMaxTxTime; } @@ -831,8 +914,6 @@ uint8_t LlGetAclRxBufs(void) * * \param pData Data buffer * - * \return None. - * * Send an ACL data packet. pData points to an ACL buffer formatted according to [1]; the host * must set the connection handle, flags, and length fields in the buffer. */ @@ -876,8 +957,6 @@ uint8_t *LlRecvAclData(void) * * \param numBufs Number of completed packets. * - * \return None. - * * Indicate that received ACL data buffer has been deallocated. */ /*************************************************************************************************/ @@ -910,7 +989,7 @@ uint8_t LlRequestPeerSca(uint16_t handle) else if ((LL_API_PARAM_CHECK == 1) && ((LctrGetUsedFeatures(handle) & LL_FEAT_SCA_UPDATE) == 0)) { - return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; + return LL_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE; } if ((pMsg = (lctrScaReq_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) @@ -955,7 +1034,7 @@ uint8_t LlModifySleepClockAccuracy(uint8_t action) else /* status = LL_SUCCESS */ { /* Update lmgrCb sca for future connections. */ - switch(action) + switch (action) { case LL_MODIFY_SCA_MORE_ACCURATE: lmgrCb.scaMod++; @@ -995,3 +1074,80 @@ uint8_t LlModifySleepClockAccuracy(uint8_t action) return status; } + +/*************************************************************************************************/ +/*! + * \brief Request change to or read peer txPower + * + * \param handle Connection handle. + * \param delta Requested change. + * \param phy Phy this change requests the change on. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlPowerCtrlReq(uint16_t handle, int8_t delta, uint8_t phy) +{ + lctrMsgPwrCtrlReq_t *pMsg; + + LL_TRACE_INFO3("### LlApi ### LlPowerCtrlReq, handle=%u, delta=%u, phy=%u", handle, delta, phy); + + if ((LL_API_PARAM_CHECK == 1) && + ((handle >= pLctrRtCfg->maxConn) || + !LctrIsConnHandleEnabled(handle))) + { + return LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + if ((LL_API_PARAM_CHECK == 1) && + (phy > LL_PC_PHY_TOTAL)) + { + return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; + } + else if ((LL_API_PARAM_CHECK == 1) && + ((LctrGetUsedFeatures(handle) & LL_FEAT_POWER_CONTROL_REQUEST) == 0)) + { + return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; + } + + if ((pMsg = (lctrMsgPwrCtrlReq_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) + { + pMsg->hdr.handle = handle; + pMsg->hdr.dispId = LCTR_DISP_CONN; + pMsg->hdr.event = LCTR_CONN_MSG_API_PWR_CTRL_REQ; + pMsg->delta = delta; + pMsg->phy = phy; + + WsfMsgSend(lmgrPersistCb.handlerId, pMsg); + } + else + { + return LL_ERROR_CODE_MEM_CAP_EXCEEDED; + } + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Set transmit power change reporting enable. + * + * \param handle Connection handle. + * \param enableLocal Enable local reporting. + * \param enableRemote Enable remote reporting. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlSetTxPowerReporting(uint16_t handle, uint8_t enableLocal, uint8_t enableRemote) +{ + LL_TRACE_INFO3("### LlApi ### LlSetTxPowerReporting, handle=%u, localEnable=%u, remoteEnable=%u", handle, enableLocal, enableRemote); + + if ((LL_API_PARAM_CHECK == 1) && + ((handle >= pLctrRtCfg->maxConn) || + !LctrIsConnHandleEnabled(handle))) + { + return LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + + return lctrSetTxPowerReporting(handle, enableLocal, enableRemote); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_master.c index 359a031758..0ec5c62477 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) slave parameter interface implementation file. + * \file + * + * \brief Link layer (LL) slave parameter interface implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -171,8 +172,6 @@ uint8_t LlCreateConn(const LlInitParam_t *pInitParam, const LlConnSpec_t *pConnS /*! * \brief Cancel a create connection operation. * - * \return None. - * * Cancel a connection before it is established. This function is only used when operating * in master role. This command is used to cancel extended and legacy create connection. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_master_ae.c index ddecd4a5cf..2dd04fca97 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_master_ae.c @@ -1,29 +1,31 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) master extended control interface implementation file. + * \file + * + * \brief Link layer (LL) master extended control interface implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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 "lctr_api_adv_master_ae.h" #include "lctr_api_init_master_ae.h" #include "lmgr_api_adv_master_ae.h" +#include "lctr_api_conn.h" #include "ll_math.h" #include "wsf_assert.h" #include "wsf_msg.h" @@ -32,46 +34,16 @@ /*************************************************************************************************/ /*! - * \brief Validate Connection spec parameters + * \brief Validate extended connection spec parameters. * - * \param pConnSpec + * \param pParam Pointer to connection spec parameters. * - * \return TRUE if valid, FALSE otherwise. + * \return Status error code. */ /*************************************************************************************************/ -static bool_t llValidateConnSpecParams(const LlConnSpec_t *pParam) +static uint8_t llValidateConnSpecParams(const LlConnSpec_t *pParam) { - /* Connection interval. */ - if ((LL_API_PARAM_CHECK == 1) && - ((pParam->connIntervalMin > pParam->connIntervalMax) || - (pParam->connIntervalMax < pParam->connIntervalMin) || - (pParam->connIntervalMax < HCI_CONN_INTERVAL_MIN) || - (pParam->connIntervalMin < HCI_CONN_INTERVAL_MIN) || - (pParam->connIntervalMax > HCI_CONN_INTERVAL_MAX) || - (pParam->connIntervalMin > HCI_CONN_INTERVAL_MAX) )) - { - return FALSE; - } - - /* Connection latency. */ - if ((LL_API_PARAM_CHECK == 1) && - ((pParam->connLatency > HCI_CONN_LATENCY_MAX))) - { - return FALSE; - } - - /* Supervision timeout. */ - uint32_t supTimeoutMin = ((uint32_t) pParam->connLatency + 1) * LL_CONN_INTERVAL_VAL_TO_US((uint32_t) pParam->connIntervalMax) * 2; - uint32_t supTimeoutUs = LL_SUP_TIMEOUT_VAL_TO_US((uint32_t) pParam->supTimeout); - if ((LL_API_PARAM_CHECK == 1) && - ((supTimeoutUs <= supTimeoutMin) || - (pParam->supTimeout < HCI_SUP_TIMEOUT_MIN) || - (pParam->supTimeout > HCI_SUP_TIMEOUT_MAX))) - { - return FALSE; - } - - return TRUE; + return LctrValidateConnSpec(pParam); } /*************************************************************************************************/ @@ -167,7 +139,7 @@ uint8_t LlExtCreateConn(const LlExtInitParam_t *pInitParam, const LlExtInitScanP if ((LL_API_PARAM_CHECK == 1) && ((pInitParam->initPhys & supportedPhys) != pInitParam->initPhys)) { - LL_TRACE_WARN0("Unsupported PHY bit was set."); + LL_TRACE_WARN0("Unsupported PHY bit was set"); return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE; } @@ -181,7 +153,7 @@ uint8_t LlExtCreateConn(const LlExtInitParam_t *pInitParam, const LlExtInitScanP { for (unsigned int i = 0; i < numInitPhyBits; i++) { - if ((!llValidateConnSpecParams(&connSpec[i])) || (!llValidateInitiateScanParams(&scanParam[i]))) + if ((llValidateConnSpecParams(&connSpec[i]) != LL_SUCCESS) || (!llValidateInitiateScanParams(&scanParam[i]))) { return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_slave.c index 606295b568..1cc0eb5cea 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_conn_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) slave control interface implementation file. + * \file + * + * \brief Link layer (LL) slave control interface implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_diag.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_diag.c index fc715e18f2..674d7753b4 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_diag.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_diag.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) test interface implementation file. + * \file + * + * \brief Link layer (LL) test interface implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ @@ -51,7 +52,7 @@ uint8_t LlGetTime(uint32_t *pTime) return LL_ERROR_CODE_CMD_DISALLOWED; } - *pTime = PalBbGetCurrentTime(USE_RTC_BB_CLK); + *pTime = PalBbGetCurrentTime(); return LL_SUCCESS; } @@ -70,5 +71,5 @@ uint8_t LlGetTime(uint32_t *pTime) /*************************************************************************************************/ uint32_t LlCalcDeltaTimeUsec(uint32_t endTime, uint32_t startTime) { - return BB_TICKS_TO_US(endTime - startTime); + return endTime - startTime; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_dtm.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_dtm.c index 236e2edb94..95befc6dd9 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_dtm.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_dtm.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) DTM interface implementation file. + * \file + * + * \brief Link layer (LL) DTM interface implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -180,8 +181,6 @@ uint8_t llConvertRfChanToChanIdx(uint8_t rfChan) * \param pBuf Buffer to fill. * \param len Number of bytes to fill. * - * \return None. - * * Fill payload with random numbers. */ /*************************************************************************************************/ @@ -262,8 +261,6 @@ static void llBuildTxPkt(uint8_t len, uint8_t pktType, uint8_t *pBuf) * \brief Tx operation end callback. * * \param pOp Tx operation descriptor. - * - * \return None. */ /*************************************************************************************************/ static void llTestTxOpEndCback(BbOpDesc_t *pOp) @@ -346,7 +343,7 @@ static void llTestTxOpEndCback(BbOpDesc_t *pOp) * \return TRUE if next receive should be set up. */ /*************************************************************************************************/ -static bool_t llTestTxCb(BbOpDesc_t *pOp, uint8_t status) +static bool_t llTestTxComplete(BbOpDesc_t *pOp, uint8_t status) { BbBleData_t * const pBle = pOp->prot.pBle; BbBleTestTx_t * const pTx = &pBle->op.testTx; @@ -359,6 +356,12 @@ static bool_t llTestTxCb(BbOpDesc_t *pOp, uint8_t status) return FALSE; } + if (status != BB_STATUS_SUCCESS) + { + LL_TRACE_ERR2("Terminating Tx test mode due to failure, status=%u, numTx=%u", status, llTestCb.rpt.numTx); + return FALSE; + } + if (llTestCb.state == LL_TEST_STATE_TX) { /* Operating parameters have changed. */ @@ -541,7 +544,6 @@ uint8_t LlEnhancedTxTest(uint8_t rfChan, uint8_t len, uint8_t pktType, uint8_t p llTestCb.numPkt = numPkt; pOp->protId = BB_PROT_BLE_DTM; pOp->endCback = llTestTxOpEndCback; - pOp->dueOffsetUsec = 0; /*** BLE General Setup ***/ @@ -564,7 +566,7 @@ uint8_t LlEnhancedTxTest(uint8_t rfChan, uint8_t len, uint8_t pktType, uint8_t p /* Longest packet for dynamic test changes. */ pTx->txLen = WSF_MAX(LL_DTM_MAX_PDU_LEN, LL_ADVB_MAX_LEN); - pTx->testCback = llTestTxCb; + pTx->testCback = llTestTxComplete; pTx->pktInterUsec = llCalcPacketInterval(llTestCb.tx.pduLen, pBle->chan.txPhy, pBle->chan.initTxPhyOptions); if ((pTx->pTxBuf = WsfBufAlloc(pTx->txLen)) == NULL) @@ -612,8 +614,6 @@ uint8_t LlTxTest(uint8_t rfChan, uint8_t len, uint8_t pktType, uint16_t numPkt) * \brief Rx operation completion callback. * * \param pOp Rx operation descriptor. - * - * \return None. */ /*************************************************************************************************/ static void llTestRxOpEndCback(BbOpDesc_t *pOp) @@ -681,7 +681,7 @@ static void llTestRxOpEndCback(BbOpDesc_t *pOp) * \return TRUE if next receive should be set up. */ /*************************************************************************************************/ -static bool_t llTestRxCb(BbOpDesc_t *pBod, uint8_t status) +static bool_t llTestRxComplete(BbOpDesc_t *pBod, uint8_t status) { switch (status) { @@ -799,7 +799,6 @@ uint8_t LlEnhancedRxTest(uint8_t rfChan, uint8_t phy, uint8_t modIdx, uint16_t n llTestCb.numPkt = numPkt; pOp->protId = BB_PROT_BLE_DTM; pOp->endCback = llTestRxOpEndCback; - pOp->dueOffsetUsec = 0; /*** BLE General Setup ***/ @@ -831,7 +830,7 @@ uint8_t LlEnhancedRxTest(uint8_t rfChan, uint8_t phy, uint8_t modIdx, uint16_t n pRx->rxSyncDelayUsec = pLctrRtCfg->dtmRxSyncMs * 1000; pRx->rxLen = WSF_MAX(LL_DTM_MAX_PDU_LEN, LL_ADVB_MAX_LEN); - pRx->testCback = llTestRxCb; + pRx->testCback = llTestRxComplete; uint16_t allocLen = WSF_MAX(pRx->rxLen, BB_FIXED_DATA_PKT_LEN); if ((pRx->pRxBuf = WsfBufAlloc(allocLen)) == NULL) @@ -954,8 +953,6 @@ uint8_t LlSetTxTestErrorPattern(uint32_t pattern) /*************************************************************************************************/ /*! * \brief Test reset handler. - * - * \return None. */ /*************************************************************************************************/ static void llTestResetHandler(void) @@ -969,8 +966,6 @@ static void llTestResetHandler(void) * \brief Test message dispatcher. * * \param pMsg Pointer to message buffer. - * - * \return None. */ /*************************************************************************************************/ static void llTestDisp(lctrMsgHdr_t *pMsg) @@ -1000,8 +995,6 @@ static void llTestDisp(lctrMsgHdr_t *pMsg) /*************************************************************************************************/ /*! * \brief Initialize link layer controller resources for test. - * - * \return None. */ /*************************************************************************************************/ void LlTestInit(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_enc_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_enc_master.c index d21ca0fb9d..77fb203ced 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_enc_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_enc_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) slave control interface implementation file. + * \file + * + * \brief Link layer (LL) slave control interface implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_enc_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_enc_slave.c index 3f3c837a9d..c28c16ad21 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_enc_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_enc_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) slave control interface implementation file. + * \file + * + * \brief Link layer (LL) slave control interface implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -26,7 +27,7 @@ #include "ll_math.h" #include "wsf_msg.h" #include "wsf_trace.h" -#include "stack/platform/include/pal_crypto.h" +#include "pal_crypto.h" #include /*************************************************************************************************/ @@ -57,8 +58,6 @@ uint8_t LlEncrypt(uint8_t *pKey, uint8_t *pData) * \param handle Connection handle. * \param pKey Pointer to new key. * - * \return None. - * * Provide the requested LTK encryption key. This function is only used when operating in * slave mode. */ @@ -103,8 +102,6 @@ uint8_t LlLtkReqReply(uint16_t handle, const uint8_t *pKey) * * \param handle Connection handle. * - * \return None. - * * Requested LTK encryption key not available. This function is only used when operating in * slave mode. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_iso.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_iso.c new file mode 100644 index 0000000000..b795fddeb6 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_iso.c @@ -0,0 +1,278 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) slave parameter interface implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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 "ll_api.h" +#include "wsf_cs.h" +#include "wsf_math.h" +#include "wsf_msg.h" +#include "wsf_trace.h" +#include "util/bstream.h" +#include +#include "lctr_api_iso.h" +#include "lmgr_api_iso.h" + +/*************************************************************************************************/ +/*! + * \brief Get the maximum ISO buffers size. + * + * \return Maximum buffers size in bytes. + */ +/*************************************************************************************************/ +uint16_t LlGetIsoMaxBufSize(void) +{ + LL_TRACE_INFO1("### LlApi ### LlGetIsoMaxBufSize, maxBufSize=%u", pLctrRtCfg->maxIsoSduLen); + + return pLctrRtCfg->maxIsoSduLen; +} + +/*************************************************************************************************/ +/*! + * \brief Get the number of buffers in the LL ISO transmit queue. + * + * \return Number of buffers. + */ +/*************************************************************************************************/ +uint8_t LlGetIsoTxBufs(void) +{ + LL_TRACE_INFO1("### LlApi ### LlGetIsoTxBufs, numBufs=%u", pLctrRtCfg->numIsoTxBuf); + + return pLctrRtCfg->numIsoTxBuf; +} + +/*************************************************************************************************/ +/*! + * \brief Get the number of buffers in the LL ISO receive queue. + * + * \return Number of buffers. + */ +/*************************************************************************************************/ +uint8_t LlGetIsoRxBufs(void) +{ + LL_TRACE_INFO1("### LlApi ### LlGetIsoRxBufs, numBufs=%u", pLctrRtCfg->numIsoRxBuf); + + return pLctrRtCfg->numIsoRxBuf; +} + +/*************************************************************************************************/ +/*! + * \brief Read ISO link Quality stats. + * + * \param handle connection handle. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlReadIsoLinkQual(uint16_t handle, LlIsoLinkQual_t * pStats) +{ + LL_TRACE_INFO1("### LlApi ### LlReadIsoLinkQual, handle=%u", handle); + + return LctrReadIsoLinkQual(handle, pStats); +} + +/*************************************************************************************************/ +/*! + * \brief Initialize LL for use with an audio codec. + */ +/*************************************************************************************************/ +void LlInitCodec(void) +{ + LctrInitCodec(); +} + +/*************************************************************************************************/ +/*! + * \brief Send an ISO data packet. + * + * \param pData Data buffer + * + * Send an ISO data packet. pData points to an ACL buffer formatted according to [1]; the host + * must set the connection handle, flags, and length fields in the buffer. + */ +/*************************************************************************************************/ +void LlSendIsoData(uint8_t *pData) +{ + if (lmgrIsoCb.availTxBuf == 0) + { + LL_TRACE_WARN0("!!! ISO flow control detected; dropping Tx data PDU"); + + /* Drop packet. */ + WsfMsgFree(pData); + return; + } + + LctrTxIso(pData); +} + +/*************************************************************************************************/ +/*! + * \brief Receive an ISO data packet + * + * \return Data buffer. + * + * Receive an ISO data packet. This function returns a pointer to an ISO buffer formatted + * according to [1]. The host must parse the header to determine the connection handle, flags, + * and length fields. If no ISO buffers are available this function returns NULL. + * + * The host must deallocate the buffer by calling WsfMsgFree() and then calling + * LlRecvIsoDataComplete(). + */ +/*************************************************************************************************/ +uint8_t *LlRecvIsoData(void) +{ + return LctrRxIso(); +} + +/*************************************************************************************************/ +/*! + * \brief Indicate that received ISO data buffer has been deallocated + * + * \param numBufs Number of completed packets. + * + * Indicate that received ISO data buffer has been deallocated. + */ +/*************************************************************************************************/ +void LlRecvIsoDataComplete(uint8_t numBufs) +{ + LctrRxIsoComplete(numBufs); +} + +/*************************************************************************************************/ +/*! + * \brief Used to identify and enable the isochronous data path between the host and the + * controller for each connected isochronous or broadcast isochronous stream. + * + * \param handle BIS or CIS handle. + * \param pPktSn Packet sequence number. + * \param pTs Timestamp. + * \param pTimeOffs Time offset. + * + * \return Status error code. + */ +/*************************************************************************************************/ +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 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. + */ +/*************************************************************************************************/ +uint8_t LlSetupIsoDataPath(LlIsoSetupDataPath_t *pSetupDataPath) +{ + LL_TRACE_INFO3("### LlApi ### LlSetupIsoDataPath, handle=%u, dpDir=%u, dpId=%u", pSetupDataPath->handle, pSetupDataPath->dpDir, pSetupDataPath->dpId); + + return LctrSetupIsoDataPath(pSetupDataPath); +} + +/*************************************************************************************************/ +/*! + * \brief Used to remove the isochronous data path associated with the + * connected isochronous stream or broadcast isochronous stream. + * + * \param handle CIS or BIS handle. + * \param dpDir Direction of data path to remove. + */ +/*************************************************************************************************/ +uint8_t LlRemoveIsoDataPath(uint16_t handle, uint8_t dpDir) +{ + LL_TRACE_INFO2("### LlApi ### LlRemoveIsoDataPath, handle=%u, dpDir=%u", handle, dpDir); + + return LctrRemoveIsoDataPath(handle, dpDir); +} + +/*************************************************************************************************/ +/*! + * \brief Enable ISO Tx test. + * + * \param handle CIS or BIS handle. + * \param pldType Payload type. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlIsoTxTest(uint16_t handle, uint8_t pldType) +{ + LL_TRACE_INFO2("### LlApi ### LlIsoTxTest handle=%d pldType=%d", handle, pldType); + + return LctrIsoTxTest(handle, pldType); +} + +/*************************************************************************************************/ +/*! + * \brief Enable ISO Rx test. + * + * \param handle CIS or BIS handle. + * \param pldType Payload type. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlIsoRxTest(uint16_t handle, uint8_t pldType) +{ + LL_TRACE_INFO2("### LlApi ### LlIsoRxTest handle=%d pldType=%d", handle, pldType); + + return LctrIsoRxTest(handle, pldType); +} + +/*************************************************************************************************/ +/*! + * \brief ISO read test counter. + * + * \param handle CIS or BIS handle. + * \param pCtr Test Counter. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlIsoReadTestCounter(uint16_t handle, LlIsoTestCtrs_t *pCtr) +{ + LL_TRACE_INFO1("### LlApi ### LlIsoReadTestCounter handle=%d", handle); + + LctrIsoReadTestCounter(handle, pCtr); + + return LL_SUCCESS; +} + +/*************************************************************************************************/ +/*! + * \brief Terminate ISO Tx or Rx test. + * + * \param handle CIS or BIS handle. + * \param pCtr Test counters. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlIsoTestEnd(uint16_t handle, LlIsoTestCtrs_t *pCtr) +{ + LL_TRACE_INFO1("### LlApi ### LlIsoTestEnd handle=%d", handle); + + return LctrIsoTestEnd(handle, pCtr); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_past.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_past.c index 556beec205..b41f7b9c01 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_past.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_past.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) Periodic advertising sync transfer interface implementation file. + * \file + * + * \brief Link layer (LL) Periodic advertising sync transfer interface implementation file. + * + * Copyright (c) 2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_pc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_pc.c new file mode 100644 index 0000000000..a67db0f51c --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_pc.c @@ -0,0 +1,101 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer (LL) power control interface implementation file. + * + * Copyright (c) 2019 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 "ll_api.h" +#include "lctr_api_conn.h" +#include "lmgr_api.h" +#include "lmgr_api_conn.h" +#include "wsf_assert.h" +#include "wsf_cs.h" +#include "wsf_msg.h" +#include "wsf_trace.h" +#include +#include "lctr_api_pc.h" + +/*************************************************************************************************/ +/*! + * \brief Set path loss monitoring parameters. + * + * \param handle Handle identifier for connection. + * \param highThresh High extreme threshold. + * \param highHyst High extreme hysteresis. + * \param lowThresh Low extreme threshold. + * \param lowHyst Low extreme hysteresis. + * \param minTime Minimum time spent to trigger event generation. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlSetPathLossReportingParams(uint16_t handle, uint8_t highThresh, uint8_t highHyst, uint8_t lowThresh, uint8_t lowHyst, uint16_t minTime) +{ + LL_TRACE_INFO0("### LlApi ### LlSetPathLossReportingParams"); + + if ((LL_API_PARAM_CHECK == 1) && + ((handle >= pLctrRtCfg->maxConn) || + !LctrIsConnHandleEnabled(handle))) + { + return LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + + if (highThresh == LL_PC_PATH_LOSS_UNUSED_HIGH_THRESHOLD) + { + highHyst = 0; + } + + if ((((uint16_t) highThresh + (uint16_t) highHyst) > 0x00FF) || + (lowThresh < lowHyst)) + { + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + + if ((lowThresh > highThresh) || + ((lowThresh + lowHyst) > (highThresh - highHyst))) + { + return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; + } + + return lctrSetPathLossReportingParams(handle, highThresh, highHyst, lowThresh, lowHyst, minTime); +} + +/*************************************************************************************************/ +/*! + * \brief Set path loss enable. + * + * \param handle Connection handle. + * \param enable Enable flag. + * + * \return Status error code. + */ +/*************************************************************************************************/ +uint8_t LlSetPathLossReportingEnable(uint16_t handle, uint8_t enable) +{ + LL_TRACE_INFO0("### LlApi ### LlSetPathLossReportingEnable"); + + if ((LL_API_PARAM_CHECK == 1) && + ((handle >= pLctrRtCfg->maxConn) || + !LctrIsConnHandleEnabled(handle))) + { + return LL_ERROR_CODE_UNKNOWN_CONN_ID; + } + + return lctrSetPathLossReportingEnable(handle, enable); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_phy.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_phy.c index ef70602aee..c0c28308f1 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_phy.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_phy.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) PHY features control interface implementation file. + * \file + * + * \brief Link layer (LL) PHY features control interface implementation file. + * + * Copyright (c) 2016-2019 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ @@ -106,7 +107,7 @@ static uint8_t llValidatePhyPreferences(uint8_t allPhys, uint8_t txPhys, uint8_t * \return TRUE if all specified PHYs are supported. */ /*************************************************************************************************/ -static bool_t llValidatePhySupport(uint8_t txPhys, uint8_t rxPhys) +bool_t llValidatePhySupport(uint8_t txPhys, uint8_t rxPhys) { if (((lmgrCb.features & LL_FEAT_LE_2M_PHY) == 0) && ((txPhys & LL_PHYS_LE_2M_BIT) || (rxPhys & LL_PHYS_LE_2M_BIT))) @@ -123,6 +124,7 @@ static bool_t llValidatePhySupport(uint8_t txPhys, uint8_t rxPhys) return TRUE; } + /*************************************************************************************************/ /*! * \brief Set default PHYs. diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_priv.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_priv.c index 9fe0938fa9..a6b909d4a6 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_priv.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_priv.c @@ -1,27 +1,29 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) privacy control interface implementation file. + * \file + * + * \brief Link layer (LL) privacy control interface implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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 "bb_ble_api_reslist.h" +#include "lctr_api.h" #include "lmgr_api.h" #include "lmgr_api_priv.h" #include "lctr_api_priv.h" @@ -29,6 +31,12 @@ #include "wsf_trace.h" #include "util/bstream.h" +/************************************************************************************************** + Globals +**************************************************************************************************/ +/*! \brief Function pointer for periodic sync pending check. */ +LctrPerSyncPendFn_t LctrMstPerSyncPending; + /*************************************************************************************************/ /*! * \brief Add device to resolving list. @@ -52,7 +60,12 @@ uint8_t LlAddDeviceToResolvingList(uint8_t peerAddrType, const uint8_t *pPeerIde { return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; } - if ((lmgrCb.advEnabled || lmgrCb.numExtAdvEnabled || lmgrCb.numScanEnabled || lmgrCb.numInitEnabled) && lmgrCb.addrResEna) + if ((lmgrCb.advEnabled || + lmgrCb.numExtAdvEnabled || + lmgrCb.numScanEnabled || + lmgrCb.numInitEnabled || + (LctrMstPerSyncPending && LctrMstPerSyncPending())) + && lmgrCb.addrResEna) { return LL_ERROR_CODE_CMD_DISALLOWED; } @@ -88,7 +101,12 @@ uint8_t LlRemoveDeviceFromResolvingList(uint8_t peerAddrType, const uint8_t *pPe { return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; } - if ((lmgrCb.advEnabled || lmgrCb.numExtAdvEnabled || lmgrCb.numScanEnabled || lmgrCb.numInitEnabled) && lmgrCb.addrResEna) + if ((lmgrCb.advEnabled || + lmgrCb.numExtAdvEnabled || + lmgrCb.numScanEnabled || + lmgrCb.numInitEnabled || + (LctrMstPerSyncPending && LctrMstPerSyncPending())) + && lmgrCb.addrResEna) { return LL_ERROR_CODE_CMD_DISALLOWED; } @@ -116,7 +134,12 @@ uint8_t LlClearResolvingList(void) { LL_TRACE_INFO0("### LlApi ### LlClearResolvingList"); - if ((lmgrCb.advEnabled || lmgrCb.numExtAdvEnabled || lmgrCb.numScanEnabled || lmgrCb.numInitEnabled) && lmgrCb.addrResEna) + if ((lmgrCb.advEnabled || + lmgrCb.numExtAdvEnabled || + lmgrCb.numScanEnabled || + lmgrCb.numInitEnabled || + (LctrMstPerSyncPending && LctrMstPerSyncPending())) + && lmgrCb.addrResEna) { return LL_ERROR_CODE_CMD_DISALLOWED; } @@ -240,7 +263,11 @@ uint8_t LlSetAddrResolutionEnable(uint8_t enable) { return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; } - if (lmgrCb.advEnabled || lmgrCb.numExtAdvEnabled || lmgrCb.numScanEnabled || lmgrCb.numInitEnabled) + if (lmgrCb.advEnabled || + lmgrCb.numExtAdvEnabled || + lmgrCb.numScanEnabled || + lmgrCb.numInitEnabled || + (LctrMstPerSyncPending && LctrMstPerSyncPending())) { return LL_ERROR_CODE_CMD_DISALLOWED; } @@ -302,7 +329,12 @@ uint8_t LlSetPrivacyMode(uint8_t peerAddrType, const uint8_t *pPeerIdentityAddr, return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; } - if ((lmgrCb.advEnabled || lmgrCb.numExtAdvEnabled || lmgrCb.numScanEnabled || lmgrCb.numInitEnabled) && lmgrCb.addrResEna) + if ((lmgrCb.advEnabled || + lmgrCb.numExtAdvEnabled || + lmgrCb.numScanEnabled || + lmgrCb.numInitEnabled || + (LctrMstPerSyncPending && LctrMstPerSyncPending())) + && lmgrCb.addrResEna) { return LL_ERROR_CODE_CMD_DISALLOWED; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_sc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_sc.c index b5c8a52358..a233fdaef1 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_sc.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_main_sc.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link layer (LL) secure connections control interface file. + * \file + * + * \brief Link layer (LL) secure connections control interface file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_math.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_math.c index d06c1162c7..5f1cd7da70 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_math.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/ll/ll_math.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Common math utilities generic implementation file. + * \file + * + * \brief Common math utilities generic implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -37,9 +38,7 @@ static uint32_t wsfRngZ = 521288629; /*!< Z seed for random number generation /*! * \brief Initialize random number seeds. * - * \param seed Pointer to initial seed for random numbers. - * - * \return None. + * \param pSeed Pointer to initial seed for random numbers. */ /*************************************************************************************************/ void LlMathSetSeed(const uint32_t *pSeed) @@ -104,28 +103,54 @@ uint8_t LlMathGetNumBitsSet(uint64_t num) /*************************************************************************************************/ uint32_t LlMathDivideUint32(uint32_t nu32, uint32_t de32) { - uint32_t temp = 1; - uint32_t result = 0; - uint64_t nu = nu32; - uint64_t de = de32; - - while (de <= nu) + #if (defined(__ARM_ARCH_EXT_IDIV__) && (__ARM_ARCH_EXT_IDIV__)) { - de <<= 1; - temp <<= 1; + /* Use divide instruction. */ + return nu32 / de32; } - - while (temp > 1) + #else { - de >>= 1; - temp >>= 1; + /* Use algorithmic divide. */ - if (nu >= de) + uint32_t temp = 1; + uint32_t result = 0; + uint64_t nu = nu32; + uint64_t de = de32; + + while (de <= nu) { - nu -= de; - result += temp; + de <<= 1; + temp <<= 1; } - } - return result; + while (temp > 1) + { + de >>= 1; + temp >>= 1; + + if (nu >= de) + { + nu -= de; + result += temp; + } + } + + return result; + } + #endif +} + +/*************************************************************************************************/ +/*! + * \brief Return result of a division, rounding up. + * + * \param nu32 Numerator of size 32 bits. + * \param de32 Denominator of size 32 bits. + * + * \return Result of a division. + */ +/*************************************************************************************************/ +uint32_t LlMathDivideUint32RoundUp(uint32_t nu32, uint32_t de32) +{ + return LlMathDivideUint32((nu32 + (de32 - 1)), de32); } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_events.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_events.c index 0f31a09a88..2d1bdc74a5 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_events.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_events.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link controller manager event implementation file. + * \file + * + * \brief Link controller manager event implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -33,8 +34,6 @@ * \brief Send advertising enable confirm. * * \param status Confirm status. - * - * \return None. */ /*************************************************************************************************/ void LmgrSendAdvEnableCnf(uint8_t status) @@ -55,8 +54,6 @@ void LmgrSendAdvEnableCnf(uint8_t status) * \brief Send scan enable confirm. * * \param status Confirm status. - * - * \return None. */ /*************************************************************************************************/ void LmgrSendScanEnableCnf(uint8_t status) @@ -80,8 +77,6 @@ void LmgrSendScanEnableCnf(uint8_t status) * \param status Confirm status. * \param connHandle Connection handle. * \param numEvents Number of completed events. - * - * \return None. */ /*************************************************************************************************/ void LmgrSendAdvSetTermInd(uint8_t handle, uint8_t status, uint16_t connHandle, uint8_t numEvents) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main.c index 05c1f8293f..966106a9ca 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link manager common implementation file. + * \file + * + * \brief Link manager common implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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 "ll_math.h" @@ -41,8 +42,6 @@ lmgrCtrlBlk_t lmgrCb; /*! * \brief Set default values. * - * \return None. - * * Restore default values to fields that require initial state after reset. Values that * survive reset are unchanged. */ @@ -83,18 +82,15 @@ void LmgrSetDefaults(void) 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; - LhciSetDefaultHciSupCmd(lmgrCb.hciSupCommands); - lmgrCb.chanClass = LL_CHAN_DATA_ALL; } /*************************************************************************************************/ /*! * \brief Increment reset delay counter. - * - * \return None. */ /*************************************************************************************************/ void LmgrIncResetRefCount(void) @@ -105,8 +101,6 @@ void LmgrIncResetRefCount(void) /*************************************************************************************************/ /*! * \brief Decrement reset delay counter. - * - * \return None. */ /*************************************************************************************************/ void LmgrDecResetRefCount(void) @@ -118,8 +112,6 @@ void LmgrDecResetRefCount(void) /*************************************************************************************************/ /*! * \brief Increment whitelist filter enable counter. - * - * \return None. */ /*************************************************************************************************/ void LmgrIncWhitelistRefCount(void) @@ -130,8 +122,6 @@ void LmgrIncWhitelistRefCount(void) /*************************************************************************************************/ /*! * \brief Decrement whitelist filter enable counter. - * - * \return None. */ /*************************************************************************************************/ void LmgrDecWhitelistRefCount(void) @@ -143,8 +133,6 @@ void LmgrDecWhitelistRefCount(void) /*************************************************************************************************/ /*! * \brief Increment periodiclist filter enable counter. - * - * \return None. */ /*************************************************************************************************/ void LmgrIncPeriodiclistRefCount(void) @@ -155,8 +143,6 @@ void LmgrIncPeriodiclistRefCount(void) /*************************************************************************************************/ /*! * \brief Decrement periodiclist filter enable counter. - * - * \return None. */ /*************************************************************************************************/ void LmgrDecPeriodiclistRefCount(void) @@ -242,8 +228,6 @@ bool_t LmgrIsExtCommandAllowed(void) * \brief Build channel remapping table. * * \param pChanParam Channel parameters. - * - * \return None. */ /*************************************************************************************************/ void LmgrBuildRemapTable(lmgrChanParam_t *pChanParam) @@ -346,8 +330,6 @@ uint8_t LmgrSelectNextChannel(lmgrChanParam_t *pChanParam, uint16_t eventCounter uint16_t unmapChan = LL_MATH_MOD_37(prn_e & 0xFFFF); - pChanParam->lastChanIdx = unmapChan; - /* remappingIndex */ if (!((UINT64_C(1) << unmapChan) & pChanParam->chanMask)) @@ -395,7 +377,7 @@ uint8_t LmgrSelectNextSubEvtChannel(lmgrChanParam_t *pChanParam) /* Subevent pseudo random number generator. */ prn = lmgrCalcPerm(prn); - prn = lmgrCalcMAM(prn, pChanParam->chIdentifier); /* prn is prnSubEvent_lu*/ + prn = lmgrCalcMAM(prn, pChanParam->chIdentifier); /* prn is prnSubEvent_lu */ pChanParam->prnLast = prn; @@ -413,15 +395,3 @@ uint8_t LmgrSelectNextSubEvtChannel(lmgrChanParam_t *pChanParam) return pChanParam->chanRemapTbl[subEvtIdx]; } - -/*************************************************************************************************/ -/*! - * \brief Lmgr Read HCI Supported cmd - * - * \return Supported command bitmask table. - */ -/*************************************************************************************************/ -uint8_t * LmgrReadHciSupCmd(void) -{ - return lmgrCb.hciSupCommands; -} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_adv_master_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_adv_master_ae.c index fdc2855634..8431c81778 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_adv_master_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_adv_master_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link manager extended scan implementation file. + * \file + * + * \brief Link manager extended scan implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -30,8 +31,6 @@ * \brief Send extended scan enable confirm. * * \param status Confirm status. - * - * \return None. */ /*************************************************************************************************/ void LmgrSendExtScanEnableCnf(uint8_t status) @@ -68,8 +67,6 @@ void LmgrSendExtScanEnableCnf(uint8_t status) /*************************************************************************************************/ /*! * \brief Send scan timeout indication. - * - * \return None. */ /*************************************************************************************************/ void LmgrSendScanTimeoutInd(void) @@ -90,8 +87,6 @@ void LmgrSendScanTimeoutInd(void) * \brief Send extended advertising report indication. * * \param pEvt Extended advertising report event. - * - * \return None. */ /*************************************************************************************************/ void LmgrSendExtAdvRptInd(LlExtAdvReportInd_t *pEvt) @@ -132,8 +127,6 @@ void LmgrSendPerAdvRptInd(LlPerAdvReportInd_t *pEvt) * \param status Confirm status. * \param handle Sync handle. * \param pEvt Periodic advertising sync established event. - * - * \return None. */ /*************************************************************************************************/ void LmgrSendSyncEstInd(uint8_t status, uint16_t handle, lmgrPerAdvSyncEstdInd_t *pEvt) @@ -165,8 +158,6 @@ void LmgrSendSyncEstInd(uint8_t status, uint16_t handle, lmgrPerAdvSyncEstdInd_t * \brief Send periodic advertising sync lost event. * * \param handle Sync handle. - * - * \return None. */ /*************************************************************************************************/ void LmgrSendSyncLostInd(uint16_t handle) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_adv_slave_ae.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_adv_slave_ae.c index f30900ea39..c939415732 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_adv_slave_ae.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_adv_slave_ae.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link manager extended advertising implementation file. + * \file + * + * \brief Link manager extended advertising implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -32,8 +33,6 @@ * * \param handle Advertising handle. * \param status Confirm status. - * - * \return None. */ /*************************************************************************************************/ void LmgrSendExtAdvEnableCnf(uint8_t handle, uint8_t status) @@ -76,8 +75,6 @@ void LmgrSendExtAdvEnableCnf(uint8_t handle, uint8_t status) * \param handle Advertising handle. * \param scanAddrType Scanner address type. * \param scanAddr Scanner address. - * - * \return None. */ /*************************************************************************************************/ void LmgrSendScanReqReceivedInd(uint8_t handle, uint8_t scanAddrType, uint64_t scanAddr) @@ -108,8 +105,6 @@ void LmgrSendScanReqReceivedInd(uint8_t handle, uint8_t scanAddrType, uint64_t s * * \param handle Advertising handle. * \param status Confirm status. - * - * \return None. */ /*************************************************************************************************/ void LmgrSendPeriodicAdvEnableCnf(uint8_t handle, uint8_t status) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_cis_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_cis_master.c new file mode 100644 index 0000000000..0d5d5ec5d3 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_cis_master.c @@ -0,0 +1,60 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link manager connected isochronous stream master role implementation file. + * + * Copyright (c) 2013-2018 ARM Ltd. All Rights Reserved. + * + * 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 "lmgr_api_cis_master.h" +#include "lctr_api.h" +#include + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*! \brief Master role device parameters. */ +lmgrCisMstCtrlBlk_t lmgrCisMstCb; + +/*************************************************************************************************/ +/*! + * \brief Initialize link layer manager master mode resources. + */ +/*************************************************************************************************/ +void LmgrMstCisInit(void) +{ + memset(&lmgrCisMstCb, 0, sizeof(lmgrCisMstCb)); + + lmgrCisMstCb.maxNumCis = pLctrRtCfg->maxCis; + + /* lmgrCisMstCb.numCisPend = 0; */ /* Clear by default */ +} + +/*************************************************************************************************/ +/*! + * \brief Get the maximum number of CIS. + * + * \return Maximum number of CIS. + */ +/*************************************************************************************************/ +uint8_t LmgrMstCisGetMaxNumCis(void) +{ + return lmgrCisMstCb.maxNumCis; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_conn.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_conn.c index 2bc8c3c946..74b2e09fe8 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_conn.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_conn.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link manager connection implementation file. + * \file + * + * \brief Link manager connection implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -36,8 +37,6 @@ lmgrConnCtrlBlk_t lmgrConnCb; /*************************************************************************************************/ /*! * \brief Initialize link layer manager connection resources. - * - * \return None. */ /*************************************************************************************************/ void LmgrConnInit(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_iso.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_iso.c new file mode 100644 index 0000000000..6cf9068eeb --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_iso.c @@ -0,0 +1,52 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link manager connected isochronous stream implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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 "bb_ble_api.h" +#include "lctr_api.h" +#include +#include "lmgr_api_iso.h" + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*! \brief Isochronous control block. */ +lmgrIsoCtrlBlk_t lmgrIsoCb; + +/*************************************************************************************************/ +/*! + * \brief Initialize link layer manager connection resources. + */ +/*************************************************************************************************/ +void LmgrIsoInit(void) +{ + memset(&lmgrIsoCb, 0, sizeof(lmgrIsoCb)); + + lmgrIsoCb.availTxBuf = pLctrRtCfg->numIsoTxBuf; + lmgrIsoCb.availRxBuf = pLctrRtCfg->numIsoRxBuf; + + lmgrIsoCb.allPhys = LL_ALL_PHY_TX_PREFERENCE_BIT | LL_ALL_PHY_RX_PREFERENCE_BIT; + lmgrIsoCb.rxPhys = LL_PHYS_NONE; + lmgrIsoCb.txPhys = LL_PHYS_NONE; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_master.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_master.c index 0397559ef5..0f59cb7161 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_master.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_master.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link manager master role implementation file. + * \file + * + * \brief Link manager master role implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -35,8 +36,6 @@ lmgrMstScanCtrlBlk_t lmgrMstScanCb; /*************************************************************************************************/ /*! * \brief Initialize link layer manager master mode resources. - * - * \return None. */ /*************************************************************************************************/ void LmgrMstInit(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_priv.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_priv.c index b31db6420b..9415685dbe 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_priv.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_priv.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link manager privacy implementation file. + * \file + * + * \brief Link manager privacy implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -35,8 +36,6 @@ lmgrPrivCtrlBlk_t lmgrPrivCb; /*************************************************************************************************/ /*! * \brief Initialize link layer manager privacy resources. - * - * \return None. */ /*************************************************************************************************/ void LmgrPrivInit(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_sc.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_sc.c index 921564fa7c..5d82b156ee 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_sc.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_sc.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link manager secure connections implementation file. + * \file + * + * \brief Link manager secure connections implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -35,8 +36,6 @@ lmgrScCtrlBlk_t lmgrScCb; /*************************************************************************************************/ /*! * \brief Initialize link layer manager connection resources. - * - * \return None. */ /*************************************************************************************************/ void LmgrScInit(void) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_slave.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_slave.c index 56eca1ba05..bf67cd2823 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_slave.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/lmgr/lmgr_main_slave.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Link manager slave role implementation file. + * \file + * + * \brief Link manager slave role implementation file. + * + * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -36,16 +37,14 @@ lmgrSlvAdvCtrlBlk_t lmgrSlvAdvCb; /*************************************************************************************************/ /*! * \brief Initialize link layer manager slave mode resources. - * - * \return None. */ /*************************************************************************************************/ void LmgrSlvInit(void) { static const lmgrAdvParam_t defAdvParam = { - .advInterMin = 0x0800, - .advInterMax = 0x0800, + .advInterMinUsec = BB_BLE_TO_US(0x0800), + .advInterMaxUsec = BB_BLE_TO_US(0x0800), .advType = LL_ADV_CONN_UNDIRECT, .ownAddrType = LL_ADDR_PUBLIC, .peerAddrType = LL_ADDR_PUBLIC, @@ -59,9 +58,4 @@ void LmgrSlvInit(void) lmgrSlvAdvCb.defTxPhyOpts = BB_PHY_OPTIONS_BLE_S8; lmgrSlvAdvCb.advParam = defAdvParam; - /* The maximum adv interval is 0x4000 and it times 625 still fits in uint32_t. */ - /* coverity[overflow_before_widen] */ - lmgrSlvAdvCb.advParam.advInterMin = BB_BLE_TO_BB_TICKS(lmgrSlvAdvCb.advParam.advInterMin); - /* coverity[overflow_before_widen] */ - lmgrSlvAdvCb.advParam.advInterMax = BB_BLE_TO_BB_TICKS(lmgrSlvAdvCb.advParam.advInterMax); } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_ble.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_ble.c index 5f1677378e..0c12985f63 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_ble.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_ble.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief BLE protocol scheduler implementation file. + * \file + * + * \brief BLE protocol scheduler implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -67,13 +68,13 @@ uint32_t SchBleCalcDataPktDurationUsec(uint8_t phy, uint16_t len) switch (phy) { case BB_PHY_BLE_1M: - duration += LL_DATA_LEN_TO_TIME_1M(len); + duration += LL_DATA_LEN_TO_TIME_1M(len, TRUE); break; case BB_PHY_BLE_2M: - duration += LL_DATA_LEN_TO_TIME_2M(len); + duration += LL_DATA_LEN_TO_TIME_2M(len, TRUE); break; case BB_PHY_BLE_CODED: - duration += LL_DATA_LEN_TO_TIME_CODED_S8(len); + duration += LL_DATA_LEN_TO_TIME_CODED_S8(len, TRUE); break; } @@ -122,8 +123,10 @@ uint32_t SchBleCalcAdvPktDurationUsec(uint8_t phy, uint8_t phyOptions, uint16_t * \param fragLen Fragmentation length. * \param addMafDelay MAF offset to add on top of MAF. * \param len Data length to calculate. - * \param worseCase True if we want to calculate the worst case, false for predicted case. + * \param worstCase True if we want to calculate the worst case, false for predicted case. * \param phyOptions Phy option to use when calculating coded timing. + * + * \return Advertising duration in usec. */ /*************************************************************************************************/ uint32_t SchBleCalcPerAdvDurationUsec(uint8_t txPhy, uint8_t fragLen, uint16_t addMafDelay, uint16_t len, bool_t worstCase, uint8_t phyOptions) @@ -194,14 +197,12 @@ uint32_t SchBleCalcAuxPktDurationUsec(uint8_t phy, uint8_t phyOptions, uint16_t * \param pBod Operation to compute duration. * \param fragLen Fragmentation length. * - * \return None. - * * Compute all the actions time and assign the duration of the given BOD. */ /*************************************************************************************************/ void SchBleCalcAdvOpDuration(BbOpDesc_t *pBod, uint8_t fragLen) { - uint32_t usec = 0; + uint32_t minDurUsec = 0; WSF_ASSERT(pBod->protId == BB_PROT_BLE); @@ -219,32 +220,32 @@ void SchBleCalcAdvOpDuration(BbOpDesc_t *pBod, uint8_t fragLen) { case BB_PHY_BLE_1M: default: - usec = LL_ADVB_MAX_TIME_1M; + minDurUsec = LL_ADVB_MAX_TIME_1M; break; case BB_PHY_BLE_CODED: /* Assume longest time, coded S8. */ - usec = LL_ADVB_MAX_TIME_S8; + minDurUsec = LL_ADVB_MAX_TIME_S8; break; } if (pAdv->pTxReqBuf) { - usec += LL_BLE_TIFS_US; + minDurUsec += LL_BLE_TIFS_US; /* Coded PHY doesn't have pTxReqBuf on primary channel. BB_PHY_OPTIONS_DEFAULT is OK. */ - usec += SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, BB_PHY_OPTIONS_DEFAULT, pBle->op.mstAdv.txReqLen); + minDurUsec += SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, BB_PHY_OPTIONS_DEFAULT, pBle->op.mstAdv.txReqLen); if (pAdv->pRxRspBuf) { - usec += LL_BLE_TIFS_US; + minDurUsec += LL_BLE_TIFS_US; switch (pBle->chan.rxPhy) { case BB_PHY_BLE_1M: default: - usec += LL_ADVB_MAX_TIME_1M; + minDurUsec += LL_ADVB_MAX_TIME_1M; break; case BB_PHY_BLE_CODED: /* Assume longest time, coded S8. */ - usec += LL_ADVB_MAX_TIME_S8; + minDurUsec += LL_ADVB_MAX_TIME_S8; break; } } @@ -267,28 +268,28 @@ void SchBleCalcAdvOpDuration(BbOpDesc_t *pBod, uint8_t fragLen) WSF_ASSERT(numChan > 0); - usec = (numChan - 1) * SchBleGetAlignedAuxOffsUsec(pktDuration + BbGetSchSetupDelayUs()); - usec += pktDuration; /* For the last channel. */ + minDurUsec = (numChan - 1) * SchBleGetAlignedAuxOffsUsec(pktDuration + BbGetSchSetupDelayUs()); + minDurUsec += pktDuration; /* For the last channel. */ if (pAdv->pRxReqBuf) { - usec += (LL_BLE_TIFS_US * numChan); + minDurUsec += (LL_BLE_TIFS_US * numChan); switch (pBle->chan.rxPhy) { case BB_PHY_BLE_1M: default: - usec += (LL_ADVB_MAX_TIME_1M * numChan); + minDurUsec += (LL_ADVB_MAX_TIME_1M * numChan); break; case BB_PHY_BLE_CODED: /* Assume longest time, coded S8. */ - usec += (LL_ADVB_MAX_TIME_S8 * numChan); + minDurUsec += (LL_ADVB_MAX_TIME_S8 * numChan); break; } if (pAdv->pTxRspBuf) { - usec += (LL_BLE_TIFS_US * numChan); + minDurUsec += (LL_BLE_TIFS_US * numChan); /* Coded PHY doesn't have pTxRspBuf on primary channel. BB_PHY_OPTIONS_DEFAULT is OK. */ - usec += (SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, BB_PHY_OPTIONS_DEFAULT, pBle->op.mstAdv.txReqLen) * numChan); + minDurUsec += (SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, BB_PHY_OPTIONS_DEFAULT, pBle->op.mstAdv.txReqLen) * numChan); } } break; @@ -304,41 +305,41 @@ void SchBleCalcAdvOpDuration(BbOpDesc_t *pBod, uint8_t fragLen) { case BB_PHY_BLE_1M: default: - usec = LL_EXT_ADVB_MAX_TIME_1M; + minDurUsec = LL_EXT_ADVB_MAX_TIME_1M; break; case BB_PHY_BLE_2M: - usec = LL_EXT_ADVB_MAX_TIME_2M; + 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. - usec = LL_EXT_ADVB_NORMAL_TIME_S8; + /* 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; } if (pAdv->pTxAuxReqBuf) { - usec += LL_BLE_TIFS_US; - /*if TIFS has preference, it should use this value. Otherwise, it will assume longest time, codes S8. */ - usec += SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, (pBle->chan.tifsTxPhyOptions != BB_PHY_OPTIONS_DEFAULT) ? pBle->chan.tifsTxPhyOptions : BB_PHY_OPTIONS_BLE_S8, pAdv->txAuxReqLen); + minDurUsec += LL_BLE_TIFS_US; + /* If TIFS has preference, it should use this value. Otherwise, it will assume longest time, codes S8. */ + minDurUsec += SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, (pBle->chan.tifsTxPhyOptions != BB_PHY_OPTIONS_DEFAULT) ? pBle->chan.tifsTxPhyOptions : BB_PHY_OPTIONS_BLE_S8, pAdv->txAuxReqLen); - usec += LL_BLE_TIFS_US; + minDurUsec += LL_BLE_TIFS_US; switch (pBle->chan.rxPhy) { case BB_PHY_BLE_1M: default: - usec += LL_EXT_ADVB_MAX_TIME_1M; + minDurUsec += LL_EXT_ADVB_MAX_TIME_1M; break; case BB_PHY_BLE_2M: - usec += LL_EXT_ADVB_MAX_TIME_2M; + minDurUsec += LL_EXT_ADVB_MAX_TIME_2M; break; case BB_PHY_BLE_CODED: /* Assume longest time, coded S8. */ - usec += LL_EXT_ADVB_MAX_TIME_S8; + minDurUsec += LL_EXT_ADVB_MAX_TIME_S8; break; } } @@ -350,24 +351,24 @@ void SchBleCalcAdvOpDuration(BbOpDesc_t *pBod, uint8_t fragLen) { case BB_PHY_BLE_1M: default: - usec = LL_EXT_ADVB_MAX_TIME_1M; + minDurUsec = LL_EXT_ADVB_MAX_TIME_1M; break; case BB_PHY_BLE_2M: - usec = LL_EXT_ADVB_MAX_TIME_2M; + minDurUsec = LL_EXT_ADVB_MAX_TIME_2M; break; case BB_PHY_BLE_CODED: /* Assume longest time, coded S8. */ - usec = LL_EXT_ADVB_MAX_TIME_S8; + minDurUsec = LL_EXT_ADVB_MAX_TIME_S8; break; } if (pAdv->pTxAuxReqBuf) { - usec += LL_BLE_TIFS_US; + minDurUsec += LL_BLE_TIFS_US; /* Ff TIFS has preference, it should use this value. Otherwise, it will assume longest time, coded S8. */ - usec += SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, (pBle->chan.tifsTxPhyOptions != BB_PHY_OPTIONS_DEFAULT) ? pBle->chan.tifsTxPhyOptions : BB_PHY_OPTIONS_BLE_S8, LL_ADV_HDR_LEN + LL_CONN_IND_PDU_LEN); /* aux_conn_req */ - usec += LL_BLE_TIFS_US; + minDurUsec += SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, (pBle->chan.tifsTxPhyOptions != BB_PHY_OPTIONS_DEFAULT) ? pBle->chan.tifsTxPhyOptions : BB_PHY_OPTIONS_BLE_S8, LL_ADV_HDR_LEN + LL_CONN_IND_PDU_LEN); /* aux_conn_req */ + minDurUsec += LL_BLE_TIFS_US; /* Assume longest time, coded S8. */ - usec += SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, BB_PHY_OPTIONS_BLE_S8, LL_ADV_HDR_LEN + LL_CONN_RSP_PDU_LEN); /* aux_conn_rsp */ + minDurUsec += SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, BB_PHY_OPTIONS_BLE_S8, LL_ADV_HDR_LEN + LL_CONN_RSP_PDU_LEN); /* aux_conn_rsp */ } } break; @@ -383,25 +384,25 @@ void SchBleCalcAdvOpDuration(BbOpDesc_t *pBod, uint8_t fragLen) if (pAuxAdv->pRxAuxReqBuf) /* Scannable advertising */ { - usec += SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, pBle->chan.initTxPhyOptions, SCH_AUX_ADV_NO_CHAIN_HDR_LEN); - usec += LL_BLE_TIFS_US; + minDurUsec += SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, pBle->chan.initTxPhyOptions, SCH_AUX_ADV_NO_CHAIN_HDR_LEN); + minDurUsec += LL_BLE_TIFS_US; switch (pBle->chan.rxPhy) { case BB_PHY_BLE_1M: default: - usec += LL_EXT_ADVB_MAX_TIME_1M; + minDurUsec += LL_EXT_ADVB_MAX_TIME_1M; break; case BB_PHY_BLE_2M: - usec += LL_EXT_ADVB_MAX_TIME_2M; + minDurUsec += LL_EXT_ADVB_MAX_TIME_2M; break; case BB_PHY_BLE_CODED: /* Assume longest time, coded S8. */ - usec += LL_EXT_ADVB_MAX_TIME_S8; + minDurUsec += LL_EXT_ADVB_MAX_TIME_S8; break; } - usec += LL_BLE_TIFS_US; + minDurUsec += LL_BLE_TIFS_US; } extHeadLen = WSF_MAX(pAuxAdv->txAuxAdvPdu[0].len, SCH_AUX_ADV_NO_CHAIN_HDR_LEN); @@ -414,36 +415,35 @@ void SchBleCalcAdvOpDuration(BbOpDesc_t *pBod, uint8_t fragLen) if (dataLen <= maxDataBytesNoChain) { - usec += SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, pBle->chan.initTxPhyOptions, extHeadLen + dataLen); + minDurUsec += SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, pBle->chan.initTxPhyOptions, extHeadLen + dataLen); } else { uint16_t remDataLen; uint16_t numFragWithAuxPtr = dataLen / maxDataBytesWithChain; - usec += numFragWithAuxPtr * SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, pBle->chan.initTxPhyOptions, SCH_AUX_ADV_W_CHAIN_HDR_LEN + maxDataBytesWithChain); - usec += numFragWithAuxPtr * LL_BLE_MAFS_US; + minDurUsec += numFragWithAuxPtr * SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, pBle->chan.initTxPhyOptions, SCH_AUX_ADV_W_CHAIN_HDR_LEN + maxDataBytesWithChain); + minDurUsec += numFragWithAuxPtr * LL_BLE_MAFS_US; remDataLen = dataLen - (numFragWithAuxPtr * maxDataBytesWithChain); if (remDataLen) { - usec += SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, pBle->chan.initTxPhyOptions, SCH_AUX_ADV_NO_CHAIN_HDR_LEN + remDataLen); + minDurUsec += SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, pBle->chan.initTxPhyOptions, SCH_AUX_ADV_NO_CHAIN_HDR_LEN + remDataLen); } } - break; } case BB_BLE_OP_SLV_PER_ADV_EVENT: { /* The calculation for the periodic event is estimate here because we do not have information how optional header bytes are going to be filled later. */ - uint16_t dataLen = 0; + uint16_t dataLen = LL_EXT_ADV_HDR_MAX_LEN; if (pBod->pDataLen) { - dataLen = *pBod->pDataLen; + dataLen = WSF_MAX(dataLen, *pBod->pDataLen); } - usec = SchBleCalcPerAdvDurationUsec(pBle->chan.txPhy, 0, 0, dataLen, FALSE, pBle->chan.initTxPhyOptions); + minDurUsec = SchBleCalcPerAdvDurationUsec(pBle->chan.txPhy, 0, 0, dataLen, FALSE, pBle->chan.initTxPhyOptions); break; } case BB_BLE_OP_MST_PER_SCAN_EVENT: @@ -452,18 +452,18 @@ void SchBleCalcAdvOpDuration(BbOpDesc_t *pBod, uint8_t fragLen) { case BB_PHY_BLE_1M: default: - usec = LL_EXT_ADVB_MAX_TIME_1M; + minDurUsec = LL_EXT_ADVB_MAX_TIME_1M; break; case BB_PHY_BLE_2M: - usec = LL_EXT_ADVB_MAX_TIME_2M; + minDurUsec = LL_EXT_ADVB_MAX_TIME_2M; break; case BB_PHY_BLE_CODED: /* Setting min & max duration differently so that other BOD's can run after minDuration. */ /* 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. - usec = LL_EXT_ADVB_NORMAL_TIME_S8; + /* 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; } @@ -471,11 +471,11 @@ void SchBleCalcAdvOpDuration(BbOpDesc_t *pBod, uint8_t fragLen) } default: - usec = 0; + minDurUsec = 0; break; } - pBod->minDurUsec = usec; + pBod->minDurUsec = minDurUsec; } /*************************************************************************************************/ @@ -499,7 +499,7 @@ bool_t SchBleGetNextMstConnDueTime(uint32_t *pDueTime) if ((pCur->protId == BB_PROT_BLE) && (pCur->prot.pBle->chan.opType == BB_BLE_OP_MST_CONN_EVENT)) { - *pDueTime = pCur->due; + *pDueTime = pCur->dueUsec; return TRUE; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_int_rm.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_int_rm.h index 42924e4448..72342806fb 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_int_rm.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_int_rm.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal scheduler resource manager interface file. + * \file + * + * \brief Internal scheduler resource manager interface file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -45,17 +46,17 @@ extern "C" { #define SCH_RM_DIV_PREF_PER(n) ((uint32_t)(((uint64_t)(n) * UINT64_C(1717987)) >> 34)) /*! \brief Minimum offset unit of reservation manager in microseconds. (Half of minimum isochronous interval) */ -#define SCH_RM_MIN_OFFSET_UNIT 2500 +#define SCH_RM_MIN_OFFSET_UNIT_US 2500 -/*! \brief Distance between common reservation and uncommon reservation. */ -#define SCH_RM_OFFSET_UNCOMMON 3750 +/*! \brief Default distance in microseconds between common reservation and uncommon reservation. */ +#define SCH_RM_OFFSET_UNCOMMON_US 3750 + +/*! \brief Margin in microseconds from the duration of the common reservation to uncommon reservation. */ +#define SCH_RM_MARGIN_UNCOMMON_US 50 /*! \brief Maximum depth to be searched between intervals. (4 means 16 times(2^4) */ #define SCH_RM_MAX_SEARCH_DEPTH 4 -/*! \brief Maximum span of scheduler elements. */ -#define SCH_RM_MAX_SPAN 0x80000000 - /************************************************************************************************** Data Types **************************************************************************************************/ @@ -65,8 +66,9 @@ typedef struct { uint8_t handle; /*!< Reservation handle. */ bool_t commIntUsed; /*!< Reservation is controlled by common interval. */ - uint8_t offsetBit; /*! < Offset bit location. */ + uint8_t offsetBit; /*!< Offset bit location. */ uint32_t interUsec; /*!< Interval in microseconds. */ + uint32_t durUsec; /*!< Duration in microseconds. */ GetRefTimeCb_t refTimeCb; /*!< Callback function to get reference time of the handle. */ } schRmRsvn_t; @@ -94,6 +96,7 @@ extern SchRmCb_t schRmCb; **************************************************************************************************/ void schRmSortListDescending(uint32_t item[], uint8_t numItems); +uint8_t schRmIntCalculateDepth(uint32_t intLarge, uint32_t intSmall); #ifdef __cplusplus }; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_int_tm.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_int_tm.h new file mode 100644 index 0000000000..6929e21674 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_int_tm.h @@ -0,0 +1,88 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief BLE topology manager internal interface file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 SCH_INT_TM_H +#define SCH_INT_TM_H + +#include "sch_api.h" +#include "sch_api_ble.h" +#include "ll_math.h" +#include "cfg_mac_ble.h" +#include "pal_bb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief Maximum link amount. */ +#define SCH_TM_MAX_LINK (LL_MAX_CONN + LL_MAX_PER_SCAN + LL_MAX_CIG) + +/*! \brief Decide if given time is in the future compared to reference time. */ +#define SCH_TM_IS_IN_FUTURE(x, ref) (BbGetTargetTimeDelta(x, ref) > 0) + +/*! \brief Decide if given time is in the past compared to reference time. */ +#define SCH_TM_IS_IN_PAST(x, ref) (BbGetTargetTimeDelta(ref, x) > 0) + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief Topology link descriptor. */ +typedef struct +{ + bool_t enabled; /*!< TRUE if the link is enabled. */ + bool_t movable; /*!< TRUE if the link is movable. */ + uint32_t interUsec; /*!< Interval in microseconds. */ + uint32_t durUsec; /*!< Duration in microseconds. */ + GetTopRefTimeCb_t refTimeCb; /*!< Callback function to get reference time of the handle. */ +} schTmLink_t; + +/*! \brief Topology manager control block. */ +typedef struct +{ + schTmLink_t tlink[SCH_TM_MAX_LINK]; /*!< Information for each topology link. */ +} SchTmCb_t; + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +extern SchTmCb_t schTmCb; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +uint32_t SchTmGetFirstAnchor(uint32_t refTime, uint32_t defOffsUsec, uint32_t interUsec, uint32_t durUsec); +bool_t SchTmCheckConflict(uint32_t refBegin, uint32_t interUsec, uint32_t durUsec); + +#ifdef __cplusplus +}; +#endif + +#endif /* SCH_INT_TM_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_rm.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_rm.c index 3a0df954ce..812d7ce88f 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_rm.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_rm.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Operation list maintenance implementation file. + * \file + * + * \brief Operation list maintenance implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -55,6 +56,7 @@ /*************************************************************************************************/ #include "sch_int_rm.h" +#include "sch_int_tm.h" #include "wsf_assert.h" #include "wsf_math.h" #include @@ -69,8 +71,8 @@ WSF_CT_ASSERT((SCH_RM_MAX_RSVN <= 32)); /*! \brief Total number of reservation bins. */ #define SCH_RM_MAX_RSVN_BINS ((sizeof(schRmRsvnRatio)/sizeof(schRmRsvnRatio[0])) - 1) -/*! \brief Nominal window widening in microseconds in slave scheduler. */ -#define SCH_RM_SLAVE_WW_USECS 100 +/*! \brief Maximum number of attempts to add reservation. */ +#define SCH_RM_ADD_MAX_ATTEMPTS 3 /************************************************************************************************** Global Variables @@ -245,7 +247,7 @@ static bool_t schRmCheckRsvnCapacity(uint8_t handle, uint32_t interUsec) * \return Depth between intervals. */ /*************************************************************************************************/ -static uint8_t schRmIntCalculateDepth(uint32_t intLarge, uint32_t intSmall) +uint8_t schRmIntCalculateDepth(uint32_t intLarge, uint32_t intSmall) { uint8_t x; uint8_t depth = 0; @@ -253,7 +255,7 @@ static uint8_t schRmIntCalculateDepth(uint32_t intLarge, uint32_t intSmall) WSF_ASSERT(intLarge > intSmall); - for (x = 0; (x < SCH_RM_MAX_SEARCH_DEPTH) && (tmpInt > SCH_RM_MIN_OFFSET_UNIT); x++) + for (x = 0; (x < SCH_RM_MAX_SEARCH_DEPTH) && (tmpInt > SCH_RM_MIN_OFFSET_UNIT_US); x++) { tmpInt >>= 1; if (tmpInt == intSmall) @@ -272,16 +274,35 @@ static uint8_t schRmIntCalculateDepth(uint32_t intLarge, uint32_t intSmall) * * \param handle Client defined reservation handle. * \param depth Offset depth of the interval of the handle compared to maxConInt. + * \param interUsec Interval of the reservation in microseconds. + * \param durUsec Duration of the reservation in microseconds. * * \return TRUE if update was successful, FALSE otherwise.. */ /*************************************************************************************************/ -static bool_t schRmIntAddRmOffset(uint8_t handle, uint8_t depth) +static bool_t schRmIntAddRmOffset(uint8_t handle, uint8_t depth, uint32_t interUsec, uint32_t durUsec) { bool_t updated = FALSE; - uint8_t x, y, numBitsOn; + uint32_t offsetUnitUs = schRmCb.commonInt >> 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); + + /* If duration is 12ms while offset unit is 5ms, the reservation will occupy 3 consecutive offset bits. */ + while (durUsec >= offsetUnitUs) + { + numBitsPerRes++; + durUsec -= offsetUnitUs; + } + + if (numBitsPerRes > 1) + { + /* Need to duplicate rmStatus to check if the reservation has conflict with lowest bit offset. */ + tmpRmStatus |= (tmpRmStatus << (1 << schRmCb.offsetDepth)); + } for (x = 0; x < (1 << (schRmCb.offsetDepth - depth)); x++) { @@ -290,28 +311,48 @@ static bool_t schRmIntAddRmOffset(uint8_t handle, uint8_t depth) numBitsOn = 0; for (y = 0; y < (1 << depth); y++) { - if ((schRmCb.rmStatus >> ((1 << (schRmCb.offsetDepth - depth)) * y + x)) & 0x01) + for (z = 0; z < numBitsPerRes; z++) { - numBitsOn++; + if ((tmpRmStatus >> ((1 << (schRmCb.offsetDepth - depth)) * y + x + z)) & 0x01) + { + numBitsOn++; + } } } /* Found available offset bit(s). */ if (numBitsOn == 0) { + /* Check conflict with TM links. */ + if (schRmCb.rsvn[schRmCb.refHandle].refTimeCb != NULL) + { + uint32_t rmRefTime = schRmCb.rsvn[schRmCb.refHandle].refTimeCb(schRmCb.refHandle, NULL); + uint32_t targetTime = rmRefTime + (offsetUnitUs * x); + + if (SchTmCheckConflict(targetTime, interUsec, durUsec)) + { + /* Conflict is found, move on to next offset bits. */ + continue; + } + } + /* Set all the bits */ for (y = 0; y < (1 << depth); y++) { - schRmCb.rmStatus |= (0x01 << ((1 << (schRmCb.offsetDepth - depth)) * y + x)); + for (z = 0; z < numBitsPerRes; z++) + { + schRmCb.rmStatus |= (0x01 << ((1 << (schRmCb.offsetDepth - depth)) * y + x + z)); + } } schRmCb.rsvn[handle].offsetBit = x; schRmCb.rsvn[handle].commIntUsed = TRUE; updated = TRUE; - LL_TRACE_WARN2("schRmIntAddRmOffset, handle = %u, offsetDepth = %u", handle, schRmCb.offsetDepth); - LL_TRACE_WARN1(" rmStatus = 0x%x", schRmCb.rmStatus); - LL_TRACE_WARN1(" commonInt = %u", schRmCb.commonInt); + 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); break; } } @@ -325,42 +366,71 @@ static bool_t schRmIntAddRmOffset(uint8_t handle, uint8_t depth) * * \param depth Offset depth to be increased. * - * \return None. + * \return TRUE if offset depth was increased successfully, FALSE otherwise.. */ /*************************************************************************************************/ -static void schRmIntIncOffsetDepth(uint8_t depth) +static bool_t schRmIntIncOffsetDepth(uint8_t depth) { - uint32_t tmpStatus = schRmCb.rmStatus; - uint8_t x, handle; + uint8_t y, z, handle; + uint8_t numBitsPerRes, rsvnDepth; + uint32_t durUsec; + uint32_t offsetUnitUs = schRmCb.commonInt >> (schRmCb.offsetDepth + depth); - /* b'11 becomes b'00010001, when depth is 2. */ - schRmCb.rmStatus = 0; - for (x = 0; x < (1 << schRmCb.offsetDepth); x++) + /* Check if the offsetDepth will be valid after the increase. */ + if (offsetUnitUs < SCH_RM_MIN_OFFSET_UNIT_US) { - if ((tmpStatus >> x) & 0x01) - { - schRmCb.rmStatus |= (0x01 << (x * (1 << depth))); - } + return FALSE; } + schRmCb.rmStatus = 0; schRmCb.offsetDepth += depth; /* Update database according to the new offsetDepth. */ + /* rmStatus b'11 becomes b'00010001, when depth is 2. */ for (handle = 0; handle < SCH_RM_MAX_RSVN; handle++) { if (schRmCb.rsvn[handle].commIntUsed) { + numBitsPerRes = 1; /* Number of bit offsets to be occupied by the reservation. */ + durUsec = schRmCb.rsvn[handle].durUsec; + WSF_ASSERT(durUsec < schRmCb.commonInt); + + if (schRmCb.commonInt == schRmCb.rsvn[handle].interUsec) + { + rsvnDepth = 0; + } + else + { + rsvnDepth = schRmIntCalculateDepth(schRmCb.commonInt, schRmCb.rsvn[handle].interUsec); + WSF_ASSERT(rsvnDepth > 0); + } + + while (durUsec >= offsetUnitUs) + { + numBitsPerRes++; + durUsec -= offsetUnitUs; + } + /* For example, with depth 2, bit1 will move into bit4. */ schRmCb.rsvn[handle].offsetBit *= (1 << depth); + + /* Re-construct rmStatus */ + for (y = 0; y < (1 << rsvnDepth); y++) + { + for (z = 0; z < numBitsPerRes; z++) + { + schRmCb.rmStatus |= (0x01 << ((0x01 << (schRmCb.offsetDepth - rsvnDepth)) * y + schRmCb.rsvn[handle].offsetBit + z)); + } + } } } + + return TRUE; } /*************************************************************************************************/ /*! * \brief Decrease reservation manager offset depth by one if necessary. - * - * \return None. */ /*************************************************************************************************/ static void schRmIntCheckDecOffsetDepth(void) @@ -434,14 +504,30 @@ static void schRmIntCheckDecOffsetDepth(void) /*************************************************************************************************/ static void schRmIntRemoveRmOffset(uint8_t handle) { - uint8_t x, depth; + 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; if (schRmCb.rsvn[handle].commIntUsed) { + WSF_ASSERT(schRmCb.rsvn[handle].durUsec < schRmCb.commonInt); + + /* Check how many continuous bit offsets were occupied by this reservation. */ + durUsec = schRmCb.rsvn[handle].durUsec; + while (durUsec >= offsetUnitUs) + { + numBitsPerRes++; + durUsec -= offsetUnitUs; + } + /* The interval of this handle must be equal to or smaller than the common interval. */ if (schRmCb.commonInt == schRmCb.rsvn[handle].interUsec) { - schRmCb.rmStatus &= ~(1 << schRmCb.rsvn[handle].offsetBit); + for (y = 0; y < numBitsPerRes; y++) + { + schRmCb.rmStatus &= ~(1 << (schRmCb.rsvn[handle].offsetBit + y)); + } } else { @@ -451,7 +537,10 @@ static void schRmIntRemoveRmOffset(uint8_t handle) { for (x = 0; x < (1 << depth); x++) { - schRmCb.rmStatus &= ~(1 << ((1 << (schRmCb.offsetDepth - depth)) * x + schRmCb.rsvn[handle].offsetBit)); + for (y = 0; y < numBitsPerRes; y++) + { + schRmCb.rmStatus &= ~(1 << ((1 << (schRmCb.offsetDepth - depth)) * x + schRmCb.rsvn[handle].offsetBit + y)); + } } } } @@ -468,9 +557,9 @@ static void schRmIntRemoveRmOffset(uint8_t handle) schRmCb.offsetDepth = 0; } - LL_TRACE_WARN2("schRmIntRemoveRmOffset, handle = %u, offsetDepth = %u", handle, schRmCb.offsetDepth); - LL_TRACE_WARN1(" rmStatus = 0x%x", schRmCb.rmStatus); - LL_TRACE_WARN1(" 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(" commonInt = %u", schRmCb.commonInt); } else { @@ -478,7 +567,7 @@ static void schRmIntRemoveRmOffset(uint8_t handle) { /* Uncommon handle by reservation manager. */ schRmCb.indexUncommon--; - LL_TRACE_WARN2("schRmIntRemoveRmOffset, deleted uncommon index %u, Handle = %u", schRmCb.indexUncommon, handle); + LL_TRACE_INFO2("schRmIntRemoveRmOffset, deleted uncommon index %u, Handle = %u", schRmCb.indexUncommon, handle); } } } @@ -488,8 +577,6 @@ static void schRmIntRemoveRmOffset(uint8_t handle) * \brief Increase common interval of reservation manager. * * \param depth Depth between current interval and new interval. - * - * \return None. */ /*************************************************************************************************/ static void schRmIntIncCommInterval(uint8_t depth) @@ -523,15 +610,17 @@ static void schRmIntIncCommInterval(uint8_t depth) /*! * \brief Handle Adding resource manager offset for the specified handle. * - * \param handle Client defined reservation handle. + * \param handle Client defined reservation handle. + * \param newInterUsec Interval of the reservation in microseconds. + * \param durUsec Duration of the reservation in microseconds. * * \return TRUE if update was successful, FALSE otherwise.. */ /*************************************************************************************************/ -static void schRmIntHandleAddRmOffset(uint8_t handle, uint32_t newInterUsec) +static bool_t schRmIntHandleAddRmOffset(uint8_t handle, uint32_t newInterUsec, uint32_t durUsec) { - schRmCb.rsvn[handle].handle = handle; - schRmCb.rsvn[handle].interUsec = newInterUsec; + bool_t status = TRUE; + uint8_t numAttempt = 0; /* Let's assume all connections are with common multiples. */ /* Will add function later to determine if 2 intervals are with common intervals. */ @@ -548,11 +637,23 @@ static void schRmIntHandleAddRmOffset(uint8_t handle, uint32_t newInterUsec) } else if (schRmCb.commonInt == newInterUsec) { - if (!schRmIntAddRmOffset(handle, 0)) + while (status == TRUE) { - /* Offset depth needs to be increased if RM status is full with the current depth. */ - schRmIntIncOffsetDepth(1); - (void)schRmIntAddRmOffset(handle, 0); + numAttempt++; + if (schRmIntAddRmOffset(handle, 0, newInterUsec, durUsec)) + { + break; + } + else if (numAttempt <= SCH_RM_ADD_MAX_ATTEMPTS) + { + /* Offset depth needs to be increased if RM status is full with the current depth. */ + status = schRmIntIncOffsetDepth(1); + } + else + { + /* Failed with maximum attempts. */ + status = FALSE; + } } } else if (schRmCb.commonInt < newInterUsec) /* new interval is multiple of commonInt. */ @@ -563,18 +664,30 @@ static void schRmIntHandleAddRmOffset(uint8_t handle, uint32_t newInterUsec) { schRmIntIncCommInterval(depth); - if (!schRmIntAddRmOffset(handle, 0)) + while (status == TRUE) { - /* Offset depth needs to be increased if RM status is full with the current depth. */ - schRmIntIncOffsetDepth(1); - (void)schRmIntAddRmOffset(handle, 0); + numAttempt++; + if (schRmIntAddRmOffset(handle, 0, newInterUsec, durUsec)) + { + break; + } + else if (numAttempt <= SCH_RM_ADD_MAX_ATTEMPTS) + { + /* Offset depth needs to be increased if RM status is full with the current depth. */ + status = schRmIntIncOffsetDepth(1); + } + else + { + /* Failed with maximum attempts. */ + status = FALSE; + } } } else { /* Uncommon handle by reservation manager. */ schRmCb.indexUncommon++; - LL_TRACE_WARN2("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) @@ -586,23 +699,48 @@ static void schRmIntHandleAddRmOffset(uint8_t handle, uint32_t newInterUsec) /* First update offset depth so that offset unit would be same as new interval. */ if (schRmCb.offsetDepth < depth) { - schRmIntIncOffsetDepth(depth - schRmCb.offsetDepth); + status = schRmIntIncOffsetDepth(depth - schRmCb.offsetDepth); } - if (!schRmIntAddRmOffset(handle, depth)) + while (status == TRUE) { - /* Offset depth needs to be increased if RM status is full with the current depth. */ - schRmIntIncOffsetDepth(1); - (void)schRmIntAddRmOffset(handle, depth); + numAttempt++; + if (schRmIntAddRmOffset(handle, depth, newInterUsec, durUsec)) + { + break; + } + else if (numAttempt <= SCH_RM_ADD_MAX_ATTEMPTS) + { + /* Offset depth needs to be increased if RM status is full with the current depth. */ + status = schRmIntIncOffsetDepth(1); + } + else + { + /* Failed with maximum attempts. */ + status = FALSE; + } } } else { /* Uncommon handle by reservation manager. */ schRmCb.indexUncommon++; - LL_TRACE_WARN2("Adding uncommon index %u, Handle = %u", schRmCb.indexUncommon, handle); + LL_TRACE_INFO2("Adding uncommon index %u, Handle = %u", schRmCb.indexUncommon, handle); } } + + if (status == TRUE) + { + schRmCb.rsvn[handle].handle = handle; + schRmCb.rsvn[handle].interUsec = newInterUsec; + schRmCb.rsvn[handle].durUsec = durUsec; + } + else + { + LL_TRACE_WARN2("schRmIntHandleAddRmOffset, Add RM failed, Handle = %u, Interval = %u", handle, newInterUsec); + } + + return status; } /*************************************************************************************************/ @@ -612,8 +750,6 @@ static void schRmIntHandleAddRmOffset(uint8_t handle, uint32_t newInterUsec) * \param item List of numbers. * \param numItems Number of numbers in item[]. * Descending - * - * \return None. */ /*************************************************************************************************/ void schRmSortListDescending(uint32_t item[], uint8_t numItems) @@ -650,8 +786,6 @@ void schRmSortListDescending(uint32_t item[], uint8_t numItems) /*************************************************************************************************/ /*! * \brief Initialize the resource manager. - * - * \return None. */ /*************************************************************************************************/ void SchRmInit(void) @@ -659,18 +793,6 @@ void SchRmInit(void) memset(&schRmCb, 0, sizeof(schRmCb)); } -/*************************************************************************************************/ -/*! - * \brief Preferred periodicity. - * - * \return Preferred periodicity in microseconds. - */ -/*************************************************************************************************/ -uint32_t SchRmPreferredPeriodUsec(void) -{ - return SCH_RM_PREF_PER_USEC; -} - /*************************************************************************************************/ /*! * \brief Calculate the common periodicity. @@ -701,14 +823,16 @@ uint32_t SchRmCalcCommonPeriodicityUsec(uint32_t peerPerUsec) * \param pref Preference for selecting the interval. * \param minUsec Minimum interval in microseconds. * \param maxUsec Maximum interval in microseconds. - * \param durUsec Duration of the connection in microseconds. + * \param durUsec Duration of the reservation in microseconds. * \param pInterUsec Actual interval return value in microseconds. + * \param refTimeCb Get reference time callback function. * * \return TRUE if reservation available, FALSE otherwise. */ /*************************************************************************************************/ bool_t SchRmAdd(uint8_t handle, uint8_t pref, uint32_t minUsec, uint32_t maxUsec, uint32_t durUsec, uint32_t *pInterUsec, GetRefTimeCb_t refTimeCb) { + bool_t status = FALSE; uint32_t perfPerUsec = SCH_RM_PREF_PER_CONN_USEC; WSF_ASSERT(handle < SCH_RM_MAX_RSVN); @@ -732,17 +856,20 @@ bool_t SchRmAdd(uint8_t handle, uint8_t pref, uint32_t minUsec, uint32_t maxUsec /*** Commit reservation. ***/ - schRmCb.rsvnInterUsec[handle] = prefInterUsec; - schRmCb.numRsvn++; - if (pInterUsec) + status = schRmIntHandleAddRmOffset(handle, prefInterUsec, durUsec); + if (status == TRUE) { - *pInterUsec = prefInterUsec; + schRmCb.rsvn[handle].refTimeCb = refTimeCb; + + schRmCb.rsvnInterUsec[handle] = prefInterUsec; + schRmCb.numRsvn++; + if (pInterUsec) + { + *pInterUsec = prefInterUsec; + } } - schRmIntHandleAddRmOffset(handle, prefInterUsec); - schRmCb.rsvn[handle].refTimeCb = refTimeCb; - - return TRUE; + return status; } /*************************************************************************************************/ @@ -783,7 +910,7 @@ bool_t SchRmStartUpdate(uint8_t handle, uint32_t minUsec, uint32_t maxUsec, uint *pInterUsec = prefInterUsec; schRmIntRemoveRmOffset(handle); - schRmIntHandleAddRmOffset(handle, prefInterUsec); + (void)schRmIntHandleAddRmOffset(handle, prefInterUsec, durUsec); return TRUE; } @@ -793,8 +920,6 @@ bool_t SchRmStartUpdate(uint8_t handle, uint32_t minUsec, uint32_t maxUsec, uint * \brief Commit an update to a reservation. * * \param handle Client defined reservation handle. - * - * \return None. */ /*************************************************************************************************/ void SchRmCommitUpdate(uint8_t handle) @@ -807,8 +932,6 @@ void SchRmCommitUpdate(uint8_t handle) * \brief Remove an existing reservation. * * \param handle Client defined reservation handle. - * - * \return None. */ /*************************************************************************************************/ void SchRmRemove(uint8_t handle) @@ -822,30 +945,13 @@ void SchRmRemove(uint8_t handle) schRmIntRemoveRmOffset(handle); } -/*************************************************************************************************/ -/*! - * \brief Set the current reference point. - * - * \param handle Client defined reservation handle. - * - * \return None. - * - * The handle is the last completed reservation. Set the reference point to the next reservation - * represented by this handle. - */ -/*************************************************************************************************/ -void SchRmSetReference(uint8_t handle) -{ - /* No action required. */ -} - /*************************************************************************************************/ /*! * \brief Get the next available offset in microseconds. * * \param defOffsUsec Default offset in microseconds. * \param handle Reservation handle. - * \param refTime Reference time in BB ticks. + * \param refTime Reference time in microseconds. * * \return Offset in microseconds. */ @@ -860,8 +966,9 @@ uint32_t SchRmGetOffsetUsec(uint32_t defOffsUsec, uint8_t handle, uint32_t refTi if (schRmCb.numRsvn <= 1) { - /* No competing reservations. */ - return defOffsUsec; + /* We do not have reference anchor point yet for the 1st reservation. */ + /* First anchor point will be chosen to avoid conflict with TM links. */ + return SchTmGetFirstAnchor(refTime, defOffsUsec, schRmCb.rsvn[handle].interUsec, schRmCb.rsvn[handle].durUsec); } /* rmRefTime is the time for offset bit 0. */ @@ -879,17 +986,17 @@ uint32_t SchRmGetOffsetUsec(uint32_t defOffsUsec, uint8_t handle, uint32_t refTi offsUsec += schRmCb.rsvn[handle].interUsec; } - targetTime = rmRefTime + BB_US_TO_BB_TICKS(offsUsec); + targetTime = rmRefTime + offsUsec; - LL_TRACE_WARN2("SchRmGetOffsetUsec, handle = %u, refHandle = %u", handle, schRmCb.refHandle); - LL_TRACE_WARN1(" refTime = %u", refTime); - LL_TRACE_WARN1(" targetTime = %u", targetTime); + LL_TRACE_INFO2("SchRmGetOffsetUsec, handle = %u, refHandle = %u", handle, schRmCb.refHandle); + LL_TRACE_INFO1(" refTime = %u", refTime); + LL_TRACE_INFO1(" targetTime = %u", targetTime); } else { uint8_t offsetBit = 0; uint8_t numUncommon = schRmCb.indexUncommon; - uint32_t uncommonOffsetUs = SCH_RM_OFFSET_UNCOMMON; /* Offset in microseconds for uncommon handle */ + uint32_t uncommonOffsetUs = SCH_RM_OFFSET_UNCOMMON_US; /* Offset in microseconds for uncommon handle */ numUncommon--; while (numUncommon) @@ -900,38 +1007,38 @@ 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 (uint8_t i = 0; i < SCH_RM_MAX_RSVN; i++) + 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].refTimeCb != NULL) { (void)schRmCb.rsvn[i].refTimeCb(i, &uncommonOffsetUs); - uncommonOffsetUs += BbGetSchSetupDelayUs(); + uncommonOffsetUs += BbGetSchSetupDelayUs() + SCH_RM_MARGIN_UNCOMMON_US; } } } /* Place the uncommon handle away from each common ones to avoid conflicts. */ - targetTime = rmRefTime + BB_US_TO_BB_TICKS(offsetBit * offsetUnitUs) + BB_US_TO_BB_TICKS(uncommonOffsetUs); + targetTime = rmRefTime + (offsetBit * offsetUnitUs) + uncommonOffsetUs; - LL_TRACE_WARN2("SchRmGetOffsetUsec, uncommon handle = %u, refHandle = %u", handle, schRmCb.refHandle); - LL_TRACE_WARN1(" refTime = %u", refTime); - LL_TRACE_WARN1(" targetTime = %u", targetTime); + LL_TRACE_INFO2("SchRmGetOffsetUsec, uncommon handle = %u, refHandle = %u", handle, schRmCb.refHandle); + LL_TRACE_INFO1(" refTime = %u", rmRefTime); + LL_TRACE_INFO1(" targetTime = %u", targetTime); } /* Time to return has to be future from refTime. */ - while (targetTime - refTime >= SCH_RM_MAX_SPAN) + while (BbGetTargetTimeDelta(targetTime, refTime) == 0) { - targetTime += BB_US_TO_BB_TICKS(schRmCb.rsvn[handle].interUsec); + targetTime += schRmCb.rsvn[handle].interUsec; } /* 0 < targetTime <= interval */ - while (targetTime - refTime > BB_US_TO_BB_TICKS(schRmCb.rsvn[handle].interUsec)) + while (BbGetTargetTimeDelta(targetTime, refTime) > schRmCb.rsvn[handle].interUsec) { - targetTime -= BB_US_TO_BB_TICKS(schRmCb.rsvn[handle].interUsec); + targetTime -= schRmCb.rsvn[handle].interUsec; } - LL_TRACE_WARN1(" offsUsec = %u", (targetTime - refTime)); - return BB_TICKS_TO_US(targetTime - refTime); + LL_TRACE_INFO1(" offsUsec = %u", (targetTime - refTime)); + return BbGetTargetTimeDelta(targetTime, refTime); } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_tm.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_tm.c new file mode 100644 index 0000000000..20121f8351 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/ble/sch/sch_tm.c @@ -0,0 +1,352 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief BLE topology manager implementation file. + * + * Copyright (c) 2019 Arm Ltd. All Rights Reserved. + * + * 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 "sch_int_tm.h" +#include "sch_int_rm.h" +#include "wsf_assert.h" +#include "wsf_math.h" +#include + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief Topology link node descriptor. */ +typedef struct +{ + uint32_t tBegin; /*!< Begin time of topology link node. */ + uint32_t tEnd; /*!< End time of topology link node. */ +} schTmNode_t; + +/*! \brief Topology link node control block. */ +typedef struct +{ + schTmNode_t tnode[SCH_TM_MAX_LINK + 1]; /*!< Information for each topology node. */ +} schTmNodeCb_t; + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*! \brief Topology manager control block. */ +SchTmCb_t schTmCb; + +/*************************************************************************************************/ +/*! + * \brief Initialize the topology manager. + */ +/*************************************************************************************************/ +void SchTmInit(void) +{ + memset(&schTmCb, 0, sizeof(schTmCb)); +} + +/*************************************************************************************************/ +/*! + * \brief Add a new topology link. + * + * \param handle Client defined topology handle. + * \param interUsec Interval in microseconds. + * \param durUsec Duration of the topology link in microseconds. + * \param movable Movable. + * \param refTimeCb Callback function to get reference time. + */ +/*************************************************************************************************/ +void SchTmAdd(uint8_t handle, uint32_t interUsec, uint32_t durUsec, bool_t movable, GetTopRefTimeCb_t refTimeCb) +{ + WSF_ASSERT(handle < SCH_TM_MAX_LINK); + + schTmCb.tlink[handle].enabled = TRUE; + schTmCb.tlink[handle].movable = movable; + schTmCb.tlink[handle].interUsec = interUsec; + schTmCb.tlink[handle].durUsec = durUsec; + schTmCb.tlink[handle].refTimeCb = refTimeCb; + + LL_TRACE_INFO2("Topology Add, handle=%u, interval_ms=%u", handle, LL_MATH_DIV_10E3(interUsec)); + LL_TRACE_INFO1("Topology Add, durUsec=%u", durUsec); +} + +/*************************************************************************************************/ +/*! + * \brief Remove an existing topology link. + * + * \param handle Client defined topology handle. + */ +/*************************************************************************************************/ +void SchTmRemove(uint8_t handle) +{ + WSF_ASSERT(handle < SCH_TM_MAX_LINK); + + schTmCb.tlink[handle].enabled = FALSE; + LL_TRACE_INFO1("Topology Remove, handle=%u", handle); +} + +/*************************************************************************************************/ +/*! + * \brief Check if given timing parameters have conflict with any topology links. + * + * \param refBegin Reference time in microseconds. + * \param interUsec Interval in microseconds. + * \param durUsec Duration in microseconds. + * + * \return TRUE if conflict is found with any of topology links. + */ +/*************************************************************************************************/ +bool_t SchTmCheckConflict(uint32_t refBegin, uint32_t interUsec, uint32_t durUsec) +{ + uint32_t refEnd = refBegin + durUsec + BbGetSchSetupDelayUs(); /* End time of the link to be compared. */ + uint32_t linkBegin, linkEnd; /* Begin and end time of topology link. */ + uint8_t i; + + for (i = 0; i < SCH_TM_MAX_LINK; i++) + { + if ((schTmCb.tlink[i].enabled == TRUE) && schTmCb.tlink[i].refTimeCb) + { + /* First check if the links have common interval. */ + if (((interUsec > schTmCb.tlink[i].interUsec) && (schRmIntCalculateDepth(interUsec, schTmCb.tlink[i].interUsec) == 0)) || + ((interUsec < schTmCb.tlink[i].interUsec) && (schRmIntCalculateDepth(schTmCb.tlink[i].interUsec, interUsec) == 0))) + { + continue; + } + + linkBegin = schTmCb.tlink[i].refTimeCb(i); + + /* Start from the time when the TM link is in the past from the reference time. */ + while (SCH_TM_IS_IN_FUTURE(linkBegin, refBegin)) + { + linkBegin -= schTmCb.tlink[i].interUsec; + } + + linkEnd = linkBegin + schTmCb.tlink[i].durUsec + BbGetSchSetupDelayUs(); + + /* Now, check conflicts between TM link and the reference. */ + while (!SCH_TM_IS_IN_FUTURE(linkBegin, refEnd)) + { + /* Found conflict. */ + if (!SCH_TM_IS_IN_PAST(linkEnd, refBegin)) + { + LL_TRACE_WARN1("SchTmCheckConflict, ======>>> Found conflict with TM link %u ", i); + return TRUE; + } + + /* Use the smaller interval to check conflicts. */ + linkBegin += (interUsec < schTmCb.tlink[i].interUsec) ? interUsec : schTmCb.tlink[i].interUsec; + linkEnd = linkBegin + schTmCb.tlink[i].durUsec + BbGetSchSetupDelayUs(); + } + } + } + + return FALSE; +} + +/*************************************************************************************************/ +/*! + * \brief Find the best location to place the first anchor point. + * + * \param refTime Reference time in microseconds. + * \param defOffsUsec Default offset in microseconds. + * \param interUsec Interval in microseconds. + * \param durUsec Duration in microseconds. + * + * \return Anchor point offset from the reference time. + */ +/*************************************************************************************************/ +uint32_t SchTmGetFirstAnchor(uint32_t refTime, uint32_t defOffsUsec, uint32_t interUsec, uint32_t durUsec) +{ + schTmNodeCb_t schTmNodeCb; + uint8_t i, numNode, refLink, curLink, bestIndex; + uint32_t lastEnd, curBegin, rangeBegin, rangeEnd; + uint32_t nextBegin, nextEnd; /* Begin and end time of the next node to add. */ + uint32_t gap, biggestGap, commInterUsec; + bool_t done[SCH_TM_MAX_LINK]; + + numNode = 0; + commInterUsec = interUsec; + memset(done, FALSE, SCH_TM_MAX_LINK); + + /* Construct schTmNodeCb from schTmCb. */ + /* When there are 3 links(A,B,C), the order in schTmNodeCb will be A0 - B0 - C0 - A1.*/ + for (i = 0; i < SCH_TM_MAX_LINK; i++) + { + /* Find the first link which will be used as a reference time. */ + if ((schTmCb.tlink[i].enabled == TRUE) && schTmCb.tlink[i].refTimeCb) + { + /* Check if the links have common interval. */ + if (((interUsec > schTmCb.tlink[i].interUsec) && (schRmIntCalculateDepth(interUsec, schTmCb.tlink[i].interUsec) == 0)) || + ((interUsec < schTmCb.tlink[i].interUsec) && (schRmIntCalculateDepth(schTmCb.tlink[i].interUsec, interUsec) == 0))) + { + done[i] = TRUE; + } + else + { + /* Use smaller common interval. */ + commInterUsec = WSF_MIN(commInterUsec, schTmCb.tlink[i].interUsec); + + if (numNode == 0) + { + refLink = i; + schTmNodeCb.tnode[numNode].tBegin = schTmCb.tlink[i].refTimeCb(i); + schTmNodeCb.tnode[numNode].tEnd = schTmNodeCb.tnode[numNode].tBegin + schTmCb.tlink[i].durUsec; + + rangeBegin = schTmNodeCb.tnode[numNode].tBegin; + done[i] = TRUE; + numNode++; + } + } + } + else + { + done[i] = TRUE; + } + } + + if (numNode == 0) + { + /* Nothing to do. */ + return defOffsUsec; + } + + rangeEnd = rangeBegin + commInterUsec; + + /* Find next ones. */ + while (TRUE) + { + lastEnd = schTmNodeCb.tnode[numNode - 1].tEnd; + curLink = 0xFF; /* invalid */ + nextBegin = 0; /* invalid */ + + /* Find node which is closest from nextBegin. */ + for (i = 0; i < SCH_TM_MAX_LINK; i++) + { + if (done[i] == FALSE) + { + /* curBegin should be between rangeBegin and rangeEnd. */ + curBegin = schTmCb.tlink[i].refTimeCb(i); + while (SCH_TM_IS_IN_PAST(curBegin, rangeBegin)) + { + curBegin += commInterUsec; + } + + while (SCH_TM_IS_IN_FUTURE(curBegin, rangeEnd)) + { + curBegin -= commInterUsec; + } + + if (curLink == 0xFF) + { + curLink = i; + nextBegin = curBegin; + } + else + { + if (SCH_TM_IS_IN_PAST(curBegin, nextBegin)) + { + curLink = i; + nextBegin = curBegin; + } + } + } + } + + if (curLink != 0xFF) + { + done[curLink] = TRUE; + nextEnd = nextBegin + schTmCb.tlink[curLink].durUsec; + + /* Check if we can merge two nodes when they overlap. */ + if (SCH_TM_IS_IN_FUTURE(nextBegin, lastEnd)) + { + schTmNodeCb.tnode[numNode].tBegin = nextBegin; + schTmNodeCb.tnode[numNode].tEnd = nextBegin + schTmCb.tlink[curLink].durUsec; + numNode++; + } + else + { + /* Overlap. Merge nodes. */ + schTmNodeCb.tnode[numNode - 1].tEnd = SCH_TM_IS_IN_FUTURE(nextEnd, lastEnd) ? nextEnd : lastEnd; + } + } + else + { + /* Finished sorting. */ + break; + } + } + + /* Add A1(next instance of link A) at the end. */ + if (numNode > 0) + { + lastEnd = schTmNodeCb.tnode[numNode - 1].tEnd; + nextBegin = schTmNodeCb.tnode[0].tBegin + commInterUsec; + nextEnd = nextBegin + schTmCb.tlink[refLink].durUsec; + + /* Check if we can merge two nodes when they overlap. */ + if (SCH_TM_IS_IN_FUTURE(nextBegin, lastEnd)) + { + schTmNodeCb.tnode[numNode].tBegin = nextBegin; + schTmNodeCb.tnode[numNode].tEnd = nextBegin + schTmCb.tlink[refLink].durUsec; + numNode++; + } + else + { + /* Overlap. Merge nodes. */ + schTmNodeCb.tnode[numNode - 1].tEnd = SCH_TM_IS_IN_FUTURE(nextEnd, lastEnd) ? nextEnd : lastEnd; + } + } + + WSF_ASSERT(numNode >= 2); + + biggestGap = 0; + bestIndex = 0; + + /* Find biggest gap between nodes. */ + for (i = 0; i < (numNode - 1); i++) + { + gap = schTmNodeCb.tnode[i + 1].tBegin - schTmNodeCb.tnode[i].tEnd; + + if (gap > biggestGap) + { + biggestGap = gap; + bestIndex = i; + } + } + + uint32_t anchorTime = schTmNodeCb.tnode[bestIndex].tEnd + (biggestGap >> 1) - (durUsec >> 1); + + while (SCH_TM_IS_IN_PAST(anchorTime, refTime)) + { + anchorTime += commInterUsec; + } + + while (SCH_TM_IS_IN_FUTURE(anchorTime, (refTime + interUsec))) + { + anchorTime -= commInterUsec; + } + + LL_TRACE_INFO1("Topology SchTmGetFirstAnchor, refTime=%u", refTime); + LL_TRACE_INFO1("Topology SchTmGetFirstAnchor, anchorTime=%u", anchorTime); + + /* Return value should be 0 ~ defOffsecUsec. */ + return (anchorTime - refTime); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/bb/bb_int.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/bb/bb_int.h index 6f9b65d96e..f2433394c8 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/bb/bb_int.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/bb/bb_int.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal baseband interface file. + * \file + * + * \brief Internal baseband interface file. + * + * Copyright (c) 2016-2018 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ @@ -48,6 +49,7 @@ typedef struct BbBodCback_t cancelOpCback; /*!< Cancel operation handler. */ BbProtCback_t startProtCback; /*!< Start protocol handler. */ BbProtCback_t stopProtCback; /*!< Stop protocol handler. */ + BbLowPowerCback_t lowPowerOpCback; /*!< Low power operation handler. */ uint32_t startCnt; /*!< Start counter. */ } prot[BB_PROT_NUM]; /*!< Protocol callbacks. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/bb/bb_main.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/bb/bb_main.c index c7f1d7f786..9c90edbab8 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/bb/bb_main.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/bb/bb_main.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Generic baseband driver implementation file. + * \file + * + * \brief Generic baseband driver implementation file. + * + * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -43,8 +44,6 @@ const BbRtCfg_t *pBbRtCfg = NULL; /*!< Runtime configuration. */ * * \param pCfg Pointer to runtime configuration parameters (data must be static). * - * \return None. - * * This function initializes the BB subsystem's runtime configuration. * * \note This routine must be called only once before any other initialization routine. @@ -59,6 +58,7 @@ void BbInitRunTimeCfg(const BbRtCfg_t *pCfg) WSF_ASSERT(pCfg->rfSetupDelayUs > 0); WSF_ASSERT(pCfg->maxScanPeriodMs > 0); WSF_ASSERT(pCfg->schSetupDelayUs > 0); + WSF_ASSERT(pCfg->BbTimerBoundaryUs > 0); pBbRtCfg = pCfg; } @@ -67,8 +67,6 @@ void BbInitRunTimeCfg(const BbRtCfg_t *pCfg) /*! * \brief Initialize the BB. * - * \return None. - * * Initialize baseband resources. */ /*************************************************************************************************/ @@ -87,8 +85,6 @@ void BbInit(void) * * \param eventCback Event callback. * - * \return None. - * * Register operation completion handler. */ /*************************************************************************************************/ @@ -102,8 +98,6 @@ void BbRegister(BbBodCompCback_t eventCback) * \brief Start BB processing of given protocol. * * \param protId Protocol ID. - * - * \return None. */ /*************************************************************************************************/ static void bbProtStart(uint8_t protId) @@ -125,8 +119,6 @@ static void bbProtStart(uint8_t protId) * * \param protId Protocol ID. * - * \return None. - * * Enable BB and start processing the list of BODs. This routine may be called several times, if * a protocol layers has several simultaneously-enabled operations. However, \ref BbStop() must * be called an equal number of time to disable the baseband. @@ -153,8 +145,6 @@ void BbStart(uint8_t protId) * \brief Stop BB processing of given protocol. * * \param protId Protocol ID. - * - * \return None. */ /*************************************************************************************************/ static void bbProtStop(uint8_t protId) @@ -203,8 +193,6 @@ void BbStop(uint8_t protId) * * \param pBod Pointer to the BOD to execute. * - * \return None. - * * Execute the protocol specific BOD handler. */ /*************************************************************************************************/ @@ -250,8 +238,6 @@ void BbExecuteBod(BbOpDesc_t *pBod) /*************************************************************************************************/ /*! * \brief Cancel current executing BOD. - * - * \return None. */ /*************************************************************************************************/ void BbCancelBod(void) @@ -286,8 +272,6 @@ BbOpDesc_t *BbGetCurrentBod(void) /*! * \brief Set termination flag of current executing BOD. * - * \return None. - * * \note This function is expected to be called during the execution context of the * current executing BOD, typically in the related ISRs. In the end, termination * flag will help to decide if BbTerminateBod() should be called. @@ -317,8 +301,6 @@ bool_t BbGetBodTerminateFlag(void) /*! * \brief Terminate a BOD immediately. * - * \return None. - * * \note This function is expected to be called during the execution context of the * current executing BOD, typically in the related ISRs. */ @@ -327,6 +309,13 @@ void BbTerminateBod(void) { WSF_ASSERT(bbCb.bodCompCback); + BbOpDesc_t * const pBod = bbCb.pOpInProgress; + if (pBod && + (bbCb.prot[pBod->protId].lowPowerOpCback != NULL)) + { + bbCb.prot[pBod->protId].lowPowerOpCback(); + } + bbCb.pOpInProgress = NULL; bbCb.termBod = TRUE; bbCb.bodCompCback(); @@ -346,6 +335,19 @@ uint16_t BbGetClockAccuracy(void) return pBbRtCfg->clkPpm; } +/*************************************************************************************************/ +/*! + * \brief Get BB timer boundary before wraparound. + * + * \return Time boundary in microseconds. + * + */ +/*************************************************************************************************/ +uint32_t BbGetBbTimerBoundaryUs(void) +{ + return pBbRtCfg->BbTimerBoundaryUs; +} + /*************************************************************************************************/ /*! * \brief Get scheduler setup delay. @@ -360,6 +362,96 @@ uint16_t BbGetSchSetupDelayUs(void) return pBbRtCfg->schSetupDelayUs; } +/*************************************************************************************************/ +/*! + * \brief Adjust new time tick with wraparound. + * + * \param dueUsec Time tick without wraparound in microseconds. + + * + * \return Time tick with wraparound. + * + * \note dueUsec can only be at most +/-(BbTimerBoundaryUs/2) out of range. + */ +/*************************************************************************************************/ +uint32_t BbAdjustTime(uint32_t dueUsec) +{ + /* If and only of dueUsec is outside the range of [0, BbTimerBoundaryUs], mapping adjustment is needed. */ + if (dueUsec > pBbRtCfg->BbTimerBoundaryUs) + { + /* dueUsec is in range [-(BbTimerBoundaryUs + 1)/2, 0). */ + if (dueUsec >= ~(pBbRtCfg->BbTimerBoundaryUs >> 1)) + { + dueUsec += (pBbRtCfg->BbTimerBoundaryUs + 1); + } + /* dueUsec is in range [(BbTimerBoundaryUs + 1), (BbTimerBoundaryUs + 1) + (BbTimerBoundaryUs + 1) / 2). */ + else if (dueUsec <= (pBbRtCfg->BbTimerBoundaryUs + 1 + (pBbRtCfg->BbTimerBoundaryUs >> 1))) + { + dueUsec -= (pBbRtCfg->BbTimerBoundaryUs + 1); + } + else + { + /* It should never happen here. */ + WSF_ASSERT(FALSE); + } + } + + /* If dueUsec is in range [0, BbTimerBoundaryUs], no need to adjust. */ + return dueUsec; +} + +/*************************************************************************************************/ +/*! + * \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. + * + * \return Positive number in microseconds if target time is in the future. + * Zero if target time is in the past or same compared with reference time. + * + * \note Caller has to make sure target time and reference time are within SCH_MAX_SPAN. + */ +/*************************************************************************************************/ +uint32_t BbGetTargetTimeDelta(uint32_t targetUsec, uint32_t refUsec) +{ + targetUsec = BbAdjustTime(targetUsec); + refUsec = BbAdjustTime(refUsec); + + uint32_t delta = 0; + + if (targetUsec > refUsec) + { + /* Always bigger number minus smaller number. */ + if ((targetUsec - refUsec) < ((pBbRtCfg->BbTimerBoundaryUs >> 1) + 1)) + { + /* Normal case. */ + delta = targetUsec - refUsec; + } + else + { + /* reference time must be wraparound and target time is in the past.*/ + delta = 0; + } + } + else + { + /* Always bigger number minus smaller number. */ + if ((refUsec - targetUsec) < ((pBbRtCfg->BbTimerBoundaryUs >> 1) + 1)) + { + /* target time is in the past. */ + delta = 0; + } + else + { + /* Target time must be wraparound. */ + delta = pBbRtCfg->BbTimerBoundaryUs - (refUsec - targetUsec) + 1; + } + } + + return delta; +} + /*************************************************************************************************/ /*! * \brief Returns the ID of the active protocol. @@ -381,12 +473,10 @@ uint8_t BbGetActiveProtocol(void) * \param cancelOpCback Cancel operation callback. * \param startProtCback Start protocol callback. * \param stopProtCback Stop protocol callback. - * - * \return None. */ /*************************************************************************************************/ -void BbRegisterProt(uint8_t protId, BbBodCback_t execOpCback, BbBodCback_t cancelOpCback, - BbProtCback_t startProtCback, BbProtCback_t stopProtCback) +void BbRegisterProt(PalBbProt_t protId, BbBodCback_t execOpCback, BbBodCback_t cancelOpCback, + BbProtCback_t startProtCback, BbProtCback_t stopProtCback) { WSF_ASSERT(protId < BB_PROT_NUM); WSF_ASSERT(startProtCback != NULL); @@ -397,3 +487,18 @@ void BbRegisterProt(uint8_t protId, BbBodCback_t execOpCback, BbBodCback_t cance bbCb.prot[protId].startProtCback = startProtCback; bbCb.prot[protId].stopProtCback = stopProtCback; } + +/*************************************************************************************************/ +/*! + * \brief Register protocol handlers for low power. + * + * \param protId Protocol ID. + * \param lowPowerOpCback Low power operation callback. + */ +/*************************************************************************************************/ +void BbRegisterProtLowPower(PalBbProt_t protId, BbLowPowerCback_t lowPowerOpCback) +{ + WSF_ASSERT(protId < BB_PROT_NUM); + WSF_ASSERT(lowPowerOpCback != NULL); + bbCb.prot[protId].lowPowerOpCback = lowPowerOpCback; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/chci/chci_tr.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/chci/chci_tr.c index c77fb5aac2..391e9d69ac 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/chci/chci_tr.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/chci/chci_tr.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Controller HCI transport module implementation file. + * \file + * + * \brief Controller HCI transport module implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -34,8 +35,12 @@ #if (CHCI_TR_UART == 1) #include "pal_uart.h" #include "pal_sys.h" -#else -#include "fake_lhci_drv.h" +#endif + +#if (CHCI_TR_CUSTOM == 1) +/* Custom transport */ +extern void ChciTrInit(uint16_t maxAclLen, uint16_t maxIsoSduLen); +extern void ChciTrWrite(uint8_t prot, uint8_t type, uint16_t len, uint8_t *pData); #endif /************************************************************************************************** @@ -51,6 +56,9 @@ /*! \brief Maximum read header length. */ #define LHCI_MAX_RD_HDR_LEN (1 + 4) /* type + max header length */ +/*! \brief Maximum write buffer length allowed by UART DMA. */ +#define LHCI_MAX_DATA_LEN 4096 + /************************************************************************************************** Data Types **************************************************************************************************/ @@ -64,6 +72,9 @@ typedef struct uint8_t protPending; /*!< Protocol in progress. */ uint8_t nextAvailMask; /*!< Next available mask. */ + uint16_t maxAclLen; /*!< Maximum ACL data length. */ + uint16_t maxIsoSduLen; /*!< Maximum ISO data length. */ + uint32_t cmdCount; /*!< Counter of commands */ uint32_t evtCount; /*!< Counter of events */ @@ -77,17 +88,17 @@ typedef struct } protCbacks[CHCI_TR_PROT_NUM]; /*!< Callback array indexed by protocol ID. */ /* Read buffer state. */ - uint8_t rxPktState; /*!< Receive state. */ - uint8_t rdHdr[LHCI_MAX_RD_HDR_LEN]; /*!< Read header buffer. */ - uint16_t rdBufOffs; /*!< Write data buffer offset. */ - uint16_t rdBufLen; /*!< Write data buffer length. */ - uint8_t *pRdBuf; /*!< Read data buffer. */ + uint8_t rxPktState; /*!< Receive state. */ + uint8_t rdHdr[LHCI_MAX_RD_HDR_LEN]; /*!< Read header buffer. */ + uint16_t rdBufOffs; /*!< Write data buffer offset. */ + uint16_t rdBufLen; /*!< Write data buffer length. */ + uint8_t *pRdBuf; /*!< Read data buffer. */ /* Write buffer state. */ - 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. */ + 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. */ @@ -116,30 +127,11 @@ enum /*! \brief Current event data in progress. */ chciTrCtrlBlk_t chciTrCb; -/*************************************************************************************************/ -/*! - * \brief Signal a hardware error. - * - * \param code Error code. - * - * \return None. - */ -/*************************************************************************************************/ -static void chciTrHwError(uint8_t code) -{ - if (chciTrCb.sendHwErrorCback != NULL) - { - chciTrCb.sendHwErrorCback(code); - } -} - /*************************************************************************************************/ /*! * \brief Increment the command and event counters. * * \param type Type of message. - * - * \return None. */ /*************************************************************************************************/ static void chciTrIncrementCounters(uint8_t type) @@ -154,14 +146,29 @@ static void chciTrIncrementCounters(uint8_t type) } } +#if (CHCI_TR_UART == 1) + +/*************************************************************************************************/ +/*! + * \brief Signal a hardware error. + * + * \param code Error code. + */ +/*************************************************************************************************/ +static void chciTrHwError(uint8_t code) +{ + if (chciTrCb.sendHwErrorCback != NULL) + { + chciTrCb.sendHwErrorCback(code); + } +} + /*************************************************************************************************/ /*! * \brief Setup a read data buffer. * * \param len Number of bytes to write. * \param pData Byte array to write. - * - * \return None. */ /*************************************************************************************************/ static void chciTrRead(uint16_t len, uint8_t *pData) @@ -175,8 +182,6 @@ static void chciTrRead(uint16_t len, uint8_t *pData) /*************************************************************************************************/ /*! * \brief Receive packet state machine. - * - * \return None. */ /*************************************************************************************************/ static void chciRxPacketSM(void) @@ -186,7 +191,7 @@ static void chciRxPacketSM(void) { chciTrCb.rxPktState = CHCI_RX_STATE_HEADER; /* Determine header length based on packet type. */ - switch(chciTrCb.rdHdr[0]) + switch (chciTrCb.rdHdr[0]) { case HCI_CMD_TYPE: chciTrRead(HCI_CMD_HDR_LEN, &chciTrCb.rdHdr[1]); @@ -213,6 +218,7 @@ static void chciRxPacketSM(void) { uint8_t hdrLen = 0; uint16_t dataLen = 0; + uint16_t allocLen = 0; /* Extract data length from header. */ switch (chciTrCb.rdHdr[0]) @@ -220,26 +226,50 @@ static void chciRxPacketSM(void) case HCI_CMD_TYPE: hdrLen = HCI_CMD_HDR_LEN; dataLen = (uint16_t)chciTrCb.rdHdr[3]; + allocLen = dataLen; break; case HCI_ACL_TYPE: hdrLen = HCI_ACL_HDR_LEN; BYTES_TO_UINT16(dataLen, &chciTrCb.rdHdr[3]); + if (dataLen > chciTrCb.maxAclLen) + { + chciTrHwError(CHCI_TR_CODE_INVALID_DATA_LEN); + chciTrCb.rxPktState = CHCI_RX_STATE_IDLE; + return; + } + /* Use data buffers located in the large pool. */ + allocLen = chciTrCb.maxAclLen + CHCI_BUF_TAILROOM; break; case HCI_ISO_TYPE: hdrLen = HCI_ISO_HDR_LEN; BYTES_TO_UINT16(dataLen, &chciTrCb.rdHdr[3]); + if (dataLen > (chciTrCb.maxIsoSduLen + HCI_ISO_DL_MAX_LEN)) + { + chciTrHwError(CHCI_TR_CODE_INVALID_DATA_LEN); + chciTrCb.rxPktState = CHCI_RX_STATE_IDLE; + return; + } + /* Use data buffers located in the large pool. */ + allocLen = HCI_ISO_DL_MAX_LEN + chciTrCb.maxIsoSduLen + CHCI_BUF_TAILROOM; break; case CHCI_15P4_CMD_TYPE: case CHCI_15P4_DATA_TYPE: hdrLen = CHCI_15P4_HDR_LEN; BYTES_TO_UINT16(dataLen, &chciTrCb.rdHdr[2]); + allocLen = dataLen; break; default: /* already validated in CHCI_RX_STATE_TYPE */ break; } - if ((chciTrCb.pRdBuf = (uint8_t *)WsfMsgAlloc(hdrLen + dataLen + CHCI_BUF_TAILROOM)) != NULL) + if (dataLen > LHCI_MAX_DATA_LEN) + { + /* Invalid byte received. */ + chciTrHwError(CHCI_TR_CODE_INVALID_DATA); + chciTrCb.rxPktState = CHCI_RX_STATE_IDLE; + } + else if ((chciTrCb.pRdBuf = (uint8_t *)WsfMsgAlloc(hdrLen + allocLen)) != NULL) { if (dataLen > 0) { @@ -294,20 +324,20 @@ static void chciRxPacketSM(void) switch (chciTrCb.rdHdr[0]) { - case HCI_CMD_TYPE: - chciTrRecv(CHCI_TR_PROT_BLE, CHCI_TR_TYPE_CMD, chciTrCb.pRdBuf); - break; - case HCI_ACL_TYPE: - chciTrRecv(CHCI_TR_PROT_BLE, CHCI_TR_TYPE_DATA, chciTrCb.pRdBuf); - break; case HCI_ISO_TYPE: chciTrRecv(CHCI_TR_PROT_BLE, CHCI_TR_TYPE_ISO, chciTrCb.pRdBuf); break; + case HCI_ACL_TYPE: + chciTrRecv(CHCI_TR_PROT_BLE, CHCI_TR_TYPE_ACL, chciTrCb.pRdBuf); + break; + case HCI_CMD_TYPE: + chciTrRecv(CHCI_TR_PROT_BLE, CHCI_TR_TYPE_CMD, chciTrCb.pRdBuf); + break; case CHCI_15P4_CMD_TYPE: chciTrRecv(CHCI_TR_PROT_15P4, CHCI_TR_TYPE_CMD, chciTrCb.pRdBuf); break; case CHCI_15P4_DATA_TYPE: - chciTrRecv(CHCI_TR_PROT_15P4, CHCI_TR_TYPE_DATA, chciTrCb.pRdBuf); + chciTrRecv(CHCI_TR_PROT_15P4, CHCI_TR_TYPE_ACL, chciTrCb.pRdBuf); break; default: break; @@ -331,8 +361,6 @@ static void chciRxPacketSM(void) /*************************************************************************************************/ /*! * \brief Tx complete callback. - * - * \return None. */ /*************************************************************************************************/ static void chciTxComplete(void) @@ -353,6 +381,8 @@ static void chciTxComplete(void) } } +#endif /* (CHCI_TR_UART == 1) */ + /*************************************************************************************************/ /*! * \brief Write data the driver. @@ -362,8 +392,6 @@ static void chciTxComplete(void) * \param len Number of bytes to write. * \param pData Byte array to write. * - * \return None. - * * \note The type parameter allows the driver layer to prepend the data with a header on the * same write transaction. */ @@ -383,7 +411,7 @@ static void chciTrWrite(uint8_t prot, uint8_t type, uint16_t len, uint8_t *pData { *(pData - 1) = HCI_EVT_TYPE; } - else if (type == CHCI_TR_TYPE_DATA) + else if (type == CHCI_TR_TYPE_ACL) { *(pData - 1) = HCI_ACL_TYPE; } @@ -399,10 +427,10 @@ 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(); -#else - FakeChciTrWrite(prot, type, len, pData); - chciTrCb.wrBufComp = TRUE; - ChciTrService(); +#endif + +#if (CHCI_TR_CUSTOM == 1) + ChciTrWrite(prot, type, len, pData); #endif } @@ -410,13 +438,11 @@ static void chciTrWrite(uint8_t prot, uint8_t type, uint16_t len, uint8_t *pData /*! * \brief Signal the completion of a message write. * - * \return None. - * * This routine is used for asynchronous write operations. When the driver has completed the * use of the write buffer, this routine is called to free the buffer and release flow control. */ /*************************************************************************************************/ -static void chciTrSendComplete(void) +void chciTrSendComplete(void) { uint8_t *pBuf = chciTrCb.pDataPending; uint8_t type = chciTrCb.typePending; @@ -436,8 +462,6 @@ static void chciTrSendComplete(void) * * \param pCmdCount Pointer to uint32_t to hold command count. * \param pEvtCount Pointer to uint32_t to hold event count. - * - * \return None. */ /*************************************************************************************************/ void ChciTrGetCmdEvtCounts(uint32_t *pCmdCount, uint32_t *pEvtCount) @@ -449,8 +473,6 @@ void ChciTrGetCmdEvtCounts(uint32_t *pCmdCount, uint32_t *pEvtCount) /*************************************************************************************************/ /*! * \brief Reset the HCI command and event counts to zero. - * - * \return None. */ /*************************************************************************************************/ void ChciTrResetCmdEvtCounts(void) @@ -464,28 +486,33 @@ void ChciTrResetCmdEvtCounts(void) * \brief Initialize the transport handler. * * \param handlerId Handler ID. - * - * \return None. + * \param maxAclLen Maximum ACL data length. + * \param maxIsoSduLen Maximum ISO data length. */ /*************************************************************************************************/ -void ChciTrHandlerInit(wsfHandlerId_t handlerId) +void ChciTrHandlerInit(wsfHandlerId_t handlerId, uint16_t maxAclLen, uint16_t maxIsoSduLen) { memset(&chciTrCb, 0, sizeof(chciTrCb)); chciTrCb.handlerId = handlerId; + chciTrCb.maxAclLen = maxAclLen; + chciTrCb.maxIsoSduLen = maxIsoSduLen; #if (CHCI_TR_UART == 1) PalUartConfig_t cfg; cfg.baud = UART_BAUD; - cfg.hwFlow = UART_DEFAULT_CONFIG_HWFC; + cfg.hwFlow = UART_HWFC; cfg.rdCback = chciRxPacketSM; cfg.wrCback = chciTxComplete; PalUartInit(PAL_UART_ID_CHCI, &cfg); + + /* Start receiver. */ + chciRxPacketSM(); +#elif (CHCI_TR_CUSTOM == 1) + ChciTrInit(maxAclLen, maxIsoSduLen); #else (void)chciRxPacketSM; (void)chciTxComplete; #endif - /* Start receiver. */ - chciRxPacketSM(); } /*************************************************************************************************/ @@ -494,8 +521,6 @@ void ChciTrHandlerInit(wsfHandlerId_t handlerId) * * \param event WSF event. * \param pMsg WSF message. - * - * \return None. */ /*************************************************************************************************/ void ChciTrHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) @@ -536,8 +561,6 @@ void ChciTrHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) * \param recvCback Message received callback. * \param sendCompleteCback Message send complete callback. * \param serviceCback Service callback. - * - * \return None. */ /*************************************************************************************************/ void ChciTrSetCbacks(uint8_t prot, ChciTrRecvCback_t recvCback, ChciTrSendCompleteCback_t sendCompleteCback, @@ -556,8 +579,6 @@ void ChciTrSetCbacks(uint8_t prot, ChciTrRecvCback_t recvCback, ChciTrSendComple * \brief Set send hardware error callback. * * \param sendHwErrorCback Send hardware error callback. - * - * \return None. */ /*************************************************************************************************/ void ChciTrSetSendHwErrorCback(ChciTrSendHwErrorCback_t sendHwErrorCback) @@ -570,8 +591,6 @@ void ChciTrSetSendHwErrorCback(ChciTrSendHwErrorCback_t sendHwErrorCback) * \brief Flag protocol for needing service. * * \param prot Protocol. - * - * \return None. */ /*************************************************************************************************/ void ChciTrNeedsService(uint8_t prot) @@ -589,8 +608,6 @@ void ChciTrNeedsService(uint8_t prot) * \param prot Protocol. * \param type Message type. * \param pBuf Message. - * - * \return None. */ /*************************************************************************************************/ void chciTrRecv(uint8_t prot, uint8_t type, uint8_t *pBuf) @@ -620,15 +637,15 @@ void chciTrRecv(uint8_t prot, uint8_t type, uint8_t *pBuf) /*************************************************************************************************/ bool_t ChciTrService(void) { +#if (CHCI_TR_UART == 1) if (chciTrCb.wrBufComp) { chciTrCb.wrBufComp = FALSE; chciTrSendComplete(); - #if (CHCI_TR_UART == 1) PalSysSetIdle(); - #endif return TRUE; } +#endif return FALSE; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_int.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_int.h index 20d1ca969b..b687c8d0f0 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_int.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_int.h @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Internal multi-protocol scheduler interface file. + * \file + * + * \brief Internal multi-protocol scheduler interface file. + * + * Copyright (c) 2013-2019 ARM Ltd. All Rights Reserved. + * + * Copyright (c) 2019 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. */ /*************************************************************************************************/ @@ -36,8 +37,8 @@ extern "C" { Macros **************************************************************************************************/ -/*! \brief Maximum span of scheduler elements. */ -#define SCH_MAX_SPAN 0x80000000 +/*! \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 @@ -47,11 +48,11 @@ extern "C" { **************************************************************************************************/ /*! \brief Scheduler states. */ -enum +typedef enum { SCH_STATE_IDLE, /*!< Scheduler idle. */ SCH_STATE_EXEC /*!< Scheduler executing BOD. */ -}; +} schState_t; /************************************************************************************************** Data Types @@ -60,12 +61,17 @@ enum /*! \brief Scheduler control block. */ typedef struct { - bool_t state; /*!< Current scheduler state. */ - uint8_t eventSetFlagCount; /*!< Scheduler event set count. */ - wsfHandlerId_t handlerId; /*!< System event handler ID. */ + schState_t state:8; /*!< Current scheduler state. */ + uint8_t eventSetFlagCount; /*!< Scheduler event set count. */ + 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. */ + 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; /************************************************************************************************** @@ -96,17 +102,9 @@ void schRemoveHead(void); /*************************************************************************************************/ static inline bool_t schDueTimeInFuture(BbOpDesc_t *pBod) { - bool_t result = FALSE; + const uint32_t curTime = PalBbGetCurrentTime(); - const uint32_t curTime = PalBbGetCurrentTime(USE_RTC_BB_CLK); - const uint32_t delta = pBod->due - curTime; - - if (delta < SCH_MAX_SPAN) /* due time has not passed */ - { - result = TRUE; - } - - return result; + return (BbGetTargetTimeDelta(pBod->dueUsec, curTime) > 0); } @@ -123,17 +121,17 @@ static inline uint32_t schGetTimeToExecBod(BbOpDesc_t *pBod) { uint32_t result = 0; - const uint32_t curTime = PalBbGetCurrentTime(USE_RTC_BB_CLK); - const uint32_t delta = pBod->due - curTime; + const uint32_t curTime = PalBbGetCurrentTime(); - if ((delta >= BB_US_TO_BB_TICKS(SCH_LOAD_DELAY_US)) && /* sufficient time to cancel */ - (delta < SCH_MAX_SPAN)) /* due time has not passed */ + result = BbGetTargetTimeDelta(pBod->dueUsec, curTime); + + if (result >= SCH_LOAD_DELAY_US) { - result = BB_TICKS_TO_US(delta - BB_US_TO_BB_TICKS(SCH_LOAD_DELAY_US)); + result -= SCH_LOAD_DELAY_US; } else { - result = 0; + result = 0; } return result; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_list.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_list.c index 1acb01a1bb..0b53e3741a 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_list.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_list.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Operation list maintenance implementation file. + * \file + * + * \brief Operation list maintenance implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -33,25 +34,25 @@ **************************************************************************************************/ /*! \brief Total BOD time including setup delay. */ -#define SCH_TOTAL_DUR(p) (p->minDurUsec + BbGetSchSetupDelayUs()) +#define SCH_TOTAL_DUR(p) (p->minDurUsec + BbGetSchSetupDelayUs()) /*! \brief Time immediately after the given BOD. */ -#define SCH_END_TIME(p) (p->due + BB_US_TO_BB_TICKS(SCH_TOTAL_DUR(p))) +#define SCH_END_TIME(p) (p->dueUsec + SCH_TOTAL_DUR(p)) /*! \brief Is BOD[a] due time before BOD[b] due time (rt = reference time). */ -#define SCH_IS_DUE_BEFORE(a, b, rt) ((((a)->due) - (rt)) < (((b)->due) - (rt))) +#define SCH_IS_DUE_BEFORE(a, b) (BbGetTargetTimeDelta(((b)->dueUsec), ((a)->dueUsec)) > 0) /*! \brief Is BOD[a] completion time before BOD[b] due time (rt = reference time). */ -#define SCH_IS_DONE_BEFORE(a, b, rt) ((SCH_END_TIME(a) - (rt)) <= (((b)->due) - (rt))) +#define SCH_IS_DONE_BEFORE(a, b) (BbGetTargetTimeDelta(SCH_END_TIME(a), ((b)->dueUsec)) == 0) /*! \brief Is BOD[a] due time after BOD[b] completion time. */ -#define SCH_IS_DUE_AFTER(a, b, rt) SCH_IS_DONE_BEFORE(b, a, rt) +#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 5 +#define SCH_MIN_TIMER_USEC 200 /*! \brief Margin in microseconds to cancel a BOD. */ -#define SCH_CANCEL_MARGIN_USEC 15 +#define SCH_CANCEL_MARGIN_USEC 15 #ifndef SCH_TRACE_ENABLE /*! \brief Enable scheduler trace. */ @@ -59,10 +60,10 @@ #endif #if SCH_TRACE_ENABLE -#define SCH_TRACE_INFO0(msg) WSF_TRACE0("SCH", "INFO", msg) -#define SCH_TRACE_INFO1(msg, var1) WSF_TRACE1("SCH", "INFO", msg, var1) -#define SCH_TRACE_WARN0(msg) WSF_TRACE0("SCH", "WARN", msg) -#define SCH_TRACE_WARN1(msg, var1) WSF_TRACE1("SCH", "WARN", msg, var1) +#define SCH_TRACE_INFO0(msg) WSF_TRACE0("SCH", "INFO", msg) +#define SCH_TRACE_INFO1(msg, var1) WSF_TRACE1("SCH", "INFO", msg, var1) +#define SCH_TRACE_WARN0(msg) WSF_TRACE0("SCH", "WARN", msg) +#define SCH_TRACE_WARN1(msg, var1) WSF_TRACE1("SCH", "WARN", msg, var1) #else /*! \brief Information trace with 0 parameters. */ #define SCH_TRACE_INFO0(msg) @@ -74,10 +75,10 @@ #define SCH_TRACE_WARN1(msg, var1) #endif /*! \brief Maximum allowed number of deleted BOD due to conflicts. */ -#define SCH_MAX_DELETE_BOD 8 +#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) @@ -86,8 +87,6 @@ * \brief Ensure BOD is not already inserted in the list. * * \param pBod Target BOD. - * - * \return None. */ /*************************************************************************************************/ static inline void SchCheckIsNotInserted(BbOpDesc_t *pBod) @@ -141,11 +140,10 @@ static inline bool_t SchEnoughTimeToCancel(BbOpDesc_t *pBod) { bool_t result = FALSE; - const uint32_t curTime = PalBbGetCurrentTime(USE_RTC_BB_CLK); - const uint32_t delta = pBod->due - curTime; + const uint32_t curTime = PalBbGetCurrentTime(); + const uint32_t delta = BbGetTargetTimeDelta(pBod->dueUsec, curTime); - if ((delta >= BB_US_TO_BB_TICKS(BbGetSchSetupDelayUs())) && /* sufficient time to cancel */ - (delta < SCH_MAX_SPAN)) /* due time has not passed */ + if (delta >= BbGetSchSetupDelayUs()) { result = TRUE; } @@ -153,27 +151,6 @@ static inline bool_t SchEnoughTimeToCancel(BbOpDesc_t *pBod) return result; } -/*************************************************************************************************/ -/*! - * \brief Get start reference time. - * - * \return Start reference time. - * - * Returns the earliest time as a time base for calculations. - */ -/*************************************************************************************************/ -static inline uint32_t SchGetStartRefTime(void) -{ - if (schCb.pHead) - { - return schCb.pHead->due - SCH_MAX_SPAN; - } - else - { - return PalBbGetCurrentTime(USE_RTC_BB_CLK); - } -} - /*************************************************************************************************/ /*! * \brief Check and return the status of whether it is ok to cancel the head BOD. @@ -210,8 +187,6 @@ static inline bool_t schCheckCancelHead(void) * \brief Insert item into an empty list. * * \param pItem Item to insert. - * - * \return None. */ /*************************************************************************************************/ static inline void schInsertToEmptyList(BbOpDesc_t *pItem) @@ -227,7 +202,7 @@ static inline void schInsertToEmptyList(BbOpDesc_t *pItem) pItem->pNext = NULL; SCH_TRACE_INFO1("++| schInsertToEmptyList |++ pBod=0x%08x", (uint32_t)pItem); - SCH_TRACE_INFO1("++| |++ .due=%u", pItem->due); + SCH_TRACE_INFO1("++| |++ .dueUsec=%u", pItem->dueUsec); SCH_TRACE_INFO1("++| |++ .minDurUsec=%u", pItem->minDurUsec); SCH_TRACE_INFO1("++| |++ .maxDurUsec=%u", pItem->maxDurUsec); } @@ -238,8 +213,6 @@ static inline void schInsertToEmptyList(BbOpDesc_t *pItem) * * \param pItem Item to insert. * \param pTgt Target position. - * - * \return None. */ /*************************************************************************************************/ static inline void schInsertBefore(BbOpDesc_t *pItem, BbOpDesc_t *pTgt) @@ -261,7 +234,7 @@ static inline void schInsertBefore(BbOpDesc_t *pItem, BbOpDesc_t *pTgt) } SCH_TRACE_INFO1("++| schInsertBefore |++ pBod=0x%08x", (uint32_t)pItem); - SCH_TRACE_INFO1("++| |++ .due=%u", pItem->due); + SCH_TRACE_INFO1("++| |++ .dueUsec=%u", pItem->dueUsec); SCH_TRACE_INFO1("++| |++ .minDurUsec=%u", pItem->minDurUsec); SCH_TRACE_INFO1("++| |++ .maxDurUsec=%u", pItem->maxDurUsec); } @@ -272,8 +245,6 @@ static inline void schInsertBefore(BbOpDesc_t *pItem, BbOpDesc_t *pTgt) * * \param pItem Item to insert. * \param pTgt Target position. - * - * \return None. */ /*************************************************************************************************/ static inline void schInsertAfter(BbOpDesc_t *pItem, BbOpDesc_t *pTgt) @@ -295,7 +266,7 @@ static inline void schInsertAfter(BbOpDesc_t *pItem, BbOpDesc_t *pTgt) } SCH_TRACE_INFO1("++| schInsertAfter |++ pBod=0x%08x", (uint32_t)pItem); - SCH_TRACE_INFO1("++| |++ .due=%u", pItem->due); + SCH_TRACE_INFO1("++| |++ .dueUsec=%u", pItem->dueUsec); SCH_TRACE_INFO1("++| |++ .minDurUsec=%u", pItem->minDurUsec); SCH_TRACE_INFO1("++| |++ .maxDurUsec=%u", pItem->maxDurUsec); } @@ -303,8 +274,6 @@ static inline void schInsertAfter(BbOpDesc_t *pItem, BbOpDesc_t *pTgt) /*************************************************************************************************/ /*! * \brief Remove head item from BOD list. - * - * \return None. */ /*************************************************************************************************/ void schRemoveHead(void) @@ -329,8 +298,6 @@ void schRemoveHead(void) * \brief Remove non-head item from BOD list. * * \param pBod Element to remove. - * - * \return None. */ /*************************************************************************************************/ static void schRemoveMiddle(BbOpDesc_t *pBod) @@ -501,8 +468,6 @@ static bool_t SchResolveConflict(BbOpDesc_t *pItem, BbOpDesc_t *pTgt) int numDeletedBod = 0; BbOpDesc_t *pDeleted[SCH_MAX_DELETE_BOD]; - const uint32_t startRef = SchGetStartRefTime(); - WSF_ASSERT(pTgt); WSF_ASSERT(pItem); @@ -517,7 +482,7 @@ static bool_t SchResolveConflict(BbOpDesc_t *pItem, BbOpDesc_t *pTgt) pDeleted[numDeletedBod++] = pCur; if ((pCur->pNext == NULL) || /* pCur is the tail. */ - (SCH_IS_DONE_BEFORE(pItem, pCur->pNext, startRef))) /* Only conflict with pCur. */ + (SCH_IS_DONE_BEFORE(pItem, pCur->pNext))) /* Only conflict with pCur. */ { /* Remove only 1 conflicting BOD. */ result = schRemoveForConflict(pCur); @@ -584,7 +549,7 @@ static bool_t SchResolveConflict(BbOpDesc_t *pItem, BbOpDesc_t *pTgt) static bool_t SchIsConflictResolvable(BbOpDesc_t *pItem, BbOpDesc_t *pTgt, BbConflictAct_t conflictCback) { bool_t result; - const uint32_t startRef = SchGetStartRefTime(); + BbOpDesc_t *pCur = pTgt; WSF_ASSERT(pTgt) @@ -593,7 +558,7 @@ static bool_t SchIsConflictResolvable(BbOpDesc_t *pItem, BbOpDesc_t *pTgt, BbCon while (TRUE) { if ((pCur->pNext == NULL) || /* pCur is the tail. */ - (SCH_IS_DONE_BEFORE(pItem, pCur->pNext, startRef))) /* Only conflict with pCur. */ + (SCH_IS_DONE_BEFORE(pItem, pCur->pNext))) /* Only conflict with pCur. */ { /* Only 1 conflicting BOD. */ result = SchIsBodResolvable(pItem, pCur, conflictCback); @@ -619,8 +584,6 @@ static bool_t SchIsConflictResolvable(BbOpDesc_t *pItem, BbOpDesc_t *pTgt, BbCon * \brief Try to load or add scheduler timer for inserted item if possible. * * \param pBod Inserted BOD. - * - * \return None. */ /*************************************************************************************************/ static inline void SchInsertTryLoadBod(BbOpDesc_t *pBod) @@ -656,7 +619,7 @@ static inline void SchInsertTryLoadBod(BbOpDesc_t *pBod) 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) == 0); + WSF_ASSERT(schGetTimeToExecBod(schCb.pHead) < SCH_MIN_TIMER_USEC); if (execTimeUsec >= SCH_MIN_TIMER_USEC) { @@ -681,8 +644,6 @@ static inline void SchInsertTryLoadBod(BbOpDesc_t *pBod) * * \param pBod Element to insert. * - * \return None. - * * Insert this BOD in the active BOD list where its duration can be accommodated. */ /*************************************************************************************************/ @@ -692,15 +653,13 @@ void SchInsertNextAvailable(BbOpDesc_t *pBod) SchCheckIsNotInserted(pBod); #endif - const uint32_t startRef = SchGetStartRefTime(); - - pBod->due = PalBbGetCurrentTime(USE_RTC_BB_CLK) + BB_US_TO_BB_TICKS(BbGetSchSetupDelayUs()); + pBod->dueUsec = PalBbGetCurrentTime() + BbGetSchSetupDelayUs(); if (schCb.pHead == NULL) { schInsertToEmptyList(pBod); } - else if (SCH_IS_DONE_BEFORE(pBod, schCb.pHead, startRef) && + else if (SCH_IS_DONE_BEFORE(pBod, schCb.pHead) && schCheckCancelHead()) { /* Insert at head */ @@ -716,13 +675,13 @@ void SchInsertNextAvailable(BbOpDesc_t *pBod) WSF_ASSERT(pBod != pCur); /* Only update due time when pCur ends in the future. */ - if (SCH_END_TIME(pCur) > pBod->due) + if (!SCH_IS_DONE_BEFORE(pCur, pBod)) { - pBod->due = SCH_END_TIME(pCur); + pBod->dueUsec = SCH_END_TIME(pCur); } if ((pCur->pNext == NULL) || /* insert at tail */ - SCH_IS_DONE_BEFORE(pBod, pCur->pNext, startRef)) + SCH_IS_DONE_BEFORE(pBod, pCur->pNext)) { schInsertAfter(pBod, pCur); break; @@ -755,8 +714,6 @@ bool_t SchInsertAtDueTime(BbOpDesc_t *pBod, BbConflictAct_t conflictCback) SchCheckIsNotInserted(pBod); #endif - const uint32_t startRef = SchGetStartRefTime(); - if (!schDueTimeInFuture(pBod)) { return FALSE; @@ -777,8 +734,7 @@ bool_t SchInsertAtDueTime(BbOpDesc_t *pBod, BbConflictAct_t conflictCback) while (TRUE) { WSF_ASSERT(pBod != pCur); - - if (SCH_IS_DONE_BEFORE(pBod, pCur, startRef)) /* BOD is due and done before pCur(no overlap), try to insert before. */ + if (SCH_IS_DONE_BEFORE(pBod, pCur)) /* BOD is due and done before pCur(no overlap), try to insert before. */ { if (pCur == schCb.pHead) { @@ -789,7 +745,7 @@ bool_t SchInsertAtDueTime(BbOpDesc_t *pBod, BbConflictAct_t conflictCback) result = TRUE; break; } - else if (!SCH_IS_DONE_BEFORE(pCur, pBod, startRef)) /* 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 BOD. */ { if ((result = SchIsConflictResolvable(pBod, pCur, conflictCback)) == TRUE) { @@ -798,7 +754,7 @@ bool_t SchInsertAtDueTime(BbOpDesc_t *pBod, BbConflictAct_t conflictCback) } break; } - else if (pCur->pNext == NULL) /* BOD is due after pCur and pCur is tail, insert after. */ + else if (pCur->pNext == NULL) /* BOD is due after pCur and pCur is tail, insert after. */ { schInsertAfter(pBod, pCur); result = TRUE; @@ -842,77 +798,82 @@ bool_t SchInsertEarlyAsPossible(BbOpDesc_t *pBod, uint32_t min, uint32_t max) bool_t result = FALSE; - const uint32_t startRef = SchGetStartRefTime(); - const uint32_t dueOrigin = pBod->due; + const uint32_t dueOrigin = pBod->dueUsec; /* Try inserting at minimum interval. */ - pBod->due += min; + pBod->dueUsec += min; - if ((max == SCH_MAX_SPAN) && !schDueTimeInFuture(pBod)) + if (!schDueTimeInFuture(pBod)) { - /* With SCH_MAX_SPAN, this function will insert the BOD regardless of the current due. */ - pBod->due = PalBbGetCurrentTime(USE_RTC_BB_CLK) + BB_US_TO_BB_TICKS(BbGetSchSetupDelayUs()); - } - - if (schDueTimeInFuture(pBod)) - { - if (schCb.pHead == NULL) + if (max != SCH_MAX_SPAN) { - schInsertToEmptyList(pBod); - result = TRUE; - } - else if (SCH_IS_DUE_BEFORE (pBod, schCb.pHead, startRef) && - SCH_IS_DONE_BEFORE(pBod, schCb.pHead, startRef) && - schCheckCancelHead()) - { - /* Insert at head */ - WSF_ASSERT(pBod != schCb.pHead); - schInsertBefore(pBod, schCb.pHead); - result = TRUE; - } - else if (SCH_IS_DONE_BEFORE(schCb.pTail, pBod, startRef)) - { - /* Insert at tail */ - WSF_ASSERT(pBod != schCb.pTail); - schInsertAfter(pBod, schCb.pTail); - result = TRUE; + /* Reset due time origin. */ + pBod->dueUsec = dueOrigin; + return FALSE; } else { - BbOpDesc_t *pCur = schCb.pHead; + /* With SCH_MAX_SPAN, this function will insert the BOD regardless of the current due. */ + pBod->dueUsec = PalBbGetCurrentTime() + BbGetSchSetupDelayUs(); + } + } - while (pCur) + if (schCb.pHead == NULL) + { + schInsertToEmptyList(pBod); + result = TRUE; + } + else if (SCH_IS_DUE_BEFORE (pBod, schCb.pHead) && + SCH_IS_DONE_BEFORE(pBod, schCb.pHead) && + schCheckCancelHead()) + { + /* Insert at head */ + WSF_ASSERT(pBod != schCb.pHead); + schInsertBefore(pBod, schCb.pHead); + result = TRUE; + } + else if (SCH_IS_DONE_BEFORE(schCb.pTail, pBod)) + { + /* Insert at tail */ + WSF_ASSERT(pBod != schCb.pTail); + schInsertAfter(pBod, schCb.pTail); + result = TRUE; + } + else + { + BbOpDesc_t *pCur = schCb.pHead; + + while (pCur) + { + WSF_ASSERT(pBod != pCur); + + /* Only update due time when pCur ends in the future. */ + if (!SCH_IS_DONE_BEFORE(pCur, pBod)) { - WSF_ASSERT(pBod != pCur); - - /* Only update due time when pCur ends in the future. */ - if (SCH_END_TIME(pCur) > pBod->due) - { - pBod->due = SCH_END_TIME(pCur); - } - uint32_t nextAvailInter = pBod->due - dueOrigin; - - if ((nextAvailInter >= min) && - (nextAvailInter <= max)) - { - if (pCur->pNext == NULL) - { - /* Insert at tail */ - schInsertAfter(pBod, pCur); - result = TRUE; - break; - } - else if (SCH_IS_DONE_BEFORE(pBod, pCur->pNext, startRef)) - { - /* Insert middle. */ - schInsertBefore(pBod, pCur->pNext); - result = TRUE; - break; - } - } - - pCur = pCur->pNext; + pBod->dueUsec = SCH_END_TIME(pCur); } + uint32_t nextAvailInter = pBod->dueUsec - dueOrigin; + + if ((nextAvailInter >= min) && + (nextAvailInter <= max)) + { + if (pCur->pNext == NULL) + { + /* Insert at tail */ + schInsertAfter(pBod, pCur); + result = TRUE; + break; + } + else if (SCH_IS_DONE_BEFORE(pBod, pCur->pNext)) + { + /* Insert middle. */ + schInsertBefore(pBod, pCur->pNext); + result = TRUE; + break; + } + } + + pCur = pCur->pNext; } } @@ -924,7 +885,7 @@ bool_t SchInsertEarlyAsPossible(BbOpDesc_t *pBod, uint32_t min, uint32_t max) if (!result) { /* Reset due time origin. */ - pBod->due = dueOrigin; + pBod->dueUsec = dueOrigin; } return result; @@ -954,11 +915,10 @@ bool_t SchInsertLateAsPossible(BbOpDesc_t *pBod, uint32_t min, uint32_t max) SchCheckIsNotInserted(pBod); #endif - const uint32_t startRef = SchGetStartRefTime(); - const uint32_t dueOrigin = pBod->due; + const uint32_t dueOrigin = pBod->dueUsec; /* Try inserting at maximum interval. */ - pBod->due = dueOrigin + max; + pBod->dueUsec = dueOrigin + max; if (schCb.pTail == NULL) { @@ -968,7 +928,7 @@ bool_t SchInsertLateAsPossible(BbOpDesc_t *pBod, uint32_t min, uint32_t max) result = TRUE; } } - else if (SCH_IS_DUE_AFTER(pBod, schCb.pTail, startRef)) + else if (SCH_IS_DUE_AFTER(pBod, schCb.pTail)) { if (schDueTimeInFuture(pBod)) { @@ -986,19 +946,16 @@ bool_t SchInsertLateAsPossible(BbOpDesc_t *pBod, uint32_t min, uint32_t max) { WSF_ASSERT(pBod != pCur); + /* The current BOD is the head BOD, check to see if there is time to schedule it before. */ if (pCur->pPrev == NULL) { - pBod->due = pCur->due - BB_US_TO_BB_TICKS(SCH_TOTAL_DUR(pBod)); + uint32_t nextAvailInter = BbGetTargetTimeDelta((pCur->dueUsec - SCH_TOTAL_DUR(pBod)), dueOrigin); + uint32_t targetOffset = WSF_MIN(max, nextAvailInter); + pBod->dueUsec = dueOrigin + targetOffset; - if (!schDueTimeInFuture(pBod)) - { - break; - } - - uint32_t nextAvailInter = pBod->due - dueOrigin; - - if ((nextAvailInter >= min) && - (nextAvailInter <= max) && + if ((targetOffset >= min) && + SCH_IS_DUE_BEFORE(pBod, pCur) && + schDueTimeInFuture(pBod) && schCheckCancelHead()) { /* Insert at head. */ @@ -1007,20 +964,21 @@ bool_t SchInsertLateAsPossible(BbOpDesc_t *pBod, uint32_t min, uint32_t max) break; } } + /* The current BOD is a intermediate BOD, check to see if we can insert in-between BODs. */ else { - pBod->due = SCH_END_TIME(pCur->pPrev); + pBod->dueUsec = SCH_END_TIME(pCur->pPrev); if (!schDueTimeInFuture(pBod)) { break; } - uint32_t nextAvailInter = pBod->due - dueOrigin; + uint32_t nextAvailInter = BbGetTargetTimeDelta(pBod->dueUsec, dueOrigin); if ((nextAvailInter >= min) && (nextAvailInter <= max) && - SCH_IS_DONE_BEFORE(pBod, pCur, startRef)) + SCH_IS_DONE_BEFORE(pBod, pCur)) { /* Insert middle. */ schInsertBefore(pBod, pCur); @@ -1041,7 +999,7 @@ bool_t SchInsertLateAsPossible(BbOpDesc_t *pBod, uint32_t min, uint32_t max) if (!result) { /* Reset due time origin. */ - pBod->due = dueOrigin; + pBod->dueUsec = dueOrigin; } return result; @@ -1053,7 +1011,7 @@ bool_t SchInsertLateAsPossible(BbOpDesc_t *pBod, uint32_t min, uint32_t max) * * \param pBod Element to remove. * - * \return Return TRUE if removed successfully, FALSE if item not in the list. + * \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. */ @@ -1064,7 +1022,7 @@ bool_t SchRemove(BbOpDesc_t *pBod) if (!SchCheckIsInserted(pBod)) { - LL_TRACE_WARN0("No such BOD to remove."); + LL_TRACE_WARN0("No such BOD to remove"); return FALSE; } @@ -1147,7 +1105,7 @@ bool_t SchRemove(BbOpDesc_t *pBod) pBod->abortCback(pBod); } SCH_TRACE_INFO1("--| SchRemove |-- pBod=0x%08x", (uint32_t)pBod); - SCH_TRACE_INFO1("--| |-- .due=%u", pBod->due); + SCH_TRACE_INFO1("--| |-- .dueUsec=%u", pBod->dueUsec); } return result; @@ -1159,8 +1117,6 @@ bool_t SchRemove(BbOpDesc_t *pBod) * * \param pBod Element to reload. * - * \return None. - * * Only if the head operation, cancel the operation and re-start it. */ /*************************************************************************************************/ @@ -1169,6 +1125,7 @@ void SchReload(BbOpDesc_t *pBod) if ((schCb.pHead == pBod) && schCheckCancelHead()) { + PalTimerStop(); SchInsertTryLoadBod(pBod); } @@ -1190,12 +1147,10 @@ bool_t SchIsBodCancellable(BbOpDesc_t *pBod) WSF_ASSERT(pBod); bool_t result = FALSE; - const uint32_t curTime = PalBbGetCurrentTime(USE_RTC_BB_CLK); - const uint32_t delta = pBod->due - curTime; + const uint32_t curTime = PalBbGetCurrentTime(); + const uint32_t delta = BbGetTargetTimeDelta(pBod->dueUsec, curTime); - /* Checking if bod can be cancelled by the client. */ - if ((delta >= (uint32_t)(BB_US_TO_BB_TICKS(BbGetSchSetupDelayUs() + SCH_CANCEL_MARGIN_USEC))) && /* sufficient time to cancel */ - (delta < SCH_MAX_SPAN)) /* due time has not passed */ + if (delta >= (uint32_t)(BbGetSchSetupDelayUs() + SCH_CANCEL_MARGIN_USEC)) { result = TRUE; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_main.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_main.c index 343c0bb5c2..a29178a957 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_main.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/controller/sources/common/sch/sch_main.c @@ -1,23 +1,24 @@ -/* Copyright (c) 2019 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. - */ - /*************************************************************************************************/ /*! - * \file - * \brief Operation list maintenance implementation file. + * \file + * + * \brief Operation list maintenance implementation file. + * + * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. + * + * 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. */ /*************************************************************************************************/ @@ -47,14 +48,9 @@ enum /*! \brief Scheduler control block. */ SchCtrlBlk_t schCb; -/*! \brief Handler duration watermark in microseconds. */ -static uint16_t schHandlerWatermarkUsec = 0; - /*************************************************************************************************/ /*! * \brief BOD completion handler. - * - * \return None. */ /*************************************************************************************************/ static void schBodCompHandler(void) @@ -66,8 +62,6 @@ static void schBodCompHandler(void) /*************************************************************************************************/ /*! * \brief BOD abortion handler. - * - * \return None. */ /*************************************************************************************************/ static void schBodAbortHandler(void) @@ -79,8 +73,6 @@ static void schBodAbortHandler(void) /*************************************************************************************************/ /*! * \brief BOD curtail handler. - * - * \return None. */ /*************************************************************************************************/ static void schBodCurtailHandler(void) @@ -92,8 +84,6 @@ static void schBodCurtailHandler(void) /*************************************************************************************************/ /*! * \brief BOD load handler. - * - * \return None. */ /*************************************************************************************************/ static void schBodLoadHandler(void) @@ -105,46 +95,57 @@ static void schBodLoadHandler(void) 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; + } + return; } + + /* Try load head if scheduler is idle. */ + if (schCb.state == SCH_STATE_IDLE) + { + if (!schTryLoadHead()) + { + /* Head load failed. */ + schBodAbortHandler(); + } + /* Move to next BOD. */ + pNextBod = pNextBod->pNext; + } +#if SCH_TIMER_REQUIRED == TRUE + /* If head is executed, check cur tail operation is needed or not. */ else { - /* Try load head if scheduler is idle. */ - if (schCb.state == SCH_STATE_IDLE) - { - if (!schTryLoadHead()) - { - /* Head load failed. */ - schBodAbortHandler(); - } - /* Move to next BOD. */ - pNextBod = pNextBod->pNext; - } -#if SCH_TIMER_REQUIRED == TRUE - /* If head is executed, check cur tail operation is needed or not. */ - else - { - /* Head BOD and next BOD must exist. */ - WSF_ASSERT(schCb.pHead); - WSF_ASSERT(schCb.pHead->pNext); - pNextBod = pNextBod->pNext; + /* Head BOD and next BOD must exist. */ + WSF_ASSERT(schCb.pHead); + WSF_ASSERT(schCb.pHead->pNext); + pNextBod = pNextBod->pNext; - /* Skip curtail load if next BOD has same or lower priority than current BOD. */ - if ((pNextBod->reschPolicy) >= (schCb.pHead->reschPolicy)) + /* 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) { - /* Delay loading until idle state. */ - WsfSetEvent(schCb.handlerId, SCH_EVENT_BOD_LOAD); - return; + schCb.delayLoadWatermarkCount = schCb.delayLoadCount; } - - if (!schTryCurTailLoadNext()) - { - /* Curtail load failed. */ - schBodAbortHandler(); - } - /* Move to the next next BOD. */ - pNextBod = pNextBod->pNext; + return; } + + if (!schTryCurTailLoadNext()) + { + /* Curtail load failed. */ + schBodAbortHandler(); + } + /* Move to the next next BOD. */ + pNextBod = pNextBod->pNext; } /* If pNextBod exists, it should start scheduler timer. */ @@ -161,19 +162,17 @@ static void schBodLoadHandler(void) else { /* If this happens, it means there's something wrong with the scheduler list. */ - LL_TRACE_WARN0(" Next BOD overlaps with current BOD. "); + LL_TRACE_WARN0("Next BOD overlaps with current BOD"); /* Send scheduler load event. */ SchLoadHandler(); } -#endif } +#endif } /*************************************************************************************************/ /*! * \brief Scheduler load handler. - * - * \return None. */ /*************************************************************************************************/ void SchLoadHandler(void) @@ -184,8 +183,6 @@ void SchLoadHandler(void) /*************************************************************************************************/ /*! * \brief Initialize the scheduler subsystem. - * - * \return None. */ /*************************************************************************************************/ void SchInit(void) @@ -201,8 +198,6 @@ void SchInit(void) * * \param handlerId WSF handler ID. * - * \return None. - * * \note This initialization to used to enable task-based scheduler completions. For * ISR-based scheduler completions, do not call this routine. Instead install an * ISR which calls SchHandler() on BOD completions. @@ -220,8 +215,6 @@ void SchHandlerInit(wsfHandlerId_t handlerId) /*************************************************************************************************/ /*! * \brief Reset the scheduler subsystem. - * - * \return None. */ /*************************************************************************************************/ void SchReset(void) @@ -229,6 +222,9 @@ void SchReset(void) schCb.state = SCH_STATE_IDLE; schCb.pHead = NULL; schCb.pTail = NULL; + schCb.schHandlerWatermarkUsec = 0; + schCb.delayLoadWatermarkCount = 0; + schCb.delayLoadTotalCount = 0; } /*************************************************************************************************/ @@ -237,8 +233,6 @@ void SchReset(void) * * \param event WSF event. * \param pMsg WSF message. - * - * \return None. */ /*************************************************************************************************/ void SchHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) @@ -247,81 +241,86 @@ void SchHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) (void)pMsg; /* Assume scheduler clock started. */ - uint32_t startTime = PalTimerGetCurrentTime(); + uint32_t startTime = PalBbGetCurrentTime(); - BbOpDesc_t *pBod = schCb.pHead; - - if (!pBod) + while (event != 0) { - schCb.state = SCH_STATE_IDLE; - return; - } + BbOpDesc_t *pBod = schCb.pHead; - if (event & SCH_EVENT_BOD_COMPLETE) - { - WSF_ASSERT(schCb.state == SCH_STATE_EXEC); - WSF_ASSERT(schCb.eventSetFlagCount); - - /*** Complete current BOD ***/ - - schCb.state = SCH_STATE_IDLE; - schRemoveHead(); - if (pBod->endCback) + if (!pBod) { - pBod->endCback(pBod); + schCb.eventSetFlagCount = 0; + schCb.state = SCH_STATE_IDLE; + return; } - schCb.eventSetFlagCount--; + + if (event & SCH_EVENT_BOD_COMPLETE) + { + WSF_ASSERT(schCb.state == SCH_STATE_EXEC); + WSF_ASSERT(schCb.eventSetFlagCount); + + /*** Complete current BOD ***/ + + schCb.state = SCH_STATE_IDLE; + schRemoveHead(); + if (pBod->endCback) + { + pBod->endCback(pBod); + } + schCb.eventSetFlagCount--; #if SCH_TIMER_REQUIRED == FALSE - schBodLoadHandler(); + schBodLoadHandler(); #endif - } - - 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); + event &= ~SCH_EVENT_BOD_COMPLETE; } - schCb.eventSetFlagCount--; + + 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(); + schBodLoadHandler(); #endif - } - - if (event & SCH_EVENT_BOD_CURTAIL) - { - WSF_ASSERT(schCb.state == SCH_STATE_EXEC); - WSF_ASSERT(schCb.eventSetFlagCount); - - /*** Complete previous BOD ***/ - schRemoveHead(); - if (pBod->endCback) - { - pBod->endCback(pBod); + 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; } - schCb.eventSetFlagCount--; } - if (event & SCH_EVENT_BOD_LOAD) + uint32_t endTime = PalBbGetCurrentTime(); + uint32_t durUsec = BbGetTargetTimeDelta(endTime, startTime); + if (schCb.schHandlerWatermarkUsec < durUsec) { - schBodLoadHandler(); - } - - uint32_t curTick = PalTimerGetCurrentTime(); - /* Consider both count-up or counter-down timer type. */ - uint32_t durTick = (curTick- startTime < 0x80000000) ? (curTick - startTime) : (startTime - curTick); - uint16_t durUsec = PAL_TIMER_TICKS_TO_US(durTick); - if (schHandlerWatermarkUsec < durUsec) - { - schHandlerWatermarkUsec = durUsec; + schCb.schHandlerWatermarkUsec = durUsec; } } @@ -329,17 +328,20 @@ 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; + bool_t loaded = FALSE; if (schDueTimeInFuture(pBod)) { /* Setup BB services. */ BbExecuteBod(pBod); + schCb.delayLoadCount = 0; if (!BbGetBodTerminateFlag()) { @@ -361,7 +363,7 @@ static bool_t schLoadBod(BbOpDesc_t *pBod) else { /* This might occur due to the delay of conflict resolution. */ - LL_TRACE_WARN1("!!! Head element in the past, pBod=0x%08x", pBod); + LL_TRACE_ERR1("!!! Head element in the past, pBod=0x%08x", pBod); } return loaded; @@ -445,5 +447,29 @@ bool_t schTryLoadHead(void) /*************************************************************************************************/ uint16_t SchStatsGetHandlerWatermarkUsec(void) { - return schHandlerWatermarkUsec; + 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/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/arduino_primo.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/arduino_primo.h index 07fe47950c..2e462c17d7 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/arduino_primo.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/arduino_primo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * Copyright (c) 2016 - 2019, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/boards.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/boards.c index b438f82387..4c7fe5d25d 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/boards.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/boards.c @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * Copyright (c) 2016 - 2019, Nordic Semiconductor ASA * * All rights reserved. * @@ -43,7 +43,6 @@ #endif #include #include -#include "nrf_assert.h" #if LEDS_NUMBER > 0 static const uint8_t m_board_led_list[LEDS_NUMBER] = LEDS_LIST; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/boards.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/boards.h index 1ab0629c04..35421d23ad 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/boards.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/boards.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA + * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA * * All rights reserved. * @@ -65,6 +65,8 @@ #include "pca10040.h" #elif defined(BOARD_PCA10056) #include "pca10056.h" +#elif defined(BOARD_PCA10100) + #include "pca10100.h" #elif defined(BOARD_PCA20020) #include "pca20020.h" #elif defined(BOARD_PCA10059) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/nrf6310.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/nrf6310.h index c4488228ec..bd52945873 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/nrf6310.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/nrf6310.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA + * Copyright (c) 2012 - 2019, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10000.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10000.h index 3c33494673..01fe58ba2c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10000.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10000.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA + * Copyright (c) 2012 - 2019, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10001.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10001.h index 8121516d0e..9c7f228d6a 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10001.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10001.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA + * Copyright (c) 2012 - 2019, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10003.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10003.h index 724cb0c0ca..3562fd80f8 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10003.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10003.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA + * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10028.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10028.h index 946f158fdc..bd365db6c4 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10028.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10028.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA + * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10031.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10031.h index 538dedc4b6..b8c6d6976f 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10031.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10031.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA + * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10036.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10036.h index 560a68c16a..6aaddc5eca 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10036.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10036.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA + * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10040.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10040.h index 2fa0fbe89d..597ff69c6e 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10040.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10040.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA + * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10056.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10056.h index 00ecc91689..8689dc00cd 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10056.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10056.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * Copyright (c) 2016 - 2019, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10059.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10059.h index 50fd2b2e09..711edd428b 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10059.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10059.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * Copyright (c) 2017 - 2019, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10100.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10100.h new file mode 100644 index 0000000000..c44fb1bfc6 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca10100.h @@ -0,0 +1,155 @@ +/** + * Copyright (c) 2019, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef PCA10100_H +#define PCA10100_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nrf_gpio.h" + +// LEDs definitions for PCA10056 +#define LEDS_NUMBER 4 + +#define LED_1 NRF_GPIO_PIN_MAP(0,13) +#define LED_2 NRF_GPIO_PIN_MAP(0,14) +#define LED_3 NRF_GPIO_PIN_MAP(0,15) +#define LED_4 NRF_GPIO_PIN_MAP(0,16) +#define LED_START LED_1 +#define LED_STOP LED_4 + +#define LEDS_ACTIVE_STATE 0 + +#define LEDS_LIST { LED_1, LED_2, LED_3, LED_4 } + +#define LEDS_INV_MASK LEDS_MASK + +#define BSP_LED_0 13 +#define BSP_LED_1 14 +#define BSP_LED_2 15 +#define BSP_LED_3 16 + +#define BUTTONS_NUMBER 4 + +#define BUTTON_1 11 +#define BUTTON_2 12 +#define BUTTON_3 24 +#define BUTTON_4 25 +#define BUTTON_PULL NRF_GPIO_PIN_PULLUP + +#define BUTTONS_ACTIVE_STATE 0 + +#define BUTTONS_LIST { BUTTON_1, BUTTON_2, BUTTON_3, BUTTON_4 } + +#define BSP_BUTTON_0 BUTTON_1 +#define BSP_BUTTON_1 BUTTON_2 +#define BSP_BUTTON_2 BUTTON_3 +#define BSP_BUTTON_3 BUTTON_4 + +#define RX_PIN_NUMBER 8 +#define TX_PIN_NUMBER 6 +#define CTS_PIN_NUMBER 7 +#define RTS_PIN_NUMBER 5 +#define HWFC true + +// serialization APPLICATION board - temp. setup for running serialized MEMU tests +#define SER_APP_RX_PIN NRF_GPIO_PIN_MAP(1,13) // UART RX pin number. +#define SER_APP_TX_PIN NRF_GPIO_PIN_MAP(1,14) // UART TX pin number. +#define SER_APP_CTS_PIN NRF_GPIO_PIN_MAP(0,2) // UART Clear To Send pin number. +#define SER_APP_RTS_PIN NRF_GPIO_PIN_MAP(1,15) // UART Request To Send pin number. + +#define SER_APP_SPIM0_SCK_PIN NRF_GPIO_PIN_MAP(0,27) // SPI clock GPIO pin number. +#define SER_APP_SPIM0_MOSI_PIN NRF_GPIO_PIN_MAP(0,2) // SPI Master Out Slave In GPIO pin number +#define SER_APP_SPIM0_MISO_PIN NRF_GPIO_PIN_MAP(0,26) // SPI Master In Slave Out GPIO pin number +#define SER_APP_SPIM0_SS_PIN NRF_GPIO_PIN_MAP(1,13) // SPI Slave Select GPIO pin number +#define SER_APP_SPIM0_RDY_PIN NRF_GPIO_PIN_MAP(1,15) // SPI READY GPIO pin number +#define SER_APP_SPIM0_REQ_PIN NRF_GPIO_PIN_MAP(1,14) // SPI REQUEST GPIO pin number + +// serialization CONNECTIVITY board +#define SER_CON_RX_PIN NRF_GPIO_PIN_MAP(1,14) // UART RX pin number. +#define SER_CON_TX_PIN NRF_GPIO_PIN_MAP(1,13) // UART TX pin number. +#define SER_CON_CTS_PIN NRF_GPIO_PIN_MAP(1,15) // UART Clear To Send pin number. Not used if HWFC is set to false. +#define SER_CON_RTS_PIN NRF_GPIO_PIN_MAP(0,2) // UART Request To Send pin number. Not used if HWFC is set to false. + + +#define SER_CON_SPIS_SCK_PIN NRF_GPIO_PIN_MAP(0,27) // SPI SCK signal. +#define SER_CON_SPIS_MOSI_PIN NRF_GPIO_PIN_MAP(0,2) // SPI MOSI signal. +#define SER_CON_SPIS_MISO_PIN NRF_GPIO_PIN_MAP(0,26) // SPI MISO signal. +#define SER_CON_SPIS_CSN_PIN NRF_GPIO_PIN_MAP(1,13) // SPI CSN signal. +#define SER_CON_SPIS_RDY_PIN NRF_GPIO_PIN_MAP(1,15) // SPI READY GPIO pin number. +#define SER_CON_SPIS_REQ_PIN NRF_GPIO_PIN_MAP(1,14) // SPI REQUEST GPIO pin number. + +#define SER_CONN_CHIP_RESET_PIN NRF_GPIO_PIN_MAP(1,1) // Pin used to reset connectivity chip + +// Arduino board mappings +#define ARDUINO_SCL_PIN 27 // SCL signal pin +#define ARDUINO_SDA_PIN 26 // SDA signal pin +#define ARDUINO_AREF_PIN 2 // Aref pin + +#define ARDUINO_13_PIN NRF_GPIO_PIN_MAP(1, 23) // Digital pin 13 +#define ARDUINO_12_PIN NRF_GPIO_PIN_MAP(1, 22) // Digital pin 12 +#define ARDUINO_11_PIN NRF_GPIO_PIN_MAP(1, 21) // Digital pin 11 +#define ARDUINO_10_PIN NRF_GPIO_PIN_MAP(1, 20) // Digital pin 10 +#define ARDUINO_9_PIN NRF_GPIO_PIN_MAP(1, 19) // Digital pin 9 +#define ARDUINO_8_PIN NRF_GPIO_PIN_MAP(1, 17) // Digital pin 8 + +#define ARDUINO_7_PIN NRF_GPIO_PIN_MAP(1, 8) // Digital pin 7 +#define ARDUINO_6_PIN NRF_GPIO_PIN_MAP(1, 7) // Digital pin 6 +#define ARDUINO_5_PIN NRF_GPIO_PIN_MAP(1, 6) // Digital pin 5 +#define ARDUINO_4_PIN NRF_GPIO_PIN_MAP(1, 5) // Digital pin 4 +#define ARDUINO_3_PIN NRF_GPIO_PIN_MAP(1, 4) // Digital pin 3 +#define ARDUINO_2_PIN NRF_GPIO_PIN_MAP(1, 3) // Digital pin 2 +#define ARDUINO_1_PIN NRF_GPIO_PIN_MAP(1, 2) // Digital pin 1 +#define ARDUINO_0_PIN NRF_GPIO_PIN_MAP(1, 1) // Digital pin 0 + +#define ARDUINO_A0_PIN 3 // Analog channel 0 +#define ARDUINO_A1_PIN 4 // Analog channel 1 +#define ARDUINO_A2_PIN 28 // Analog channel 2 +#define ARDUINO_A3_PIN 29 // Analog channel 3 +#define ARDUINO_A4_PIN 30 // Analog channel 4 +#define ARDUINO_A5_PIN 31 // Analog channel 5 + + +#ifdef __cplusplus +} +#endif + +#endif // PCA10100_H diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca20006.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca20006.h index 3cedfc9ea8..e8e3d68dc2 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca20006.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca20006.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA + * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca20020.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca20020.h index e253f4a150..4d3a906503 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca20020.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/pca20020.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * Copyright (c) 2017 - 2019, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/wt51822.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/wt51822.h index eb0552b0a0..53cfbecffa 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/wt51822.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/nordic-bsp/components/boards/wt51822.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA + * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA * * All rights reserved. * diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/uecc/uECC.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/uecc/uECC.c index ea351a6e43..6ae4c45193 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/uecc/uECC.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/uecc/uECC.c @@ -471,7 +471,7 @@ void uECC_set_rng(uECC_RNG_Function rng_function) { g_rng_function = rng_function; } -#if defined __GNUC__ && !defined(__ARMCC_VERSION) /* Only support GCC inline asm for now */ +#ifdef __GNUC__ /* Only support GCC inline asm for now */ #if (uECC_ASM && (uECC_PLATFORM == uECC_avr)) #include "asm_avr.inc" #endif diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/uecc/uECC_ll.c b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/uecc/uECC_ll.c index abb8b20e0a..41324c3985 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/uecc/uECC_ll.c +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/uecc/uECC_ll.c @@ -168,7 +168,7 @@ void uECC_set_rng_ll(uECC_RNG_Function rng_function) { g_rng_function = rng_function; } -#if !defined(__ARMCC_VERSION) && !defined(__ICCARM__) && defined(__GNUC__) /* Only support GCC inline asm for now */ +#ifdef __GNUC__ /* Only support GCC inline asm for now */ #if (uECC_ASM && (uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \ uECC_PLATFORM == uECC_arm_thumb2)) #include "asm_arm.inc" diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/uecc/uECC_ll.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/uecc/uECC_ll.h index 173bc12b68..d580bf44a8 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/uecc/uECC_ll.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_LL/stack/thirdparty/uecc/uECC_ll.h @@ -29,11 +29,7 @@ uECC_asm_fast - Use GCC inline assembly optimized for maximum speed. */ #define uECC_asm_small 1 #define uECC_asm_fast 2 #ifndef uECC_ASM - #if !defined(__ARMCC_VERSION) && !defined(__ICCARM__) && defined(__GNUC__) /* Only support GCC inline asm for now */ - #define uECC_ASM uECC_asm_fast - #else // DG: ARMCC 5, unlike GCC, IAR and CLANG, doesn't support GNU-style inline assembly - #define uECC_ASM uECC_asm_none - #endif + #define uECC_ASM uECC_asm_fast #endif /* Curve selection options. */