mirror of https://github.com/ARMmbed/mbed-os.git
Update Cordio host & controller stack to 21.04
parent
cf54d36bfb
commit
8afb1c5bac
|
@ -24,6 +24,7 @@
|
|||
#include "ble/common/BLETypes.h"
|
||||
#include "ble/driver/CordioHCITransportDriver.h"
|
||||
#include "ble/common/blecommon.h"
|
||||
#include "hal/ticker_api.h"
|
||||
|
||||
// FIXME: make this invisible!
|
||||
#include "wsf_buf.h"
|
||||
|
@ -145,7 +146,14 @@ public:
|
|||
*
|
||||
* Any call to write signals to the driver that the host stack is active.
|
||||
*/
|
||||
virtual void on_host_stack_inactivity();
|
||||
virtual void on_host_stack_inactivity();
|
||||
|
||||
/**
|
||||
* React to host stack preparing to enter deep sleep.
|
||||
*
|
||||
* \param[in] wakeTimeMs The amount of time in which to wake.
|
||||
*/
|
||||
virtual void on_deep_sleep(timestamp_t wakeTimeMs) {}
|
||||
|
||||
/* BLE Tester commands */
|
||||
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
Change Log
|
||||
r21.04
|
||||
|
||||
Improvements:
|
||||
|
||||
FW-3921 Deprecate power management API
|
||||
FW-3996 Improve interoperability with connection establishment when LL_OP_MODE_FLAG_ENA_FEAT_LLCP_STARTUP is enabled
|
||||
FW-4045 Relocate CIS Audio codec decode to end of CIS ISO event
|
||||
FW-4047 CIS Should change RTE parameters if it cannot honor host-requested value
|
||||
|
||||
Defects fixed:
|
||||
|
||||
FW-3851 HCI_LE_CIS_Established event has MAX_PDUs fields zero on both Master and Slave
|
||||
FW-3879 Incorrect AuxOffsetPtr value with large skip values
|
||||
FW-3890 Master may not synchronize with PAST
|
||||
FW-3981 HCI_LE_Setup_ISO_Data_Path for a BIS may incorrectly return success when clearing
|
||||
FW-3982 HCI_LE_Read_Remote_Features may return bits not in controller-to-controller mask
|
||||
FW-3986 HCI_Disconnect for CIS should return HCI_ERR_LOCAL_TERMINATED
|
||||
FW-3987 CIS ISO test Rx mode incorrectly counts successful packets
|
||||
FW-3989 Framed CIS test Rx mode will hang when receiving a data packet
|
||||
FW-3995 HCI_LE_Read_Remote_Features with LL_OP_MODE_FLAG_ENA_FEAT_LLCP_STARTUP enabled may be disallowed
|
||||
FW-3997 HCI_LE_Set_Address_Resolution_Enable set to FALSE may prevents controller from generating RPA for peer
|
||||
FW-3998 HCI_LE_Set_Address_Resolution_Enable set to FALSE may incorrectly continue to resolve RPA packets
|
||||
FW-3999 HCI_LE_ISO_Receive_Test for BIS does not receive when datapath is disabled
|
||||
FW-4004 HCI_LE_Transmit_Power_Reporting not generated when delta is 0
|
||||
FW-4005 Flushing of a PDU when a framed assembly has not started will discard the next valid PDU
|
||||
FW-4020 Allow payload with SYNC_INFO when synchronizing with Periodic Advertiser
|
||||
FW-4021 Periodic Synchronizer may use incorrect Aux Offset
|
||||
FW-4028 IAL BIS case times out before able to complete test procedure
|
||||
FW-4035 LL initialization directives are multiply defined
|
||||
FW-4039 LL_FEAT_ISO_SYNC feature bit not set
|
||||
FW-4042 CIS has MIC failure if two data packets are sent in same ISO event
|
||||
FW-4044 Peripheral CIS is not able to be schedule after a connection update
|
||||
FW-4046 CIS acknowledgement scheme does not work correctly
|
||||
FW-4048 Peripheral CIS may not advance payloads even after central acknowledges them
|
||||
|
||||
Known limitations:
|
||||
|
||||
FW-3789 ISO timestamps and packet counters may not be aligned in certain scenarios
|
||||
FW-3886 DLE max packet time should cap at 1M PHY when LE Coded PHY is disabled
|
||||
FW-4063 HCI_LE_Advertising_Set_Terminated may report incorrect Num_Completed_Extended_Advertising_Events with ExtAdv using LE Coded PHY
|
||||
|
||||
r21.02
|
||||
|
||||
Improvements:
|
||||
|
||||
FW-3988 LeSetCigParams defensive coding for zero-division
|
||||
|
||||
Known limitations:
|
||||
|
||||
FW-3981 HCI_LE_Setup_ISO_Data_Path for a BIS may incorrectly return success when clearing
|
||||
FW-3982 HCI_LE_Read_Remote_Features may return bits not in controller-to-controller mask
|
||||
FW-3986 HCI_Disconnect for CIS should return HCI_ERR_LOCAL_TERMINATED
|
||||
FW-3789 ISO timestamps and packet counters may not be aligned in certain scenarios
|
||||
FW-3851 HCI_LE_CIS_Established event has MAX_PDUs fields zero on both Master and Slave
|
||||
FW-3879 Incorrect AuxOffsetPtr value with large skip values
|
||||
FW-3886 DLE max packet time should cap at 1M PHY when LE Coded PHY is disabled
|
||||
FW-3890 Master may not synchronize with PAST
|
||||
FW-3987 CIS ISO test Rx mode incorrectly counts successful packets
|
||||
FW-3989 Framed CIS test Rx mode will hang when receiving a data packet
|
||||
FW-3995 HCI_LE_Read_Remote_Features with LL_OP_MODE_FLAG_ENA_FEAT_LLCP_STARTUP enabled may be disallowed
|
||||
FW-3997 HCI_LE_Set_Address_Resolution_Enable set to FALSE may prevents controller from generating RPA for peer
|
||||
FW-3998 HCI_LE_Set_Address_Resolution_Enable set to FALSE may incorrectly continue to resolve RPA packets
|
||||
FW-3999 HCI_LE_ISO_Receive_Test for BIS does not receive when datapath is disabled
|
||||
FW-4004 HCI_LE_Transmit_Power_Reporting not generated when delta is 0
|
||||
FW-4005 Flushing of a PDU when a framed assembly has not started will discard the next valid PDU
|
||||
|
||||
r20.12
|
||||
|
||||
Improvements:
|
||||
|
||||
FW-3385 Non-blocking scheme for PAL flash
|
||||
FW-3728 Packetcraft Audio Cape for PCA10056
|
||||
FW-3838 Token monitor utility script
|
||||
FW-3848 CIS and BIS recombination of SDUs
|
||||
FW-3862 BV32 codec integrated on nRF52840
|
||||
FW-3864 Write flash between radio events on nRF52840
|
||||
FW-3865 Nordic secure bootloader updates firmware from internal flash
|
||||
FW-3876 Tester should have a way to sequentially queue ISO Packets
|
||||
FW-3899 Controller should queue up disconnect commands for multiple CIS
|
||||
FW-3905 Change BIS datapath to use generic functions
|
||||
FW-3907 ITM SWO trace diagnostics
|
||||
FW-3931 Power control monitor improvements
|
||||
FW-3943 Sydney erratta: CIS RTE max removed (0x0F -> 0xFF)
|
||||
FW-3949 LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2 force CIS to use Coded PHY S2 option
|
||||
|
||||
Defects fixed:
|
||||
|
||||
FW-3263 Scanner may not filter AdvReport events when Filter Policy is 0x02 and RPA is used
|
||||
FW-3781 Some broadcaster BIS PTO combinations may fail
|
||||
FW-3821 BIS broadcaster may corrupt transmitted ISO SDUs
|
||||
FW-3822 HCI_LE_BIG_Create_Sync does not filter on BIS[i]
|
||||
FW-3831 HCI_GetVersion does not report build number
|
||||
FW-3837 Incorrect BIS length will prevent adjacent BIS from receive
|
||||
FW-3839 CIS interleaved uses incorrect channels on subevent 3+
|
||||
FW-3841 Timer may expire early
|
||||
FW-3845 CIS and ACL are using wrong channel parameters
|
||||
FW-3846 BIS encryption may use incorrect packet counter
|
||||
FW-3849 Command complete for setting CIG params will always return CIG=0
|
||||
FW-3850 Disconnecting ACL with CIS does not return a terminated event for CIS
|
||||
FW-3856 BIS should send lost packet SDUs to the host if no PDU is received
|
||||
FW-3857 BIS Framed PDUs are not sent in consecutive subevents
|
||||
FW-3858 Unframed BIS may send duplicate Data PDUs when BN > 1
|
||||
FW-3868 LE_REMOVE_CIG command doesn't have CIG ID field.
|
||||
FW-3869 Radio scheduler may operate on list out of order
|
||||
FW-3870 PHY incorrect when using CIS encryption that differs in PHY with ACL
|
||||
FW-3872 Removing CIS output data path returns command disallowed
|
||||
FW-3873 Closing and re-opening the same CIS will not properly establish the second CIS
|
||||
FW-3875 Controller will not send LLCP anymore if receiving UNKNOWN_RSP for a power control LLCP
|
||||
FW-3877 LhciRegisterSendTrCompleteHandler() callback does not persist after HCI_Reset
|
||||
FW-3878 Inline decryption does not filter encrypted packets that are NACK'ed
|
||||
FW-3881 CIS may attempt transmission after a failed receive
|
||||
FW-3882 CIS may receive on incorrect PHY when encrypted
|
||||
FW-3883 CIS rx timeout will cause the whole ISO event to be canceled
|
||||
FW-3884 CIS Slave encryption will not transmit correctly when bn StoM>0 and NSE>1
|
||||
FW-3894 CIS Slave will not respond to ACL events if CIS is disconnected
|
||||
FW-3895 CIS will not pass up lost or invalid SDUs to host
|
||||
FW-3896 MIC failure upon establishing 2 CIS
|
||||
FW-3906 Radio scheduler may overlap reservations
|
||||
FW-3908 Periodic Advertising may not send SyncInfo when restarting
|
||||
FW-3937 CIS MIC error returns two discconnection events
|
||||
FW-3941 Advertising while scanning may skip first advertising event
|
||||
FW-3942 CIS may duplicate packets when using codec datapath
|
||||
|
||||
Known limitations:
|
||||
|
||||
FW-3789 ISO timestamps and packet counters may not be aligned in certain scenarios
|
||||
FW-3851 HCI_LE_CIS_Established event has MAX_PDUs fields zero on both Master and Slave
|
||||
FW-3879 Incorrect AuxOffsetPtr value with large skip values
|
||||
FW-3886 DLE max packet time should cap at 1M PHY when LE Coded PHY is disabled
|
||||
FW-3890 Master may not synchronize with PAST
|
|
@ -350,6 +350,24 @@ void BbBleGetPerScanStats(BbBlePerScanPktStats_t *pStats);
|
|||
/*************************************************************************************************/
|
||||
void BbBleGetConnStats(BbBleDataPktStats_t *pStats);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Get CIS packet statistics.
|
||||
*
|
||||
* \param pStats CIS data statistics.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void BbBleGetCisStats(BbBleDataPktStats_t *pStats);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Get BIS packet statistics.
|
||||
*
|
||||
* \param pStats BIS data statistics.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void BbBleGetBisStats(BbBleDataPktStats_t *pStats);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Get test mode packet statistics.
|
||||
|
@ -404,15 +422,6 @@ void BbBleBisMasterInit(void);
|
|||
/*************************************************************************************************/
|
||||
void BbBleBisSlaveInit(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Get CIS packet statistics.
|
||||
*
|
||||
* \param pStats CIS data statistics.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void BbBleGetCisStats(BbBleDataPktStats_t *pStats);
|
||||
|
||||
/*! \} */ /* BB_API_BLE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2016-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -99,6 +99,15 @@ typedef void (*BbBleTxAdvSetup_t)(BbOpDesc_t *pBod, uint32_t advTxTime);
|
|||
/*! \brief Chain indication PDU transmit setup call signature. */
|
||||
typedef uint32_t (*BbBleTxAuxSetup_t)(BbOpDesc_t *pBod, bool_t isChainInd);
|
||||
|
||||
/*! \brief Aux Rx setup call signature. Returns TRUE if Scan was programmed. */
|
||||
typedef bool_t (*BbBleRxAuxSetup_t)(BbOpDesc_t *pBod, uint32_t refTime, uint32_t remScanDur);
|
||||
|
||||
/*! \brief Aux Tx complete call signature. Returns TRUE if BOD is complete. */
|
||||
typedef bool_t (*BbBleAuxTxComp_t)(BbOpDesc_t *pBod, uint8_t status);
|
||||
|
||||
/*! \brief Aux Rx complete call signature. Returns TRUE if BOD is complete. */
|
||||
typedef bool_t (*BbBleAuxRxComp_t)(BbOpDesc_t * const pCur, uint8_t status, int8_t rssi, uint32_t crc, uint32_t timestamp, uint8_t rxPhyOptions);
|
||||
|
||||
/*! \brief Returns TRUE if an scan request/response required. */
|
||||
typedef bool_t (*BbBleAdvComp_t)(BbOpDesc_t *pBod, const uint8_t *pBuf);
|
||||
|
||||
|
@ -152,6 +161,13 @@ typedef struct
|
|||
BbBleAdvComp_t txReqCback; /*!< Scan request completion callback. */
|
||||
BbBleAdvComp_t rxRspCback; /*!< Scan response completion callback. */
|
||||
|
||||
/* Aux Scan BOD link */
|
||||
BbOpDesc_t *auxScanBod; /*!< Pointer to the Aux Scan BOD */
|
||||
BbBleRxAuxSetup_t auxScanCheckCback; /*!< Setup an Aux Scan that needs to be programmed ASAP. */
|
||||
BbBleAuxTxComp_t auxScanTxCompCback; /*!< Aux Scan Tx complete. */
|
||||
BbBleAuxRxComp_t auxScanRxCompCback; /*!< Aux Scan Rx complete. */
|
||||
bool_t auxScanOpRunning; /*!< Informs if an Aux Scan operation is running in the context of the Ext Scan BOD. */
|
||||
|
||||
uint8_t txReqLen; /*!< Scan request buffer length. */
|
||||
|
||||
uint8_t scanChMap; /*!< Scan channel map. */
|
||||
|
@ -202,6 +218,7 @@ typedef struct
|
|||
uint8_t *pTxAuxReqBuf; /*!< Scan request buffer. */
|
||||
|
||||
BbBleAdvComp_t rxAuxAdvCback; /*!< Advertising completion callback. */
|
||||
BbBleAdvPost_t rxAuxAdvPostCback; /*!< Advertising completion post callback. */
|
||||
BbBleAdvComp_t rxAuxRspCback; /*!< Scan response completion callback. */
|
||||
BbBleRxChain_t rxAuxChainCback; /*!< Chain completion callback. */
|
||||
BbBleRxChainPost_t rxAuxChainPostCback;/*!< Chain completion post callback. */
|
||||
|
@ -291,13 +308,14 @@ typedef struct
|
|||
/*! \brief CIS master event operation data (\ref BB_BLE_OP_MST_CIS_EVENT). */
|
||||
typedef struct
|
||||
{
|
||||
BbBleCisCheckContOp_t checkContOpCback; /*!< Check whether to continue current operation callback. */
|
||||
BbBleExec_t execCback; /*!< Execute callback. */
|
||||
BbBleExec_t contExecCback; /*!< Continue execute callback. */
|
||||
BbBleCisPostExec_t postSubEvtCback; /*!< Post subevent callback. */
|
||||
BbBleCancel_t cancelCback; /*!< Cancel callback. */
|
||||
BbBleTxDataComp_t txDataCback; /*!< Transmit completion callback. */
|
||||
BbBleCisRxDataComp_t rxDataCback; /*!< Receive completion callback. */
|
||||
BbBleCisCheckContOp_t checkContOpCback; /*!< Check whether to continue current operation callback. */
|
||||
BbBleCisCheckContOp_t checkContOpPostCback; /*!< Check whether to continue current operation callback. */
|
||||
BbBleExec_t execCback; /*!< Execute callback. */
|
||||
BbBleExec_t contExecCback; /*!< Continue execute callback. */
|
||||
BbBleCisPostExec_t postSubEvtCback; /*!< Post subevent callback. */
|
||||
BbBleCancel_t cancelCback; /*!< Cancel callback. */
|
||||
BbBleTxDataComp_t txDataCback; /*!< Transmit completion callback. */
|
||||
BbBleCisRxDataComp_t rxDataCback; /*!< Receive completion callback. */
|
||||
/* Return parameters. */
|
||||
int8_t rssi; /*!< RSSI of the last received packet. */
|
||||
uint8_t rxPhyOptions; /*!< Rx PHY options. */
|
||||
|
@ -306,13 +324,14 @@ typedef struct
|
|||
/*! \brief CIS slave event operation data (\ref BB_BLE_OP_SLV_CIS_EVENT). */
|
||||
typedef struct
|
||||
{
|
||||
BbBleCisCheckContOp_t checkContOpCback; /*!< Check whether to continue current operation callback. */
|
||||
BbBleExec_t execCback; /*!< Execute callback. */
|
||||
BbBleExec_t contExecCback; /*!< Continue execute callback. */
|
||||
BbBleCisPostExec_t postSubEvtCback; /*!< Post subevent callback. */
|
||||
BbBleCancel_t cancelCback; /*!< Cancel callback. */
|
||||
BbBleTxDataComp_t txDataCback; /*!< Transmit completion callback. */
|
||||
BbBleRxDataComp_t rxDataCback; /*!< Receive completion callback. */
|
||||
BbBleCisCheckContOp_t checkContOpCback; /*!< Check whether to continue current operation callback. */
|
||||
BbBleCisCheckContOp_t checkContOpPostCback; /*!< Check whether to continue current operation callback. */
|
||||
BbBleExec_t execCback; /*!< Execute callback. */
|
||||
BbBleExec_t contExecCback; /*!< Continue execute callback. */
|
||||
BbBleCisPostExec_t postSubEvtCback; /*!< Post subevent callback. */
|
||||
BbBleCancel_t cancelCback; /*!< Cancel callback. */
|
||||
BbBleTxDataComp_t txDataCback; /*!< Transmit completion callback. */
|
||||
BbBleRxDataComp_t rxDataCback; /*!< Receive completion callback. */
|
||||
|
||||
/* Return parameters. */
|
||||
bool_t isFirstTs; /*!< True for the first timestamp. */
|
||||
|
@ -490,6 +509,49 @@ void BbBleBisRxData(uint8_t *pBuf, uint16_t len, uint32_t nextPduTime, PalBbBleC
|
|||
/*************************************************************************************************/
|
||||
void BbBleBisRxDataReAcq(uint32_t syncTime, PalBbBleChan_t *pChan);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Execute auxiliary scanning master BOD.
|
||||
*
|
||||
* \param pBod Pointer to the BOD to execute.
|
||||
* \param pBle BLE operation parameters.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void BbMstExecuteLinkedAuxScanOp(BbOpDesc_t *pBod, BbBleData_t *pBle);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Tx completion for auxiliary scanning master operation.
|
||||
*
|
||||
* \param status Completion status.
|
||||
* \param pBod Pointer to the BOD
|
||||
*
|
||||
* Setup for next action in the operation or complete the operation.
|
||||
*
|
||||
* \return TRUE if BOD is complete, FALSE otherwise.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t BbMstAuxScanTxCompHandler(BbOpDesc_t * const pBod, uint8_t status);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Rx completion for auxiliary scanning master operation.
|
||||
*
|
||||
* \param pCur Pointer to the BOD
|
||||
* \param status Reception status.
|
||||
* \param rssi RSSI value.
|
||||
* \param crc CRC value.
|
||||
* \param timestamp Start of packet timestamp in microseconds.
|
||||
* \param rxPhyOptions Rx PHY options.
|
||||
*
|
||||
* Setup for next action in the operation or complete the operation.
|
||||
*
|
||||
* \return TRUE if BOD is complete, FALSE otherwise.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t BbMstAuxScanRxCompHandler(BbOpDesc_t * const pCur, uint8_t status, int8_t rssi, uint32_t crc,
|
||||
uint32_t timestamp, uint8_t rxPhyOptions);
|
||||
|
||||
/*! \} */ /* BB_API_BLE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -44,6 +44,10 @@ extern "C" {
|
|||
/*! \brief Set a flag. */
|
||||
#define BB_BLE_PDU_FILT_SET_FLAG(pFilt, flag) (pFilt)->flags |= BB_BLE_PDU_FILT_FLAG_##flag;
|
||||
|
||||
/*! \brief Clear a flag. */
|
||||
#define BB_BLE_PDU_FILT_CLR_FLAG(pFilt, flag) (pFilt)->flags &= ~(BB_BLE_PDU_FILT_FLAG_##flag);
|
||||
|
||||
|
||||
/*! \brief PDU filtering flags. */
|
||||
enum
|
||||
{
|
||||
|
|
|
@ -76,6 +76,7 @@ void LhciBisSlaveInit(void);
|
|||
void LhciBisMasterInit(void);
|
||||
void LhciIsoInit(void);
|
||||
void LhciPowerControlInit(void);
|
||||
void LhciEnhConnUpdateInit(void);
|
||||
void LhciVsExtInit(lhciCmdHandler_t decodeCmd);
|
||||
void LhciHandlerInit(wsfHandlerId_t handlerId);
|
||||
void LhciHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -36,7 +36,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
/*! \brief Version number. */
|
||||
#define LL_VER_NUM 1366
|
||||
#define LL_VER_NUM 21015
|
||||
|
||||
/**************************************************************************************************
|
||||
Data Types
|
||||
|
@ -164,6 +164,11 @@ typedef struct
|
|||
bool_t phyCodedSup; /*!< Coded PHY supported. */
|
||||
bool_t stableModIdxTxSup; /*!< Tx stable modulation index supported. */
|
||||
bool_t stableModIdxRxSup; /*!< Rx stable modulation index supported. */
|
||||
/* Power control */
|
||||
int8_t pcHighThreshold; /*!< High RSSI threshold for power monitoring. */
|
||||
int8_t pcLowThreshold; /*!< Low RSSI threshold for power monitoring. */
|
||||
/* Channel classification reporting. */
|
||||
uint8_t chClassIntSpacing; /*!< Interval spacing of channel classification reporting. */
|
||||
} LlRtCfg_t;
|
||||
|
||||
/*! \} */ /* LL_API_INIT */
|
||||
|
@ -253,15 +258,23 @@ typedef struct
|
|||
#define LL_FEAT_CIS_MASTER_ROLE (UINT64_C(1) << 28) /*!< Connected Isochronous Stream Master Role supported. */
|
||||
#define LL_FEAT_CIS_SLAVE_ROLE (UINT64_C(1) << 29) /*!< Connected Isochronous Stream Slave Role supported. */
|
||||
#define LL_FEAT_ISO_BROADCASTER (UINT64_C(1) << 30) /*!< Isochronous Broadcaster Role supported. */
|
||||
#define LL_FEAT_ISO_SYNC (UINT64_C(1) << 31) /*!< Isochronous Synchronizer Role supported. */
|
||||
#define LL_FEAT_ISO_SYNC (UINT64_C(1) << 31) /*!< Isochronous Synchronized Receiver Role supported. */
|
||||
#define LL_FEAT_ISO_HOST_SUPPORT (UINT64_C(1) << 32) /*!< Host support for ISO Channels. */
|
||||
#define LL_FEAT_POWER_CONTROL_REQUEST (UINT64_C(1) << 33) /*!< Power control requests supported. */
|
||||
#define LL_FEAT_POWER_CHANGE_IND (UINT64_C(1) << 34) /*!< Power control power change indication supported. */
|
||||
#define LL_FEAT_PATH_LOSS_MONITOR (UINT64_C(1) << 35) /*!< Path loss monitoring supported. */
|
||||
/* --- Core Spec Sydney --- */
|
||||
#define LL_FEAT_PER_ADV_ADI_SUP (UINT64_C(1) << 36) /*!< Periodic advertising ADI field supported. */
|
||||
#define LL_FEAT_CONN_SUBRATE (UINT64_C(1) << 37) /*!< Connection subrating supported. */
|
||||
#define LL_FEAT_CONN_SUBRATE_HOST_SUPPORT (UINT64_C(1) << 38) /*!< Host support for connection subrating. */
|
||||
#define LL_FEAT_CHANNEL_CLASSIFICATION (UINT64_C(1) << 39) /*!< Channel classification supported. */
|
||||
/* Bits 56 - 62 are RFU for testing. */
|
||||
|
||||
#define LL_HOST_CONTROLLED_FEAT LL_FEAT_ISO_HOST_SUPPORT /*!< Feature bits controlled by the host. */
|
||||
/*! \brief Feature bits controlled by the host. */
|
||||
#define LL_HOST_CONTROLLED_FEAT (LL_FEAT_ISO_HOST_SUPPORT | LL_FEAT_CONN_SUBRATE_HOST_SUPPORT)
|
||||
|
||||
#define LL_FEAT_ALL_MASK (UINT64_C(0x0000000FFF01FFFF)) /*!< All feature mask, need to be updated when new features are added. */
|
||||
/*! \brief All feature mask. */
|
||||
#define LL_FEAT_ALL_MASK (UINT64_C(0x000000FFFFFFFFFF))
|
||||
|
||||
/*! \brief This parameter identifies the device role. */
|
||||
typedef enum
|
||||
|
@ -289,14 +302,19 @@ enum
|
|||
LL_OP_MODE_FLAG_ENA_MST_CIS_NULL_PDU = (1 << 12), /*!< Enable CIS master sends additional NULL PDU for acknowledge scheme. */
|
||||
LL_OP_MODE_FLAG_ENA_SLV_AUX_IND_ADVA = (1 << 13), /*!< AdvA will be included in AUX_ADV_IND instead of ADV_EXT_IND. */
|
||||
LL_OP_MODE_FLAG_ENA_ADV_CHAN_RAND = (1 << 14), /*!< Enable advertising channel randomization. */
|
||||
LL_OP_MODE_DISABLE_POWER_MONITOR = (1 << 15), /*!< Disable power monitoring. */
|
||||
LL_OP_MODE_FLAG_DIS_POWER_MONITOR = (1 << 15), /*!< Disable power monitoring. */
|
||||
LL_OP_MODE_FLAG_ENA_BIS_RECV_DUP = (1 << 16), /*!< Enable BIS receive duplicates. */
|
||||
LL_OP_MODE_FLAG_ENA_ISO_LOST_NOTIFY = (1 << 17), /*!< Enable HCI ISO lost SDU notification. */
|
||||
LL_OP_MODE_FLAG_ENA_CH_RPT_LLCP_AFTER_FEAT = (1 << 18), /*!< Perform channel report LLCP after feature exchange. */
|
||||
LL_OP_MODE_FLAG_IGNORE_CRC_ERR_TS = (1 << 19), /*!< Ignore timestamp of Rx packet with CRC error. */
|
||||
LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2 = (1 << 20), /*!< Force CIS to use Coded PHY with S2 option. */
|
||||
/* diagnostics only */
|
||||
LL_OP_MODE_FLAG_ENA_ADV_DLY = (1 << 16), /*!< Enable advertising delay. */
|
||||
LL_OP_MODE_FLAG_ENA_SCAN_BACKOFF = (1 << 17), /*!< Enable scan backoff. */
|
||||
LL_OP_MODE_FLAG_ENA_WW = (1 << 18), /*!< Enable window widening. */
|
||||
LL_OP_MODE_FLAG_ENA_SLV_LATENCY = (1 << 19), /*!< Enable slave latency. */
|
||||
LL_OP_MODE_FLAG_ENA_LLCP_TIMER = (1 << 20), /*!< Enable LLCP timer. */
|
||||
LL_OP_MODE_FLAG_IGNORE_CRC_ERR_TS = (1 << 21) /*!< Ignore timestamp of RX packet with CRC error. */
|
||||
LL_OP_MODE_FLAG_ENA_ADV_DLY = (1 << 24), /*!< Enable advertising delay. */
|
||||
LL_OP_MODE_FLAG_ENA_SCAN_BACKOFF = (1 << 25), /*!< Enable scan backoff. */
|
||||
LL_OP_MODE_FLAG_ENA_WW = (1 << 26), /*!< Enable window widening. */
|
||||
LL_OP_MODE_FLAG_ENA_SLV_LATENCY = (1 << 27), /*!< Enable slave latency. */
|
||||
LL_OP_MODE_FLAG_ENA_LLCP_TIMER = (1 << 28), /*!< Enable LLCP timer. */
|
||||
LL_OP_MODE_FLAG_ENA_SUBRATE_CE = (1 << 29) /*!< Enable subrating connection events. */
|
||||
};
|
||||
|
||||
/*! \} */ /* LL_API_DEVICE */
|
||||
|
@ -485,7 +503,14 @@ enum
|
|||
};
|
||||
|
||||
/*! \brief Periodic advertising create sync options valid bits. */
|
||||
#define LL_PER_ADV_CREATE_SYNC_OPTIONS_BITS 0x03
|
||||
#define LL_PER_ADV_CREATE_SYNC_OPTIONS_BITS 0x07
|
||||
|
||||
/*! \brief Periodic advertising enable bits. */
|
||||
enum
|
||||
{
|
||||
LL_PER_ADV_ENABLE_ADV_ENABLE_BIT = (1 << 0), /*!< Enable bit for periodic advertising enable command. */
|
||||
LL_PER_ADV_ENABLE_ADI_ENABLE_BIT = (1 << 1) /*!< Enable bit for periodic advertising ADI inclusion. */
|
||||
};
|
||||
|
||||
/*! \brief Periodic advertising create sync command. */
|
||||
typedef struct
|
||||
|
@ -732,8 +757,8 @@ typedef enum
|
|||
/*! \brief ISO data path. */
|
||||
typedef enum
|
||||
{
|
||||
LL_ISO_DATA_PATH_HCI = 0x00,
|
||||
LL_ISO_DATA_PATH_VS = 0x01, /*!< Vendor Specific. */
|
||||
LL_ISO_DATA_PATH_HCI = 0x00, /*!< HCI data path. */
|
||||
LL_ISO_DATA_PATH_VS = 0x01, /*!< Vendor Specific data path. */
|
||||
|
||||
LL_ISO_DATA_PATH_TOTAL, /*!< Total number of data path methods. */
|
||||
|
||||
|
@ -747,6 +772,15 @@ enum
|
|||
LL_ISO_DATA_PATH_OUTPUT_BIT = (1 << 1) /*!< Data path output bit. */
|
||||
};
|
||||
|
||||
/*! \brief LE setup ISO Data Path command. */
|
||||
typedef struct
|
||||
{
|
||||
LlIsoDataPathDir_t dpDir:8; /*!< Data path direction. */
|
||||
uint8_t dpId; /*!< Data path ID. */
|
||||
uint8_t vsCfgLen; /*!< Length of \a pVsCfg. */
|
||||
const uint8_t *pVsCfg; /*!< VS configuration buffer. */
|
||||
} LlIsoConfigDataPath_t;
|
||||
|
||||
/*! \brief LE setup ISO Data Path command. */
|
||||
typedef struct
|
||||
{
|
||||
|
@ -756,18 +790,19 @@ typedef struct
|
|||
uint8_t codecFormat; /*!< Codec Format. */
|
||||
uint16_t codecCompId; /*!< Codec Company ID. */
|
||||
uint16_t codecId; /*!< Codec ID. */
|
||||
uint32_t ctrDly; /*!< Codec ID. */
|
||||
uint32_t ctrDly; /*!< Controller delay. */
|
||||
uint8_t codecConfigLen; /*!< Codec configuration length. */
|
||||
uint8_t *pCodecConfig; /*!< Codec configuration. */
|
||||
const uint8_t *pCodecConfig; /*!< Codec configuration. */
|
||||
} LlIsoSetupDataPath_t;
|
||||
|
||||
/*! \brief BIG Create BIG message. */
|
||||
/*! \brief BIG Create BIG command. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bigHandle; /*!< Used to identify the BIG. */
|
||||
uint8_t advHandle; /*!< Used to identify the periodic advertising train. */
|
||||
uint8_t numBis; /*!< Total number of BISes in the BIG. */
|
||||
uint32_t sduInterUsec; /*!< Interval, in microseconds, of BIG SDUs. */
|
||||
uint8_t bcstCode[LL_BC_LEN];/*!< Session key used to encrypt and decrypt BIS payloads. */
|
||||
uint16_t maxSdu; /*!< Maximum size of an SDU. */
|
||||
uint16_t mtlMs; /*!< Maximum time in milliseconds. */
|
||||
uint8_t rtn; /*!< Retransmitted number. */
|
||||
|
@ -775,16 +810,16 @@ typedef struct
|
|||
uint8_t packing; /*!< Sequential or Interleaved packing. */
|
||||
LlFraming_t framing:8; /*!< Unframed or Framed. */
|
||||
uint8_t encrypt; /*!< Unencrypted or Encrypted. */
|
||||
uint8_t bcstCode[LL_BC_LEN];/*!< Session key used to encrypt and decrypt BIS payloads. */
|
||||
} LlCreateBig_t;
|
||||
|
||||
/*! \brief BIG Create BIG Test message. */
|
||||
/*! \brief BIG Create BIG Test command. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bigHandle; /*!< Used to identify the BIG. */
|
||||
uint8_t advHandle; /*!< Used to identify the periodic advertising train. */
|
||||
uint8_t numBis; /*!< Total number of BISes in the BIG. */
|
||||
uint32_t sduInterUsec; /*!< Interval in microseconds of BIG SDUs. */
|
||||
uint8_t bcstCode[LL_BC_LEN];/*!< Code used to derive the session key. */
|
||||
uint16_t isoInter; /*!< Duration of an isochronous interval for BIG PDUs in 1.25ms unit. */
|
||||
uint8_t nse; /*!< Total number of subevents in each interval of each BIS in the BIG. */
|
||||
uint16_t maxSdu; /*!< Maximum size of a SDU. */
|
||||
|
@ -796,10 +831,9 @@ typedef struct
|
|||
uint8_t irc; /*!< Number of times the scheduled payload(s) are transmitted in a given event. */
|
||||
uint8_t pto; /*!< Offset used for pre-transmissions. */
|
||||
uint8_t encrypt; /*!< Unencrypted or Encrypted. */
|
||||
uint8_t bcstCode[LL_BC_LEN];/*!< Code used to derive the session key. */
|
||||
} LlCreateBigTest_t;
|
||||
|
||||
/*! \brief BIG Create Sync message. */
|
||||
/*! \brief BIG Create Sync command. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bigHandle; /*!< Used to identify the BIG. */
|
||||
|
@ -814,6 +848,21 @@ typedef struct
|
|||
|
||||
/*! \} */ /* LL_API_ISO */
|
||||
|
||||
/*! \addtogroup LL_API_ECU
|
||||
* \{ */
|
||||
|
||||
/*! \brief Subrate parameter. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t srMin; /*!< Subrate minimum value. */
|
||||
uint16_t srMax; /*!< Subrate maximum value. */
|
||||
uint16_t maxLatency; /*!< Maximum latency. */
|
||||
uint16_t contNum; /*!< Continuation number. */
|
||||
uint16_t svt; /*!< Supervision timeout in 10ms units. */
|
||||
} LlSubrateParam_t;
|
||||
|
||||
/*! \} */ /* LL_API_ECU */
|
||||
|
||||
/*! \addtogroup LL_API_ENCRYPT
|
||||
* \{ */
|
||||
|
||||
|
@ -903,7 +952,6 @@ typedef struct
|
|||
uint32_t duplicatePkt; /*!< Retransmitted CIS data PDUs. */
|
||||
} LlIsoLinkQual_t;
|
||||
|
||||
|
||||
/*! \} */ /* LL_API_TEST */
|
||||
|
||||
/*! \addtogroup LL_API_EVENT
|
||||
|
@ -966,7 +1014,9 @@ enum
|
|||
LL_TX_POWER_REPORTING_IND, /*!< LL txPower change report received. */
|
||||
LL_PATH_LOSS_REPORTING_IND, /*!< Path loss reporting event. */
|
||||
LL_ISO_EVT_CMPL_IND, /*!< ISO Event complete event. */
|
||||
LL_BIG_INFO_ADV_REPORT_IND /*!< BIG Info advertising report event. */
|
||||
LL_BIG_INFO_ADV_REPORT_IND, /*!< BIG Info advertising report event. */
|
||||
/* --- Core Spec Sydney --- */
|
||||
LL_SUBRATE_CHANGE_IND /*!< Enhanced connection update complete. */
|
||||
};
|
||||
|
||||
/*! \brief Advertising report indication */
|
||||
|
@ -1069,6 +1119,7 @@ typedef struct
|
|||
uint8_t status; /*!< Status. */
|
||||
uint16_t handle; /*!< Connection handle. */
|
||||
bool_t enabled; /*!< Encryption enabled. */
|
||||
uint8_t encKeySize; /*!< Encryption key size. */
|
||||
} LlEncChangeInd_t;
|
||||
|
||||
/*! \brief Key refresh indication */
|
||||
|
@ -1456,7 +1507,19 @@ typedef struct
|
|||
uint16_t connHandle; /*!< Connection handle. */
|
||||
uint8_t curPathLoss; /*!< Current path loss. */
|
||||
uint8_t zoneEntered; /*!< Zone entered. */
|
||||
} LlPathLossThresholdEvt_t;
|
||||
} LlPathLossThresholdInd_t;
|
||||
|
||||
/*! \brief Subrate change event. */
|
||||
typedef struct
|
||||
{
|
||||
wsfMsgHdr_t hdr; /*!< Event header. */
|
||||
uint8_t status; /*!< Status. */
|
||||
uint16_t handle; /*!< Connection handle. */
|
||||
uint16_t srFactor; /*!< Subrate factor. */
|
||||
uint16_t perLatency; /*!< Peripheral latency. */
|
||||
uint16_t contNum; /*!< Continuation number. */
|
||||
uint16_t svt; /*!< Supervision timeout in 10ms units. */
|
||||
} LlSubrateChangeInd_t;
|
||||
|
||||
/*! \brief Union of all event types */
|
||||
typedef union
|
||||
|
@ -1507,9 +1570,11 @@ typedef union
|
|||
LlBigSyncLostInd_t bigSyncLostInd; /*!< LE BIG sync lost. */
|
||||
LlPeerScaCnf_t peerScaCnf; /*!< LE request peer SCA complete. */
|
||||
LlPowerReportInd_t powerRptInd; /*!< LE transmit power reporting indication. */
|
||||
LlIsoEventCmplInd_t isoEvtCmplInd; /*!< VS ISO Event complete. */
|
||||
LlIsoEventCmplInd_t isoEvtCmplInd; /*!< ISO Event complete. */
|
||||
LlBigInfoAdvRptInd_t bigInfoInd; /*!< LE Big Info indication. */
|
||||
LlPathLossThresholdEvt_t pathLossEvt; /*!< LE Path loss threshold reporting event. */
|
||||
LlPathLossThresholdInd_t pathLossInd; /*!< LE Path loss threshold reporting indication. */
|
||||
/* --- Core Spec Sydney --- */
|
||||
LlSubrateChangeInd_t subrateChangeInd; /*!< Subrate change event. */
|
||||
} LlEvt_t;
|
||||
|
||||
/*! \brief Event callback */
|
||||
|
@ -3841,27 +3906,31 @@ void LlGetPerScanContextSize(uint8_t *pMaxPerScan, uint16_t *pPerScanCtxSize);
|
|||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Get CIG context size.
|
||||
* \brief Get CIS context size.
|
||||
*
|
||||
* \param pMaxCig Buffer to return the maximum number of CIG.
|
||||
* \param pCigCtxSize Buffer to return the size in bytes of the CIG context.
|
||||
*
|
||||
* Return the connection context sizes.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void LlGetCigContextSize(uint8_t *pMaxCig, uint16_t *pCigCtxSize);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Get CIS context size.
|
||||
*
|
||||
* \param pMaxCis Buffer to return the maximum number of CIS.
|
||||
* \param pCisCtxSize Buffer to return the size in bytes of the CIS context.
|
||||
*
|
||||
* Return the connection context sizes.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void LlGetCisContextSize(uint8_t *pMaxCis, uint16_t *pCisCtxSize);
|
||||
void LlGetCisContextSize(uint8_t *pMaxCig, uint16_t *pCigCtxSize, uint8_t *pMaxCis, uint16_t *pCisCtxSize);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Get BIS context size.
|
||||
*
|
||||
* \param pMaxBig Buffer to return the maximum number of BIG.
|
||||
* \param pBigCtxSize Buffer to return the size in bytes of the BIG context.
|
||||
* \param pMaxBis Buffer to return the maximum number of BIS.
|
||||
* \param pBisCtxSize Buffer to return the size in bytes of the BIS context.
|
||||
*
|
||||
* Return the connection context sizes.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void LlGetBisContextSize(uint8_t *pMaxBig, uint16_t *pBigCtxSize, uint8_t *pMaxBis, uint16_t *pBisCtxSize);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
|
@ -3874,9 +3943,67 @@ uint16_t LlStatsGetHandlerWatermarkUsec(void);
|
|||
|
||||
/*! \} */ /* LL_API_DIAG */
|
||||
|
||||
/*! \addtogroup LL_API_CIS
|
||||
/*! \addtogroup LL_API_ISO
|
||||
* \{ */
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Used by a broadcaster host to command is used to create one or more BISes of a BIG
|
||||
* in the controller.
|
||||
*
|
||||
* \param pCreateBig Create BIG parameters.
|
||||
*
|
||||
* \return Status error code.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t LlCreateBig(LlCreateBig_t *pCreateBig);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Used by a broadcaster host to command is used to create one or more BISes of a BIG
|
||||
* in the ISO test mode.
|
||||
*
|
||||
* \param pCreateBigTest Create BIG Test parameters.
|
||||
*
|
||||
* \return Status error code.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t LlCreateBigTest(LlCreateBigTest_t *pCreateBigTest);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Used to terminate the transmission of all BISes of a BIG, or to cancel the process
|
||||
* of creating a BIG using the HCI_LE_Create_BIG command from the Isochronous Broadcaster.
|
||||
*
|
||||
* \param bigHandle Used to identify the BIG.
|
||||
* \param reason Termination reason.
|
||||
*
|
||||
* \return Status error code.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t LlTerminateBig(uint8_t bigHandle, uint8_t reason);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Used to synchronize and receive PDUs from one or more BISes within a BIG.
|
||||
*
|
||||
* \param pCreateSync BIG Create Sync parameters.
|
||||
*
|
||||
* \return Status error code.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t LlBigCreateSync(LlBigCreateSync_t *pCreateSync);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Used to stop synchronization with the BIG or to cancel the process of synchronizing
|
||||
* to BISes invoked by the HCI_LE_BIG_Create_Sync command
|
||||
*
|
||||
* \param bigHandle Used to identify the BIG.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void LlBigTerminateSync(uint8_t bigHandle);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Used by a master host to set the parameters of all connected isochronous streams
|
||||
|
@ -3951,64 +4078,6 @@ uint8_t LlAcceptCisReq(uint16_t cisHandle);
|
|||
/*************************************************************************************************/
|
||||
uint8_t LlRejectCisReq(uint16_t cisHandle, uint8_t reason);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Used by a broadcaster host to command is used to create one or more BISes of a BIG
|
||||
* in the controller.
|
||||
*
|
||||
* \param pCreateBig Create BIG parameters.
|
||||
*
|
||||
* \return Status error code.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t LlCreateBig(LlCreateBig_t *pCreateBig);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Used by a broadcaster host to command is used to create one or more BISes of a BIG
|
||||
* in the ISO test mode.
|
||||
*
|
||||
* \param pCreateBigTest Create BIG Test parameters.
|
||||
*
|
||||
* \return Status error code.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t LlCreateBigTest(LlCreateBigTest_t *pCreateBigTest);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Used to terminate the transmission of all BISes of a BIG, or to cancel the process
|
||||
* of creating a BIG using the HCI_LE_Create_BIG command from the Isochronous Broadcaster.
|
||||
*
|
||||
* \param bigHandle Used to identify the BIG.
|
||||
* \param reason Termination reason.
|
||||
*
|
||||
* \return Status error code.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t LlTerminateBig(uint8_t bigHandle, uint8_t reason);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Used to synchronize and receive PDUs from one or more BISes within a BIG.
|
||||
*
|
||||
* \param pCreateSync BIG Create Sync parameters.
|
||||
*
|
||||
* \return Status error code.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t LlBigCreateSync(LlBigCreateSync_t *pCreateSync);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Used to stop synchronization with the BIG or to cancel the process of synchronizing
|
||||
* to BISes invoked by the HCI_LE_BIG_Create_Sync command
|
||||
*
|
||||
* \param bigHandle Used to identify the BIG.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void LlBigTerminateSync(uint8_t bigHandle);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Read the Time_Stamp and Time_Offset of a transmitted ISO_SDU identified by the
|
||||
|
@ -4024,6 +4093,18 @@ void LlBigTerminateSync(uint8_t bigHandle);
|
|||
/*************************************************************************************************/
|
||||
uint8_t LlReadIsoTxSync(uint16_t handle, uint16_t *pPktSn, uint32_t *pTs, uint32_t *pTimeOffs);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Used to request the Controller to configure the data transport path in a given
|
||||
* direction between the Controller and the Host.
|
||||
*
|
||||
* \param pConfigDataPath Parameters for configure data path.
|
||||
*
|
||||
* \return Status error code.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t LlConfigureDataPath(LlIsoConfigDataPath_t *pConfigDataPath);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Used to identify and enable the isochronous data path between the host and the
|
||||
|
@ -4182,7 +4263,49 @@ uint8_t *LlRecvIsoData(void);
|
|||
/*************************************************************************************************/
|
||||
void LlRecvIsoDataComplete(uint8_t numBufs);
|
||||
|
||||
/*! \} */ /* LL_API_CIS */
|
||||
/*! \} */ /* LL_API_ISO */
|
||||
|
||||
/*! \addtogroup LL_API_ECU
|
||||
* \{ */
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Initialize LL subsystem for enhanced connection update.
|
||||
*
|
||||
* This function initializes the LL subsystem for use with enhanced connection updates.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void LlEnhConnUpdateInit(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Set the initial values for subrating requests.
|
||||
*
|
||||
* \param pSubrate Subrate parameter.
|
||||
*
|
||||
* \return Status error code.
|
||||
*
|
||||
* Set the initial values for the acceptable parameters for subrating requests for all future ACL
|
||||
* connections where the Controller is the Central. This command does not affect any existing
|
||||
* connection.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t LlSetDefaultSubrate(LlSubrateParam_t *pSubrate);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Request subrate change.
|
||||
*
|
||||
* \param handle Connection handle.
|
||||
* \param pSubrate Subrate parameter.
|
||||
*
|
||||
* Used by a Central or a Peripheral to request a change to the subrating factor and/or other
|
||||
* parameters applied to an existing connection using the Connection Subrate Update procedure.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void LlSubrateReq(uint16_t handle, LlSubrateParam_t *pSubrate);
|
||||
|
||||
/*! \} */ /* LL_API_ECU */
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
|
|
|
@ -62,7 +62,7 @@ extern "C" {
|
|||
|
||||
#ifndef BT_VER
|
||||
/*! \brief Initialize default BT version. */
|
||||
#define BT_VER LL_VER_BT_CORE_SPEC_5_1
|
||||
#define BT_VER LL_VER_BT_CORE_SPEC_5_0
|
||||
#endif
|
||||
|
||||
/**************************************************************************************************
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -56,7 +56,7 @@ extern "C" {
|
|||
enum
|
||||
{
|
||||
SCH_RM_PREF_PERFORMANCE, /*!< Performance is preferred, search from minimum interval. */
|
||||
SCH_RM_PREF_CAPACITY /*!< Capacity is preferred, search from maximum interval. */
|
||||
SCH_RM_PREF_CAPACITY /*!< Capacity is preferred, search from maximum interval. */
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2018 ARM Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -159,6 +159,8 @@ typedef struct BbOpDesc_tag
|
|||
|
||||
PalBbProt_t protId:8; /*!< Protocol type. */
|
||||
|
||||
bool_t recoverable; /*!< Indicates if the BOD can recover if the dueUsec time is in the past. */
|
||||
|
||||
BbBodCback_t endCback; /*!< End of BOD callback (when BOD ends). */
|
||||
BbBodCback_t abortCback; /*!< Abort BOD callback (when BOD is removed before beginning). */
|
||||
|
||||
|
@ -375,7 +377,7 @@ uint32_t BbAdjustTime(uint32_t dueUsec);
|
|||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Get Delta between target and reference time. Only valid if target time is in the future.
|
||||
* \brief Get delta between target and reference time. Only valid if target time is in the future.
|
||||
*
|
||||
* \param targetUsec Target time in microseconds.
|
||||
* \param refUsec Reference time in microseconds.
|
||||
|
|
|
@ -39,12 +39,6 @@ extern "C" {
|
|||
#define CHCI_BUF_TAILROOM 4 /*!< Extra byte allocation required for buffer (e.g., for MIC). */
|
||||
#endif
|
||||
|
||||
/*** Scheduler ***/
|
||||
|
||||
#ifndef SCH_TIMER_REQUIRED
|
||||
#define SCH_TIMER_REQUIRED TRUE /*!< If hardware timer is required for radio access scheduler.*/
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -91,6 +91,18 @@ extern "C" {
|
|||
#define LL_MAX_BN 8 /*!< Absolute maximum number of bursts. */
|
||||
#endif
|
||||
|
||||
#ifndef LL_PC_TBL_POW
|
||||
#define LL_PC_TBL_POW 2 /*!< Running average power control array sizes, must be a power of 2. */
|
||||
#endif
|
||||
|
||||
#ifndef LL_PC_SERVICE_MS
|
||||
#define LL_PC_SERVICE_MS 1000 /*!< Power control service intervals in milliseconds. */
|
||||
#endif
|
||||
|
||||
#ifndef LL_PC_REQ_CHANGE_DBM
|
||||
#define LL_PC_REQ_CHANGE_DBM 5 /*!< Request of increase/decrease in power value in units of dBm. */
|
||||
#endif
|
||||
|
||||
#ifndef LHCI_ENABLE_VS
|
||||
#define LHCI_ENABLE_VS 1 /*!< Enable vendor specific command processing. */
|
||||
#endif
|
||||
|
@ -108,7 +120,8 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#ifndef BB_ADV_PLD_MAX_LEN
|
||||
#define BB_ADV_PLD_MAX_LEN 255 /*!< Maximum advertising channel payload length (valid range 95 to 255). */
|
||||
#define BB_ADV_PLD_MAX_LEN (BB_DATA_PLD_MAX_LEN + 4)
|
||||
/*!< Maximum advertising channel payload length (valid range 95 to 255). */
|
||||
#endif
|
||||
|
||||
#ifndef BB_FIXED_DATA_PKT_LEN
|
||||
|
|
|
@ -68,15 +68,6 @@ void chciTrRecv(uint8_t prot, uint8_t type, uint8_t *pBuf);
|
|||
/*************************************************************************************************/
|
||||
void chciTrSendComplete(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Service the transport device.
|
||||
*
|
||||
* \return TRUE if work pending, FALSE if no work is pending.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t ChciTrService(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 ARM Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -49,19 +49,16 @@ void SchInit(void);
|
|||
void SchHandlerInit(wsfHandlerId_t handlerId);
|
||||
void SchReset(void);
|
||||
uint16_t SchStatsGetHandlerWatermarkUsec(void);
|
||||
uint16_t SchStatsGetDelayLoadWatermarkCount(void);
|
||||
uint32_t SchStatsGetDelayLoadTotalCount(void);
|
||||
|
||||
/* Control */
|
||||
void SchHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg);
|
||||
void SchLoadHandler(void);
|
||||
|
||||
/* List maintenance */
|
||||
void SchInsertNextAvailable(BbOpDesc_t *pBod);
|
||||
bool_t SchInsertAtDueTime(BbOpDesc_t *pBod, BbConflictAct_t conflictCback);
|
||||
bool_t SchInsertEarlyAsPossible(BbOpDesc_t *pBod, uint32_t min, uint32_t max);
|
||||
bool_t SchInsertLateAsPossible(BbOpDesc_t *pBod, uint32_t min, uint32_t max);
|
||||
bool_t SchRemove(BbOpDesc_t *pBod);
|
||||
void SchRemove(BbOpDesc_t *pBod);
|
||||
void SchReload(BbOpDesc_t *pBod);
|
||||
bool_t SchIsBodCancellable(BbOpDesc_t *pBod);
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -53,7 +53,7 @@ extern const BbRtCfg_t *pBbRtCfg;
|
|||
*
|
||||
* \return Scan duration in microseconds.
|
||||
*
|
||||
* This function is calculates the duration of the scan examining:
|
||||
* This function calculates the duration of the scan examining:
|
||||
* - total elapsed scan time
|
||||
* - neighboring BOD
|
||||
* - maximum scan period
|
||||
|
@ -98,7 +98,6 @@ static uint32_t bbBleCalcScanDurationUsec(BbOpDesc_t *pBod, BbBleMstAdvEvent_t *
|
|||
|
||||
if (pBod->pNext)
|
||||
{
|
||||
|
||||
uint32_t timeToNextOpUsec = BbGetTargetTimeDelta(pBod->pNext->dueUsec, refTime);
|
||||
|
||||
/* Limit scanning to the edge of neighboring BOD. */
|
||||
|
@ -151,6 +150,13 @@ static bool_t bbContScanOp(BbOpDesc_t *pBod, BbBleMstAdvEvent_t *pScan)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Check if an Aux Scan needs to be started ASAP because of a short auxOffset. */
|
||||
if (pScan->auxScanCheckCback && pScan->auxScanCheckCback(pBod, curTime, scanDurUsec))
|
||||
{
|
||||
pBod->prot.pBle->op.mstAdv.auxScanOpRunning = TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bbBleCb.bbParam.dueUsec = BbAdjustTime(bbBleCb.lastScanStartUsec + BbGetSchSetupDelayUs());
|
||||
bbBleCb.bbParam.rxTimeoutUsec = scanDurUsec;
|
||||
PalBbBleSetDataParams(&bbBleCb.bbParam);
|
||||
|
@ -191,6 +197,18 @@ static void bbMstScanTxCompCback(uint8_t status)
|
|||
bool_t bodComplete = FALSE;
|
||||
bool_t bodCont = FALSE;
|
||||
|
||||
if (pScan->auxScanTxCompCback && (pScan->auxScanOpRunning == TRUE))
|
||||
{
|
||||
/* This is a linked operation. Call the Aux Scan callback. */
|
||||
if (pScan->auxScanTxCompCback(pScan->auxScanBod, status) == TRUE)
|
||||
{
|
||||
/* BOD complete. Clear the linked BOD. */
|
||||
pScan->auxScanBod = NULL;
|
||||
pScan->auxScanOpRunning = FALSE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#if (BB_SNIFFER_ENABLED == TRUE)
|
||||
/* Save evtState to be used later in packet forwarding. */
|
||||
uint8_t evtState = bbBleCb.evtState;
|
||||
|
@ -318,6 +336,19 @@ static void bbMstScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint
|
|||
bool_t bodComplete = FALSE;
|
||||
bool_t bodCont = FALSE;
|
||||
|
||||
if (pScan->auxScanRxCompCback && pScan->auxScanOpRunning == TRUE)
|
||||
{
|
||||
/* This is a linked operation. Call the Aux Scan callback. */
|
||||
if (pScan->auxScanRxCompCback(pScan->auxScanBod, status, rssi, crc, timestamp, rxPhyOptions) == TRUE)
|
||||
{
|
||||
/* BOD complete. Clear the linked BOD. */
|
||||
pScan->auxScanBod = NULL;
|
||||
pScan->auxScanOpRunning = FALSE;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#if (BB_SNIFFER_ENABLED == TRUE)
|
||||
/* Save evtState to be used later in packet forwarding. */
|
||||
uint8_t evtState = bbBleCb.evtState;
|
||||
|
@ -521,6 +552,16 @@ static void bbMstScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint
|
|||
static void bbMstExecuteScanOp(BbOpDesc_t *pBod, BbBleData_t *pBle)
|
||||
{
|
||||
BbBleMstAdvEvent_t * const pScan = &pBod->prot.pBle->op.mstAdv;
|
||||
uint32_t curTime = PalBbGetCurrentTime();
|
||||
|
||||
/* Check if dueUsec time is in the past. */
|
||||
if (BbGetTargetTimeDelta(pBod->dueUsec, curTime) == 0)
|
||||
{
|
||||
/* Update dueUsec time and start Scan for the remaining duration. */
|
||||
bbBleCb.lastScanStartUsec = pBod->dueUsec;
|
||||
pBod->dueUsec = curTime + BbGetSchSetupDelayUs();
|
||||
pScan->elapsedUsec = BbGetTargetTimeDelta(curTime, bbBleCb.lastScanStartUsec);
|
||||
}
|
||||
|
||||
if (pScan->preExecCback)
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -52,15 +52,16 @@ static uint8_t bbPerScanBuf[LL_EXT_ADVB_MAX_LEN];
|
|||
* \brief Tx completion for auxiliary scanning master operation.
|
||||
*
|
||||
* \param status Completion status.
|
||||
* \param pBod Pointer to the BOD
|
||||
*
|
||||
* Setup for next action in the operation or complete the operation.
|
||||
*
|
||||
* \return TRUE if BOD is complete, FALSE otherwise.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void bbMstAuxScanTxCompCback(uint8_t status)
|
||||
bool_t BbMstAuxScanTxCompHandler(BbOpDesc_t *pBod, uint8_t status)
|
||||
{
|
||||
BB_ISR_START();
|
||||
|
||||
WSF_ASSERT(BbGetCurrentBod());
|
||||
WSF_ASSERT(pBod);
|
||||
|
||||
bool_t bodComplete = FALSE;
|
||||
|
||||
|
@ -72,7 +73,6 @@ static void bbMstAuxScanTxCompCback(uint8_t status)
|
|||
{
|
||||
pPkt = bbSnifferCtx.snifferGetPktFn();
|
||||
}
|
||||
BbOpDesc_t * const pCur = BbGetCurrentBod();
|
||||
#endif
|
||||
|
||||
switch (bbBleCb.evtState++)
|
||||
|
@ -128,10 +128,30 @@ static void bbMstAuxScanTxCompCback(uint8_t status)
|
|||
pPkt->pktType.meta.status = status;
|
||||
pPkt->pktType.meta.state = evtState;
|
||||
|
||||
bbBleSnifferMstAuxScanPktHandler(pCur, pPkt);
|
||||
bbBleSnifferMstAuxScanPktHandler(pBod, pPkt);
|
||||
}
|
||||
#else
|
||||
(void)pBod;
|
||||
#endif
|
||||
|
||||
return bodComplete;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Tx completion for auxiliary scanning master operation.
|
||||
*
|
||||
* \param status Completion status.
|
||||
*
|
||||
* Setup for next action in the operation or complete the operation.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void bbMstAuxScanTxCompCback(uint8_t status)
|
||||
{
|
||||
BB_ISR_START();
|
||||
|
||||
(void)BbMstAuxScanTxCompHandler(BbGetCurrentBod(), status);
|
||||
|
||||
BB_ISR_MARK(bbAuxScanStats.txIsrUsec);
|
||||
}
|
||||
|
||||
|
@ -139,6 +159,7 @@ static void bbMstAuxScanTxCompCback(uint8_t status)
|
|||
/*!
|
||||
* \brief Rx completion for auxiliary scanning master operation.
|
||||
*
|
||||
* \param pCur Pointer to the BOD
|
||||
* \param status Reception status.
|
||||
* \param rssi RSSI value.
|
||||
* \param crc CRC value.
|
||||
|
@ -146,15 +167,14 @@ static void bbMstAuxScanTxCompCback(uint8_t status)
|
|||
* \param rxPhyOptions Rx PHY options.
|
||||
*
|
||||
* Setup for next action in the operation or complete the operation.
|
||||
*
|
||||
* \return TRUE if BOD is complete, FALSE otherwise.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void bbMstAuxScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint32_t timestamp, uint8_t rxPhyOptions)
|
||||
bool_t BbMstAuxScanRxCompHandler(BbOpDesc_t * const pCur, uint8_t status, int8_t rssi, uint32_t crc, uint32_t timestamp, uint8_t rxPhyOptions)
|
||||
{
|
||||
BB_ISR_START();
|
||||
WSF_ASSERT(pCur);
|
||||
|
||||
WSF_ASSERT(BbGetCurrentBod());
|
||||
|
||||
BbOpDesc_t * const pCur = BbGetCurrentBod();
|
||||
BbBleData_t * const pBle = pCur->prot.pBle;
|
||||
BbBleMstAuxAdvEvent_t * const pAuxScan = &pBle->op.mstAuxAdv;
|
||||
|
||||
|
@ -195,54 +215,65 @@ static void bbMstAuxScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u
|
|||
#endif
|
||||
|
||||
uint32_t auxOffsetUsec;
|
||||
if (pAuxScan->rxAuxAdvCback(pCur, bbAuxAdvBuf))
|
||||
bool_t txScanReq = pAuxScan->rxAuxAdvCback(pCur, bbAuxAdvBuf);
|
||||
if ((txScanReq) && (pAuxScan->pTxAuxReqBuf))
|
||||
{
|
||||
if (pAuxScan->pTxAuxReqBuf)
|
||||
{
|
||||
/* Tx response PDU. */
|
||||
/* Tx response PDU. */
|
||||
|
||||
bbBleCb.evtState = BB_EVT_STATE_TX_SCAN_OR_CONN_INIT;
|
||||
bbBleCb.evtState = BB_EVT_STATE_TX_SCAN_OR_CONN_INIT;
|
||||
|
||||
BB_ISR_MARK(bbAuxScanStats.txSetupUsec);
|
||||
BB_ISR_MARK(bbAuxScanStats.txSetupUsec);
|
||||
|
||||
PalBbBleTxBufDesc_t desc = {.pBuf = pAuxScan->pTxAuxReqBuf, .len = pAuxScan->txAuxReqLen};
|
||||
PalBbBleTxBufDesc_t desc = {.pBuf = pAuxScan->pTxAuxReqBuf, .len = pAuxScan->txAuxReqLen};
|
||||
|
||||
bbBleSetTifs();
|
||||
PalBbBleTxTifsData(&desc, 1);
|
||||
}
|
||||
}
|
||||
else if ((pAuxScan->rxAuxChainCback) &&
|
||||
((auxOffsetUsec = pAuxScan->rxAuxChainCback(pCur, bbAuxAdvBuf)) > 0))
|
||||
{
|
||||
/* Rx chain indication PDU. */
|
||||
|
||||
bbBleCb.evtState = BB_EVT_STATE_RX_CHAIN_IND;
|
||||
|
||||
/* Cancel Tifs operation is needed for passive scan and non connectable/scannable adv with chain. */
|
||||
PalBbBleCancelTifs();
|
||||
|
||||
PalBbBleSetChannelParam(&pBle->chan);
|
||||
bbBleCb.bbParam.dueUsec = BbAdjustTime(timestamp + auxOffsetUsec);
|
||||
PalBbBleSetDataParams(&bbBleCb.bbParam);
|
||||
|
||||
BB_ISR_MARK(bbAuxScanStats.rxSetupUsec);
|
||||
|
||||
bbBleClrIfs(); /* CHAIN_IND does not use TIFS. */
|
||||
PalBbBleRxData(bbAuxAdvBuf, sizeof(bbAuxAdvBuf));
|
||||
|
||||
WSF_ASSERT(pAuxScan->rxAuxChainPostCback);
|
||||
if (pAuxScan->rxAuxChainPostCback(pCur, bbAuxAdvBuf) == FALSE)
|
||||
{
|
||||
bodCont = TRUE;
|
||||
}
|
||||
bbBleSetTifs();
|
||||
PalBbBleTxTifsData(&desc, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pAuxScan->rxAuxChainPostCback)
|
||||
PalBbBleCancelTifs();
|
||||
}
|
||||
|
||||
if (pAuxScan->rxAuxAdvPostCback)
|
||||
{
|
||||
pAuxScan->rxAuxAdvPostCback(pCur, bbAuxAdvBuf);
|
||||
}
|
||||
|
||||
if (!txScanReq)
|
||||
{
|
||||
if ((pAuxScan->rxAuxChainCback) &&
|
||||
((auxOffsetUsec = pAuxScan->rxAuxChainCback(pCur, bbAuxAdvBuf)) > 0))
|
||||
{
|
||||
pAuxScan->rxAuxChainPostCback(pCur, bbAuxAdvBuf);
|
||||
/* Rx chain indication PDU. */
|
||||
|
||||
bbBleCb.evtState = BB_EVT_STATE_RX_CHAIN_IND;
|
||||
|
||||
/* Cancel Tifs operation is needed for passive scan and non connectable/scannable adv with chain. */
|
||||
PalBbBleCancelTifs();
|
||||
|
||||
PalBbBleSetChannelParam(&pBle->chan);
|
||||
bbBleCb.bbParam.dueUsec = BbAdjustTime(timestamp + auxOffsetUsec);
|
||||
PalBbBleSetDataParams(&bbBleCb.bbParam);
|
||||
|
||||
BB_ISR_MARK(bbAuxScanStats.rxSetupUsec);
|
||||
|
||||
bbBleClrIfs(); /* CHAIN_IND does not use TIFS. */
|
||||
PalBbBleRxData(bbAuxAdvBuf, sizeof(bbAuxAdvBuf));
|
||||
|
||||
WSF_ASSERT(pAuxScan->rxAuxChainPostCback);
|
||||
if (pAuxScan->rxAuxChainPostCback(pCur, bbAuxAdvBuf) == FALSE)
|
||||
{
|
||||
bodCont = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pAuxScan->rxAuxChainPostCback)
|
||||
{
|
||||
pAuxScan->rxAuxChainPostCback(pCur, bbAuxAdvBuf);
|
||||
}
|
||||
bodCont = TRUE;
|
||||
}
|
||||
bodCont = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -494,8 +525,29 @@ static void bbMstAuxScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, u
|
|||
}
|
||||
#endif
|
||||
|
||||
BB_ISR_MARK(bbAuxScanStats.rxIsrUsec);
|
||||
return bodComplete;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Rx completion for auxiliary scanning master operation.
|
||||
*
|
||||
* \param status Reception status.
|
||||
* \param rssi RSSI value.
|
||||
* \param crc CRC value.
|
||||
* \param timestamp Start of packet timestamp in microseconds.
|
||||
* \param rxPhyOptions Rx PHY options.
|
||||
*
|
||||
* Setup for next action in the operation or complete the operation.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void bbMstAuxScanRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint32_t timestamp, uint8_t rxPhyOptions)
|
||||
{
|
||||
BB_ISR_START();
|
||||
|
||||
(void)BbMstAuxScanRxCompHandler(BbGetCurrentBod(), status, rssi, crc, timestamp, rxPhyOptions);
|
||||
|
||||
BB_ISR_MARK(bbAuxScanStats.rxIsrUsec);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -856,3 +908,34 @@ void BbBleGetPerScanStats(BbBlePerScanPktStats_t *pStats)
|
|||
*pStats = bbPerScanStats;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Execute auxiliary scanning master BOD.
|
||||
*
|
||||
* \param pBod Pointer to the BOD to execute.
|
||||
* \param pBle BLE operation parameters.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void BbMstExecuteLinkedAuxScanOp(BbOpDesc_t *pBod, BbBleData_t *pBle)
|
||||
{
|
||||
BbBleMstAuxAdvEvent_t * const pAuxScan = &pBod->prot.pBle->op.mstAuxAdv;
|
||||
|
||||
PalBbBleSetChannelParam(&pBle->chan);
|
||||
|
||||
bbBleCb.bbParam.rxTimeoutUsec = pAuxScan->rxSyncDelayUsec;
|
||||
bbBleCb.bbParam.dueUsec = BbAdjustTime(pBod->dueUsec);
|
||||
pBod->dueUsec = bbBleCb.bbParam.dueUsec;
|
||||
PalBbBleSetDataParams(&bbBleCb.bbParam);
|
||||
|
||||
bbBleCb.evtState = 0;
|
||||
|
||||
if (pAuxScan->pTxAuxReqBuf)
|
||||
{
|
||||
bbBleSetTifs(); /* active scan or initiating */
|
||||
}
|
||||
else
|
||||
{
|
||||
bbBleClrIfs(); /* passive scan */
|
||||
}
|
||||
PalBbBleRxData(bbAuxAdvBuf, sizeof(bbAuxAdvBuf));
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ static bool_t bbSetupAdvOp(BbOpDesc_t *pBod, BbBleSlvAdvEvent_t *pAdv, uint8_t s
|
|||
{
|
||||
/* Schedule with absolute frame gap. */
|
||||
uint32_t advGap = SchBleCalcAdvPktDurationUsec(pBle->chan.txPhy, pBle->chan.initTxPhyOptions, pAdv->txAdvLen) +
|
||||
BbGetSchSetupDelayUs();
|
||||
BbGetSchSetupDelayUs();
|
||||
uint32_t auxOffsUsec = SchBleGetAlignedAuxOffsUsec(advGap);
|
||||
bbBleCb.bbParam.dueUsec = BbAdjustTime(bbBleCb.bbParam.dueUsec + auxOffsUsec);
|
||||
}
|
||||
|
|
|
@ -193,7 +193,6 @@ Cleanup:
|
|||
BbTerminateBod();
|
||||
}
|
||||
|
||||
|
||||
#if (BB_SNIFFER_ENABLED == TRUE)
|
||||
if (pPkt)
|
||||
{
|
||||
|
|
|
@ -137,7 +137,14 @@ void BbBleBisSlaveInit(void)
|
|||
/*************************************************************************************************/
|
||||
void BbBleBisTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt, uint32_t nextPduTime, PalBbBleChan_t *pNextChan)
|
||||
{
|
||||
bbBleSetAbsIfs(nextPduTime, pNextChan);
|
||||
if (pNextChan)
|
||||
{
|
||||
bbBleSetAbsIfs(nextPduTime, pNextChan);
|
||||
}
|
||||
else
|
||||
{
|
||||
bbBleClrIfs();
|
||||
}
|
||||
|
||||
if (bbBleCb.evtState == 0)
|
||||
{
|
||||
|
@ -149,3 +156,13 @@ void BbBleBisTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt, uint32_t nextPduTi
|
|||
PalBbBleTxTifsData(descs, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Get BIS packet statistics.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void BbBleGetBisStats(BbBleDataPktStats_t *pStats)
|
||||
{
|
||||
*pStats = bbBisStats;
|
||||
}
|
||||
|
|
|
@ -80,10 +80,10 @@ void BbBleCisTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt)
|
|||
/*************************************************************************************************/
|
||||
void BbBleCisRxData(uint8_t *pBuf, uint16_t len)
|
||||
{
|
||||
WSF_ASSERT(!bbBleCb.pRxCisDataBuf);
|
||||
WSF_ASSERT(!bbBleCb.pRxDataBuf);
|
||||
|
||||
bbBleCb.pRxCisDataBuf = pBuf;
|
||||
bbBleCb.rxCisDataLen = len;
|
||||
bbBleCb.pRxDataBuf = pBuf;
|
||||
bbBleCb.rxDataLen = len;
|
||||
|
||||
if ((BbGetCurrentBod()->prot.pBle->chan.opType == BB_BLE_OP_SLV_CIS_EVENT) &&
|
||||
(bbBleCb.evtState == 0))
|
||||
|
@ -95,7 +95,7 @@ void BbBleCisRxData(uint8_t *pBuf, uint16_t len)
|
|||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Get connection packet statistics.
|
||||
* \brief Get CIS packet statistics.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void BbBleGetCisStats(BbBleDataPktStats_t *pStats)
|
||||
|
|
|
@ -71,6 +71,11 @@ static bool_t bbMstCisCheckContOp(BbOpDesc_t *pCur, BbBleMstCisEvent_t *pCis, bo
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Cancel TIFS timer. */
|
||||
PalBbBleCancelTifs();
|
||||
|
||||
(void)pCis->checkContOpPostCback(pCur, pNewCisCtx);
|
||||
|
||||
/* Updated channel parameter. */
|
||||
BbBleData_t *pBle = pCur->prot.pBle;
|
||||
PalBbBleSetChannelParam(&pBle->chan);
|
||||
|
@ -121,13 +126,13 @@ static void bbMstCisTxCompCback(uint8_t status)
|
|||
|
||||
pCis->txDataCback(pCur, status);
|
||||
|
||||
if (bbBleCb.pRxCisDataBuf &&
|
||||
if (bbBleCb.pRxDataBuf &&
|
||||
(status == BB_STATUS_SUCCESS))
|
||||
{
|
||||
BB_ISR_MARK(bbCisStats.rxSetupUsec);
|
||||
|
||||
bbBleSetTifs(); /* TODO set only if Tx may follow in CE */
|
||||
PalBbBleRxTifsData(bbBleCb.pRxCisDataBuf, bbBleCb.rxDataLen);
|
||||
PalBbBleRxTifsData(bbBleCb.pRxDataBuf, bbBleCb.rxDataLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -140,10 +145,10 @@ static void bbMstCisTxCompCback(uint8_t status)
|
|||
case BB_STATUS_FAILED:
|
||||
default:
|
||||
/* Free Rx data buffer before BOD end. */
|
||||
if (bbBleCb.pRxCisDataBuf != NULL) /* buffer should always exist, but still check */
|
||||
if (bbBleCb.pRxDataBuf != NULL) /* buffer should always exist, but still check */
|
||||
{
|
||||
uint8_t *pBuf = bbBleCb.pRxCisDataBuf;
|
||||
bbBleCb.pRxCisDataBuf = NULL;
|
||||
uint8_t *pBuf = bbBleCb.pRxDataBuf;
|
||||
bbBleCb.pRxDataBuf = NULL;
|
||||
pCis->rxDataCback(pCur, pBuf, BB_STATUS_CANCELED);
|
||||
}
|
||||
break;
|
||||
|
@ -199,9 +204,9 @@ static void bbMstCisRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint3
|
|||
pCis->rssi = rssi;
|
||||
pCis->rxPhyOptions = rxPhyOptions;
|
||||
|
||||
WSF_ASSERT(bbBleCb.pRxCisDataBuf);
|
||||
uint8_t *pBuf = bbBleCb.pRxCisDataBuf;
|
||||
bbBleCb.pRxCisDataBuf = NULL;
|
||||
WSF_ASSERT(bbBleCb.pRxDataBuf);
|
||||
uint8_t *pBuf = bbBleCb.pRxDataBuf;
|
||||
bbBleCb.pRxDataBuf = NULL;
|
||||
|
||||
pCis->rxDataCback(pCur, pBuf, status);
|
||||
|
||||
|
@ -210,7 +215,7 @@ static void bbMstCisRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint3
|
|||
|
||||
if (BbGetBodTerminateFlag() || bodComplete)
|
||||
{
|
||||
WSF_ASSERT(!bbBleCb.pRxCisDataBuf);
|
||||
WSF_ASSERT(!bbBleCb.pRxDataBuf);
|
||||
|
||||
/* Cancel TIFS timer if active. */
|
||||
switch (status)
|
||||
|
@ -280,6 +285,7 @@ static void bbMstExecuteCisOp(BbOpDesc_t *pBod, BbBleData_t *pBle)
|
|||
WSF_ASSERT(pBle->op.mstCis.rxDataCback);
|
||||
WSF_ASSERT(pBle->op.mstCis.execCback);
|
||||
WSF_ASSERT(pBle->op.mstCis.checkContOpCback);
|
||||
WSF_ASSERT(pBle->op.mstCis.checkContOpPostCback);
|
||||
|
||||
#if(LL_ENABLE_TESTER)
|
||||
pBle->chan.txPower += pBle->chan.txPwrOffset;
|
||||
|
@ -317,10 +323,10 @@ static void bbMstCancelCisOp(BbOpDesc_t *pBod, BbBleData_t *pBle)
|
|||
|
||||
PalBbBleCancelData();
|
||||
|
||||
if (bbBleCb.pRxCisDataBuf)
|
||||
if (bbBleCb.pRxDataBuf)
|
||||
{
|
||||
uint8_t *pBuf = bbBleCb.pRxCisDataBuf;
|
||||
bbBleCb.pRxCisDataBuf = NULL;
|
||||
uint8_t *pBuf = bbBleCb.pRxDataBuf;
|
||||
bbBleCb.pRxDataBuf = NULL;
|
||||
|
||||
/* Buffer free expected to be called during this routine. */
|
||||
pBle->op.mstCis.rxDataCback(pBod, pBuf, BB_STATUS_CANCELED);
|
||||
|
|
|
@ -83,6 +83,11 @@ static bool_t bbSlvCisCheckNextOp(BbOpDesc_t *pCur, BbBleSlvCisEvent_t *pCis, bo
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Cancel TIFS timer. */
|
||||
PalBbBleCancelTifs();
|
||||
|
||||
(void)pCis->checkContOpPostCback(pCur, pNewCisCtx);
|
||||
|
||||
/* Update channel parameter. */
|
||||
BbBleData_t *pBle = pCur->prot.pBle;
|
||||
PalBbBleSetChannelParam(&pBle->chan);
|
||||
|
@ -148,10 +153,10 @@ static void bbSlvCisTxCompCback(uint8_t status)
|
|||
{
|
||||
if (bodComplete)
|
||||
{
|
||||
if (bbBleCb.pRxCisDataBuf != NULL)
|
||||
if (bbBleCb.pRxDataBuf != NULL)
|
||||
{
|
||||
uint8_t *pBuf = bbBleCb.pRxCisDataBuf;
|
||||
bbBleCb.pRxCisDataBuf = NULL;
|
||||
uint8_t *pBuf = bbBleCb.pRxDataBuf;
|
||||
bbBleCb.pRxDataBuf = NULL;
|
||||
pCis->rxDataCback(pCur, pBuf, BB_STATUS_CANCELED);
|
||||
}
|
||||
|
||||
|
@ -168,10 +173,10 @@ static void bbSlvCisTxCompCback(uint8_t status)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (bbBleCb.pRxCisDataBuf != NULL)
|
||||
if (bbBleCb.pRxDataBuf != NULL)
|
||||
{
|
||||
uint8_t *pBuf = bbBleCb.pRxCisDataBuf;
|
||||
bbBleCb.pRxCisDataBuf = NULL;
|
||||
uint8_t *pBuf = bbBleCb.pRxDataBuf;
|
||||
bbBleCb.pRxDataBuf = NULL;
|
||||
pCis->rxDataCback(pCur, pBuf, BB_STATUS_CANCELED);
|
||||
}
|
||||
|
||||
|
@ -231,7 +236,7 @@ static void bbSlvCisRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint3
|
|||
|
||||
if (pCis->isFirstTs == TRUE)
|
||||
{
|
||||
/* Update startTs for the successful rx, otherwise use the due time. */
|
||||
/* Update startTs for the successful Rx, otherwise use the due time. */
|
||||
if (status == BB_STATUS_SUCCESS)
|
||||
{
|
||||
pCis->startTsUsec = timestamp;
|
||||
|
@ -245,30 +250,49 @@ static void bbSlvCisRxCompCback(uint8_t status, int8_t rssi, uint32_t crc, uint3
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Update rxTs for the successful rx, otherwise use the due time. */
|
||||
/* Update rxTs for the successful Rx, otherwise use the due time. */
|
||||
if (status == BB_STATUS_SUCCESS)
|
||||
{
|
||||
pCis->rxTsUsec = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
WSF_ASSERT(bbBleCb.pRxCisDataBuf);
|
||||
WSF_ASSERT(bbBleCb.pRxDataBuf);
|
||||
|
||||
uint8_t *pBuf = bbBleCb.pRxCisDataBuf;
|
||||
bbBleCb.pRxCisDataBuf = NULL;
|
||||
uint8_t *pBuf = bbBleCb.pRxDataBuf;
|
||||
bbBleCb.pRxDataBuf = NULL;
|
||||
|
||||
/* Set Tx buffer or BOD cancel expected to be called during this routine. */
|
||||
pCis->rxDataCback(pCur, pBuf, status);
|
||||
|
||||
if ((status != BB_STATUS_RX_TIMEOUT) && /* BB_STATUS_RX_TIMEOUT will setup Tx which will be failed and terminate BOD. */
|
||||
BbGetBodTerminateFlag())
|
||||
bool_t bodComplete = FALSE;
|
||||
bool_t newCisCtx = FALSE;
|
||||
|
||||
switch (status)
|
||||
{
|
||||
WSF_ASSERT(!bbBleCb.pRxCisDataBuf);
|
||||
case BB_STATUS_RX_TIMEOUT:
|
||||
case BB_STATUS_FAILED:
|
||||
bodComplete = bbSlvCisCheckNextOp(pCur, pCis, &newCisCtx);
|
||||
|
||||
/* Skip the post subevent callback if switching to the new CIS context. */
|
||||
if (newCisCtx == FALSE)
|
||||
{
|
||||
bbSlvCisPostSubEvt(pCur, pCis, status);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (BbGetBodTerminateFlag() || bodComplete)
|
||||
{
|
||||
WSF_ASSERT(!bbBleCb.pRxDataBuf);
|
||||
|
||||
/* Cancel TIFS timer if active. */
|
||||
switch (status)
|
||||
{
|
||||
case BB_STATUS_SUCCESS:
|
||||
case BB_STATUS_CRC_FAILED:
|
||||
PalBbBleCancelTifs();
|
||||
break;
|
||||
default:
|
||||
|
@ -320,6 +344,7 @@ static void bbSlvExecuteCisOp(BbOpDesc_t *pBod, BbBleData_t *pBle)
|
|||
WSF_ASSERT(pCis->rxDataCback);
|
||||
WSF_ASSERT(pCis->execCback);
|
||||
WSF_ASSERT(pCis->checkContOpCback);
|
||||
WSF_ASSERT(pCis->checkContOpPostCback);
|
||||
|
||||
pCis->isFirstTs = TRUE;
|
||||
pCis->rxTsUsec = pBod->dueUsec;
|
||||
|
@ -357,10 +382,10 @@ static void bbSlvCancelCisOp(BbOpDesc_t *pBod, BbBleData_t *pBle)
|
|||
|
||||
PalBbBleCancelData();
|
||||
|
||||
if (bbBleCb.pRxCisDataBuf)
|
||||
if (bbBleCb.pRxDataBuf)
|
||||
{
|
||||
uint8_t *pBuf = bbBleCb.pRxCisDataBuf;
|
||||
bbBleCb.pRxCisDataBuf = NULL;
|
||||
uint8_t *pBuf = bbBleCb.pRxDataBuf;
|
||||
bbBleCb.pRxDataBuf = NULL;
|
||||
|
||||
/* Buffer free expected to be called during this routine. */
|
||||
pBle->op.slvCis.rxDataCback(pBod, pBuf, BB_STATUS_CANCELED);
|
||||
|
|
|
@ -94,10 +94,6 @@ typedef struct
|
|||
|
||||
uint16_t rxDataLen; /*!< Receive data buffer length. */
|
||||
uint8_t *pRxDataBuf; /*!< Current Rx data buffer. */
|
||||
|
||||
/* TODO combine with above? */
|
||||
uint16_t rxCisDataLen; /*!< Receive CIS data buffer length. */
|
||||
uint8_t *pRxCisDataBuf; /*!< Current Rx CIS data buffer. */
|
||||
} bbBleCtrlBlk_t;
|
||||
|
||||
/**************************************************************************************************
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -99,6 +99,13 @@ enum
|
|||
LCTR_SCAN_PHY_ALL = 0xFF /*!< All PHY scanners. */
|
||||
};
|
||||
|
||||
/*! \brief Periodic scan receive enable bits. */
|
||||
enum
|
||||
{
|
||||
LCTR_PER_RECV_ENABLE_REPORT_BIT_POS = 0, /*!< Enable periodic scan reports. */
|
||||
LCTR_PER_RECV_ENABLE_FILTERING_BIT_POS = 1 /*!< Enable filtering by ADI of periodic advertising trains. */
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Data Types
|
||||
**************************************************************************************************/
|
||||
|
@ -142,6 +149,7 @@ typedef struct
|
|||
uint64_t advAddr; /*!< Advertiser Address. */
|
||||
uint16_t skip; /*!< Skip. */
|
||||
uint16_t syncTimeOut; /*!< Synchronization Timeout. */
|
||||
uint8_t dupFilterEnable; /*!< Duplicate filtering enable. */
|
||||
} lctrPerCreateSyncMsg_t;
|
||||
|
||||
/*! \brief Periodic transfer sync message. */
|
||||
|
@ -204,7 +212,7 @@ uint64_t LctrGetPerScanChanMap(uint16_t handle);
|
|||
bool_t lctrMstPerIsSyncHandleValid(uint16_t syncHandle);
|
||||
void LctrPastInit(void);
|
||||
uint8_t LctrPeriodicAdvSyncTransfer(uint16_t connHandle, uint16_t serviceData, uint16_t syncHandle);
|
||||
void LctrMstPerSetRcvEnable(uint16_t syncHandle, bool_t enable);
|
||||
void LctrMstPerSetRcvEnable(uint16_t syncHandle, uint8_t enable);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -88,7 +88,7 @@ enum
|
|||
LCTR_CONN_MSG_API_CIS_REQ_ACCEPT, /*!< Peer CIS request accept API event. */
|
||||
LCTR_CONN_MSG_API_CIS_REQ_REJECT, /*!< Peer CIS request accept API event. */
|
||||
LCTR_CONN_MSG_API_PWR_CTRL_REQ, /*!< Peer power control request API event. */
|
||||
|
||||
LCTR_CONN_MSG_API_SUBRATE_REQ, /*!< Subrate request API event. */
|
||||
/* Internal events */
|
||||
_LCTR_CONN_INT_EVENTS = 40,
|
||||
LCTR_CONN_DATA_PENDING, /*!< New data pending. */
|
||||
|
@ -100,9 +100,12 @@ enum
|
|||
LCTR_CONN_LLCP_VERSION_EXCH, /*!< LL initiated remote version exchange. */
|
||||
LCTR_CONN_LLCP_FEATURE_EXCH, /*!< LL initiated remote feature exchange. */
|
||||
LCTR_CONN_LLCP_LENGTH_EXCH, /*!< LL initiated data length exchange. */
|
||||
LCTR_CONN_LLCP_PWR_CTRL_REQ, /*!< LL initiated power control request. */
|
||||
LCTR_CONN_LLCP_PWR_CTRL_SERVICE, /*!< Service power control monitor. */
|
||||
LCTR_CONN_LLCP_TERM, /*!< LL initiated termination. */
|
||||
LCTR_CONN_LLCP_CHANNEL_STATUS, /*!< LL initiated channel status. */
|
||||
LCTR_CONN_LLCP_CHANNEL_REPORTING, /*!< LL initiated channel reporting. */
|
||||
LCTR_CONN_LLCP_PROC_CMPL, /*!< LLCP procedure completed. */
|
||||
LCTR_CONN_LLCP_PROC_ABORTED, /*!< LLCP procedure aborted. */
|
||||
LCTR_CONN_LLCP_START_PENDING, /*!< Start pending LLCP procedure. */
|
||||
LCTR_CONN_LLCP_SKIP_CONN_PARAM, /*!< Skip connection parameter exchange. */
|
||||
LCTR_CONN_LLCP_REJECT_CONN_UPD, /*!< Reject a connection update. */
|
||||
|
@ -240,6 +243,34 @@ typedef struct
|
|||
uint8_t phy; /*!< PHY requested. */
|
||||
} lctrMsgPwrCtrlReq_t;
|
||||
|
||||
/*! \brief Internal subrate request message. */
|
||||
typedef struct
|
||||
{
|
||||
lctrMsgHdr_t hdr; /*!< Message Header. */
|
||||
uint16_t srMin; /*!< Subrate minimum value. */
|
||||
uint16_t srMax; /*!< Subrate maximum value. */
|
||||
uint16_t maxLatency; /*!< Maximum latency. */
|
||||
uint16_t contNum; /*!< Continuation number. */
|
||||
uint16_t svt; /*!< Supervision timeout in 10ms units. */
|
||||
} lctrMsgSubrateReq_t;
|
||||
|
||||
/*! \brief Channel reporting indication message. */
|
||||
typedef struct
|
||||
{
|
||||
lctrMsgHdr_t hdr; /*!< Message Header. */
|
||||
uint8_t enable; /*!< Enable. */
|
||||
uint8_t minSpacing; /*!< Minimum status report spacing. */
|
||||
uint8_t maxDelay; /*!< Maximum status report delay. */
|
||||
} lctrMsgChRptInd_t;
|
||||
|
||||
/*! \brief Channel status indication message. */
|
||||
typedef struct
|
||||
{
|
||||
lctrMsgHdr_t hdr; /*!< Message Header. */
|
||||
uint8_t chanStatus[LL_MAX_NUM_CHAN_DATA];
|
||||
/*!< Status of used channels. */
|
||||
} lctrMsgChStatusInd_t;
|
||||
|
||||
/*! \brief Link layer controller message data. */
|
||||
typedef union
|
||||
{
|
||||
|
@ -258,6 +289,9 @@ typedef union
|
|||
lctrPerAdvSyncTrsf_t perAdvSyncTrsf; /*!< Periodic advertising sync transfer data. */
|
||||
lctrScaReq_t scaReq; /*!< Sleep clock accuracy request. */
|
||||
lctrMsgPwrCtrlReq_t pwrCtrlReq; /*!< Power control request. */
|
||||
lctrMsgSubrateReq_t subrateReq; /*!< Subrate request. */
|
||||
lctrMsgChRptInd_t chanRptInd; /*!< Channel report indication. */
|
||||
lctrMsgChStatusInd_t chanStatusInd; /*!< Channel status indication. */
|
||||
|
||||
/* CIS */
|
||||
lctrCreateCis_t createCis; /*!< Create CIS message data. */
|
||||
|
@ -314,6 +348,8 @@ void LctrVsConnInit(const LctrVsHandlers_t *pHdlrs);
|
|||
uint8_t LctrValidateConnSpec(const LlConnSpec_t *pConnSpec);
|
||||
uint8_t LctrValidateModifyScaParam(uint8_t action);
|
||||
bool_t LctrIsProcActPended(uint16_t handle, uint8_t event);
|
||||
bool_t LctrIsFeatExchHostInit(uint16_t handle);
|
||||
void LctrSetHostNotifyFeatExch(uint16_t handle);
|
||||
|
||||
/* Status */
|
||||
bool_t LctrIsConnHandleEnabled(uint16_t handle);
|
||||
|
@ -326,6 +362,7 @@ uint64_t LctrGetChannelMap(uint16_t handle);
|
|||
uint64_t LctrGetUsedFeatures(uint16_t handle);
|
||||
uint8_t LctrGetTxPhy(uint16_t handle);
|
||||
uint8_t LctrGetRxPhy(uint16_t handle);
|
||||
bool_t LctrCisTerminationInProgress(uint16_t handle);
|
||||
void LctrGetPeerMinUsedChan(uint16_t handle, uint8_t *pPeerMinUsedChan);
|
||||
bool_t LctrIsWaitingForReply(uint16_t handle, uint8_t reply);
|
||||
bool_t LctrIsCisEnabled(uint16_t handle);
|
||||
|
@ -341,7 +378,6 @@ bool_t LctrSetEncMode(uint16_t handle, const LlEncMode_t *pMode);
|
|||
void LctrSetConnOpFlags(uint16_t handle, uint32_t flags, bool_t enable);
|
||||
uint8_t lctrSetPowerMonitorEnable(uint16_t handle, bool_t enable);
|
||||
|
||||
|
||||
/* Data path */
|
||||
void LctrTxAcl(uint8_t *pAclBuf);
|
||||
uint8_t *LctrRxAcl(void);
|
||||
|
|
|
@ -45,6 +45,7 @@ void LctrTxIso(uint8_t *pIsoBuf);
|
|||
uint8_t *LctrRxIso(void);
|
||||
void LctrRxIsoComplete(uint8_t numBufs);
|
||||
uint8_t LctrReadIsoTxSync(uint16_t handle, uint16_t *pPktSn, uint32_t *pTs, uint32_t *pTimeOffs);
|
||||
uint8_t LctrConfigureDataPath(LlIsoConfigDataPath_t *pConfigDataPath);
|
||||
uint8_t LctrSetupIsoDataPath(LlIsoSetupDataPath_t *pSetupDataPath);
|
||||
uint8_t LctrRemoveIsoDataPath(uint16_t handle, uint8_t dpDir);
|
||||
uint8_t LctrIsoTxTest(uint16_t handle, uint8_t pldType);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -53,14 +53,22 @@ typedef struct
|
|||
|
||||
uint32_t dataPendMsk; /*!< Bitmask of connection handles with new pending data. */
|
||||
|
||||
/* PHY */
|
||||
uint8_t allPhys; /*!< Default all PHYs. */
|
||||
uint8_t txPhys; /*!< Default transmitter PHYs. */
|
||||
uint8_t rxPhys; /*!< Default receiver PHYs. */
|
||||
|
||||
/* PAST */
|
||||
uint8_t syncMode; /*!< Default sync transfer mode. */
|
||||
uint16_t syncSkip; /*!< Default sync skip for periodic adv sync transfer. */
|
||||
uint16_t syncTimeout; /*!< Default sync timeout for periodic adv sync transfer. */
|
||||
|
||||
/* Enhanced Connection Update */
|
||||
uint16_t defSrMin; /*!< Default subrate minimum value. */
|
||||
uint16_t defSrMax; /*!< Default subrate maximum value. */
|
||||
uint16_t defMaxLatency; /*!< Default maximum latency. */
|
||||
uint16_t defContNum; /*!< Default continuation number. */
|
||||
uint16_t defSvt; /*!< Default supervision timeout. */
|
||||
} lmgrConnCtrlBlk_t;
|
||||
|
||||
/**************************************************************************************************
|
||||
|
|
|
@ -154,7 +154,6 @@ void LlInitLlInit(void)
|
|||
#if (BT_VER >= LL_VER_BT_CORE_SPEC_5_2)
|
||||
LlCisMasterInit();
|
||||
LlBisMasterInit();
|
||||
LlPowerControlInit();
|
||||
#endif
|
||||
#else
|
||||
#ifdef INIT_OBSERVER
|
||||
|
@ -171,7 +170,6 @@ void LlInitLlInit(void)
|
|||
#if (BT_VER >= LL_VER_BT_CORE_SPEC_5_2)
|
||||
LlCisSlaveInit();
|
||||
LlBisSlaveInit();
|
||||
LlPowerControlInit();
|
||||
#endif
|
||||
#else
|
||||
#ifdef INIT_BROADCASTER
|
||||
|
@ -187,6 +185,12 @@ void LlInitLlInit(void)
|
|||
#if (BT_VER >= LL_VER_BT_CORE_SPEC_5_1)
|
||||
LlPastInit();
|
||||
#endif
|
||||
#if (BT_VER >= LL_VER_BT_CORE_SPEC_5_2)
|
||||
LlPowerControlInit();
|
||||
#endif
|
||||
#if (BT_VER >= LL_VER_BT_CORE_SPEC_SYDNEY)
|
||||
LlEnhConnUpdateInit();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -263,10 +267,13 @@ uint32_t LlInitSetLlRtCfg(const LlRtCfg_t *pLlRtCfg, uint8_t *pFreeMem, uint32_t
|
|||
LlInitRunTimeCfg(pLlRtCfg);
|
||||
|
||||
#if defined (INIT_PERIPHERAL) || defined (INIT_CENTRAL)
|
||||
memUsed = LlInitConnMem(pFreeMem, freeMemAvail);
|
||||
pFreeMem += memUsed;
|
||||
freeMemAvail -= memUsed;
|
||||
totalMemUsed += memUsed;
|
||||
if (pLlRtCfg->maxConn)
|
||||
{
|
||||
memUsed = LlInitConnMem(pFreeMem, freeMemAvail);
|
||||
pFreeMem += memUsed;
|
||||
freeMemAvail -= memUsed;
|
||||
totalMemUsed += memUsed;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (BT_VER >= LL_VER_BT_CORE_SPEC_5_0)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -118,6 +118,9 @@ void LlInitLhciInit(void)
|
|||
#if (BT_VER >= LL_VER_BT_CORE_SPEC_5_1)
|
||||
LhciPastInit();
|
||||
#endif
|
||||
#if (BT_VER >= LL_VER_BT_CORE_SPEC_SYDNEY)
|
||||
LhciEnhConnUpdateInit();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
@ -141,6 +144,7 @@ void LlInitLhciInit(void)
|
|||
#endif
|
||||
|
||||
LhciIsoInit();
|
||||
LhciPowerControlInit();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -164,5 +168,12 @@ uint32_t LlInitControllerInit(LlInitRtCfg_t *pCfg)
|
|||
LlInitLhciHandler();
|
||||
LhciInitFinalize();
|
||||
|
||||
#if (CHCI_TR_COMP_ENA)
|
||||
{
|
||||
extern void LhciTrEventComplete(void);
|
||||
LhciRegisterSendTrCompleteHandler(LhciTrEventComplete);
|
||||
}
|
||||
#endif
|
||||
|
||||
return totalMemUsed;
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ static uint8_t lctrPerScanSetup(lctrPerCreateSyncCtrlBlk_t *pPerCreateSync, lctr
|
|||
pPerScanCtx->syncTimeOutMs = LCTR_PER_SYNC_TIMEOUT_TO_MS(pMsg->syncTimeOut);
|
||||
pPerScanCtx->createDispId = createDispId;
|
||||
pPerScanCtx->repDisabled = pMsg->repDisabled;
|
||||
pPerScanCtx->dupFilterEnable = pMsg->dupFilterEnable;
|
||||
|
||||
return LL_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -106,7 +106,6 @@ void lctrExtAdvActStart(lctrAdvSet_t *pAdvSet)
|
|||
pAdvSet->pExtAdvAuxPtr = NULL;
|
||||
pAdvSet->connIndRcvd = FALSE;
|
||||
pAdvSet->shutdown = FALSE;
|
||||
pAdvSet->bodTermCnt = 0;
|
||||
|
||||
uint8_t status;
|
||||
if ((status = lctrSlvExtAdvBuildOp(pAdvSet, pLctrSlvExtAdvMsg->enable.durMs)) != LL_SUCCESS)
|
||||
|
@ -150,7 +149,6 @@ void lctrExtAdvActSelfStart(lctrAdvSet_t *pAdvSet)
|
|||
pAdvSet->pExtAdvAuxPtr = NULL;
|
||||
pAdvSet->connIndRcvd = FALSE;
|
||||
pAdvSet->shutdown = FALSE;
|
||||
pAdvSet->bodTermCnt = 0;
|
||||
|
||||
uint8_t status;
|
||||
if ((status = lctrSlvExtAdvBuildOp(pAdvSet, pLctrSlvExtAdvMsg->enable.durMs)) != LL_SUCCESS)
|
||||
|
@ -217,9 +215,10 @@ void lctrExtAdvActShutdown(lctrAdvSet_t *pAdvSet)
|
|||
/*************************************************************************************************/
|
||||
void lctrExtAdvActResetShutdown(lctrAdvSet_t *pAdvSet)
|
||||
{
|
||||
/* LCTR_MSG_RESET is broadcasted by hciReset and the processing order between ext ADV SM and periodic ADV SM is not guaranteed. */
|
||||
/* If ext ADV SM runs first, it will purge all info and periodic ADV SM may not run as intended. */
|
||||
/* So, reset cleanup of periodic advertising has to be done from extended ADV SM. */
|
||||
/* LCTR_MSG_RESET is broadcasted by hciReset and the processing order between ext ADV SM and
|
||||
* periodic ADV SM is not guaranteed. If ext ADV SM runs first, it will purge all info and periodic
|
||||
* ADV SM may not run as intended. So, reset cleanup of periodic advertising has to be done from
|
||||
* extended ADV SM. */
|
||||
if (pAdvSet->perParam.perState == LCTR_PER_ADV_STATE_ENABLED)
|
||||
{
|
||||
lctrPeriodicAdvActShutdown(pAdvSet);
|
||||
|
@ -424,9 +423,10 @@ void lctrExtAdvActAdvTerm(lctrAdvSet_t *pAdvSet)
|
|||
/*************************************************************************************************/
|
||||
void lctrExtAdvActReset(lctrAdvSet_t *pAdvSet)
|
||||
{
|
||||
/* LCTR_MSG_RESET is broadcasted by hciReset and the processing order between ext ADV SM and periodic ADV SM is not guaranteed. */
|
||||
/* If ext ADV SM runs first, it will purge all info and periodic ADV SM may not run as intended. */
|
||||
/* So, reset cleanup of periodic advertising has to be done from extended ADV SM. */
|
||||
/* LCTR_MSG_RESET is broadcasted by hciReset and the processing order between ext ADV SM and
|
||||
* periodic ADV SM is not guaranteed. If ext ADV SM runs first, it will purge all info and periodic
|
||||
* ADV SM may not run as intended. So, reset cleanup of periodic advertising has to be done from
|
||||
* extended ADV SM. */
|
||||
if (pAdvSet->perParam.perState == LCTR_PER_ADV_STATE_ENABLED)
|
||||
{
|
||||
lctrPeriodicAdvActShutdown(pAdvSet);
|
||||
|
@ -468,6 +468,9 @@ void lctrExtAdvActDurationExpired(lctrAdvSet_t *pAdvSet)
|
|||
|
||||
/* Signal shutdown, event completion occurs in lctrExtAdvActSelfTerm(). */
|
||||
pAdvSet->shutdown = TRUE;
|
||||
|
||||
SchRemove(&pAdvSet->advBod);
|
||||
SchRemove(&pAdvSet->auxAdvBod);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -541,6 +544,11 @@ void lctrPeriodicAdvActStart(lctrAdvSet_t *pAdvSet)
|
|||
pAdvSet->didPerUpdate = TRUE;
|
||||
}
|
||||
|
||||
if (pAdvSet->perParam.enableAdi)
|
||||
{
|
||||
pAdvSet->perParam.advDID = lctrCalcDID(pAdvSet->advData.pBuf, pAdvSet->advData.len);
|
||||
}
|
||||
|
||||
LmgrSendPeriodicAdvEnableCnf(pAdvSet->handle, LL_SUCCESS);
|
||||
LmgrIncResetRefCount();
|
||||
}
|
||||
|
|
|
@ -51,11 +51,13 @@ static void lctrNotifyHostBigCreateSyncComplete(lctrBigCtx_t *pBigCtx, LlStatus_
|
|||
evt.irc = pBigCtx->irc;
|
||||
evt.maxPdu = pBigCtx->maxPdu;
|
||||
evt.isoInterval = LL_MATH_DIV_1250(pBigCtx->isoInterUsec);
|
||||
evt.numBis = pBigCtx->numBis;
|
||||
|
||||
for (unsigned int i = 0; i < evt.numBis; i++)
|
||||
for (unsigned int i = 0; i < LL_MAX_BIS; i++)
|
||||
{
|
||||
evt.bisHandle[i] = pBigCtx->pBisCtx[i]->handle;
|
||||
if (pBigCtx->pBisCtx[i])
|
||||
{
|
||||
evt.bisHandle[evt.numBis++] = pBigCtx->pBisCtx[i]->handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,12 +154,42 @@ void lctrMstBigActBigSync(lctrBigCtx_t *pBigCtx)
|
|||
for (unsigned int i = 0; i < pBigInfo->numBis; i++)
|
||||
{
|
||||
lctrBisCtx_t *pBisCtx;
|
||||
unsigned int j;
|
||||
|
||||
/* Availability is verified on BIG Create Sync command. */
|
||||
pBisCtx = lctrAllocBisCtx(pBigCtx);
|
||||
WSF_ASSERT(pBisCtx);
|
||||
for (j = 0; j < pBigCtx->roleData.mst.numBisIdx; j++)
|
||||
{
|
||||
/* Check host BIS filter. */
|
||||
if (pBigCtx->roleData.mst.bisIdx[j] == (i + 1))
|
||||
{
|
||||
/* Availability is verified on BIG Create Sync command. */
|
||||
pBisCtx = lctrAllocBisCtx(pBigCtx);
|
||||
WSF_ASSERT(pBisCtx);
|
||||
|
||||
lctrSetupBisContext(pBisCtx, pBigInfo->seedAccAddr, pBigInfo->baseCrcInit, pBigInfo->chanMap, pBigInfo->phy);
|
||||
lctrSetupBisContext(pBisCtx, pBigInfo->seedAccAddr, pBigInfo->baseCrcInit, pBigInfo->chanMap, pBigInfo->phy);
|
||||
|
||||
if (pBigCtx->roleData.mst.pFirstBisCtx == NULL)
|
||||
{
|
||||
/* Optimize ISR by reducing lookup on every event; store first BIS. */
|
||||
pBigCtx->roleData.mst.pFirstBisCtx = pBisCtx;
|
||||
pBigCtx->roleData.mst.firstBisOffsUsec = pBigCtx->bisSpaceUsec * i;
|
||||
pBigCtx->roleData.mst.firstBisEvtIdx = i;
|
||||
}
|
||||
else if (pBigCtx->roleData.mst.pSecondBisCtx == NULL)
|
||||
{
|
||||
/* Optimize ISR by reducing lookup on every event; store second BIS; NULL if none. */
|
||||
pBigCtx->roleData.mst.pSecondBisCtx = pBisCtx;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (j == pBigCtx->roleData.mst.numBisIdx)
|
||||
{
|
||||
/* Disable BIS subevent. */
|
||||
pBigCtx->pBisCtx[pBigCtx->numBis++] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
lctrMstBigBuildOp(pBigCtx, &pLctrMstBigMsg->bigInfo.data);
|
||||
|
@ -176,13 +208,9 @@ void lctrMstBigActBigSync(lctrBigCtx_t *pBigCtx)
|
|||
/*************************************************************************************************/
|
||||
void lctrMstBigActTerm(lctrBigCtx_t *pBigCtx)
|
||||
{
|
||||
BbStop(BB_PROT_BLE);
|
||||
/* Shutdown completes with events generated in BOD end callback. */
|
||||
|
||||
lctrFreeBigCtx(pBigCtx);
|
||||
|
||||
LmgrDecResetRefCount();
|
||||
|
||||
lctrNotifyHostSyncLost(pBigCtx->handle, pBigCtx->bcp.term.reason);
|
||||
pBigCtx->roleData.mst.syncLostReason = pBigCtx->bcp.term.reason;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -194,12 +222,7 @@ void lctrMstBigActTerm(lctrBigCtx_t *pBigCtx)
|
|||
/*************************************************************************************************/
|
||||
void lctrMstBigActShutdown(lctrBigCtx_t *pBigCtx)
|
||||
{
|
||||
/* By removing BOD from scheduler, BOD end callback will be called. */
|
||||
/* Shutdown completes with events generated in BOD end callback. */
|
||||
if (!SchRemove(&pBigCtx->bod))
|
||||
{
|
||||
lctrMstBigSendMsg(pBigCtx, LCTR_MST_BIG_INT_TERMINATED_SYNC);
|
||||
}
|
||||
/* Shutdown completes with events generated in BOD end callback. */
|
||||
|
||||
if (pBigCtx->state == LCTR_MST_BIG_STATE_SYNCING)
|
||||
{
|
||||
|
@ -216,12 +239,7 @@ void lctrMstBigActShutdown(lctrBigCtx_t *pBigCtx)
|
|||
/*************************************************************************************************/
|
||||
void lctrMstBigActSyncLost(lctrBigCtx_t *pBigCtx)
|
||||
{
|
||||
/* By removing BOD from scheduler, BOD end callback will be called. */
|
||||
/* Shutdown completes with events generated in BOD end callback. */
|
||||
if (!SchRemove(&pBigCtx->bod))
|
||||
{
|
||||
lctrMstBigSendMsg(pBigCtx, LCTR_MST_BIG_INT_TERMINATED_SYNC);
|
||||
}
|
||||
/* Shutdown completes with events generated in BOD end callback. */
|
||||
|
||||
pBigCtx->roleData.mst.syncLostReason = LL_ERROR_CODE_CONN_TIMEOUT;
|
||||
}
|
||||
|
@ -235,12 +253,7 @@ void lctrMstBigActSyncLost(lctrBigCtx_t *pBigCtx)
|
|||
/*************************************************************************************************/
|
||||
void lctrMstBigActMicFailed(lctrBigCtx_t *pBigCtx)
|
||||
{
|
||||
/* By removing BOD from scheduler, BOD end callback will be called. */
|
||||
/* Shutdown completes with events generated in BOD end callback. */
|
||||
if (!SchRemove(&pBigCtx->bod))
|
||||
{
|
||||
lctrMstBigSendMsg(pBigCtx, LCTR_MST_BIG_INT_TERMINATED_SYNC);
|
||||
}
|
||||
/* Shutdown completes with events generated in BOD end callback. */
|
||||
|
||||
pBigCtx->roleData.mst.syncLostReason = LL_ERROR_CODE_CONN_TERM_MIC_FAILURE;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -36,6 +36,46 @@
|
|||
Local Functions
|
||||
**************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send next CIS disconnect LLCP to be processed, if needed.
|
||||
*
|
||||
* \param ACL Handle that can continue CIS termination procedures.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void lctrCheckPendingCisTermination(uint16_t aclHandle)
|
||||
{
|
||||
for (unsigned int i = 0; i < pLctrRtCfg->maxCis; i++)
|
||||
{
|
||||
lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i];
|
||||
lctrCisDisc_t *pMsg;
|
||||
|
||||
if ((pCisCtx->aclHandle == aclHandle) &&
|
||||
!pCisCtx->isClosing && pCisCtx->termPend)
|
||||
{
|
||||
if ((pMsg = (lctrCisDisc_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL)
|
||||
{
|
||||
pMsg->hdr.handle = pCisCtx->aclHandle;
|
||||
pMsg->hdr.dispId = LCTR_DISP_CONN;
|
||||
pMsg->hdr.event = LCTR_CONN_MSG_API_DISCONNECT;
|
||||
|
||||
pMsg->cisHandle = pCisCtx->cisHandle;
|
||||
pMsg->reason = pCisCtx->reason;
|
||||
|
||||
WsfMsgSend(lmgrPersistCb.handlerId, pMsg);
|
||||
|
||||
pCisCtx->termPend = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_WARN1("lctrCisActDisc: CIS OOM while terminating handle %d", pCisCtx->cisHandle);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send CIS termination indication PDU.
|
||||
|
@ -94,16 +134,16 @@ void lctrNotifyHostCisTerm(lctrCisCtx_t *pCisCtx)
|
|||
{
|
||||
LlDisconnectInd_t evt =
|
||||
{
|
||||
.hdr =
|
||||
{
|
||||
.param = pCisCtx->cisHandle,
|
||||
.event = LL_DISCONNECT_IND,
|
||||
.status = LL_SUCCESS
|
||||
},
|
||||
.hdr =
|
||||
{
|
||||
.param = pCisCtx->cisHandle,
|
||||
.event = LL_DISCONNECT_IND,
|
||||
.status = LL_SUCCESS
|
||||
},
|
||||
|
||||
.status = LL_SUCCESS,
|
||||
.handle = pCisCtx->cisHandle,
|
||||
.reason = pCisCtx->reason
|
||||
.status = LL_SUCCESS,
|
||||
.handle = pCisCtx->cisHandle,
|
||||
.reason = pCisCtx->reason
|
||||
};
|
||||
|
||||
LL_TRACE_INFO2("### LlEvent ### LL_DISCONNECT_IND, handle=%u, status=LL_SUCCESS, reason=%u", pCisCtx->cisHandle, pCisCtx->reason);
|
||||
|
@ -126,9 +166,9 @@ void lctrNotifyHostCisEst(lctrCisCtx_t *pCisCtx, uint8_t status, uint32_t cigSyn
|
|||
{
|
||||
.hdr =
|
||||
{
|
||||
.param = pCisCtx->cisHandle,
|
||||
.event = LL_CIS_EST_IND,
|
||||
.status = status
|
||||
.param = pCisCtx->cisHandle,
|
||||
.event = LL_CIS_EST_IND,
|
||||
.status = status
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -146,6 +186,9 @@ void lctrNotifyHostCisEst(lctrCisCtx_t *pCisCtx, uint8_t status, uint32_t cigSyn
|
|||
evt.ftMToS = pCisCtx->ftMToS;
|
||||
evt.ftSToM = pCisCtx->ftSToM;
|
||||
evt.isoInterval = pCisCtx->isoInterval;
|
||||
evt.maxPduMToS = (pCisCtx->role == LL_ROLE_MASTER) ? pCisCtx->localDataPdu.maxTxLen : pCisCtx->localDataPdu.maxRxLen;
|
||||
evt.maxPduSToM = (pCisCtx->role == LL_ROLE_SLAVE) ? pCisCtx->localDataPdu.maxTxLen : pCisCtx->localDataPdu.maxRxLen;
|
||||
|
||||
|
||||
LL_TRACE_INFO2("### LlEvent ### LL_CIS_EST_IND, cisHandle=%u, status=%u", pCisCtx->cisHandle, status);
|
||||
|
||||
|
@ -311,18 +354,13 @@ void lctrCisActCisEst(lctrCisCtx_t *pCisCtx)
|
|||
BbBleData_t *pBle = &pConnCtx->bleData;
|
||||
pCigCtx->numCisEsted++;
|
||||
|
||||
LL_TRACE_INFO1("lctrCisActCisEst, pCigCtx->numCisEsted=%u", pCigCtx->numCisEsted);
|
||||
|
||||
/* Initialize txPower. */
|
||||
uint8_t txPhy = (pCisCtx->role == LL_ROLE_MASTER) ? pCisCtx->phyMToS : pCisCtx->phySToM;
|
||||
uint8_t option = pBle->chan.initTxPhyOptions;
|
||||
int8_t txPwr = LCTR_GET_TXPOWER(pConnCtx, txPhy, option);
|
||||
LL_TRACE_INFO1("lctrCisActCisEst phy = %d", txPhy);
|
||||
|
||||
if ((txPwr == LL_PWR_CTRL_TXPOWER_UNMANAGED) && (pConnCtx->peerReqRecvd))
|
||||
{
|
||||
LL_TRACE_INFO0(" txPower previously unmanaged. Initalized txPower.");
|
||||
|
||||
LCTR_SET_TXPOWER(pConnCtx, txPhy, pLctrRtCfg->defTxPwrLvl);
|
||||
|
||||
if (txPhy == LL_PHY_LE_CODED)
|
||||
|
@ -330,7 +368,7 @@ void lctrCisActCisEst(lctrCisCtx_t *pCisCtx)
|
|||
LCTR_SET_TXPOWER(pConnCtx, LL_PC_PHY_CODED_S2, pLctrRtCfg->defTxPwrLvl);
|
||||
}
|
||||
|
||||
/* pCisCtx->bleData.chan.txPower = LCTR_GET_TXPOWER(pConnCtx, txPhy, option); //Handled in the init */
|
||||
/* pCisCtx->bleData.chan.txPower = LCTR_GET_TXPOWER(pConnCtx, txPhy, option); */ /* Handled during initialization. */
|
||||
if (pConnCtx->usedFeatSet & LL_FEAT_POWER_CHANGE_IND)
|
||||
{
|
||||
pCisCtx->powerIndReq = TRUE;
|
||||
|
@ -338,10 +376,10 @@ void lctrCisActCisEst(lctrCisCtx_t *pCisCtx)
|
|||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_INFO1(" txPower = %d", txPwr);
|
||||
pCisCtx->bleData.chan.txPower = txPwr;
|
||||
}
|
||||
|
||||
LL_TRACE_INFO2("lctrCisActCisEst, numCisEsted=%u txPower=%u", pCigCtx->numCisEsted, txPwr);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -378,16 +416,30 @@ void lctrCisActDisc(lctrCisCtx_t *pCisCtx)
|
|||
{
|
||||
lctrCisDisc_t *pMsg;
|
||||
|
||||
if ((pMsg = (lctrCisDisc_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL)
|
||||
if (!LctrCisTerminationInProgress(pCisCtx->aclHandle))
|
||||
{
|
||||
pMsg->hdr.handle = pCisCtx->aclHandle;
|
||||
pMsg->hdr.dispId = LCTR_DISP_CONN;
|
||||
pMsg->hdr.event = LCTR_CONN_MSG_API_DISCONNECT;
|
||||
if ((pMsg = (lctrCisDisc_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL)
|
||||
{
|
||||
pMsg->hdr.handle = pCisCtx->aclHandle;
|
||||
pMsg->hdr.dispId = LCTR_DISP_CONN;
|
||||
pMsg->hdr.event = LCTR_CONN_MSG_API_DISCONNECT;
|
||||
|
||||
pMsg->cisHandle = pCisCtx->cisHandle;
|
||||
pMsg->reason = pCisCtx->reason;
|
||||
pMsg->cisHandle = pCisCtx->cisHandle;
|
||||
pMsg->reason = pCisCtx->reason;
|
||||
|
||||
WsfMsgSend(lmgrPersistCb.handlerId, pMsg);
|
||||
WsfMsgSend(lmgrPersistCb.handlerId, pMsg);
|
||||
|
||||
pCisCtx->termPend = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_WARN1("lctrCisActDisc: CIS OOM while terminating handle %d", pCisCtx->cisHandle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_INFO1("lctrCisActDisc: CIS Termination pending, CIS Termination queued for handle %d", pCisCtx->cisHandle);
|
||||
pCisCtx->termPend = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,19 +452,11 @@ void lctrCisActDisc(lctrCisCtx_t *pCisCtx)
|
|||
/*************************************************************************************************/
|
||||
void lctrCisActClosed(lctrCisCtx_t *pCisCtx)
|
||||
{
|
||||
/* Stop output data path. */
|
||||
switch (pCisCtx->dataPathOutCtx.id)
|
||||
{
|
||||
case LL_ISO_DATA_PATH_VS:
|
||||
WSF_ASSERT(lctrCodecHdlr.stop);
|
||||
lctrCodecHdlr.stop(pCisCtx->cisHandle);
|
||||
break;
|
||||
case LL_ISO_DATA_PATH_DISABLED:
|
||||
case LL_ISO_DATA_PATH_HCI:
|
||||
default:
|
||||
/* No action required. */
|
||||
break;
|
||||
}
|
||||
uint16_t aclHandle = pCisCtx->aclHandle;
|
||||
|
||||
/* Must do one at a time in case one datapath is not used. */
|
||||
LctrRemoveIsoDataPath(pCisCtx->cisHandle, LL_ISO_DATA_PATH_INPUT_BIT);
|
||||
LctrRemoveIsoDataPath(pCisCtx->cisHandle, LL_ISO_DATA_PATH_OUTPUT_BIT);
|
||||
|
||||
LL_TRACE_INFO1("lctrCisActClosed, pCisCtx->cisHandle=%u", pCisCtx->cisHandle);
|
||||
|
||||
|
@ -433,6 +477,8 @@ void lctrCisActClosed(lctrCisCtx_t *pCisCtx)
|
|||
pCisCtx->isClosing = FALSE;
|
||||
lctrCleanupCtx(pCisCtx);
|
||||
}
|
||||
|
||||
lctrCheckPendingCisTermination(aclHandle);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -449,12 +495,11 @@ void lctrCisActFail(lctrCisCtx_t *pCisCtx)
|
|||
|
||||
LL_TRACE_INFO2("lctrCisActFail, pCisCtx->cisHandle=%u pCisCtx->state=%u", pCisCtx->cisHandle, pCisCtx->state);
|
||||
|
||||
/* Supervision timeout case */
|
||||
/* Supervision timeout or MIC timeout case */
|
||||
if (pCisCtx->state == LCTR_CIS_STATE_EST)
|
||||
{
|
||||
pCisCtx->isClosing = TRUE; /* Close the context in the CIG BOD end callback. */
|
||||
SchRemove(&pCigCtx->cigBod);
|
||||
lctrNotifyHostCisTerm(pCisCtx);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -50,8 +50,9 @@ static void lctrCalCeRefFirstCis(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx)
|
|||
uint32_t refTime;
|
||||
|
||||
pCisCtx->ceRef = pCtx->eventCounter +
|
||||
LL_MIN_INSTANT + 1 + /* +1 for next CE */
|
||||
pCtx->maxLatency; /* ensure slave will listen to this packet */
|
||||
((LL_MIN_INSTANT + 1 + /* +1 for next CE */
|
||||
pCtx->maxLatency) * /* ensure slave will listen to this packet */
|
||||
pCtx->ecu.srFactor); /* include subrating factor */
|
||||
pCisCtx->cisCeRef = 0;
|
||||
|
||||
refTime = pConnBod->dueUsec + (pCisCtx->ceRef - pCtx->eventCounter) * LCTR_CONN_IND_US(pCtx->connInterval);
|
||||
|
@ -94,8 +95,9 @@ static void lctrCalCeRefNotFirstCis(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx)
|
|||
uint32_t offsetUsec = 0;
|
||||
|
||||
pCisCtx->ceRef = pCtx->eventCounter +
|
||||
LL_MIN_INSTANT + 1 + /* +1 for next CE */
|
||||
pCtx->maxLatency; /* ensure slave will listen to this packet */
|
||||
((LL_MIN_INSTANT + 1 + /* +1 for next CE */
|
||||
pCtx->maxLatency) * /* ensure slave will listen to this packet */
|
||||
pCtx->ecu.srFactor); /* include subrating factor */
|
||||
|
||||
aclRefTime = pConnBod->dueUsec + (pCisCtx->ceRef - pCtx->eventCounter) * LCTR_CONN_IND_US(pCtx->connInterval);
|
||||
|
||||
|
@ -301,7 +303,7 @@ void lctrMstCisLlcpActHostCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx)
|
|||
/* Check whether the parameter for the BOD is valid or not. */
|
||||
if (pCigCtx->isValid == FALSE)
|
||||
{
|
||||
LL_TRACE_WARN0("Fail to create CIS due to invalid parameters");
|
||||
LL_TRACE_WARN0("lctrMstCisLlcpActHostCisReq: Fail to create CIS due to invalid parameters");
|
||||
lctrCisStoreLocalLowResourceTerminateReason(pCisCtx);
|
||||
result = FALSE;
|
||||
}
|
||||
|
@ -313,9 +315,11 @@ void lctrMstCisLlcpActHostCisReq(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx)
|
|||
SCH_RM_PREF_PERFORMANCE,
|
||||
LCTR_ISO_INT_TO_US(pCigCtx->isoInterval),
|
||||
LCTR_ISO_INT_TO_US(pCigCtx->isoInterval),
|
||||
pCigCtx->cigSyncDelayUsec, NULL, lctrGetCigRefTime))
|
||||
pCigCtx->cigSyncDelayUsec,
|
||||
NULL,
|
||||
lctrGetCigRefTime))
|
||||
{
|
||||
LL_TRACE_WARN0("Fail to create CIS due to scheduling limitation");
|
||||
LL_TRACE_WARN0("lctrMstCisLlcpActHostCisReq: Fail to create CIS due to scheduling limitation");
|
||||
lctrCisStoreLocalLowResourceTerminateReason(pCisCtx);
|
||||
result = FALSE;
|
||||
}
|
||||
|
@ -418,7 +422,7 @@ void lctrMstCisLlcpActPeerCisRsp(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx)
|
|||
|
||||
if (pCigCtx->isBodBuilt == FALSE)
|
||||
{
|
||||
WSF_ASSERT(pCisCtx->cisCeRef == 0)
|
||||
WSF_ASSERT(pCisCtx->cisCeRef == 0);
|
||||
|
||||
lctrMstCisBuildCigOp(pCigCtx);
|
||||
}
|
||||
|
|
|
@ -168,12 +168,12 @@ static void lctrNotifyHostCisReq(lctrCisCtx_t *pCisCtx)
|
|||
{
|
||||
LlCisReqInd_t evt =
|
||||
{
|
||||
.hdr =
|
||||
{
|
||||
.param = pCisCtx->cisHandle,
|
||||
.event = LL_CIS_REQ_IND,
|
||||
.status = LL_SUCCESS
|
||||
}
|
||||
.hdr =
|
||||
{
|
||||
.param = pCisCtx->cisHandle,
|
||||
.event = LL_CIS_REQ_IND,
|
||||
.status = LL_SUCCESS
|
||||
}
|
||||
};
|
||||
|
||||
evt.aclHandle = pCisCtx->aclHandle;
|
||||
|
@ -181,7 +181,7 @@ static void lctrNotifyHostCisReq(lctrCisCtx_t *pCisCtx)
|
|||
evt.cigId = pCisCtx->cigId;
|
||||
evt.cisId = pCisCtx->cisId;
|
||||
|
||||
LL_TRACE_INFO1("### LlEvent ### LL_CIS_REQ_IND, cisHandle=%u", pCisCtx->cisHandle);
|
||||
LL_TRACE_INFO3("### LlEvent ### LL_CIS_REQ_IND, cisHandle=%u cigId=%u cisId=%u", pCisCtx->cisHandle, pCisCtx->cigId, pCisCtx->cisId);
|
||||
|
||||
bool_t evtSent = LmgrSendEvent((LlEvt_t *)&evt);
|
||||
|
||||
|
@ -363,7 +363,7 @@ void lctrSlvCisLlcpActPeerCisInd(lctrConnCtx_t *pCtx, lctrCisCtx_t *pCisCtx)
|
|||
{
|
||||
/* If the anchor point of the stream is before end of the first stream, it is interleaved packing scheme. */
|
||||
if (BbGetTargetTimeDelta(cigRefTime + pHeadCisCtx->subIntervUsec,
|
||||
pCisCtx->data.slv.anchorOffsetUsec + pCtx->data.slv.anchorPointUsec + LCTR_CONN_IND_US(pCtx->connInterval)) > 0)
|
||||
pCisCtx->data.slv.anchorOffsetUsec + pCtx->data.slv.anchorPointUsec + LCTR_CONN_IND_US(pCtx->connInterval)) > 0)
|
||||
{
|
||||
pCigCtx->packing = LL_PACKING_INTERLEAVED;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -42,7 +42,7 @@
|
|||
Macros
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! \brief Valid feature bits applicable between controllers */
|
||||
/*! \brief Valid feature bits applicable between controllers. */
|
||||
#define LCTR_FEAT_PEER_MASK (LL_FEAT_ENCRYPTION | \
|
||||
LL_FEAT_CONN_PARAM_REQ_PROC | \
|
||||
LL_FEAT_EXT_REJECT_IND | \
|
||||
|
@ -68,12 +68,15 @@
|
|||
LL_FEAT_ISO_HOST_SUPPORT | \
|
||||
LL_FEAT_POWER_CONTROL_REQUEST | \
|
||||
LL_FEAT_POWER_CHANGE_IND | \
|
||||
LL_FEAT_PATH_LOSS_MONITOR)
|
||||
LL_FEAT_PATH_LOSS_MONITOR | \
|
||||
LL_FEAT_CONN_SUBRATE | \
|
||||
LL_FEAT_CONN_SUBRATE_HOST_SUPPORT | \
|
||||
LL_FEAT_CHANNEL_CLASSIFICATION)
|
||||
|
||||
/*! \brief Used feature bitmask. */
|
||||
#define LCTR_USED_FEAT_SET_MASK 0x000000FFFF
|
||||
|
||||
/*! \brief Features bits mask over the air */
|
||||
/*! \brief Features bits mask over the air. */
|
||||
#define LCTR_OTA_FEAT_MASK (~LL_FEAT_REMOTE_PUB_KEY_VALIDATION & LCTR_FEAT_PEER_MASK)
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -99,7 +102,6 @@ static bool_t lctrValidateConnParam(const lctrConnParam_t *pConnParam)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Compute the sleep clock accuracy index in connection context.
|
||||
|
@ -126,6 +128,39 @@ static uint8_t lctrComputeConnSca(lctrConnCtx_t *pCtx)
|
|||
return (uint8_t) (sca + pCtx->scaMod);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Queue channel reporting indication to be sent out.
|
||||
*
|
||||
* \param pCtx Connection context.
|
||||
* \param enable Enable/disable.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void lctrQueueChannelReportingInd(lctrConnCtx_t *pCtx, bool_t enable)
|
||||
{
|
||||
|
||||
lctrMsgChRptInd_t *pMsg;
|
||||
if ((pMsg = (lctrMsgChRptInd_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL)
|
||||
{
|
||||
pMsg->hdr.handle = LCTR_GET_CONN_HANDLE(pCtx);
|
||||
pMsg->hdr.dispId = LCTR_DISP_CONN;
|
||||
pMsg->hdr.event = LCTR_CONN_LLCP_CHANNEL_REPORTING;
|
||||
|
||||
/* Use default if the run-time configuration is not within spec range. */
|
||||
uint8_t spacing = pLctrRtCfg->chClassIntSpacing;
|
||||
if ((spacing > LL_CH_RPT_SPACING_MAX) ||
|
||||
(spacing < LL_CH_RPT_SPACING_MIN))
|
||||
{
|
||||
spacing = LL_CH_RPT_SPACING_DEFAULT;
|
||||
}
|
||||
pMsg->enable = enable;
|
||||
pMsg->maxDelay = spacing;
|
||||
pMsg->minSpacing = spacing;
|
||||
|
||||
WsfMsgSend(lmgrPersistCb.handlerId, pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Notify host of connect indication.
|
||||
|
@ -306,8 +341,9 @@ void lctrSendChanMapUpdateInd(lctrConnCtx_t *pCtx)
|
|||
#endif
|
||||
{
|
||||
pCtx->chanMapUpd.instant = pCtx->eventCounter +
|
||||
LL_MIN_INSTANT + 1 + /* +1 for next CE */
|
||||
pCtx->maxLatency; /* ensure slave will listen to this packet */
|
||||
((LL_MIN_INSTANT + 1 + /* +1 for next CE */
|
||||
pCtx->maxLatency) * /* ensure slave will listen to this packet */
|
||||
pCtx->ecu.srFactor); /* include subrating factor */
|
||||
}
|
||||
|
||||
/*** Assemble control PDU. ***/
|
||||
|
@ -407,6 +443,9 @@ void lctrSendFeatureRsp(lctrConnCtx_t *pCtx)
|
|||
/*************************************************************************************************/
|
||||
void lctrStoreUsedFeatures(lctrConnCtx_t *pCtx)
|
||||
{
|
||||
pCtx->peerFeatures = lctrDataPdu.pld.featReqRsp.featSet & LCTR_FEAT_PEER_MASK;
|
||||
|
||||
/* TODO: make usedFeatSet calculated when needed based on peerFeatures. Use function LctrGetUsedFeatures. */
|
||||
pCtx->usedFeatSet = lmgrCb.features & lctrDataPdu.pld.featReqRsp.featSet & LCTR_FEAT_PEER_MASK;
|
||||
pCtx->featExchFlag = TRUE;
|
||||
|
||||
|
@ -415,6 +454,27 @@ void lctrStoreUsedFeatures(lctrConnCtx_t *pCtx)
|
|||
(lctrDataPdu.pld.featReqRsp.featSet & LL_FEAT_STABLE_MOD_IDX_TRANSMITTER) ? TRUE : FALSE;
|
||||
pCtx->bleData.chan.peerRxStableModIdx =
|
||||
(lctrDataPdu.pld.featReqRsp.featSet & LL_FEAT_STABLE_MOD_IDX_RECEIVER) ? TRUE : FALSE;
|
||||
|
||||
/* If channel classification is supported and enabled, turn on channel classification. */
|
||||
if ((pCtx->role == LL_ROLE_MASTER) && (!pCtx->chanStatRptEnable) &&
|
||||
(pCtx->usedFeatSet & LL_FEAT_CHANNEL_CLASSIFICATION) &&
|
||||
(lctrGetConnOpFlag(pCtx, LL_OP_MODE_FLAG_ENA_CH_RPT_LLCP_AFTER_FEAT)))
|
||||
{
|
||||
lctrQueueChannelReportingInd(pCtx, TRUE);
|
||||
}
|
||||
|
||||
/* Start timer for power monitor if the feature is supported. */
|
||||
if ((pCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST) &&
|
||||
(pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) &&
|
||||
(pCtx->powerMonitorScheme == LCTR_PC_MONITOR_AUTO) &&
|
||||
!lmgrGetOpFlag(LL_OP_MODE_FLAG_DIS_POWER_MONITOR))
|
||||
{
|
||||
WsfTimerStartMs(&pCtx->tmrPowerCtrl, LL_PC_SERVICE_MS);
|
||||
}
|
||||
else
|
||||
{
|
||||
WsfTimerStop(&pCtx->tmrPowerCtrl);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -937,7 +997,6 @@ static void lctrSendDataLengthPdu(lctrConnCtx_t *pCtx, uint8_t opcode)
|
|||
{
|
||||
uint8_t *pBuf = pPdu;
|
||||
|
||||
|
||||
/*** Assemble control PDU. ***/
|
||||
|
||||
UINT8_TO_BSTREAM (pBuf, opcode);
|
||||
|
@ -945,7 +1004,7 @@ static void lctrSendDataLengthPdu(lctrConnCtx_t *pCtx, uint8_t opcode)
|
|||
uint16_t maxRxTime = pCtx->localDataPdu.maxRxTime;
|
||||
uint16_t maxTxTime = pCtx->localDataPdu.maxTxTime;
|
||||
|
||||
/* If LL_FEAT_LE_CODED_PHY is not supported, maxRxTime and maxTxTime can not be more than 2128.*/
|
||||
/* If LL_FEAT_LE_CODED_PHY is not supported, maxRxTime and maxTxTime can not be more than 2120 (2128 if CTEs are supported).*/
|
||||
if (!pCtx->featExchFlag ||
|
||||
!(pCtx->usedFeatSet & LL_FEAT_LE_CODED_PHY))
|
||||
{
|
||||
|
@ -1023,7 +1082,7 @@ void lctrStoreRemoteDataLength(lctrConnCtx_t *pCtx)
|
|||
uint16_t maxRxTime = pCtx->localDataPdu.maxRxTime;
|
||||
uint16_t maxTxTime = pCtx->localDataPdu.maxTxTime;
|
||||
|
||||
/* If LL_FEAT_LE_CODED_PHY is not supported, maxRxTime and maxTxTime can not be more than 2128. */
|
||||
/* If LL_FEAT_LE_CODED_PHY is not supported, maxRxTime and maxTxTime can not be more than 2120 (2128 if CTEs are supported). */
|
||||
if (!pCtx->featExchFlag ||
|
||||
!(pCtx->usedFeatSet & LL_FEAT_LE_CODED_PHY))
|
||||
{
|
||||
|
@ -1185,6 +1244,209 @@ static void lctrSendPeerScaReqPdu(lctrConnCtx_t *pCtx, uint8_t opcode)
|
|||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send channel reporting indication PDU.
|
||||
*
|
||||
* \param pCtx Connection context.
|
||||
* \param opcode PDU opcode.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void lctrSendChannelReportingIndPdu(lctrConnCtx_t *pCtx)
|
||||
{
|
||||
uint8_t *pPdu;
|
||||
|
||||
if ((pPdu = lctrTxCtrlPduAlloc(LL_CH_REPORTING_LEN)) != NULL)
|
||||
{
|
||||
uint8_t *pBuf = pPdu;
|
||||
|
||||
/*** Assemble control PDU. ***/
|
||||
UINT8_TO_BSTREAM (pBuf, LL_PDU_CH_REPORTING_IND);
|
||||
UINT8_TO_BSTREAM (pBuf, pLctrConnMsg->chanRptInd.enable);
|
||||
UINT8_TO_BSTREAM (pBuf, pLctrConnMsg->chanRptInd.minSpacing);
|
||||
UINT8_TO_BSTREAM (pBuf, pLctrConnMsg->chanRptInd.maxDelay);
|
||||
|
||||
/*** Queue for transmit. ***/
|
||||
|
||||
lctrTxCtrlPduQueue(pCtx, pPdu);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send channel status indication PDU.
|
||||
*
|
||||
* \param pCtx Connection context.
|
||||
* \param opcode PDU opcode.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void lctrSendChannelStatusIndPdu(lctrConnCtx_t *pCtx)
|
||||
{
|
||||
static uint8_t CHAN_STATUS_BIT_LENGTH = 2;
|
||||
uint8_t *pPdu;
|
||||
|
||||
if ((pPdu = lctrTxCtrlPduAlloc(LL_CH_STATUS_LEN)) != NULL)
|
||||
{
|
||||
uint8_t *pBuf = pPdu;
|
||||
uint8_t i, packedChanByte;
|
||||
uint8_t curCh = 0;
|
||||
|
||||
/*** Assemble control PDU. ***/
|
||||
|
||||
UINT8_TO_BSTREAM (pBuf, LL_PDU_CH_STATUS_IND);
|
||||
|
||||
/* Pack all but final byte */
|
||||
for (i = 0; i < (LL_CH_STATUS_LEN - 2); i++)
|
||||
{
|
||||
packedChanByte =
|
||||
(pLctrConnMsg->chanStatusInd.chanStatus[curCh]) |
|
||||
(pLctrConnMsg->chanStatusInd.chanStatus[curCh + 1] << (CHAN_STATUS_BIT_LENGTH * 1)) |
|
||||
(pLctrConnMsg->chanStatusInd.chanStatus[curCh + 2] << (CHAN_STATUS_BIT_LENGTH * 2)) |
|
||||
(pLctrConnMsg->chanStatusInd.chanStatus[curCh + 3] << (CHAN_STATUS_BIT_LENGTH * 3));
|
||||
|
||||
UINT8_TO_BSTREAM (pBuf, packedChanByte);
|
||||
curCh += 4;
|
||||
}
|
||||
|
||||
/* Pack final byte here (outside loop because it is not fully packed). */
|
||||
packedChanByte = pLctrConnMsg->chanStatusInd.chanStatus[curCh];
|
||||
UINT8_TO_BSTREAM (pBuf, packedChanByte);
|
||||
|
||||
/*** Queue for transmit. ***/
|
||||
|
||||
lctrTxCtrlPduQueue(pCtx, pPdu);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send channel status indication.
|
||||
*
|
||||
* \param pCtx Connection context.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void lctrSendChannelStatusInd(lctrConnCtx_t *pCtx)
|
||||
{
|
||||
lctrSendChannelStatusIndPdu(pCtx);
|
||||
|
||||
/* The procedure completes after sending out the indication. */
|
||||
pCtx->llcpNotifyMask &= ~(1 << LCTR_PROC_CMN_CH_STATUS_REPORT);
|
||||
lctrSendConnMsg(pCtx, LCTR_CONN_LLCP_PROC_CMPL);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Store received channel status indication.
|
||||
*
|
||||
* \param pCtx Connection context.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void lctrStoreChannelStatusInd(lctrConnCtx_t *pCtx)
|
||||
{
|
||||
if (pCtx->role != LL_ROLE_MASTER)
|
||||
{
|
||||
LL_TRACE_WARN1("Received CHANNEL_STATUS_IND on peripheral connection handle=%u", LCTR_GET_CONN_HANDLE(pCtx));
|
||||
|
||||
/* The procedure completes after receiving the indication. */
|
||||
lctrSendConnMsg(pCtx, LCTR_CONN_LLCP_PROC_CMPL);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t receivedTime = PalBbGetCurrentTime();
|
||||
if (BbGetTargetTimeDelta(receivedTime, pCtx->data.mst.recvdChanStatTs) >= pCtx->data.mst.chanStatMinIntUs)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < LL_CH_STATUS_LEN - 2; i ++)
|
||||
{
|
||||
pCtx->data.mst.peerChannelStatus[i * 4] = lctrDataPdu.pld.chanStatusInd.chanStatusMap[i] & (0x03 << 0);
|
||||
pCtx->data.mst.peerChannelStatus[(i * 4) + 1] = lctrDataPdu.pld.chanStatusInd.chanStatusMap[i] & (0x03 << 2);
|
||||
pCtx->data.mst.peerChannelStatus[(i * 4) + 2] = lctrDataPdu.pld.chanStatusInd.chanStatusMap[i] & (0x03 << 4);
|
||||
pCtx->data.mst.peerChannelStatus[(i * 4) + 3] = lctrDataPdu.pld.chanStatusInd.chanStatusMap[i] & (0x03 << 6);
|
||||
}
|
||||
|
||||
/* Final byte has less than 4 channels. */
|
||||
pCtx->data.mst.peerChannelStatus[i * 4] = lctrDataPdu.pld.chanStatusInd.chanStatusMap[i] & (0x03 << 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_WARN1("Received channel status from peripheral too early. Handle=%u", LCTR_GET_CONN_HANDLE(pCtx));
|
||||
}
|
||||
|
||||
/* The procedure completes after receiving the indication. */
|
||||
lctrSendConnMsg(pCtx, LCTR_CONN_LLCP_PROC_CMPL);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send channel reporting indication.
|
||||
*
|
||||
* \param pCtx Connection context.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void lctrSendChannelReportingInd(lctrConnCtx_t *pCtx)
|
||||
{
|
||||
if (pCtx->role != LL_ROLE_MASTER)
|
||||
{
|
||||
LL_TRACE_WARN0("lctrSendChannelReportingInd: Shall not be called as a peripheral.");
|
||||
pCtx->llcpNotifyMask &= ~(1 << LCTR_PROC_CMN_CH_CLASS_REPORTING);
|
||||
lctrSendConnMsg(pCtx, LCTR_CONN_LLCP_PROC_CMPL);
|
||||
return;
|
||||
}
|
||||
|
||||
lctrSendChannelReportingIndPdu(pCtx);
|
||||
pCtx->chanStatRptEnable = pLctrConnMsg->chanRptInd.enable;
|
||||
pCtx->data.mst.chanStatMinIntUs = LCTR_CH_RPT_IND_US(pLctrConnMsg->chanRptInd.minSpacing);
|
||||
|
||||
/* Minus minimum spacing to allow a controller to send LL_CHANNEL_STATUS_IND right away if desired. */
|
||||
pCtx->data.mst.recvdChanStatTs = PalBbGetCurrentTime() - pCtx->data.mst.chanStatMinIntUs;
|
||||
|
||||
/* The procedure completes after sending out the indication. */
|
||||
pCtx->llcpNotifyMask &= ~(1 << LCTR_PROC_CMN_CH_CLASS_REPORTING);
|
||||
lctrSendConnMsg(pCtx, LCTR_CONN_LLCP_PROC_CMPL);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Store received channel reporting indication.
|
||||
*
|
||||
* \param pCtx Connection context.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void lctrStoreChannelReportingInd(lctrConnCtx_t *pCtx)
|
||||
{
|
||||
if (pCtx->role != LL_ROLE_SLAVE)
|
||||
{
|
||||
LL_TRACE_WARN1("lctrStoreChannelReportingInd: Received LL_CH_RPT_IND as a central. Handle=%d", LCTR_GET_CONN_HANDLE(pCtx));
|
||||
pCtx->llcpNotifyMask &= ~(1 << LCTR_PROC_CMN_CH_CLASS_REPORTING);
|
||||
lctrSendConnMsg(pCtx, LCTR_CONN_LLCP_PROC_CMPL);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((lctrDataPdu.pld.chanRptInd.enable > TRUE) ||
|
||||
(lctrDataPdu.pld.chanRptInd.minSpacing < LL_CH_RPT_SPACING_MIN) ||
|
||||
(lctrDataPdu.pld.chanRptInd.maxDelay < LL_CH_RPT_SPACING_MIN) ||
|
||||
(lctrDataPdu.pld.chanRptInd.minSpacing > LL_CH_RPT_SPACING_MAX) ||
|
||||
(lctrDataPdu.pld.chanRptInd.maxDelay > LL_CH_RPT_SPACING_MAX) ||
|
||||
(lctrDataPdu.pld.chanRptInd.maxDelay < lctrDataPdu.pld.chanRptInd.minSpacing))
|
||||
{
|
||||
lctrSendRejectInd(pCtx, LL_ERROR_CODE_INVALID_LMP_PARAMS, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pCtx->chanStatRptEnable = lctrDataPdu.pld.chanRptInd.enable;
|
||||
pCtx->data.slv.chanStatMinIntUs = LCTR_CH_RPT_IND_US(lctrDataPdu.pld.chanRptInd.minSpacing);
|
||||
pCtx->data.slv.chanStatMaxDelay = LCTR_CH_RPT_IND_US(lctrDataPdu.pld.chanRptInd.maxDelay);
|
||||
if (pCtx->chanStatRptEnable)
|
||||
{
|
||||
pCtx->data.slv.queuedChanStatusTs = PalBbGetCurrentTime();
|
||||
}
|
||||
pCtx->data.slv.lastStatusSentTs = PalBbGetCurrentTime();
|
||||
}
|
||||
|
||||
/* The procedure completes after receiving the indication. */
|
||||
lctrSendConnMsg(pCtx, LCTR_CONN_LLCP_PROC_CMPL);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Update action for sca processing.
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2018 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -179,13 +179,16 @@ void lctrCalcSessionKey(lctrConnCtx_t *pCtx)
|
|||
/* Use AES to transform LTK to session key using session key diversifier as seed. */
|
||||
PalCryptoAesEcb(pCtx->ltk, pEnc->sk, pCtx->skd);
|
||||
|
||||
WSF_ASSERT(lctrInitCipherBlkHdlr);
|
||||
memcpy(pEnc->iv, pCtx->iv, sizeof(pEnc->iv));
|
||||
pEnc->dir = (pCtx->role == LL_ROLE_MASTER) ? 1 : 0; /* master = 1; slave = 0 */
|
||||
pEnc->type = PAL_BB_TYPE_ACL;
|
||||
pCtx->txPktCounter = 0;
|
||||
pCtx->rxPktCounter = 0;
|
||||
lctrInitCipherBlkHdlr(pEnc, LCTR_GET_CONN_HANDLE(pCtx), pEnc->dir);
|
||||
|
||||
if (lctrInitCipherBlkHdlr)
|
||||
{
|
||||
lctrInitCipherBlkHdlr(pEnc, LCTR_GET_CONN_HANDLE(pCtx), pEnc->dir);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* \brief Link layer controller connection power control state machine action routines.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -37,6 +37,27 @@
|
|||
#include <string.h>
|
||||
#include "lctr_int_pc.h"
|
||||
|
||||
/**************************************************************************************************
|
||||
Constants
|
||||
**************************************************************************************************/
|
||||
|
||||
#ifndef PC_ENABLE_DEBUG
|
||||
/*! \brief Enable power control debug statements. */
|
||||
#define PC_ENABLE_DEBUG FALSE
|
||||
#endif
|
||||
|
||||
#if PC_ENABLE_DEBUG
|
||||
#define LCTR_PC_DBG_TRACE_INFO0(m) LL_TRACE_INFO0(m)
|
||||
#define LCTR_PC_DBG_TRACE_INFO1(m, v1) LL_TRACE_INFO1(m, v1)
|
||||
#define LCTR_PC_DBG_TRACE_INFO2(m, v1, v2) LL_TRACE_INFO2(m, v1, v2)
|
||||
#define LCTR_PC_DBG_TRACE_INFO3(m, v1, v2, v3) LL_TRACE_INFO3(m, v1, v2, v3)
|
||||
#else
|
||||
#define LCTR_PC_DBG_TRACE_INFO0(m)
|
||||
#define LCTR_PC_DBG_TRACE_INFO1(m, v1)
|
||||
#define LCTR_PC_DBG_TRACE_INFO2(m, v1, v2)
|
||||
#define LCTR_PC_DBG_TRACE_INFO3(m, v1, v2, v3)
|
||||
#endif
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Return the power control index of a phy bit.
|
||||
|
@ -83,7 +104,7 @@ int8_t lctrAttemptTxPowerChange(lctrConnCtx_t *pCtx, uint8_t phy, int8_t delta)
|
|||
int8_t reqTxPower, curTxPower, newTxPower;
|
||||
if (LCTR_GET_TXPOWER(pCtx, phy, option) == LL_PWR_CTRL_TXPOWER_UNAVAILABLE)
|
||||
{
|
||||
/* The current controller does not support this phy. */
|
||||
/* The current controller does not support this PHY. */
|
||||
return 0;
|
||||
}
|
||||
else if (LCTR_GET_TXPOWER(pCtx, phy, option) == LL_PWR_CTRL_TXPOWER_UNMANAGED)
|
||||
|
@ -107,7 +128,7 @@ int8_t lctrAttemptTxPowerChange(lctrConnCtx_t *pCtx, uint8_t phy, int8_t delta)
|
|||
newTxPower = PalRadioIncreasePower(reqTxPower, delta);
|
||||
|
||||
/* Update txPower. */
|
||||
LL_TRACE_INFO3("lctrAttemptTxPowerChange: Power change -> handle=%d phy=%d txPow=%d", LCTR_GET_CONN_HANDLE(pCtx), phy + (option == BB_PHY_OPTIONS_BLE_S2) ? 1 : 0, newTxPower);
|
||||
LCTR_PC_DBG_TRACE_INFO3("lctrAttemptTxPowerChange: Power change -> handle=%d phy=%d txPow=%d", LCTR_GET_CONN_HANDLE(pCtx), phy + (option == BB_PHY_OPTIONS_BLE_S2) ? 1 : 0, newTxPower);
|
||||
LCTR_SET_TXPOWER(pCtx, phy + (((phy == LL_PHY_LE_CODED) && (option == BB_PHY_OPTIONS_BLE_S2)) ? 1 : 0), newTxPower);
|
||||
|
||||
/* Update current txPower if necessary. */
|
||||
|
@ -204,7 +225,7 @@ void lctrStorePowerControlAction(lctrConnCtx_t *pCtx)
|
|||
pCtx->delta = pLctrConnMsg->pwrCtrlReq.delta;
|
||||
pCtx->reqPhy = pLctrConnMsg->pwrCtrlReq.phy;
|
||||
|
||||
LL_TRACE_INFO2("lctrStorePowerControlAction, PHY=%u delta=%u", pCtx->reqPhy, pCtx->delta);
|
||||
LCTR_PC_DBG_TRACE_INFO2("lctrStorePowerControlAction, phy=%u delta=%u", pCtx->reqPhy, pCtx->delta);
|
||||
|
||||
/* If the power wasn't managed before, start managing it now. */
|
||||
if (LCTR_GET_TXPOWER(pCtx, pCtx->reqPhy, BB_PHY_OPTIONS_BLE_S2) == LL_PWR_CTRL_TXPOWER_UNMANAGED)
|
||||
|
@ -268,7 +289,7 @@ void lctrStorePeerPowerControlReq(lctrConnCtx_t *pCtx)
|
|||
(pCtx->bleData.chan.rxPhy == phyIdx) &&
|
||||
(pCtx->peerTxPower != pld.txPower))
|
||||
{
|
||||
lctrNotifyPowerReportInd(pCtx, LL_POWER_REPORT_REASON_REMOTE, phyIdx, pld.txPower,
|
||||
lctrNotifyPowerReportInd(pCtx, LL_SUCCESS, LL_POWER_REPORT_REASON_REMOTE, phyIdx, pld.txPower,
|
||||
lctrGetPowerLimits(pld.txPower),
|
||||
pld.txPower - pCtx->peerTxPower);
|
||||
}
|
||||
|
@ -281,11 +302,11 @@ void lctrStorePeerPowerControlReq(lctrConnCtx_t *pCtx)
|
|||
if ((pCtx->peerTxPower == LL_PWR_CTRL_TXPOWER_UNAVAILABLE) ||
|
||||
(pCtx->peerTxPower == LL_PWR_CTRL_TXPOWER_UNMANAGED))
|
||||
{
|
||||
LL_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower unmanaged or unavailable. Phy=%d", pld.phy);
|
||||
LCTR_PC_DBG_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower unmanaged or unavailable, phy=%d", pld.phy);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower=%d", pCtx->peerTxPower);
|
||||
LCTR_PC_DBG_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower=%d", pCtx->peerTxPower);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,7 +336,7 @@ void lctrStorePeerPowerControlReq(lctrConnCtx_t *pCtx)
|
|||
}
|
||||
|
||||
int8_t newTxPower = LCTR_GET_TXPOWER(pCtx, phy, option);
|
||||
lctrNotifyPowerReportInd(pCtx, LL_POWER_REPORT_REASON_LOCAL, phyIdx, newTxPower,
|
||||
lctrNotifyPowerReportInd(pCtx, LL_SUCCESS, LL_POWER_REPORT_REASON_LOCAL, phyIdx, newTxPower,
|
||||
lctrGetPowerLimits(newTxPower),
|
||||
pCtx->delta);
|
||||
}
|
||||
|
@ -338,7 +359,7 @@ void lctrSendPeerPowerControlRsp(lctrConnCtx_t *pCtx)
|
|||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_WARN0("lctrSendPeerPowerControlRsp: Peer sent invalid parameters for power control request.");
|
||||
LL_TRACE_WARN0("lctrSendPeerPowerControlRsp: peer sent invalid parameters for power control request");
|
||||
lctrSendRejectInd(pCtx, pCtx->reqErrCode, TRUE);
|
||||
pCtx->reqErrCode = LL_SUCCESS;
|
||||
}
|
||||
|
@ -359,7 +380,7 @@ void lctrStorePeerPowerControlRsp(lctrConnCtx_t *pCtx)
|
|||
if ((pCtx->powerRptRemote) &&
|
||||
(pCtx->peerTxPower != pld.txPower))
|
||||
{
|
||||
lctrNotifyPowerReportInd(pCtx, LL_POWER_REPORT_REASON_REMOTE, pCtx->reqPhy, pld.txPower,
|
||||
lctrNotifyPowerReportInd(pCtx, LL_SUCCESS, LL_POWER_REPORT_REASON_REMOTE, pCtx->reqPhy, pld.txPower,
|
||||
pld.limits,
|
||||
pld.txPower - pCtx->peerTxPower);
|
||||
}
|
||||
|
@ -374,18 +395,18 @@ void lctrStorePeerPowerControlRsp(lctrConnCtx_t *pCtx)
|
|||
if ((pCtx->peerTxPower == LL_PWR_CTRL_TXPOWER_UNAVAILABLE) ||
|
||||
(pCtx->peerTxPower == LL_PWR_CTRL_TXPOWER_UNMANAGED))
|
||||
{
|
||||
LL_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower unmanaged or unavailable. Phy=%d", pCtx->reqPhy);
|
||||
LCTR_PC_DBG_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower unmanaged or unavailable, phy=%d", pCtx->reqPhy);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower=%d", pCtx->peerTxPower);
|
||||
LCTR_PC_DBG_TRACE_INFO1("lctrStorePeerPowerControlReq: txPower=%d", pCtx->peerTxPower);
|
||||
|
||||
if (pCtx->controllerInitRead)
|
||||
{
|
||||
pCtx->controllerInitRead = FALSE;
|
||||
}
|
||||
|
||||
if (pCtx->monitoringState == LCTR_PC_MONITOR_PATH_LOSS)
|
||||
if (pCtx->powerMonitorScheme == LCTR_PC_MONITOR_PATH_LOSS)
|
||||
{
|
||||
if (pCtx->pclMonitorParam.pathLoss.initialPathLossRead)
|
||||
{
|
||||
|
@ -400,7 +421,7 @@ void lctrStorePeerPowerControlRsp(lctrConnCtx_t *pCtx)
|
|||
/* Store delta for reporting. */
|
||||
pCtx->delta = pld.delta;
|
||||
|
||||
LL_TRACE_INFO3("lctrStorePeerPowerControlRsp: peerTxPower=%d, peerPwrLimits=%d, peerApr=%d", pld.txPower, pld.limits, pld.apr);
|
||||
LCTR_PC_DBG_TRACE_INFO3("lctrStorePeerPowerControlRsp: peerTxPower=%d, peerPwrLimits=%d, peerApr=%d", pld.txPower, pld.limits, pld.apr);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -408,6 +429,7 @@ void lctrStorePeerPowerControlRsp(lctrConnCtx_t *pCtx)
|
|||
* \brief Notify host of power report indication.
|
||||
*
|
||||
* \param pCtx Connection context.
|
||||
* \param status Status code.
|
||||
* \param reason Reason this indication was sent.
|
||||
* \param phy PHY.
|
||||
* \param txPower Current txPower.
|
||||
|
@ -415,7 +437,7 @@ void lctrStorePeerPowerControlRsp(lctrConnCtx_t *pCtx)
|
|||
* \param delta Delta from last txPower.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void lctrNotifyPowerReportInd(lctrConnCtx_t *pCtx, uint8_t reason, uint8_t phy, int8_t txPower, uint8_t limits, int8_t delta)
|
||||
void lctrNotifyPowerReportInd(lctrConnCtx_t *pCtx, uint8_t status, uint8_t reason, uint8_t phy, int8_t txPower, uint8_t limits, int8_t delta)
|
||||
{
|
||||
const uint16_t handle = LCTR_GET_CONN_HANDLE(pCtx);
|
||||
|
||||
|
@ -425,7 +447,7 @@ void lctrNotifyPowerReportInd(lctrConnCtx_t *pCtx, uint8_t reason, uint8_t phy,
|
|||
{
|
||||
.param = handle,
|
||||
.event = LL_TX_POWER_REPORTING_IND,
|
||||
.status = LL_SUCCESS
|
||||
.status = status
|
||||
},
|
||||
|
||||
.status = LL_SUCCESS,
|
||||
|
@ -437,7 +459,15 @@ void lctrNotifyPowerReportInd(lctrConnCtx_t *pCtx, uint8_t reason, uint8_t phy,
|
|||
.delta = delta
|
||||
};
|
||||
|
||||
LL_TRACE_INFO2("### LlEvent ### lctrNotifyPowerReportInd , handle=%u, reason=%d, status=LL_SUCCESS", handle, reason);
|
||||
if (status == LL_SUCCESS)
|
||||
{
|
||||
LL_TRACE_INFO2("### LlEvent ### lctrNotifyPowerReportInd, handle=%u, reason=%d, status=LL_SUCCESS", handle, reason);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_INFO1("### LlEvent ### lctrNotifyPowerReportInd, Power procedure rejected, status=%d", status);
|
||||
}
|
||||
|
||||
|
||||
LmgrSendEvent((LlEvt_t *)&evt);
|
||||
}
|
||||
|
@ -463,7 +493,7 @@ static void lctrSendPowerChangePdu(lctrConnCtx_t *pCtx, uint8_t opcode, uint8_t
|
|||
|
||||
uint8_t *pPdu;
|
||||
|
||||
if ((pPdu = lctrTxCtrlPduAlloc(LL_PWR_CHNG_IND_LEN)) != NULL)
|
||||
if ((pPdu = lctrTxCtrlPduAlloc(LL_PWR_CHANGE_IND_LEN)) != NULL)
|
||||
{
|
||||
bool_t seperateIndNeeded = FALSE;
|
||||
uint8_t *pBuf = pPdu;
|
||||
|
@ -521,7 +551,7 @@ static void lctrSendPowerChangePdu(lctrConnCtx_t *pCtx, uint8_t opcode, uint8_t
|
|||
/*************************************************************************************************/
|
||||
void lctrSendPowerChangeInd(lctrConnCtx_t *pCtx, uint8_t phy, int8_t delta, int8_t txPower, bool_t phyChange)
|
||||
{
|
||||
lctrSendPowerChangePdu(pCtx, LL_PDU_PWR_CHNG_IND, phy, delta, txPower, phyChange);
|
||||
lctrSendPowerChangePdu(pCtx, LL_PDU_PWR_CHANGE_IND, phy, delta, txPower, phyChange);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -534,16 +564,15 @@ void lctrSendPowerChangeInd(lctrConnCtx_t *pCtx, uint8_t phy, int8_t delta, int8
|
|||
void lctrStorePeerPowerInd(lctrConnCtx_t *pCtx)
|
||||
{
|
||||
lctrPwrChngInd_t * pPdu = &lctrDataPdu.pld.pwrChngInd;
|
||||
LL_TRACE_INFO3("lctrStorePeerPowerInd: Phy=%d Delta=%d txPower=%d", pPdu->phy, pPdu->delta, pPdu->txPower);
|
||||
LCTR_PC_DBG_TRACE_INFO3("lctrStorePeerPowerInd: phy=%d delta=%d txPower=%d", pPdu->phy, pPdu->delta, pPdu->txPower);
|
||||
|
||||
if (pPdu->phy & (1 << (pCtx->bleData.chan.rxPhy - 1)))
|
||||
{
|
||||
if ((pCtx->peerTxPower != pPdu->txPower) &&
|
||||
(pCtx->powerRptRemote))
|
||||
if (pCtx->powerRptRemote)
|
||||
{
|
||||
lctrNotifyPowerReportInd(pCtx, LL_POWER_REPORT_REASON_REMOTE, pCtx->bleData.chan.rxPhy, pPdu->txPower,
|
||||
pPdu->limits,
|
||||
pPdu->txPower - pCtx->peerTxPower);
|
||||
lctrNotifyPowerReportInd(pCtx, LL_SUCCESS, LL_POWER_REPORT_REASON_REMOTE,
|
||||
pCtx->bleData.chan.rxPhy, pPdu->txPower, pPdu->limits,
|
||||
pPdu->txPower - pCtx->peerTxPower);
|
||||
}
|
||||
|
||||
if (pPdu->phy == pCtx->bleData.chan.rxPhy)
|
||||
|
@ -553,11 +582,11 @@ void lctrStorePeerPowerInd(lctrConnCtx_t *pCtx)
|
|||
if ((pCtx->peerTxPower == LL_PWR_CTRL_TXPOWER_UNAVAILABLE) ||
|
||||
(pCtx->peerTxPower == LL_PWR_CTRL_TXPOWER_UNMANAGED))
|
||||
{
|
||||
LL_TRACE_INFO1("lctrStorePeerPowerInd: txPower unmanaged or unavailable. Phy=%d", pPdu->phy);
|
||||
LCTR_PC_DBG_TRACE_INFO1("lctrStorePeerPowerInd: txPower unmanaged or unavailable, phy=%d", pPdu->phy);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_INFO1("lctrStorePeerPowerInd: txPower=%d", pCtx->peerTxPower);
|
||||
LCTR_PC_DBG_TRACE_INFO1("lctrStorePeerPowerInd: txPower=%d", pCtx->peerTxPower);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -578,62 +607,53 @@ void lctrSendPeerPowerRsp(lctrConnCtx_t *pCtx)
|
|||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Power monitoring action function
|
||||
* \brief Service connection power monitor.
|
||||
*
|
||||
* \param pCtx Connection context.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void lctrAutoPowerMonitorAct(lctrConnCtx_t *pCtx)
|
||||
void lctrConnServicePowerMonitor(lctrConnCtx_t *pCtx)
|
||||
{
|
||||
if (!(pCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST))
|
||||
if (!(pCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST) ||
|
||||
lmgrGetOpFlag(LL_OP_MODE_FLAG_DIS_POWER_MONITOR))
|
||||
{
|
||||
pCtx->monitoringState = LCTR_PC_MONITOR_DISABLED;
|
||||
return;
|
||||
}
|
||||
|
||||
if (lmgrCb.opModeFlags & LL_OP_MODE_DISABLE_POWER_MONITOR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int8_t sendReqDelta = 0;
|
||||
|
||||
if ((pCtx->rssi < pCtx->pclMonitorParam.autoMonitor.lowThreshold) ||
|
||||
(pCtx->lastRxStatus != BB_STATUS_SUCCESS))
|
||||
{
|
||||
pCtx->pclMonitorParam.autoMonitor.curTimeSpent++;
|
||||
/* Restore the sign after finding the absolute value average RSSI. */
|
||||
lctrRssiAddAveragePoint(&pCtx->pclMonitorParam.autoMonitor.rssiRunAvg,
|
||||
-((int8_t) (pCtx->pclMonitorParam.autoMonitor.accumulatedRssi / pCtx->pclMonitorParam.autoMonitor.totalAccumulatedRssi)));
|
||||
pCtx->pclMonitorParam.autoMonitor.accumulatedRssi = 0;
|
||||
pCtx->pclMonitorParam.autoMonitor.totalAccumulatedRssi = 0;
|
||||
|
||||
if (pCtx->pclMonitorParam.autoMonitor.curTimeSpent >= pCtx->pclMonitorParam.autoMonitor.minTimeSpent)
|
||||
{
|
||||
if (!(pCtx->peerPwrLimits & LL_PWR_CONTROL_LIMIT_MAX_BIT))
|
||||
{
|
||||
LL_TRACE_INFO1("RSSI too low, requesting increase in power. phy=%u", pCtx->bleData.chan.rxPhy);
|
||||
sendReqDelta = pCtx->pclMonitorParam.autoMonitor.requestVal;
|
||||
}
|
||||
pCtx->pclMonitorParam.autoMonitor.curTimeSpent = 0;
|
||||
}
|
||||
}
|
||||
else if (pCtx->rssi > pCtx->pclMonitorParam.autoMonitor.highThreshold)
|
||||
if (pCtx->pclMonitorParam.autoMonitor.rssiRunAvg.avgCount >= LL_PC_TBL_LEN)
|
||||
{
|
||||
pCtx->pclMonitorParam.autoMonitor.curTimeSpent++;
|
||||
int8_t averageRunning = lctrRssiGetAverage(&pCtx->pclMonitorParam.autoMonitor.rssiRunAvg);
|
||||
|
||||
if (pCtx->pclMonitorParam.autoMonitor.curTimeSpent >= pCtx->pclMonitorParam.autoMonitor.minTimeSpent)
|
||||
if ((averageRunning > pCtx->pclMonitorParam.autoMonitor.highThreshold) &&
|
||||
(!(pCtx->peerPwrLimits & LL_PWR_CONTROL_LIMIT_MIN_BIT)))
|
||||
{
|
||||
if (!(pCtx->peerPwrLimits & LL_PWR_CONTROL_LIMIT_MIN_BIT))
|
||||
{
|
||||
LL_TRACE_INFO1("RSSI too high, requesting decrease in power. phy=%u", pCtx->bleData.chan.rxPhy);
|
||||
sendReqDelta = -(pCtx->pclMonitorParam.autoMonitor.requestVal);
|
||||
}
|
||||
pCtx->pclMonitorParam.autoMonitor.curTimeSpent = 0;
|
||||
sendReqDelta = -(pCtx->pclMonitorParam.autoMonitor.requestVal);
|
||||
}
|
||||
else if ((averageRunning < pCtx->pclMonitorParam.autoMonitor.lowThreshold) &&
|
||||
!(pCtx->peerPwrLimits & LL_PWR_CONTROL_LIMIT_MAX_BIT))
|
||||
{
|
||||
sendReqDelta = pCtx->pclMonitorParam.autoMonitor.requestVal;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pCtx->pclMonitorParam.autoMonitor.curTimeSpent = 0;
|
||||
}
|
||||
|
||||
if (sendReqDelta != 0)
|
||||
{
|
||||
if ((pCtx->llcpActiveProc == LCTR_PROC_PWR_CTRL) ||
|
||||
(pCtx->llcpPendMask & (1 << LCTR_PROC_PWR_CTRL)))
|
||||
{
|
||||
LL_TRACE_WARN0("Power control LLCP already pending -- try increasing service interval");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t reqPhy = pCtx->bleData.chan.rxPhy + (((pCtx->bleData.chan.rxPhy == BB_PHY_BLE_CODED) && (pCtx->bleData.chan.initTxPhyOptions == BB_PHY_OPTIONS_BLE_S2)) ? 1 : 0);
|
||||
|
||||
lctrMsgPwrCtrlReq_t *pMsg;
|
||||
|
@ -646,5 +666,7 @@ void lctrAutoPowerMonitorAct(lctrConnCtx_t *pCtx)
|
|||
pMsg->phy = reqPhy;
|
||||
WsfMsgSend(lmgrPersistCb.handlerId, pMsg);
|
||||
}
|
||||
|
||||
pCtx->pclMonitorParam.autoMonitor.rssiRunAvg.avgCount = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -186,8 +186,9 @@ void lctrSendPhyUpdateIndPdu(lctrConnCtx_t *pCtx, uint8_t txPhys, uint8_t rxPhys
|
|||
else
|
||||
#endif
|
||||
{
|
||||
ceOffset = LL_MIN_INSTANT + 1 + /* +1 for next CE */
|
||||
pCtx->maxLatency; /* ensure slave will listen this packet */
|
||||
ceOffset = ((LL_MIN_INSTANT + 1 + /* +1 for next CE */
|
||||
pCtx->maxLatency) * /* ensure slave will listen to this packet */
|
||||
pCtx->ecu.srFactor); /* include subrating factor */
|
||||
}
|
||||
|
||||
if (txPhys || rxPhys)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -117,6 +117,15 @@ extern "C" {
|
|||
/*! \brief Change supervision timeout value to us. */
|
||||
#define LCTR_SUP_TIMEOUT_VAL_TO_US(x) (x * 10000)
|
||||
|
||||
/*! \brief Array size of running average arrays, derived from LL_PC_TBL_LEN. */
|
||||
#define LL_PC_TBL_LEN (1 << LL_PC_TBL_POW)
|
||||
|
||||
/*! \brief Calculate microsecond format from channel reporting parameter (200 millisecond ticks). */
|
||||
#define LCTR_CH_RPT_IND_US(x) ((((uint64_t) x) * 200) * 1000)
|
||||
|
||||
/*! \brief Calculate microsecond format from channel reporting parameter (200 millisecond ticks). */
|
||||
#define LCTR_CH_RPT_IND_US(x) ((((uint64_t) x) * 200) * 1000)
|
||||
|
||||
/**************************************************************************************************
|
||||
Data Types
|
||||
**************************************************************************************************/
|
||||
|
@ -136,6 +145,15 @@ typedef void (*LctrRmCback_t)(uint32_t rsvnOffs[], uint32_t refTime);
|
|||
/*! \brief Channel class update handler call signature. */
|
||||
typedef uint8_t (*lctrChClassHdlr_t)(uint64_t chanMap);
|
||||
|
||||
/*! \brief RSSI running average data type. */
|
||||
typedef struct
|
||||
{
|
||||
int8_t averageRssi[LL_PC_TBL_LEN];
|
||||
/*!< Running average RSSI. */
|
||||
uint8_t rssiIdx; /*!< Running average RSSI index. */
|
||||
uint8_t avgCount; /*!< Count of average entries since last reset. */
|
||||
} lctrRssiRunAvg_t;
|
||||
|
||||
/**************************************************************************************************
|
||||
Globals
|
||||
**************************************************************************************************/
|
||||
|
@ -164,6 +182,10 @@ uint16_t lctrCalcTotalAccuracy(uint8_t mstScaIdx);
|
|||
uint32_t lctrComputeCrcInit(void);
|
||||
uint32_t lctrCalcWindowWideningUsec(uint32_t unsyncTimeUsec, uint32_t caPpm);
|
||||
|
||||
/* RSSI Averaging. */
|
||||
int8_t lctrRssiGetAverage(lctrRssiRunAvg_t *pAvg);
|
||||
void lctrRssiAddAveragePoint(lctrRssiRunAvg_t *pAvg, int8_t value);
|
||||
|
||||
/* Host events */
|
||||
void lctrNotifyHostHwErrInd(uint8_t code);
|
||||
void lctrNotifyHostConnectInd(uint16_t handle, uint8_t role, lctrConnInd_t *pConnInd,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -191,6 +191,7 @@ typedef struct
|
|||
BbBleData_t scanBleData; /*!< BLE BB operation data. */
|
||||
BbOpDesc_t auxScanBod; /*!< Auxiliary scan BOD. */
|
||||
BbBleData_t auxBleData; /*!< Auxiliary BLE BB operation data. */
|
||||
bool_t scheduleAuxAsap; /*!< Signal BB to program Aux Scan. */
|
||||
} lctrExtScanCtx_t;
|
||||
|
||||
/*! \brief Extended scanning control block. */
|
||||
|
@ -234,6 +235,7 @@ typedef struct
|
|||
bool_t cancelByHost; /*!< Cancel command was issued from host. */
|
||||
bool_t firstPerAdvRcv; /*!< True if first periodic advertising packet is received. */
|
||||
bool_t repDisabled; /*!< Reporting disabled. */
|
||||
bool_t dupFilterEnable; /*!< Filtering by ADI field enabled. */
|
||||
bool_t bodAborted; /*!< Tue if periodic scan BOD was aborted. */
|
||||
uint8_t createDispId; /*!< Dispatcher id to tell if periodic sync was created or transferred. */
|
||||
lctrTermHdlr_t termCback; /*!< Termination callback. */
|
||||
|
@ -257,13 +259,14 @@ typedef struct
|
|||
uint32_t lastAnchorPointUsec;/*!< Last anchor point in microseconds. */
|
||||
uint16_t lastActiveEvent; /*!< Last active event counter. */
|
||||
uint16_t initEventCounter; /*!< Initial event counter received from sync_info. */
|
||||
uint16_t lastDid; /*!< Last ADI received, if applicable. */
|
||||
|
||||
/* ACAD */
|
||||
lctrAcadParam_t acadParams[LCTR_ACAD_NUM_ID]; /*!< ACAD control block array. */
|
||||
|
||||
/* Local periodic scanning parameters */
|
||||
uint16_t skip; /*!< Skip. */
|
||||
uint16_t syncTimeOutMs; /*!< Synchronization Timeout in Milliseconds. */
|
||||
uint32_t syncTimeOutMs; /*!< Synchronization Timeout in Milliseconds. */
|
||||
|
||||
/* Filtering parameters */
|
||||
bbBlePerPduFiltParams_t filtParam; /*!< Periodic scan filter parameters. */
|
||||
|
@ -356,12 +359,14 @@ void lctrMstPerScanTransferOpCommit(uint16_t connHandle);
|
|||
bool_t lctrMstDiscoverRxExtAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf);
|
||||
void lctrMstDiscoverRxExtAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf);
|
||||
bool_t lctrMstDiscoverRxAuxAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf);
|
||||
void lctrMstDiscoverRxAuxAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf);
|
||||
bool_t lctrMstDiscoverRxAuxScanRspHandler(BbOpDesc_t *pOp, const uint8_t *pRspBuf);
|
||||
uint32_t lctrMstDiscoverRxAuxChainHandler(BbOpDesc_t *pOp, const uint8_t *pChainBuf);
|
||||
bool_t lctrMstDiscoverRxAuxChainPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pChainBuf);
|
||||
bool_t lctrMstDiscoverRxLegacyAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf);
|
||||
bool_t lctrMstDiscoverTxLegacyScanReqHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf);
|
||||
bool_t lctrMstDiscoverRxLegacyScanRspHandler(BbOpDesc_t *pOp, const uint8_t *pRspBuf);
|
||||
bool_t lctrMstLinkAuxOffsetScanSetup(BbOpDesc_t *pBod, uint32_t refTime, uint32_t remScanDur);
|
||||
/* ISR: Discovery BOD handlers */
|
||||
void lctrMstExtDiscoverEndOp(BbOpDesc_t *pOp);
|
||||
void lctrMstExtDiscoverAbortOp(BbOpDesc_t *pOp);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2017 ARM Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -50,7 +50,6 @@ enum
|
|||
};
|
||||
|
||||
/*! \brief Common extended advertising PDU types. */
|
||||
|
||||
enum
|
||||
{
|
||||
LCTR_PDU_ADV_EXT_IND,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -43,7 +43,7 @@ extern "C" {
|
|||
**************************************************************************************************/
|
||||
|
||||
/*! \brief Maximum value of the AuxPtr offset field. */
|
||||
#define LCTR_AUX_PTR_MAX_OFFSET 0x3FFF
|
||||
#define LCTR_AUX_PTR_MAX_OFFSET 0x1FFF
|
||||
|
||||
/*! \brief Number of shifted bytes for Used PHY field from the AUX Offset. */
|
||||
#define LCTR_AUX_OFFS_USED_PHY_SHIFT 13
|
||||
|
@ -138,6 +138,9 @@ typedef struct
|
|||
bool_t shutdown; /*!< Client initiated shutdown flag. */
|
||||
uint32_t perAdvInterUsec; /*!< Periodic advertising interval in microseconds. */
|
||||
|
||||
bool_t enableAdi; /*!< Enable ADI field in Periodic Advertising. */
|
||||
uint16_t advDID; /*!< Advertising Data ID. */
|
||||
|
||||
uint32_t advInterMinUsec; /*!< Periodic Advertising Interval Minimum in microseconds. */
|
||||
uint32_t advInterMaxUsec; /*!< Periodic Advertising Interval Maximum in BB ticks. */
|
||||
uint16_t advEventProp; /*!< Periodic Advertising Event Properties. */
|
||||
|
@ -238,7 +241,6 @@ typedef struct
|
|||
|
||||
/* BB/ISR context */
|
||||
bool_t shutdown; /*!< Client initiated shutdown flag. */
|
||||
uint8_t bodTermCnt; /*!< Number of BOD terminated. */
|
||||
BbOpDesc_t advBod; /*!< Advertising BOD. */
|
||||
BbBleData_t bleData; /*!< BLE data. */
|
||||
BbOpDesc_t auxAdvBod; /*!< Auxiliary advertising BOD. */
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -66,22 +66,23 @@ typedef struct
|
|||
struct
|
||||
{
|
||||
/* Data */
|
||||
wsfQueue_t txDataQ; /*!< Transmit ISO queue. */
|
||||
uint8_t numTxSduComp; /*!< Number of Tx completed SDUs. */
|
||||
lctrIsoalTxCtx_t isoalTxCtx; /*!< ISOAL transmit context. */
|
||||
} slv; /*!< BIS slave specific data. */
|
||||
wsfQueue_t txDataQ; /*!< Transmit ISO queue. */
|
||||
uint8_t numTxSduComp; /*!< Number of Tx completed SDUs. */
|
||||
lctrIsoalTxCtx_t isoalTxCtx; /*!< ISOAL transmit context. */
|
||||
lctrInDataPathCtx_t dataPathInCtx; /*!< Datapath input context. */
|
||||
} slv; /*!< BIS slave specific data. */
|
||||
|
||||
struct
|
||||
{
|
||||
/* Data */
|
||||
wsfQueue_t rxDataQ; /*!< Receive ISO Data PDU pending queue. */
|
||||
wsfQueue_t rxIsoSduQ; /*!< Receive ISO SDU PDU pending queue. */
|
||||
lctrIsoalRxCtx_t isoalRxCtx; /*!< ISOAL Receive context. */
|
||||
wsfQueue_t rxDataQ; /*!< Receive ISO Data PDU pending queue. */
|
||||
lctrIsoalRxCtx_t isoalRxCtx; /*!< ISOAL receive context. */
|
||||
lctrOutDataPathCtx_t dataPathOutCtx; /*!< Output data path context. */
|
||||
|
||||
/* ISO test */
|
||||
LlIsoTestCtrs_t stats; /*!< Rx statistics. */
|
||||
} mst; /*!< BIS master specific data. */
|
||||
} roleData; /*!< Role specific data. */
|
||||
LlIsoTestCtrs_t stats; /*!< Rx statistics. */
|
||||
} mst; /*!< BIS master specific data. */
|
||||
} roleData; /*!< Role specific data. */
|
||||
|
||||
/* ISO test */
|
||||
struct
|
||||
|
@ -93,22 +94,21 @@ typedef struct
|
|||
{
|
||||
struct
|
||||
{
|
||||
uint32_t payloadCtr; /*!< Payload counter for framed transmissions. */
|
||||
} framed; /*!< Framed context. */
|
||||
uint32_t payloadCtr; /*!< Payload counter for framed transmissions. */
|
||||
} framed;
|
||||
struct
|
||||
{
|
||||
uint8_t payloadOffset; /*!< Payload offset for unframed transmissions. */
|
||||
} unframed; /*!< Unframed context. */
|
||||
} util; /*!< Role-based utility variables. */
|
||||
LlIsoPldType_t pldType:8; /*!< Test payload type. */
|
||||
} test; /*!< ISO Test data. */
|
||||
uint8_t burstIdx; /*!< BN Index for unframed transmissions. */
|
||||
} unframed;
|
||||
} util;
|
||||
LlIsoPldType_t pldType:8; /*!< Test payload type. */
|
||||
} test;
|
||||
|
||||
/* BB */
|
||||
lmgrChanParam_t chSelInfo; /*!< Channel selection state. */
|
||||
PalBbBleChan_t chan; /*!< Channelization parameters. */
|
||||
|
||||
/* Data */
|
||||
LlIsoDataPath_t path:8; /*!< Input audio data path. */
|
||||
LlIsoLlid_t lastLlid:8; /*!< Last LLID. */
|
||||
} lctrBisCtx_t;
|
||||
|
||||
|
@ -164,19 +164,26 @@ typedef struct lctrBigCtx_tag
|
|||
uint8_t bisIdx[LL_MAX_BIS]; /*!< List of indices of BISes. */
|
||||
|
||||
/* Sync timeout */
|
||||
uint32_t bigSyncTimeoutMs; /*!< Synchronization timeout in microseconds. */
|
||||
wsfTimer_t bigSyncTmr; /*!< Synchronization timeout timer. */
|
||||
|
||||
/* Event state */
|
||||
uint16_t totalAcc; /*!< Total clock accuracy. */
|
||||
uint16_t extraWwUsec; /*!< Extra window widening time in microseconds. */
|
||||
uint32_t rxSyncTime; /*!< Last received BIG anchor point. */
|
||||
uint32_t anchorPoint; /*!< BIG anchor point. */
|
||||
uint32_t bigSyncTimeoutMs; /*!< Synchronization timeout in microseconds. */
|
||||
|
||||
/* Encryption */
|
||||
uint8_t bcstCode[LL_BC_LEN]; /*!< Broadcast Code. */
|
||||
} mst; /*!< BIG master specific data. */
|
||||
} roleData; /*!< Role-specific data. */
|
||||
uint8_t bcstCode[LL_BC_LEN]; /*!< Broadcast Code. Array address should be word-aligned. */
|
||||
|
||||
/* Event state */
|
||||
uint16_t totalAcc; /*!< Total clock accuracy. */
|
||||
uint16_t initWwUsec; /*!< Initial synchronization window widening time in microseconds. */
|
||||
uint32_t rxSyncTime; /*!< Last received BIG anchor point. */
|
||||
uint32_t anchorPoint; /*!< BIG anchor point. */
|
||||
lctrBisCtx_t *pFirstBisCtx; /*!< First BIS context (ISR optimization to reduce lookups). */
|
||||
lctrBisCtx_t *pSecondBisCtx; /*!< Second BIS context (ISR optimization to reduce lookups). */
|
||||
uint32_t firstBisOffsUsec; /*!< First BIS offset from the anchor point in microseconds. */
|
||||
uint8_t firstBisEvtIdx; /*!< First BIS index. */
|
||||
|
||||
/* Reception status. */
|
||||
bool_t lastPduMissed; /*!< Rx failure on last PDU. */
|
||||
} mst; /*!< BIG master specific data. */
|
||||
} roleData; /*!< Role-specific data. */
|
||||
|
||||
/* Control */
|
||||
struct
|
||||
|
@ -210,9 +217,6 @@ typedef struct lctrBigCtx_tag
|
|||
bool_t encrypt; /*!< Encryption enable for BIS. */
|
||||
uint8_t giv[LL_GIV_LEN]; /*!< GIV. */
|
||||
uint8_t gskd[LL_GSKD_LEN]; /*!< GSKD. */
|
||||
|
||||
/* Reception status. */
|
||||
bool_t lastPduMissed; /*!< Rx failure on last PDU. */
|
||||
} lctrBigCtx_t;
|
||||
|
||||
/*! \brief ISR subevent context. */
|
||||
|
@ -245,7 +249,6 @@ bool_t lctrIsBigSynchronizing(void);
|
|||
|
||||
/* BIS Context */
|
||||
lctrBisCtx_t *lctrAllocBisCtx(lctrBigCtx_t *pBigCtx);
|
||||
void lctrCleanupBisCtx(lctrBisCtx_t *pBisCtx);
|
||||
void lctrFreeBisCtx(lctrBisCtx_t *pBisCtx);
|
||||
lctrBisCtx_t *lctrFindBisByHandle(uint16_t bisHandle);
|
||||
uint8_t lctrGetNumAvailBisCtx(void);
|
||||
|
@ -266,11 +269,11 @@ void lctrBigTxCtrlQueuePopCleanup(lctrBigCtx_t *pBigCtx);
|
|||
|
||||
/* BIS Rx Data Path */
|
||||
uint8_t *lctrBisRxIsoSduDeq(lctrBisCtx_t *pBisCtx);
|
||||
void lctrBisRxIsoSduEnq(lctrBisCtx_t *pBisCtx, uint8_t *pBuf);
|
||||
uint8_t *lctrBisRxIsoDataPduAlloc(void);
|
||||
void lctrBisRxIsoDataPduFree(uint8_t *pPdu);
|
||||
void lctrBisEnqueueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t *pRxBuf, uint64_t evtCtr);
|
||||
uint8_t *lctrBisDequeueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t *pEvtCtrLsb);
|
||||
void lctrBisEnqueueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t *pRxBuf, uint8_t burstIdx);
|
||||
uint8_t *lctrBisDequeueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t burstIdx);
|
||||
uint8_t *lctrBisDequeueRxDataPduTop(lctrBisCtx_t *pBisCtx);
|
||||
|
||||
/* ISO Test mode */
|
||||
uint8_t lctrBisTxTest(lctrBisCtx_t *pBisCtx, uint8_t pldType);
|
||||
|
@ -281,9 +284,8 @@ uint8_t LctrBisReadTestCounters(lctrBisCtx_t *pBisCtx, LlIsoTestCtrs_t *pStats);
|
|||
void lctrBisDefaults(void);
|
||||
void lctrNotifyIsoTxComplete(lctrBigCtx_t *pBigCtx);
|
||||
void lctrBisCalcGroupSessionKey(const uint8_t *pGSKD, const uint8_t *pBC, uint8_t *pGSK);
|
||||
uint8_t lctrBisSetDataPath(lctrBisCtx_t *pBisCtx, LlIsoDataPathDir_t dpDir, LlIsoDataPath_t dpId);
|
||||
bool_t lctrSlvBisCalcNextIdxSequential(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts);
|
||||
bool_t lctrSlvBisCalcNextIdxInterleaved(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts);
|
||||
bool_t lctrBisCalcNextIdxSequential(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts);
|
||||
bool_t lctrBisCalcNextIdxInterleaved(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* \brief Internal link layer controller isochronous master interface file.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -90,6 +90,7 @@ void lctrMstSetupBigChannel(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo);
|
|||
/* ISR: BOD handlers */
|
||||
void lctrMstBisRxCompletion(BbOpDesc_t *pBod, uint8_t *pBuf, uint8_t status);
|
||||
void lctrMstBigBeginOp(BbOpDesc_t *pOp);
|
||||
void lctrMstBigAbortOp(BbOpDesc_t *pOp);
|
||||
void lctrMstBigEndOp(BbOpDesc_t *pOp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -160,6 +160,8 @@ typedef struct
|
|||
uint32_t cigSyncDelayUsec; /*!< CIG synchronous delay in microsecond. */
|
||||
bool_t cisDone; /*!< CIS transfer is done, no more subevent for the CIS. Used for interleaved CIS only. */
|
||||
bool_t isClosing; /*!< TRUE if the context is closing. */
|
||||
bool_t termPend; /*!< The CIS has pended a termination. */
|
||||
bool_t hostInitTerm; /*!< The host has initiated the termination. */
|
||||
|
||||
uint8_t subEvtCounter; /*!< Sub event counter. */
|
||||
bool_t isTxDone; /*!< TRUE if all the Tx are done, start sending NULL packet. */
|
||||
|
@ -172,9 +174,10 @@ typedef struct
|
|||
uint64_t rxPktCounter; /*!< Receive packet counter. */
|
||||
|
||||
/* Buffers */
|
||||
uint8_t dataHdrBuf[LL_DATA_HDR_LEN]; /*!< Data header buffer */
|
||||
uint8_t dataBuf[10]; /*!< Data header buffer */
|
||||
uint8_t dataHdrBuf[LL_DATA_HDR_LEN]; /*!< Data header buffer. */
|
||||
uint8_t dataBuf[10]; /*!< Data header buffer. */
|
||||
uint16_t dataCounter; /*!< Data counter. */
|
||||
uint8_t dataSn; /*!< Data sequence number. */
|
||||
|
||||
/* LLCP */
|
||||
bool_t isCisReqPend; /*!< True if CIS_REQ is sent and response is not received yet. */
|
||||
|
@ -196,6 +199,7 @@ typedef struct
|
|||
uint32_t firstRxStartTsUsec; /*!< Timestamp of the first received frame regardless of CRC error in microseconds. */
|
||||
uint8_t consCrcFailed; /*!< Number of consecutive CRC failures. */
|
||||
uint8_t rxStatus; /*!< Rx status. */
|
||||
bool_t lastTxNull; /*!< Last packet sent was a null. */
|
||||
} slv; /*!< Slave connection specific data. */
|
||||
|
||||
struct
|
||||
|
@ -220,7 +224,6 @@ typedef struct
|
|||
uint8_t numTxComp; /*!< Number of completed Tx buffers. */
|
||||
uint32_t delayUsec; /*!< Time between the start of subevent to the start of next subevent in microsecond.
|
||||
Same as subEvtInter for sequential scheme, different for interleaved scheme. */
|
||||
uint8_t *pRxBuf; /*!< Pointer to the RX buffer later to be cleaned. */
|
||||
bool_t validRx; /*!< TRUE if the RX buffer is valid and shall be processed. */
|
||||
bool_t txPduIsAcked; /*!< TRUE if the TX PDU is acked. */
|
||||
bool_t txBufPendAck; /*!< A transmit buffer is pending acknowledgement. */
|
||||
|
@ -410,6 +413,7 @@ bool_t lctrCisIsListEmpty(lctrCisList_t *pList);
|
|||
uint8_t lctrCisGetListCount(lctrCisList_t *pList);
|
||||
lctrCisCtx_t * lctrCisGetHeadCis(lctrCisList_t *pList);
|
||||
bool_t lctrCisIsHeadCis(lctrCisList_t *pList, lctrCisCtx_t *pCisCtx);
|
||||
bool_t lctrCisIsTailCis(lctrCisList_t *pList, lctrCisCtx_t *pCisCtx);
|
||||
lctrCisCtx_t * lctrCisGetNextCis(lctrCisList_t *pList, lctrCisCtx_t *pCurCis);
|
||||
lctrCisCtx_t * lctrCisGetPreCis(lctrCisList_t *pList, lctrCisCtx_t *pCurCis);
|
||||
bool_t lctrCisAreCisCtxDone(lctrCisList_t *pList);
|
||||
|
@ -466,7 +470,7 @@ void lctrCisTxQueuePopCleanup(lctrCisCtx_t *pCisCtx);
|
|||
uint8_t lctrCisTxQueueClear(lctrCisCtx_t *pCisCtx);
|
||||
|
||||
/* CIS Rx data path */
|
||||
uint8_t *lctrCisRxPduAlloc(uint16_t maxRxLen);
|
||||
uint8_t *lctrCisRxPduAlloc();
|
||||
void lctrCisRxPduFree(uint8_t *pBuf);
|
||||
void lctrCisRxEnq(uint8_t *pBuf, uint16_t eventCounter, uint16_t cisHandle);
|
||||
uint8_t *lctrCisRxDeq(uint16_t *pConnHandle);
|
||||
|
@ -487,7 +491,8 @@ void lctrCisTxPduAck(lctrCisCtx_t *pCisCtx);
|
|||
void lctrCisProcessTxAckCleanup(lctrCisCtx_t *pCisCtx);
|
||||
void lctrCisRxPostProcessing(lctrCisCtx_t *pCisCtx, uint8_t *pRxBuf);
|
||||
void lctrCisTxTestPayloadHandler(lctrCisCtx_t * pCisCtx);
|
||||
void lctrCisPowerMonitorCheckRssi(int8_t rssi, uint8_t status, uint8_t phy, lctrConnCtx_t *pConnCtx);
|
||||
void lctrCisCheckUnframedFlush(lctrCisCtx_t *pCisCtx);
|
||||
void lctrCisServicePowerMonitor(lctrConnCtx_t *pConnCtx);
|
||||
|
||||
/* Scheduler */
|
||||
BbOpDesc_t *lctrCisResolveConflict(BbOpDesc_t *pNewOp, BbOpDesc_t *pExistOp);
|
||||
|
@ -506,7 +511,7 @@ static inline void lctrCisIncPacketCounterTx(lctrCisCtx_t *pCisCtx)
|
|||
/* Set the new packet counter for inline encryption. */
|
||||
if (lctrSetEncryptPktCountHdlr)
|
||||
{
|
||||
lctrSetEncryptPktCountHdlr(&pCisCtx->bleData.chan.enc, pCisCtx->txPktCounter);
|
||||
lctrSetEncryptPktCountHdlr(pCisCtx->txPktCounter);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -520,11 +525,47 @@ static inline void lctrCisIncPacketCounterTx(lctrCisCtx_t *pCisCtx)
|
|||
static inline void lctrCisIncPacketCounterRx(lctrCisCtx_t *pCisCtx)
|
||||
{
|
||||
pCisCtx->rxPktCounter++;
|
||||
}
|
||||
|
||||
/* Set the new packet counter for inline encryption. */
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Set the CIS Tx packet counter value in the BB.
|
||||
*
|
||||
* \param pCisCtx Connection context.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static inline void lctrSetBbCisPacketCounterTx(lctrCisCtx_t *pCisCtx)
|
||||
{
|
||||
if (lctrSetEncryptPktCountHdlr)
|
||||
{
|
||||
PalCryptoEnc_t * const pEnc = &pCisCtx->bleData.chan.enc;
|
||||
|
||||
if (!pEnc->enaEncrypt)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lctrSetEncryptPktCountHdlr(pCisCtx->txPktCounter);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Set the CIS Rx packet counter value in the BB.
|
||||
*
|
||||
* \param pCisCtx Connection context.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static inline void lctrSetBbCisPacketCounterRx(lctrCisCtx_t *pCisCtx)
|
||||
{
|
||||
if (lctrSetDecryptPktCountHdlr)
|
||||
{
|
||||
/* lctrSetDecryptPktCountHdlr(&pCisCtx->bleData.chan.enc, pCisCtx->rxPktCounter); */ /* Not necessary. */
|
||||
PalCryptoEnc_t * const pEnc = &pCisCtx->bleData.chan.enc;
|
||||
|
||||
if (!pEnc->enaDecrypt)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lctrSetDecryptPktCountHdlr(pCisCtx->rxPktCounter);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -88,6 +88,7 @@ void lctrMstCisCigRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status)
|
|||
|
||||
/* ISR: BOD handlers */
|
||||
uint32_t lctrMstCisCheckContOp(BbOpDesc_t *pOp, bool_t *pNewCisCtx);
|
||||
uint32_t lctrMstCisCheckContOpPostCback(BbOpDesc_t *pOp, bool_t *pNewCisCtx);
|
||||
void lctrMstCisCigBeginOp(BbOpDesc_t *pOp);
|
||||
void lctrMstCisCigContOp(BbOpDesc_t *pOp);
|
||||
void lctrMstCisCigPostSubEvt(BbOpDesc_t *pOp, uint8_t status);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -83,6 +83,7 @@ void lctrSlvCisCigBeginOp(BbOpDesc_t *pOp);
|
|||
void lctrSlvCisCigContOp(BbOpDesc_t *pOp);
|
||||
void lctrSlvCisCigPostSubEvt(BbOpDesc_t *pOp, uint8_t status);
|
||||
uint32_t lctrSlvCisCheckContOp(BbOpDesc_t *pOp, bool_t *pNewCisCtx);
|
||||
uint32_t lctrSlvCisCheckContOpPostCback(BbOpDesc_t *pOp, bool_t *pNewCisCtx);
|
||||
void lctrSlvCisCigEndOp(BbOpDesc_t *pOp);
|
||||
void lctrSlvCisCigCleanupOp(BbOpDesc_t *pOp);
|
||||
void lctrSlvCisCigAbortOp(BbOpDesc_t *pOp);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -67,25 +67,13 @@ extern "C" {
|
|||
/*! \brief Resolve connection context from the handle. */
|
||||
#define LCTR_GET_CONN_CTX(h) &(pLctrConnTbl[h])
|
||||
|
||||
/*! \brief Resolve txPower from phy index. */
|
||||
/*! \brief Resolve txPower from PHY index. */
|
||||
#define LCTR_GET_TXPOWER(pCtx, phy, option) \
|
||||
(pCtx->phyTxPower[phy - (((phy == LL_PHY_LE_CODED) && (option == BB_PHY_OPTIONS_BLE_S2)) ? 0 : 1)])
|
||||
|
||||
/*! \brief Set the txpower of a specified PHY. */
|
||||
#define LCTR_SET_TXPOWER(pCtx, phy, pow) (pCtx->phyTxPower[phy - 1] = pow)
|
||||
|
||||
/*! \brief Low threshold for power monitoring. */
|
||||
#define LCTR_RSSI_LOW_THRESHOLD -65
|
||||
|
||||
/*! \brief High threshold for power monitoring. */
|
||||
#define LCTR_RSSI_HIGH_THRESHOLD -30
|
||||
|
||||
/*! \brief Minimum time spent until request. */
|
||||
#define LCTR_PC_MIN_TIME 15
|
||||
|
||||
/*! \brief Default request of increase/decrease in value. */
|
||||
#define LCTR_PC_REQUEST_VAL 5
|
||||
|
||||
/*! \brief Special reset terminate reason. */
|
||||
#define LCTR_RESET_TERM_REASON 0xFF
|
||||
|
||||
|
@ -147,6 +135,8 @@ enum
|
|||
LCTR_PROC_CMN_SET_MIN_USED_CHAN, /*!< Set minimum number of used channels procedure. */
|
||||
LCTR_PROC_CMN_PER_ADV_SYNC_TRSF, /*!< Periodic advertising sync transfer procedure. */
|
||||
LCTR_PROC_CMN_REQ_PEER_SCA, /*!< Request peer SCA procedure. */
|
||||
LCTR_PROC_CMN_CH_CLASS_REPORTING, /*!< Channel classification reporting procedure. */
|
||||
LCTR_PROC_CMN_CH_STATUS_REPORT, /*!< Channel status reporting procedure. */
|
||||
LCTR_PROC_CMN_TOTAL, /*!< Total number of common procedures. */
|
||||
|
||||
/* Custom SM LLCP procedures. */
|
||||
|
@ -162,6 +152,7 @@ enum
|
|||
LCTR_PROC_CIS_TERM_PEER, /*!< Peer-initiated CIS termination procedure. */
|
||||
LCTR_PROC_PWR_IND, /*!< Power indication prodecure. */
|
||||
LCTR_PROC_PWR_CTRL, /*!< Power control procedure. */
|
||||
LCTR_PROC_SUBRATE, /*!< Subrate procedure. */
|
||||
|
||||
LCTR_PROC_INVALID = 0xFF /*!< Invalid ID. */
|
||||
|
||||
|
@ -225,11 +216,19 @@ typedef struct
|
|||
bool_t rxFromMaster; /*!< At least one successful packet received from master. */
|
||||
uint32_t firstRxStartTsUsec; /*!< Timestamp of the first received frame regardless of CRC error in microseconds. */
|
||||
|
||||
uint32_t lastStatusSentTs; /*!< Timestamp of last channel status update. */
|
||||
uint32_t chanStatMinIntUs; /*!< Minimum interval in us between channel status updates. */
|
||||
uint32_t chanStatMaxDelay; /*!< Max delay before a change of channel status is allowed to be sent. */
|
||||
uint32_t queuedChanStatusTs; /*!< Timestamp of last channel status that is queued to be sent out. */
|
||||
} slv; /*!< Slave connection specific data. */
|
||||
|
||||
struct
|
||||
{
|
||||
bool_t sendConnUpdInd; /*!< Send LL_CONNECTION_UPDATE_IND flag. */
|
||||
uint8_t peerChannelStatus[LL_MAX_NUM_CHAN_DATA];
|
||||
/*!< Current channel status map of peer. */
|
||||
uint32_t recvdChanStatTs; /*!< Timestamp of last received channel status from peer. */
|
||||
uint32_t chanStatMinIntUs; /*!< Minimum interval in us between channel status updates. */
|
||||
} mst; /*!< Master connection specific data. */
|
||||
} data; /*!< Role specific data. */
|
||||
|
||||
|
@ -264,6 +263,7 @@ typedef struct
|
|||
wsfQueue_t rxDataQ; /*!< Receive data pending queue. */
|
||||
uint8_t numTxComp; /*!< Number of completed Tx buffers. */
|
||||
uint8_t numRxPend; /*!< Number of Rx pending buffers. */
|
||||
uint8_t numTxPendCtrlPdu; /*!< Number of pending Control PDUs. */
|
||||
bool_t emptyPduPend; /*!< Empty PDU ACK pending. */
|
||||
bool_t emptyPduFirstAtt; /*!< Empty PDU first attempt. */
|
||||
bool_t forceStartPdu; /*!< Next data will be forced to be a start PDU */
|
||||
|
@ -302,6 +302,7 @@ typedef struct
|
|||
bool_t remoteVerValid; /*!< Peer version data valid. */
|
||||
lctrVerInd_t remoteVer; /*!< Peer version data. */
|
||||
bool_t featExchFlag; /*!< Flag for completed feature exchange. */
|
||||
uint64_t peerFeatures; /*!< Peer reported features. */
|
||||
uint64_t usedFeatSet; /*!< Used feature set. */
|
||||
uint8_t peerSca; /*!< Peer SCA. */
|
||||
|
||||
|
@ -310,6 +311,9 @@ typedef struct
|
|||
uint8_t peerApr[LL_PC_PHY_TOTAL];
|
||||
/*!< Acceptable reduction of power as calculated by the peer. */
|
||||
|
||||
/* Channel reporting parameters. */
|
||||
bool_t chanStatRptEnable; /*!< Enable status of channel status reporting. */
|
||||
|
||||
/* Data length */
|
||||
lctrDataLen_t localDataPdu; /*!< Local Data PDU parameters. */
|
||||
lctrDataLen_t effDataPdu; /*!< Effective Data PDU parameters. */
|
||||
|
@ -332,7 +336,7 @@ typedef struct
|
|||
uint16_t perServiceData; /*!< ID for periodic sync indication. */
|
||||
uint16_t perSyncHandle; /*!< Periodic sync handle. */
|
||||
|
||||
/* PAST(Periodic advertising sync transfer) parameters. */
|
||||
/* PAST parameters. */
|
||||
uint8_t syncMode; /*!< Sync transfer mode. */
|
||||
uint16_t syncSkip; /*!< Sync skip for periodic adv sync transfer. */
|
||||
uint16_t syncTimeout; /*!< Sync timeout for periodic adv sync transfer. */
|
||||
|
@ -342,6 +346,7 @@ typedef struct
|
|||
uint8_t encState; /*!< Current encryption state. */
|
||||
uint8_t pingState; /*!< Current ping state. */
|
||||
uint8_t connUpdState; /*!< Connection update state. */
|
||||
uint8_t ecuState; /*!< Enhanced connection update state. */
|
||||
uint8_t phyUpdState; /*!< PHY update state. */
|
||||
uint8_t cmnState; /*!< Common LLCP state. */
|
||||
bool_t peerReplyWaiting; /*!< Peer waiting for reply. */
|
||||
|
@ -369,6 +374,7 @@ typedef struct
|
|||
uint8_t reqErrCode; /*!< LLCP error code. */
|
||||
|
||||
/* Power Control */
|
||||
wsfTimer_t tmrPowerCtrl; /*!< Power control monitor timer. */
|
||||
int8_t delta; /*!< Power control delta storage. */
|
||||
bool_t peerReqRecvd; /*!< Peer request received. */
|
||||
uint8_t reqPhy; /*!< PHY of most recent power control request. */
|
||||
|
@ -381,10 +387,11 @@ typedef struct
|
|||
{
|
||||
struct
|
||||
{
|
||||
int8_t highThreshold; /*!< High extreme RSSI threshold. */
|
||||
int8_t lowThreshold; /*!< Low extreme RSSI threshold. */
|
||||
uint8_t minTimeSpent; /*!< Minimum time spent in an extreme RSSI zone to trigger a request. */
|
||||
uint8_t curTimeSpent; /*!< Current time spent in an extreme RSSI zone. */
|
||||
int8_t highThreshold; /*!< High RSSI threshold. */
|
||||
int8_t lowThreshold; /*!< Low RSSI threshold. */
|
||||
uint8_t totalAccumulatedRssi; /*!< Total accumulated RSSI samples in current sample slot. */
|
||||
uint32_t accumulatedRssi; /*!< Absolute value of accumulated RSSI in current RSSI sample slot (RSSI can never be positive). */
|
||||
lctrRssiRunAvg_t rssiRunAvg; /*!< RSSI running average. */
|
||||
uint8_t requestVal; /*!< Value of increase/decrease in power to request. */
|
||||
} autoMonitor; /*!< Autonomous RSSI monitoring specific data. */
|
||||
|
||||
|
@ -403,10 +410,43 @@ typedef struct
|
|||
} pclMonitorParam; /*!< Power control monitoring data. */
|
||||
|
||||
/* CIS */
|
||||
uint16_t llcpCisHandle; /*!< CIS handle for the LLCP procedure. */
|
||||
lctrCheckTermFn_t checkCisTerm; /*!< Pointer to the check CIS termination function. */
|
||||
lctrCheckCisEstAclFn_t checkCisEstAcl; /*!< Pointer to the check if CIS is established function. */
|
||||
uint8_t cisRssiExtremeTimeSpent; /*!< CIS's current time spent in an extreme zone. */
|
||||
uint16_t llcpCisHandle; /*!< CIS handle for the LLCP procedure. */
|
||||
lctrCheckTermFn_t checkCisTerm; /*!< Pointer to the check CIS termination function. */
|
||||
lctrCheckCisEstAclFn_t checkCisEstAcl; /*!< Pointer to the check if CIS is established function. */
|
||||
uint8_t cisRssiExtremeTimeSpent; /*!< CIS's current time spent in an extreme zone. */
|
||||
uint8_t cisTotalAccumulatedRssi; /*!< Total accumulated RSSI samples in current sample slot. */
|
||||
uint32_t cisAccumulatedRssi; /*!< Absolute value of accumulated RSSI in current RSSI sample slot (RSSI can never be positive). */
|
||||
lctrRssiRunAvg_t cisRunAvg; /*!< Running average of RSSI for CIS connection for power control. */
|
||||
|
||||
/* Enhanced Connection Update */
|
||||
struct
|
||||
{
|
||||
/* Default values. */
|
||||
uint16_t defSrMin; /*!< Subrate minimum value. */
|
||||
uint16_t defSrMax; /*!< Subrate maximum value. */
|
||||
uint16_t defMaxLatency; /*!< Maximum latency. */
|
||||
uint16_t defContNum; /*!< Continuation number. */
|
||||
uint16_t defSvt; /*!< Supervision timeout. */
|
||||
|
||||
/* Active values. */
|
||||
uint16_t srFactor; /*!< Active subrate factor. */
|
||||
uint16_t srBaseEvent; /*!< Subrate base event. */
|
||||
uint16_t contNum; /*!< Continuation number. */
|
||||
uint16_t svt; /*!< Supervision timeout. */
|
||||
uint16_t contNumCtr; /*!< Number of continuation number in subrate events. */
|
||||
|
||||
struct
|
||||
{
|
||||
uint16_t srFactor; /*!< Active subrate factor. */
|
||||
uint16_t srBaseEvent; /*!< Subrate base event. */
|
||||
uint16_t contNum; /*!< Continuation number. */
|
||||
uint16_t contNumCtr; /*!< Number of continuation number in subrate events. */
|
||||
uint16_t maxLatency; /*!< Maximum latency. */
|
||||
uint16_t svt; /*!< Supervision timeout. */
|
||||
} pending;
|
||||
|
||||
bool_t isSubrateTransMode; /*!< True if central in subrate transition mode. */
|
||||
} ecu; /*!< Enhanced connection update parameters. */
|
||||
} lctrConnCtx_t;
|
||||
|
||||
/*! \brief Call signature of a cipher block handler. */
|
||||
|
@ -419,7 +459,7 @@ typedef bool_t (*lctrPktEncHdlr_t)(PalCryptoEnc_t *pEnc, uint8_t *pHdr, uint8_t
|
|||
typedef bool_t (*lctrPktDecHdlr_t)(PalCryptoEnc_t *pEnc, uint8_t *pBuf);
|
||||
|
||||
/*! \brief Call signature of a set packet count handler. */
|
||||
typedef void (*lctrPktCntHdlr_t)(PalCryptoEnc_t *pEnc, uint64_t pktCnt);
|
||||
typedef void (*lctrPktCntHdlr_t)(uint64_t pktCnt);
|
||||
|
||||
/*! \brief Call signature of a LLCP state machine handler. */
|
||||
typedef bool_t (*LctrLlcpHdlr_t)(lctrConnCtx_t *pCtx, uint8_t event);
|
||||
|
@ -440,21 +480,31 @@ typedef void (*lctrPcMonAct_t)(lctrConnCtx_t *pCtx);
|
|||
typedef void (*lctrPcPowInd_t)(lctrConnCtx_t *pCtx, uint8_t phy, int8_t delta, int8_t txPower, bool_t phyChange);
|
||||
|
||||
/*! \brief Call signature of power report notification handler. */
|
||||
typedef void (*lctrPcNotifyPwr_t)(lctrConnCtx_t *pCtx, uint8_t reason, uint8_t phy, int8_t txPower, uint8_t limits, int8_t delta);
|
||||
typedef void (*lctrPcNotifyPwr_t)(lctrConnCtx_t *pCtx, uint8_t status, uint8_t reason, uint8_t phy, int8_t txPower, uint8_t limits, int8_t delta);
|
||||
|
||||
/*! \brief Call signature of CIS pend disconnect function. */
|
||||
typedef bool_t (*lctrPendCisDisc_t)(lctrConnCtx_t *pCtx);
|
||||
|
||||
/*! \brief Call signature of CIS power monitoring function. */
|
||||
typedef void (*lctrCisServicePowerMonitor_t)(lctrConnCtx_t *pCtx);
|
||||
|
||||
/*! \brief Call signature of calculate number of subrated connection events. */
|
||||
typedef uint16_t (*lctrCalcSubrateConnEvents_t)(lctrConnCtx_t *pCtx, uint16_t numDataPdu);
|
||||
|
||||
/*! \brief Call signature of check LLCP override. */
|
||||
typedef bool_t (*lctrCheckLlcpOverride_t)(lctrConnCtx_t *pCtx);
|
||||
|
||||
/*! \brief LLCP state machine handlers. */
|
||||
enum
|
||||
{
|
||||
LCTR_LLCP_SM_ENCRYPT, /*!< Encryption LLCP state machine. */
|
||||
LCTR_LLCP_SM_PING, /*!< Ping state machine. */
|
||||
LCTR_LLCP_SM_ENH_CONN_UPD, /*!< Enhanced connection update state machine. */
|
||||
LCTR_LLCP_SM_CONN_UPD, /*!< Connection update state machine. */
|
||||
LCTR_LLCP_SM_PHY_UPD, /*!< PHY update state machine. */
|
||||
LCTR_LLCP_SM_CIS_EST, /*!< CIS establishment state machine. */
|
||||
LCTR_LLCP_SM_CIS_TERM, /*!< CIS termination state machine. */
|
||||
LCTR_LLCP_SM_PC, /*!< Power control state machine. */
|
||||
LCTR_LLCP_SM_PC, /*!< Power control state machine. */
|
||||
LCTR_LLCP_SM_CMN, /*!< Common LLCP state machine. */
|
||||
LCTR_LLCP_SM_TOTAL /*!< Total number of LLCP state machine. */
|
||||
};
|
||||
|
@ -480,9 +530,12 @@ extern lctrLlcpEh_t lctrSendPerSyncFromBcstFn;
|
|||
extern lctrLlcpEh_t lctrStorePeriodicSyncTrsfFn;
|
||||
extern lctrLlcpEh_t lctrSendPeriodicSyncIndFn;
|
||||
extern lctrLlcpEh_t lctrReceivePeriodicSyncIndFn;
|
||||
extern lctrPcMonAct_t lctrPcActTbl[LCTR_PC_MONITOR_SCHEME_TOTAL];
|
||||
extern lctrPcMonAct_t lctrPathLossMonitorActFn;
|
||||
extern lctrPcPowInd_t lctrSendPowerChangeIndCback;
|
||||
extern lctrPcNotifyPwr_t lctrNotifyPowerReportIndCback;
|
||||
extern lctrCisServicePowerMonitor_t lctrCisServicePowerMonitorFn;
|
||||
extern lctrCalcSubrateConnEvents_t lctrCalcSubrateConnEventsFn;
|
||||
extern lctrCheckLlcpOverride_t lctrSlvCheckEncOverridePhyUpdateFn;
|
||||
|
||||
/**************************************************************************************************
|
||||
Function Declarations
|
||||
|
@ -573,6 +626,12 @@ void lctrSendPeerScaRsp(lctrConnCtx_t *pCtx);
|
|||
void lctrStorePeerSca(lctrConnCtx_t *pCtx);
|
||||
void lctrNotifyHostPeerScaCnf(lctrConnCtx_t *pCtx);
|
||||
|
||||
/* Channel status reporting actions. */
|
||||
void lctrSendChannelStatusInd(lctrConnCtx_t *pCtx);
|
||||
void lctrStoreChannelStatusInd(lctrConnCtx_t *pCtx);
|
||||
void lctrSendChannelReportingInd(lctrConnCtx_t *pCtx);
|
||||
void lctrStoreChannelReportingInd(lctrConnCtx_t *pCtx);
|
||||
|
||||
/* Unknown/Unsupported */
|
||||
void lctrSendUnknownRsp(lctrConnCtx_t *pCtx);
|
||||
void lctrSendRejectInd(lctrConnCtx_t *pCtx, uint8_t reason, bool_t forceRejectExtInd);
|
||||
|
@ -637,6 +696,9 @@ uint8_t lctrGetPowerLimits(int8_t txPower);
|
|||
/* Reservation */
|
||||
uint32_t lctrGetConnRefTime(uint8_t connHandle, uint32_t *pDurUsec);
|
||||
|
||||
/* Channel map updating. */
|
||||
uint8_t lctrConnChClassUpdate(uint64_t chanMap);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Set flags for link termination.
|
||||
|
@ -749,11 +811,11 @@ static inline void lctrIncPacketCounterTx(lctrConnCtx_t *pCtx)
|
|||
/*************************************************************************************************/
|
||||
static inline void lctrIncPacketCounterRx(lctrConnCtx_t *pCtx)
|
||||
{
|
||||
if (lctrSetEncryptPktCountHdlr)
|
||||
if (lctrSetDecryptPktCountHdlr)
|
||||
{
|
||||
PalCryptoEnc_t * const pEnc = &pCtx->bleData.chan.enc;
|
||||
|
||||
if ((pEnc->enaEncrypt) &&
|
||||
if ((pEnc->enaDecrypt) &&
|
||||
(pEnc->nonceMode == PAL_BB_NONCE_MODE_PKT_CNTR))
|
||||
{
|
||||
pCtx->rxPktCounter++;
|
||||
|
@ -782,10 +844,10 @@ static inline void lctrSetBbPacketCounterTx(lctrConnCtx_t *pCtx)
|
|||
switch (pEnc->nonceMode)
|
||||
{
|
||||
case PAL_BB_NONCE_MODE_PKT_CNTR:
|
||||
lctrSetEncryptPktCountHdlr(pEnc, pCtx->txPktCounter);
|
||||
lctrSetEncryptPktCountHdlr(pCtx->txPktCounter);
|
||||
break;
|
||||
case PAL_BB_NONCE_MODE_EXT16_CNTR:
|
||||
lctrSetEncryptPktCountHdlr(pEnc, pCtx->eventCounter);
|
||||
lctrSetEncryptPktCountHdlr(pCtx->eventCounter);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -814,10 +876,10 @@ static inline void lctrSetBbPacketCounterRx(lctrConnCtx_t *pCtx)
|
|||
switch (pEnc->nonceMode)
|
||||
{
|
||||
case PAL_BB_NONCE_MODE_PKT_CNTR:
|
||||
lctrSetDecryptPktCountHdlr(pEnc, pCtx->rxPktCounter);
|
||||
lctrSetDecryptPktCountHdlr(pCtx->rxPktCounter);
|
||||
break;
|
||||
case PAL_BB_NONCE_MODE_EXT16_CNTR:
|
||||
lctrSetDecryptPktCountHdlr(pEnc, pCtx->eventCounter);
|
||||
lctrSetDecryptPktCountHdlr(pCtx->eventCounter);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -870,11 +932,11 @@ static inline void lctrStoreConnTimeoutTerminateReason(lctrConnCtx_t *pCtx)
|
|||
/*************************************************************************************************/
|
||||
static inline void lctrDataTxIncAvailBuf(void)
|
||||
{
|
||||
WSF_CS_INIT();
|
||||
WSF_CS_INIT(cs);
|
||||
|
||||
WSF_CS_ENTER();
|
||||
WSF_CS_ENTER(cs);
|
||||
lmgrConnCb.availTxBuf++;
|
||||
WSF_CS_EXIT();
|
||||
WSF_CS_EXIT(cs);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -884,11 +946,11 @@ static inline void lctrDataTxIncAvailBuf(void)
|
|||
/*************************************************************************************************/
|
||||
static inline void lctrDataTxDecAvailBuf(void)
|
||||
{
|
||||
WSF_CS_INIT();
|
||||
WSF_CS_INIT(cs);
|
||||
|
||||
WSF_CS_ENTER();
|
||||
WSF_CS_ENTER(cs);
|
||||
lmgrConnCb.availTxBuf--;
|
||||
WSF_CS_EXIT();
|
||||
WSF_CS_EXIT(cs);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -900,11 +962,11 @@ static inline void lctrDataTxDecAvailBuf(void)
|
|||
/*************************************************************************************************/
|
||||
static inline void lctrDataRxIncAvailBuf(uint8_t numBufs)
|
||||
{
|
||||
WSF_CS_INIT();
|
||||
WSF_CS_INIT(cs);
|
||||
|
||||
WSF_CS_ENTER();
|
||||
WSF_CS_ENTER(cs);
|
||||
lmgrConnCb.availRxBuf += numBufs;
|
||||
WSF_CS_EXIT();
|
||||
WSF_CS_EXIT(cs);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
|
|
@ -82,23 +82,23 @@ typedef struct
|
|||
} lctrIsoTxBufDesc_t;
|
||||
|
||||
/*! \brief Start stream call signature. */
|
||||
typedef bool_t (*lctrCodecStartStream)(uint16_t id, PalCodecSreamParam_t *pParam);
|
||||
typedef bool_t (*lctrCodecStartStream)(uint16_t id, PalCodecStreamParam_t *pParam);
|
||||
|
||||
/*! \brief Stop stream call signature. */
|
||||
typedef void (*lctrCodecStopStream)(uint16_t id);
|
||||
typedef void (*lctrCodecStopStream)(uint16_t id, PalCodecDir_t dir);
|
||||
|
||||
/*! \brief Stream in data call signature. */
|
||||
typedef uint16_t (*lctrCodecStreamIn)(uint16_t id, uint8_t *pBuf, uint16_t len, uint32_t *pPktCtr);
|
||||
/*! \brief Stream in data request call signature. */
|
||||
typedef void (*lctrCodecStreamInReq)(uint16_t id, uint8_t *pData, uint16_t len);
|
||||
|
||||
/*! \brief Stream out data call signature. */
|
||||
typedef void (*lctrCodecStreamOut)(uint16_t id, const uint8_t *pBuf, uint16_t len, uint32_t pktCtr);
|
||||
typedef void (*lctrCodecStreamOut)(uint16_t id, const uint8_t *pBuf, uint16_t len, uint32_t sduRef);
|
||||
|
||||
/*! \brief Codec event handlers. */
|
||||
typedef struct
|
||||
{
|
||||
lctrCodecStartStream start; /*!< Start stream. */
|
||||
lctrCodecStopStream stop; /*!< Stop stream. */
|
||||
lctrCodecStreamIn in; /*!< Stream data input. */
|
||||
lctrCodecStreamInReq inReq; /*!< Stream data input request. */
|
||||
lctrCodecStreamOut out; /*!< Stream data output. */
|
||||
} lctrCodecHandlers_t;
|
||||
|
||||
|
@ -134,7 +134,7 @@ typedef struct
|
|||
{
|
||||
wsfQueue_t pendSduQ; /*!< Pending PDU fragments. */
|
||||
uint16_t curLen; /*!< Current length of SDU being received. */
|
||||
uint8_t ps; /*!< Packet status. */
|
||||
lctrPktStatus_t ps:8; /*!< Packet status. */
|
||||
} unframed; /*!< Unframed specific data. */
|
||||
} data; /*!< Framing-specific data. */
|
||||
} lctrIsoalRxCtx_t;
|
||||
|
@ -142,30 +142,55 @@ typedef struct
|
|||
/*! \brief Input datapath context. */
|
||||
typedef struct
|
||||
{
|
||||
LlIsoDataPath_t id; /*!< Input data path ID. */
|
||||
} lctrInDataPathCtx_t; /*!< Input datapath configuration. */
|
||||
LlIsoDataPath_t id:8; /*!< Input data path ID. */
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint16_t streamId; /*!< Stream ID. */
|
||||
} codec; /*!< Codec-specific configuration. */
|
||||
} cfg; /*!< Data path specific configuration. */
|
||||
} lctrInDataPathCtx_t; /*!< Input data path configuration. */
|
||||
|
||||
/*! \brief Output datapath context. */
|
||||
typedef struct
|
||||
{
|
||||
LlIsoDataPath_t id; /*!< Output data path ID. */
|
||||
LlIsoDataPath_t id:8; /*!< Output data path ID. */
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
wsfQueue_t rxDataQ; /*!< Receive data pending queue. */
|
||||
uint8_t numRxPend; /*!< Number of messages pending in the RX queue. */
|
||||
uint8_t numRxPend; /*!< Number of messages pending in the Rx queue. */
|
||||
} hci; /*!< HCI data path configuration. */
|
||||
} cfg; /*!< Datapath-specific configuration parameters. */
|
||||
} lctrOutDataPathCtx_t; /*!< Output datapath configuration. */
|
||||
|
||||
/*! \brief Datapath context. */
|
||||
struct
|
||||
{
|
||||
wsfQueue_t rxDataQ; /*!< Receive data pending queue. */
|
||||
uint8_t numRxPend; /*!< Number of messages pending in the Rx queue. */
|
||||
uint16_t streamId; /*!< Stream ID. */
|
||||
} codec; /*!< Codec-specific configuration. */
|
||||
} cfg; /*!< Data path specific configuration parameters. */
|
||||
} lctrOutDataPathCtx_t; /*!< Output data path configuration. */
|
||||
|
||||
/*! \brief Data path context. */
|
||||
typedef union
|
||||
{
|
||||
lctrInDataPathCtx_t in; /*!< Input context. */
|
||||
lctrOutDataPathCtx_t out; /*!< Output context. */
|
||||
} lctrDataPathCtx_t; /*!< Datapath context collection. */
|
||||
} lctrDataPathCtx_t; /*!< Data path context collection. */
|
||||
|
||||
/*! \brief Data path setup parameters. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t handle; /*!< ISO Handle. */
|
||||
uint32_t isoInt; /*!< ISO interval. */
|
||||
uint32_t pktCtr; /*!< Current packet counter. */
|
||||
uint8_t dpDir; /*!< Data path direction. */
|
||||
lctrDataPathCtx_t *pDataPathCtx; /*!< Data path context. */
|
||||
} lctrDpParams_t;
|
||||
|
||||
/**************************************************************************************************
|
||||
Function Declarations
|
||||
|
@ -179,15 +204,17 @@ void lctrNotifyHostIsoEventComplete(uint8_t handle, uint32_t evtCtr);
|
|||
/* ISO data path */
|
||||
lctrIsoTxBufDesc_t *lctrAllocIsoTxBufDesc(void);
|
||||
void lctrFreeIsoTxBufDesc(lctrIsoTxBufDesc_t *pDesc);
|
||||
uint8_t lctrSetupIsoDataPath( LlIsoSetupDataPath_t *pSetupDataPath, lctrDataPathCtx_t *pDataPathCtx);
|
||||
void lctrIsoSendCodecSdu(uint16_t id);
|
||||
bool_t lctrIsoRxConnEnq(lctrOutDataPathCtx_t *pOutDataPathCtx, uint16_t handle, uint8_t *pBuf);
|
||||
void lctrIsoOutDataPathClear(lctrOutDataPathCtx_t *pOutCtx);
|
||||
uint8_t lctrIsoSetupDataPath(lctrDpParams_t *pDpParam, LlIsoSetupDataPath_t *pSetupDataPath);
|
||||
void lctrIsoSendCodecSdu(uint16_t id, uint32_t pktCtr, uint32_t ts, uint8_t *pData, uint16_t actLen);
|
||||
bool_t lctrIsoRxConnEnq(lctrOutDataPathCtx_t *pOutDataPathCtx, uint16_t handle, uint32_t pktCtr, uint8_t *pBuf);
|
||||
void lctrIsoInDataPathClear(lctrDpParams_t *pDpParam);
|
||||
void lctrIsoOutDataPathClear(lctrDpParams_t *pDpParam);
|
||||
void lctrIsoalRxDataPathClear(lctrIsoalRxCtx_t *pRxCtx, uint8_t framing);
|
||||
void lctrIsoOutDataPathSetup(lctrOutDataPathCtx_t *pOutCtx);
|
||||
uint8_t lctrIsoInDataPathSetup(lctrDpParams_t *pDpParam, LlIsoSetupDataPath_t *pSetupDataPath);
|
||||
uint8_t lctrIsoOutDataPathSetup(lctrDpParams_t *pDpParam, LlIsoSetupDataPath_t *pSetupDataPath);
|
||||
uint8_t *lctrIsoRxConnDeq(lctrOutDataPathCtx_t *pOutCtx);
|
||||
bool_t lctrIsoUnframedRxSduPendQueue(lctrIsoalRxCtx_t *pRxCtx, uint8_t *pSdu, uint16_t handle,
|
||||
uint16_t dataLen, uint8_t llid);
|
||||
uint8_t *lctrRxSduAlloc(void);
|
||||
bool_t lctrRecombineRxUnframedSdu(lctrIsoalRxCtx_t *pRxCtx, uint8_t *pSduFrag);
|
||||
|
||||
/* ISO Test mode. */
|
||||
uint8_t *lctrGenerateIsoTestData(uint16_t handle, LlIsoPldType_t pldType, uint16_t maxSdu, uint32_t pktCtr);
|
||||
|
@ -205,11 +232,11 @@ uint8_t *lctrTxIsoDataPduAlloc(void);
|
|||
/*************************************************************************************************/
|
||||
static inline void lctrIsoSduTxIncAvailBuf(void)
|
||||
{
|
||||
WSF_CS_INIT();
|
||||
WSF_CS_INIT(cs);
|
||||
|
||||
WSF_CS_ENTER();
|
||||
WSF_CS_ENTER(cs);
|
||||
lmgrIsoCb.availTxBuf++;
|
||||
WSF_CS_EXIT();
|
||||
WSF_CS_EXIT(cs);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -219,11 +246,11 @@ static inline void lctrIsoSduTxIncAvailBuf(void)
|
|||
/*************************************************************************************************/
|
||||
static inline void lctrIsoSduTxDecAvailBuf(void)
|
||||
{
|
||||
WSF_CS_INIT();
|
||||
WSF_CS_INIT(cs);
|
||||
|
||||
WSF_CS_ENTER();
|
||||
WSF_CS_ENTER(cs);
|
||||
lmgrIsoCb.availTxBuf--;
|
||||
WSF_CS_EXIT();
|
||||
WSF_CS_EXIT(cs);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -235,11 +262,11 @@ static inline void lctrIsoSduTxDecAvailBuf(void)
|
|||
/*************************************************************************************************/
|
||||
static inline void lctrIsoDataRxIncAvailBuf(uint8_t numBufs)
|
||||
{
|
||||
WSF_CS_INIT();
|
||||
WSF_CS_INIT(cs);
|
||||
|
||||
WSF_CS_ENTER();
|
||||
WSF_CS_ENTER(cs);
|
||||
lmgrIsoCb.availRxBuf += numBufs;
|
||||
WSF_CS_EXIT();
|
||||
WSF_CS_EXIT(cs);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -249,11 +276,11 @@ static inline void lctrIsoDataRxIncAvailBuf(uint8_t numBufs)
|
|||
/*************************************************************************************************/
|
||||
static inline void lctrIsoDataRxDecAvailBuf(void)
|
||||
{
|
||||
WSF_CS_INIT();
|
||||
WSF_CS_INIT(cs);
|
||||
|
||||
WSF_CS_ENTER();
|
||||
WSF_CS_ENTER(cs);
|
||||
lmgrIsoCb.availRxBuf--;
|
||||
WSF_CS_EXIT();
|
||||
WSF_CS_EXIT(cs);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* \brief Internal link layer controller power control interface file.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -24,25 +24,17 @@
|
|||
#define LCTR_INT_PC_H
|
||||
|
||||
#include "lctr_api.h"
|
||||
#include "lctr_int_conn.h"
|
||||
#include "lctr_int_conn_slave.h"
|
||||
#include "lctr_int_conn_master.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**************************************************************************************************
|
||||
External Constants
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! \brief Master LLCP state machine table. */
|
||||
extern LctrLlcpHdlr_t lctrMstLlcpSmTbl[LCTR_LLCP_SM_TOTAL];
|
||||
|
||||
/*! \brief Slave LLCP state machine table. */
|
||||
extern LctrLlcpHdlr_t lctrSlvLlcpSmTbl[LCTR_LLCP_SM_TOTAL];
|
||||
|
||||
/*************************************************************************************************
|
||||
* Function Declarations
|
||||
*************************************************************************************************/
|
||||
|
||||
uint8_t lctrCalcPathLossZone(lctrConnCtx_t *pCtx);
|
||||
void lctrNotifyHostPathLossRpt(lctrConnCtx_t *pCtx);
|
||||
void lctrPathLossMonitorAct(lctrConnCtx_t *pCtx);
|
||||
|
@ -59,10 +51,10 @@ void lctrSendPeerPowerControlRsp(lctrConnCtx_t *pCtx);
|
|||
void lctrStorePeerPowerControlRsp(lctrConnCtx_t *pCtx);
|
||||
|
||||
/* Power monitoring actions. */
|
||||
void lctrAutoPowerMonitorAct(lctrConnCtx_t *pCtx);
|
||||
void lctrConnServicePowerMonitor(lctrConnCtx_t *pCtx);
|
||||
|
||||
/* Power reporting actions. */
|
||||
void lctrNotifyPowerReportInd(lctrConnCtx_t *pCtx, uint8_t reason, uint8_t phy, int8_t txPower, uint8_t limits, int8_t delta);
|
||||
void lctrNotifyPowerReportInd(lctrConnCtx_t *pCtx, uint8_t status, uint8_t reason, uint8_t phy, int8_t txPower, uint8_t limits, int8_t delta);
|
||||
int8_t lctrAttemptTxPowerChange(lctrConnCtx_t *pCtx, uint8_t phy, int8_t delta);
|
||||
void lctrSendPowerChangeInd(lctrConnCtx_t *pCtx, uint8_t phy, int8_t delta, int8_t txPower, bool_t phyChange);
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2016-2017 ARM Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -50,6 +50,8 @@ void lctrSendPhyUpdateIndPdu(lctrConnCtx_t *pCtx, uint8_t txPhys, uint8_t rxPhys
|
|||
|
||||
void lctrNotifyHostPhyUpdateInd(lctrConnCtx_t *pCtx, uint8_t status);
|
||||
|
||||
bool_t lctrSlvCheckEncOverridePhyUpdate(lctrConnCtx_t *pCtx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -27,6 +27,7 @@
|
|||
#include "lctr_api_bis_master.h"
|
||||
#include "sch_api.h"
|
||||
#include "sch_api_ble.h"
|
||||
#include "bb_ble_api_op.h"
|
||||
#include "bb_ble_api_reslist.h"
|
||||
#include "bb_ble_api_whitelist.h"
|
||||
#include "bb_ble_api_periodiclist.h"
|
||||
|
@ -879,6 +880,40 @@ bool_t lctrMstDiscoverRxExtAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf
|
|||
return txScanReq;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Check if an Aux Scan should be programmed ASAP because of a too small auxOffset.
|
||||
*
|
||||
* \param pBod Originating operation.
|
||||
* \param refTime Refference time in microseconds
|
||||
* \param remScanDur Remaining scan duration in microseconds
|
||||
*
|
||||
* \return TRUE if Aux Scan was programmed, FALSE otherwise.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t lctrMstLinkAuxOffsetScanSetup(BbOpDesc_t *pBod, uint32_t refTime, uint32_t remScanDur)
|
||||
{
|
||||
bool_t result = FALSE;
|
||||
lctrExtScanCtx_t * const pExtScanCtx = pBod->pCtx;
|
||||
BbOpDesc_t * const pAuxBod = &pExtScanCtx->auxScanBod;
|
||||
|
||||
if (pExtScanCtx->scheduleAuxAsap == TRUE)
|
||||
{
|
||||
pExtScanCtx->scheduleAuxAsap = FALSE;
|
||||
|
||||
/* Check if Aux Scan can be programmed in the remaining Ext Scan duration. */
|
||||
if (BbGetTargetTimeDelta(pAuxBod->dueUsec + pAuxBod->minDurUsec, refTime) < remScanDur)
|
||||
{
|
||||
/* The Aux Scan will run in the context of the Ext Scan BOD. */
|
||||
pBod->prot.pBle->op.mstAdv.auxScanBod = pAuxBod;
|
||||
BbMstExecuteLinkedAuxScanOp(pAuxBod, &pExtScanCtx->auxBleData);
|
||||
result = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Extended scan discover state advertising packet receive (primary channel)
|
||||
|
@ -947,12 +982,6 @@ void lctrMstDiscoverRxExtAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t
|
|||
else
|
||||
{
|
||||
/* Delay Non-connectable and non-scannable with auxiliary packet PDU filtering in the AUX_ADV_IND.*/
|
||||
lctrMstExtScanIsr.advAReceived = FALSE;
|
||||
lctrMstExtScanIsr.tgtAReceived = FALSE;
|
||||
lctrMstExtScanIsr.advA = 0;
|
||||
lctrMstExtScanIsr.tgtA = 0;
|
||||
lctrMstExtScanIsr.advARand = 0;
|
||||
lctrMstExtScanIsr.tgtARand = 0;
|
||||
|
||||
/* Retrieve advA and tgtA if present. */
|
||||
if (extAdvHdrFlags & LL_EXT_HDR_ADV_ADDR_BIT)
|
||||
|
@ -961,12 +990,25 @@ void lctrMstDiscoverRxExtAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t
|
|||
lctrMstExtScanIsr.advA = pExtScanCtx->extAdvHdr.advAddr;
|
||||
lctrMstExtScanIsr.advARand = advHdr.txAddrRnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
lctrMstExtScanIsr.advAReceived = FALSE;
|
||||
lctrMstExtScanIsr.advA = 0;
|
||||
lctrMstExtScanIsr.advARand = 0;
|
||||
}
|
||||
|
||||
if (extAdvHdrFlags & LL_EXT_HDR_TGT_ADDR_BIT)
|
||||
{
|
||||
lctrMstExtScanIsr.tgtAReceived = TRUE;
|
||||
lctrMstExtScanIsr.tgtA = pExtScanCtx->extAdvHdr.tgtAddr;
|
||||
lctrMstExtScanIsr.tgtARand = advHdr.rxAddrRnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
lctrMstExtScanIsr.tgtAReceived = FALSE;
|
||||
lctrMstExtScanIsr.tgtA = 0;
|
||||
lctrMstExtScanIsr.tgtARand = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* else case, delay connectable and scannable PDU filtering in the AUX_ADV_IND. */
|
||||
|
@ -1201,98 +1243,7 @@ bool_t lctrMstDiscoverRxAuxAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf
|
|||
/* Continue processing for sync establishment filter even when scan filtering failed. */
|
||||
}
|
||||
|
||||
/*** Periodic advertising event filtering. ***/
|
||||
bool_t advAMatch = FALSE;
|
||||
uint64_t peerIdAddr = 0;
|
||||
uint8_t peerIdAddrType = 0;
|
||||
|
||||
BbBlePduFiltResultsGetPeerIdAddr(&pAuxScan->filtResults, &peerIdAddr, &peerIdAddrType);
|
||||
|
||||
if ((lctrPerCreateSync.state == LCTR_CREATE_SYNC_STATE_DISCOVER) &&
|
||||
(lctrMstPerScanIsr.filtResult == FALSE))
|
||||
{
|
||||
if ((lctrPerCreateSync.filtParam.advSID != pExtScanCtx->extAdvHdr.sid) ||
|
||||
(lctrPerCreateSync.filtParam.advAddrType != (peerIdAddrType & LL_ADDR_RANDOM_BIT)) ||
|
||||
(lctrPerCreateSync.filtParam.advAddr != peerIdAddr))
|
||||
{
|
||||
/* Address type, address or SID does not match. */
|
||||
lctrMstPerScanIsr.filtResult = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((lctrPerCreateSync.state == LCTR_CREATE_SYNC_STATE_DISCOVER) &&
|
||||
(lctrMstPerScanIsr.filtResult == TRUE) &&
|
||||
(lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_ADI_BIT) &&
|
||||
((lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_ADV_ADDR_BIT) ||
|
||||
(lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_SYNC_INFO_BIT)))
|
||||
{
|
||||
if (lctrPerCreateSync.filtParam.filterPolicy == LL_PER_SCAN_FILTER_PL_BIT)
|
||||
{
|
||||
if ((BbBlePeriodicListCheckAddr((peerIdAddrType & LL_ADDR_RANDOM_BIT), peerIdAddr,
|
||||
pExtScanCtx->extAdvHdr.sid)) == FALSE)
|
||||
{
|
||||
/* Not in the periodic list. */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
lctrMstPerScanIsr.filtResult = FALSE;
|
||||
advAMatch = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((lctrPerCreateSync.filtParam.advSID != pExtScanCtx->extAdvHdr.sid) ||
|
||||
(lctrPerCreateSync.filtParam.advAddrType != (peerIdAddrType & LL_ADDR_RANDOM_BIT)) ||
|
||||
(lctrPerCreateSync.filtParam.advAddr != peerIdAddr))
|
||||
{
|
||||
/* Address type, address or SID does not match. */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
lctrMstPerScanIsr.filtResult = FALSE;
|
||||
advAMatch = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pExtScanCtx->extAdvHdr.extHdrFlags & LL_EXT_HDR_SYNC_INFO_BIT)
|
||||
{
|
||||
lctrUnpackSyncInfo(&pExtScanCtx->secSyncInfo, pExtScanCtx->extAdvHdr.pSyncInfo);
|
||||
}
|
||||
|
||||
if ((lctrPerCreateSync.state == LCTR_CREATE_SYNC_STATE_DISCOVER) &&
|
||||
(lctrMstPerScanIsr.filtResult == FALSE) &&
|
||||
(pExtScanCtx->extAdvHdr.extHdrFlags & LL_EXT_HDR_SYNC_INFO_BIT) &&
|
||||
lctrPerCreateSync.createSyncPending == FALSE)
|
||||
{
|
||||
lctrPerScanCtx_t *pPerScanCtx = lctrPerCreateSync.pPerScanCtx;
|
||||
/*** Save peer periodic advertising parameters. ***/
|
||||
pPerScanCtx->eventCounter = pExtScanCtx->secSyncInfo.eventCounter;
|
||||
pPerScanCtx->initEventCounter = pExtScanCtx->secSyncInfo.eventCounter;
|
||||
pPerScanCtx->perInterUsec = LCTR_PER_INTER_TO_US(pExtScanCtx->secSyncInfo.syncInter);
|
||||
pPerScanCtx->sca = pExtScanCtx->secSyncInfo.sca;
|
||||
pPerScanCtx->rxPhys = lctrConvertAuxPtrPhyToBbPhy(pExtScanCtx->priChAuxPtr.auxPhy);
|
||||
pPerScanCtx->skipInterUsec = pPerScanCtx->perInterUsec * pPerScanCtx->skip;
|
||||
|
||||
if (advAMatch == TRUE)
|
||||
{
|
||||
/* AdvA is received in the aux_adv_ind and pass the filtering, save info in the context. */
|
||||
pPerScanCtx->advAddr = peerIdAddr;
|
||||
pPerScanCtx->advAddrType = peerIdAddrType;
|
||||
pPerScanCtx->advSID = pExtScanCtx->extAdvHdr.sid;
|
||||
|
||||
/* Address to be used for sync transfer. */
|
||||
pPerScanCtx->trsfAdvAddr = pExtScanCtx->extAdvHdr.advAddr;
|
||||
pPerScanCtx->trsfAddrType = lctrMstExtScanIsr.advHdr.txAddrRnd;
|
||||
}
|
||||
|
||||
uint32_t endTs = pAuxScan->auxStartTsUsec +
|
||||
SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, pAuxScan->auxRxPhyOptions, pAuxScan->txAuxReqLen);
|
||||
lctrMstPerScanOpCommit(pExtScanCtx, &pExtScanCtx->priChAuxPtr, &pExtScanCtx->secSyncInfo, pAuxScan->auxStartTsUsec, endTs);
|
||||
lctrMstPerScanIsr.syncWithSlave = FALSE;
|
||||
}
|
||||
/*** Periodic advertising event filtering done in post process. ***/
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1398,6 +1349,131 @@ bool_t lctrMstDiscoverRxAuxAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf
|
|||
return txScanReq;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Auxiliary scan discover state advertising packet receive
|
||||
* post process handler.
|
||||
*
|
||||
* \param pOp Originating operation.
|
||||
* \param pAdvBuf Received advertising buffer.
|
||||
*
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void lctrMstDiscoverRxAuxAdvPktPostProcessHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf)
|
||||
{
|
||||
WSF_ASSERT(pOp->protId == BB_PROT_BLE);
|
||||
WSF_ASSERT(pOp->prot.pBle->chan.opType == BB_BLE_OP_MST_AUX_ADV_EVENT);
|
||||
|
||||
BbBleData_t * const pBle = pOp->prot.pBle;
|
||||
BbBleMstAuxAdvEvent_t * const pAuxScan = &pBle->op.mstAuxAdv;
|
||||
lctrExtScanCtx_t * pExtScanCtx = pOp->pCtx;
|
||||
|
||||
/*** Periodic advertising event filtering. ***/
|
||||
|
||||
switch (lctrMstExtScanIsr.advHdr.pduType)
|
||||
{
|
||||
case LL_PDU_AUX_ADV_IND:
|
||||
{
|
||||
bool_t advAMatch = FALSE;
|
||||
uint64_t peerIdAddr = 0;
|
||||
uint8_t peerIdAddrType = 0;
|
||||
|
||||
BbBlePduFiltResultsGetPeerIdAddr(&pAuxScan->filtResults, &peerIdAddr, &peerIdAddrType);
|
||||
|
||||
if ((lctrPerCreateSync.state == LCTR_CREATE_SYNC_STATE_DISCOVER) &&
|
||||
(lctrMstPerScanIsr.filtResult == FALSE))
|
||||
{
|
||||
if ((lctrPerCreateSync.filtParam.advSID != pExtScanCtx->extAdvHdr.sid) ||
|
||||
(lctrPerCreateSync.filtParam.advAddrType != (peerIdAddrType & LL_ADDR_RANDOM_BIT)) ||
|
||||
(lctrPerCreateSync.filtParam.advAddr != peerIdAddr))
|
||||
{
|
||||
/* Address type, address or SID does not match. */
|
||||
lctrMstPerScanIsr.filtResult = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((lctrPerCreateSync.state == LCTR_CREATE_SYNC_STATE_DISCOVER) &&
|
||||
(lctrMstPerScanIsr.filtResult == TRUE) &&
|
||||
(lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_ADI_BIT) &&
|
||||
((lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_ADV_ADDR_BIT) ||
|
||||
(lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_SYNC_INFO_BIT)))
|
||||
{
|
||||
if (lctrPerCreateSync.filtParam.filterPolicy == LL_PER_SCAN_FILTER_PL_BIT)
|
||||
{
|
||||
if ((BbBlePeriodicListCheckAddr((peerIdAddrType & LL_ADDR_RANDOM_BIT), peerIdAddr,
|
||||
pExtScanCtx->extAdvHdr.sid)) == FALSE)
|
||||
{
|
||||
/* Not in the periodic list. */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
lctrMstPerScanIsr.filtResult = FALSE;
|
||||
advAMatch = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((lctrPerCreateSync.filtParam.advSID != pExtScanCtx->extAdvHdr.sid) ||
|
||||
(lctrPerCreateSync.filtParam.advAddrType != (peerIdAddrType & LL_ADDR_RANDOM_BIT)) ||
|
||||
(lctrPerCreateSync.filtParam.advAddr != peerIdAddr))
|
||||
{
|
||||
/* Address type, address or SID does not match. */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
lctrMstPerScanIsr.filtResult = FALSE;
|
||||
advAMatch = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pExtScanCtx->extAdvHdr.extHdrFlags & LL_EXT_HDR_SYNC_INFO_BIT)
|
||||
{
|
||||
lctrUnpackSyncInfo(&pExtScanCtx->secSyncInfo, pExtScanCtx->extAdvHdr.pSyncInfo);
|
||||
}
|
||||
|
||||
if ((lctrPerCreateSync.state == LCTR_CREATE_SYNC_STATE_DISCOVER) &&
|
||||
(lctrMstPerScanIsr.filtResult == FALSE) &&
|
||||
(pExtScanCtx->extAdvHdr.extHdrFlags & LL_EXT_HDR_SYNC_INFO_BIT) &&
|
||||
lctrPerCreateSync.createSyncPending == FALSE)
|
||||
{
|
||||
lctrPerScanCtx_t *pPerScanCtx = lctrPerCreateSync.pPerScanCtx;
|
||||
/* Save peer periodic advertising parameters. */
|
||||
pPerScanCtx->eventCounter = pExtScanCtx->secSyncInfo.eventCounter;
|
||||
pPerScanCtx->initEventCounter = pExtScanCtx->secSyncInfo.eventCounter;
|
||||
pPerScanCtx->perInterUsec = LCTR_PER_INTER_TO_US(pExtScanCtx->secSyncInfo.syncInter);
|
||||
pPerScanCtx->sca = pExtScanCtx->secSyncInfo.sca;
|
||||
pPerScanCtx->rxPhys = lctrConvertAuxPtrPhyToBbPhy(pExtScanCtx->priChAuxPtr.auxPhy);
|
||||
pPerScanCtx->skipInterUsec = pPerScanCtx->perInterUsec * pPerScanCtx->skip;
|
||||
|
||||
if (advAMatch == TRUE)
|
||||
{
|
||||
/* AdvA is received in the aux_adv_ind and pass the filtering, save info in the context. */
|
||||
pPerScanCtx->advAddr = peerIdAddr;
|
||||
pPerScanCtx->advAddrType = peerIdAddrType;
|
||||
pPerScanCtx->advSID = pExtScanCtx->extAdvHdr.sid;
|
||||
|
||||
/* Address to be used for sync transfer. */
|
||||
pPerScanCtx->trsfAdvAddr = pExtScanCtx->extAdvHdr.advAddr;
|
||||
pPerScanCtx->trsfAddrType = lctrMstExtScanIsr.advHdr.txAddrRnd;
|
||||
}
|
||||
|
||||
uint32_t endTs = pAuxScan->auxStartTsUsec +
|
||||
SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, pAuxScan->auxRxPhyOptions, pAuxScan->txAuxReqLen);
|
||||
lctrMstPerScanOpCommit(pExtScanCtx, &pExtScanCtx->priChAuxPtr, &pExtScanCtx->secSyncInfo, pAuxScan->auxStartTsUsec, endTs);
|
||||
lctrMstPerScanIsr.syncWithSlave = FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
LL_TRACE_WARN1("Received advertising PDU with invalid PDU type=%u", lctrMstExtScanIsr.advHdr.pduType);
|
||||
lctrMstExtScanIsr.filtResult = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Master auxiliary scan response receive completion handler.
|
||||
|
@ -1969,6 +2045,10 @@ void lctrMstExtDiscoverEndOp(BbOpDesc_t *pOp)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Clear Aux Scan BOD link. */
|
||||
pExtScanCtx->scanBleData.op.mstAdv.auxScanOpRunning = FALSE;
|
||||
pExtScanCtx->scanBleData.op.mstAdv.auxScanBod = NULL;
|
||||
|
||||
WSF_ASSERT(pOp->protId == BB_PROT_BLE);
|
||||
WSF_ASSERT(pOp->prot.pBle->chan.opType == BB_BLE_OP_MST_ADV_EVENT);
|
||||
|
||||
|
@ -2102,7 +2182,7 @@ void lctrMstPerScanEndOp(BbOpDesc_t *pOp)
|
|||
skip = 1;
|
||||
}
|
||||
|
||||
uint16_t numUnsyncIntervals = pPerScanCtx->eventCounter - pPerScanCtx->lastActiveEvent;
|
||||
uint16_t numUnsyncIntervals = pPerScanCtx->eventCounter - pPerScanCtx->lastActiveEvent;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
|
@ -2156,6 +2236,8 @@ void lctrMstPerScanAbortOp(BbOpDesc_t *pOp)
|
|||
{
|
||||
lctrPerScanCtx_t * const pPerScanCtx = pOp->pCtx;
|
||||
|
||||
LL_TRACE_WARN2("!!! Periodic Scan BOD aborted, syncHandle=%u, eventCounter=%u", LCTR_GET_PER_SCAN_HANDLE(pPerScanCtx), pPerScanCtx->eventCounter);
|
||||
|
||||
pPerScanCtx->bodAborted = TRUE;
|
||||
lctrMstPerScanEndOp(pOp);
|
||||
}
|
||||
|
@ -2179,6 +2261,23 @@ uint32_t lctrMstPerScanRxPerAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBu
|
|||
BbBleData_t * const pBle = pOp->prot.pBle;
|
||||
lctrPerScanCtx_t * const pPerScanCtx = pOp->pCtx;
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case BB_STATUS_SUCCESS:
|
||||
break;
|
||||
case BB_STATUS_CRC_FAILED:
|
||||
LL_TRACE_WARN3("lctrMstPerScanRxPerAdvPktHandler: BB failed with status=CRC_FAILED, syncHandle=%u, bleChan=%u, eventCounter=%u", LCTR_GET_PER_SCAN_HANDLE(pPerScanCtx), pBle->chan.chanIdx, pPerScanCtx->eventCounter);
|
||||
break;
|
||||
case BB_STATUS_RX_TIMEOUT:
|
||||
LL_TRACE_WARN3("lctrMstPerScanRxPerAdvPktHandler: BB failed with status=RX_TIMEOUT, syncHandle=%u, bleChan=%u, eventCounter=%u", LCTR_GET_PER_SCAN_HANDLE(pPerScanCtx), pBle->chan.chanIdx, pPerScanCtx->eventCounter);
|
||||
break;
|
||||
case BB_STATUS_FAILED:
|
||||
LL_TRACE_WARN3("lctrMstPerScanRxPerAdvPktHandler: BB failed with status=FAILED, syncHandle=%u, bleChan=%u, eventCounter=%u", LCTR_GET_PER_SCAN_HANDLE(pPerScanCtx), pBle->chan.chanIdx, pPerScanCtx->eventCounter);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* BB_STATUS_RX_TIMEOUT or BB_STATUS_CRC_FAILED with pAdvBuf NULL. */
|
||||
if (pAdvBuf == NULL)
|
||||
{
|
||||
|
@ -2216,7 +2315,7 @@ uint32_t lctrMstPerScanRxPerAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBu
|
|||
lctrMstPerScanIsr.syncWithSlave = TRUE;
|
||||
}
|
||||
|
||||
/*** ACAD processing. ***/
|
||||
/*** ACAD processing ***/
|
||||
|
||||
lctrMstAcadHandler(pPerScanCtx);
|
||||
|
||||
|
@ -2242,7 +2341,20 @@ uint32_t lctrMstPerScanRxPerAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBu
|
|||
}
|
||||
}
|
||||
|
||||
/*** Periodic Advertising Data processing. ***/
|
||||
/*** ADI Filtering. ***/
|
||||
|
||||
if (pPerScanCtx->dupFilterEnable && (lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_ADI_BIT))
|
||||
{
|
||||
/* Duplicate data; do not listen further. */
|
||||
if (pPerScanCtx->extAdvHdr.did == pPerScanCtx->lastDid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pPerScanCtx->lastDid = pPerScanCtx->extAdvHdr.did; */ /* Done in lctrMstPerScanRxPerAdvPktPostHandler() */
|
||||
}
|
||||
|
||||
/*** Periodic Advertising Data processing ***/
|
||||
|
||||
uint32_t auxOffsetUsec = 0;
|
||||
if (lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_AUX_PTR_BIT)
|
||||
|
@ -2278,6 +2390,20 @@ bool_t lctrMstPerScanRxPerAdvPktPostHandler(BbOpDesc_t *pOp, const uint8_t *pAdv
|
|||
if (pPerScanCtx->state == LCTR_PER_SCAN_STATE_SYNC_ESTD)
|
||||
{
|
||||
WsfTimerStartMs(&pPerScanCtx->tmrSupTimeout, pPerScanCtx->syncTimeOutMs);
|
||||
|
||||
if (pPerScanCtx->dupFilterEnable)
|
||||
{
|
||||
if (lctrMstExtScanIsr.extAdvHdrFlags & LL_EXT_HDR_ADI_BIT)
|
||||
{
|
||||
/* Received this data before, do not listen further. */
|
||||
if (pPerScanCtx->extAdvHdr.did == pPerScanCtx->lastDid)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pPerScanCtx->lastDid = pPerScanCtx->extAdvHdr.did;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* BB_STATUS_RX_TIMEOUT or BB_STATUS_CRC_FAILED with pAdvBuf NULL. */
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -476,7 +476,6 @@ bool_t lctrSlvRxAuxConnReqHandler(BbOpDesc_t *pOp, const uint8_t *pReqBuf)
|
|||
|
||||
pAdvSet->rspPduHdr.txAddrRnd = (hdr >> LCTR_ADV_HDR_TX_ADD_SHIFT) & 0x0001;
|
||||
pAdvSet->rspPduHdr.rxAddrRnd = (hdr >> LCTR_ADV_HDR_RX_ADD_SHIFT) & 0x0001;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -696,19 +695,16 @@ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp)
|
|||
/* Disable (do not reschedule) advertising PDU. */
|
||||
pAdvSet->shutdown = TRUE;
|
||||
|
||||
if (pAdvSet->auxBodUsed &&
|
||||
(pAdvSet->bodTermCnt++ == 0))
|
||||
if (pAdvSet->auxBodUsed)
|
||||
{
|
||||
pAdvSet->auxBodUsed = FALSE;
|
||||
/* Ensure all BODs are de-scheduled. */
|
||||
bool_t result = SchRemove(&pAdvSet->auxAdvBod);
|
||||
SchRemove(&pAdvSet->auxAdvBod);
|
||||
}
|
||||
|
||||
/* Last BOD to terminate; send terminate event. */
|
||||
lctrSendAdvSetMsg(pAdvSet, LCTR_EXT_ADV_MSG_TERMINATE);
|
||||
|
||||
(void)result;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Last BOD to terminate; send terminate event. */
|
||||
lctrSendAdvSetMsg(pAdvSet, LCTR_EXT_ADV_MSG_TERMINATE);
|
||||
}
|
||||
return;
|
||||
|
||||
} while (FALSE);
|
||||
|
@ -728,18 +724,23 @@ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp)
|
|||
|
||||
if ((pAdvSet->param.advEventProp & LL_ADV_EVT_PROP_LEGACY_ADV_BIT) == 0)
|
||||
{
|
||||
/* Update superior PDU including AdvA and TgtA. */
|
||||
pAdv->txAdvLen = lctrPackAdvExtIndPdu(pAdvSet, pAdvSet->advHdrBuf, FALSE);
|
||||
bool_t modified = pAdvSet->advData.alt.ext.modified;
|
||||
|
||||
if (pAdvSet->advData.alt.ext.modified &&
|
||||
!pAdvSet->auxBodUsed)
|
||||
/* Update ADV set before building the PDU. */
|
||||
if (pAdvSet->advData.alt.ext.modified)
|
||||
{
|
||||
pAdvSet->advData.alt.ext.modified = FALSE;
|
||||
memcpy(pAdvSet->advData.pBuf, pAdvSet->advData.alt.ext.buf, pAdvSet->advData.alt.ext.len);
|
||||
pAdvSet->advData.len = pAdvSet->advData.alt.ext.len;
|
||||
pAdvSet->param.advDID = pAdvSet->advData.alt.ext.did;
|
||||
pAdvSet->advData.fragPref = pAdvSet->advData.alt.ext.fragPref;
|
||||
}
|
||||
|
||||
/* Update superior PDU including AdvA and TgtA. */
|
||||
pAdv->txAdvLen = lctrPackAdvExtIndPdu(pAdvSet, pAdvSet->advHdrBuf, FALSE);
|
||||
|
||||
if (modified && !pAdvSet->auxBodUsed)
|
||||
{
|
||||
/* Advertising offloading to auxiliary channel. */
|
||||
if (pAdvSet->pExtAdvAuxPtr)
|
||||
{
|
||||
|
@ -912,11 +913,6 @@ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp)
|
|||
uint32_t totalDuration = pOp->minDurUsec;
|
||||
uint32_t prefIntervalUsec;
|
||||
|
||||
if (lmgrGetOpFlag(LL_OP_MODE_FLAG_ENA_ADV_DLY))
|
||||
{
|
||||
pOp->dueUsec += BB_BLE_TO_US(lctrCalcAdvDelay());
|
||||
}
|
||||
|
||||
if (pAdvSet->auxBodUsed)
|
||||
{
|
||||
totalDuration += pAdvSet->auxAdvBod.minDurUsec;
|
||||
|
@ -928,10 +924,16 @@ void lctrSlvExtAdvEndOp(BbOpDesc_t *pOp)
|
|||
if (pAdvSet->advBodAbort)
|
||||
{
|
||||
pAdvSet->advBodAbort = FALSE;
|
||||
(void)SchInsertEarlyAsPossible(pOp, 0, LCTR_SCH_MAX_SPAN);
|
||||
SchInsertNextAvailable(pOp);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lmgrGetOpFlag(LL_OP_MODE_FLAG_ENA_ADV_DLY))
|
||||
{
|
||||
pOp->dueUsec += BB_BLE_TO_US(lctrCalcAdvDelay());
|
||||
}
|
||||
|
||||
/* Scheduling must succeed with LCTR_SCH_MAX_SPAN. */
|
||||
(void)SchInsertEarlyAsPossible(pOp, prefIntervalUsec, LCTR_SCH_MAX_SPAN);
|
||||
}
|
||||
}
|
||||
|
@ -986,18 +988,12 @@ void lctrSlvAuxAdvEndOp(BbOpDesc_t *pOp)
|
|||
pAdvSet->shutdown = TRUE;
|
||||
pAdvSet->auxBodUsed = FALSE;
|
||||
|
||||
if (pAdvSet->bodTermCnt++ == 0)
|
||||
{
|
||||
/* Ensure all BODs are de-scheduled. */
|
||||
bool_t result = SchRemove(&pAdvSet->advBod);
|
||||
/* Ensure all BODs are de-scheduled. */
|
||||
SchRemove(&pAdvSet->advBod);
|
||||
|
||||
/* Last BOD to terminate; send terminate event. */
|
||||
lctrSendAdvSetMsg(pAdvSet, LCTR_EXT_ADV_MSG_TERMINATE);
|
||||
|
||||
(void)result; /* It is possible to fail to remove BOD when BOD is not in the list(scheduling conflict) or there is not enough time to remove the BOD. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Last BOD to terminate; send terminate event. */
|
||||
lctrSendAdvSetMsg(pAdvSet, LCTR_EXT_ADV_MSG_TERMINATE);
|
||||
}
|
||||
return;
|
||||
|
||||
} while (FALSE);
|
||||
|
@ -1107,6 +1103,7 @@ void lctrSlvPeriodicAdvEndOp(BbOpDesc_t *pOp)
|
|||
pAdvSet->perAdvData.alt.ext.modified = FALSE;
|
||||
memcpy(pAdvSet->perAdvData.pBuf, pAdvSet->perAdvData.alt.ext.buf, pAdvSet->perAdvData.alt.ext.len);
|
||||
pAdvSet->perAdvData.len = pAdvSet->perAdvData.alt.ext.len;
|
||||
pAdvSet->perParam.advDID = pAdvSet->perAdvData.alt.ext.did;
|
||||
}
|
||||
|
||||
/*** Update operation ***/
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -120,12 +120,6 @@ static void lctrMstBigControlEncrypt(lctrBigCtx_t *pBigCtx)
|
|||
uint64_t pktCtr = pBigCtx->eventCounter * pBigCtx->bn;
|
||||
pBigCtx->ctrChan.enc.pTxPktCounter = &pktCtr;
|
||||
|
||||
/* Set the new packet counter for inline encryption. */
|
||||
if (lctrSetEncryptPktCountHdlr)
|
||||
{
|
||||
lctrSetEncryptPktCountHdlr(&pBigCtx->ctrChan.enc, pktCtr);
|
||||
}
|
||||
|
||||
if (pBigCtx->encrypt && lctrPktEncryptHdlr)
|
||||
{
|
||||
uint16_t len = lctrSlvBisIsr.pCtrlBuf[LCTR_ISO_DATA_PDU_LEN_OFFSET];
|
||||
|
@ -174,6 +168,13 @@ static void lctrSlvBisTxControl(lctrBigCtx_t *pBigCtx)
|
|||
LCTR_BIS_WR_CSSN(desc.pBuf[LCTR_ISO_DATA_PDU_FC_OFFSET], pBigCtx->bcp.cssn);
|
||||
LCTR_BIS_CLR_CSTF(desc.pBuf[LCTR_ISO_DATA_PDU_FC_OFFSET]);
|
||||
|
||||
/* Set the control packet counter for inline encryption. */
|
||||
if (pBigCtx->encrypt && lctrSetEncryptPktCountHdlr)
|
||||
{
|
||||
uint64_t pktCtr = pBigCtx->eventCounter * pBigCtx->bn;
|
||||
lctrSetEncryptPktCountHdlr(pktCtr);
|
||||
}
|
||||
|
||||
BbBleBisTxData(&desc, 1, 0, NULL);
|
||||
}
|
||||
|
||||
|
@ -242,6 +243,13 @@ static void lctrSlvBisTxData(lctrBigCtx_t *pBigCtx)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* set the inline encryption packet counter to the current bisPayloadCounter */
|
||||
if (pBigCtx->encrypt && lctrSetEncryptPktCountHdlr)
|
||||
{
|
||||
uint64_t pktCtr = (pBigCtx->eventCounter * pBigCtx->bn) + lctrSlvBisIsr.se.burstIdx;
|
||||
lctrSetEncryptPktCountHdlr(pktCtr);
|
||||
}
|
||||
|
||||
BbBleBisTxData(pTxDesc, descCnt,
|
||||
pBigCtx->bod.dueUsec + lctrSlvBisIsr.nextSeOffs,
|
||||
lctrSlvBisIsr.pNextChan);
|
||||
|
@ -480,7 +488,7 @@ void lctrSlvBisTxCompletionSequential(BbOpDesc_t *pOp, uint8_t status)
|
|||
|
||||
size_t numSePkts = (pBigCtx->bn * pBigCtx->irc) + lctrSlvBisIsr.se.ptIdx;
|
||||
|
||||
if (!lctrSlvBisCalcNextIdxSequential(pBigCtx, &lctrSlvBisIsr.se, numSePkts))
|
||||
if (!lctrBisCalcNextIdxSequential(pBigCtx, &lctrSlvBisIsr.se, numSePkts))
|
||||
{
|
||||
if (lctrSlvBisIsr.pCtrlBuf)
|
||||
{
|
||||
|
@ -495,13 +503,20 @@ void lctrSlvBisTxCompletionSequential(BbOpDesc_t *pOp, uint8_t status)
|
|||
|
||||
/* Compute next channel. */
|
||||
lctrSeCtx_t nextSe = lctrSlvBisIsr.se;
|
||||
if (lctrSlvBisCalcNextIdxSequential(pBigCtx, &nextSe, numSePkts))
|
||||
if (lctrBisCalcNextIdxSequential(pBigCtx, &nextSe, numSePkts))
|
||||
{
|
||||
lctrSlvBisIsr.pNextChan = &pBigCtx->pBisCtx[nextSe.bisEvtIdx]->chan;
|
||||
}
|
||||
else
|
||||
{
|
||||
lctrSlvBisIsr.pNextChan = &pBigCtx->ctrChan;
|
||||
if (lctrSlvBisIsr.pCtrlBuf == NULL)
|
||||
{
|
||||
lctrSlvBisIsr.pNextChan = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
lctrSlvBisIsr.pNextChan = &pBigCtx->ctrChan;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute next packet time. */
|
||||
|
@ -542,7 +557,7 @@ void lctrSlvBisTxCompletionInterleaved(BbOpDesc_t *pOp, uint8_t status)
|
|||
|
||||
/* BIS loop. */
|
||||
|
||||
if (!lctrSlvBisCalcNextIdxInterleaved(pBigCtx, &lctrSlvBisIsr.se, numSePkts))
|
||||
if (!lctrBisCalcNextIdxInterleaved(pBigCtx, &lctrSlvBisIsr.se, numSePkts))
|
||||
{
|
||||
if (lctrSlvBisIsr.pCtrlBuf)
|
||||
{
|
||||
|
@ -558,13 +573,20 @@ void lctrSlvBisTxCompletionInterleaved(BbOpDesc_t *pOp, uint8_t status)
|
|||
|
||||
/* Compute next channel. */
|
||||
lctrSeCtx_t nextSe = lctrSlvBisIsr.se;
|
||||
if (lctrSlvBisCalcNextIdxInterleaved(pBigCtx, &nextSe, numSePkts))
|
||||
if (lctrBisCalcNextIdxInterleaved(pBigCtx, &nextSe, numSePkts))
|
||||
{
|
||||
lctrSlvBisIsr.pNextChan = &pBigCtx->pBisCtx[nextSe.bisEvtIdx]->chan;
|
||||
}
|
||||
else
|
||||
{
|
||||
lctrSlvBisIsr.pNextChan = &pBigCtx->ctrChan;
|
||||
if (lctrSlvBisIsr.pCtrlBuf == NULL)
|
||||
{
|
||||
lctrSlvBisIsr.pNextChan = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
lctrSlvBisIsr.pNextChan = &pBigCtx->ctrChan;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute next packet time. */
|
||||
|
@ -724,10 +746,29 @@ void lctrSlvBigEndOp(BbOpDesc_t *pOp)
|
|||
LL_TRACE_WARN2("!!! BIG schedule conflict handle=%u, ec[15:0]=%u", pBigCtx->handle, pBigCtx->eventCounter);
|
||||
}
|
||||
|
||||
/* SDU generator. */
|
||||
/* SDU input. */
|
||||
|
||||
lctrSlvBisTxTestPayloadHandler(pBigCtx);
|
||||
|
||||
for (unsigned int i = 0; i < pBigCtx->numBis; i++)
|
||||
{
|
||||
lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[i];
|
||||
|
||||
if (pBisCtx->roleData.slv.dataPathInCtx.id == LL_ISO_DATA_PATH_VS)
|
||||
{
|
||||
uint8_t *pSduBuf;
|
||||
if ((pSduBuf = WsfMsgAlloc(pLctrRtCfg->maxIsoSduLen + HCI_ISO_DL_MAX_LEN)) != NULL)
|
||||
{
|
||||
WSF_ASSERT(lctrCodecHdlr.inReq);
|
||||
lctrCodecHdlr.inReq(pBisCtx->handle, pSduBuf + HCI_ISO_HDR_LEN + HCI_ISO_DL_MAX_LEN, pBigCtx->maxSdu);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_WARN1("!!! Out of memory; dropping input SDU, handle=%u", pBisCtx->handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update BIG Info. */
|
||||
|
||||
lctrAdvSet_t * const pAdvSet = pBigCtx->roleData.slv.pAdvSet;
|
||||
|
@ -740,9 +781,13 @@ void lctrSlvBigEndOp(BbOpDesc_t *pOp)
|
|||
|
||||
/* SDU queue maintenance. */
|
||||
|
||||
if (pBigCtx->framing == LL_ISO_PDU_TYPE_FRAMED)
|
||||
switch (pBigCtx->framing)
|
||||
{
|
||||
lctrSlvCheckPendingSdu(pBigCtx);
|
||||
case LL_ISO_PDU_TYPE_FRAMED:
|
||||
lctrSlvCheckPendingSdu(pBigCtx);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Notifications. */
|
||||
|
@ -765,7 +810,10 @@ void lctrSlvBigAbortOp(BbOpDesc_t *pOp)
|
|||
WSF_ASSERT(pOp->protId == BB_PROT_BLE);
|
||||
WSF_ASSERT(pOp->prot.pBle->chan.opType == BB_BLE_OP_SLV_BIS_EVENT);
|
||||
|
||||
LL_TRACE_WARN1("BIG BOD aborted, eventCounter=%u", ((lctrBigCtx_t *)pOp->pCtx)->eventCounter);
|
||||
LL_TRACE_WARN1("!!! BIG Broadcaster BOD aborted, eventCounter=%u", ((lctrBigCtx_t *)pOp->pCtx)->eventCounter);
|
||||
|
||||
/* Clear state since abort is called without lctrMstBigBeginOp() initializing state. */
|
||||
memset(&lctrSlvBisIsr, 0, sizeof(lctrSlvBisIsr));
|
||||
|
||||
lctrSlvBigEndOp(pOp);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 ARM Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -120,9 +120,9 @@ bool_t lctrCisProcessRxAck(lctrCisCtx_t *pCisCtx)
|
|||
{
|
||||
bool_t result = FALSE;
|
||||
|
||||
/* Nulls must not be ACKed. */
|
||||
if (pCisCtx->rxHdr.np == 1)
|
||||
{
|
||||
/* NULL PDU doesn't need to be acked or processed.*/
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,10 @@ bool_t lctrCisProcessRxAck(lctrCisCtx_t *pCisCtx)
|
|||
if ((pCisCtx->rxHdr.len) ||
|
||||
((pCisCtx->rxHdr.len == 0) && (pCisCtx->rxHdr.llid == LL_LLID_ISO_UNF_END_PDU)))
|
||||
{
|
||||
/* lctrCisIncPacketCounterRx(pCisCtx) */ /* done after decryption in lctrCisRxPendingHandler */
|
||||
if (lctrSetDecryptPktCountHdlr)
|
||||
{
|
||||
lctrCisIncPacketCounterRx(pCisCtx);
|
||||
}
|
||||
result = TRUE;
|
||||
}
|
||||
else /* Empty PDU. */
|
||||
|
@ -152,7 +155,10 @@ bool_t lctrCisProcessRxAck(lctrCisCtx_t *pCisCtx)
|
|||
/* length of 0 and LLID of LL_LLID_EMPTY_PDU implies padding/empty PDU. */
|
||||
|
||||
pCisCtx->txHdr.nesn++;
|
||||
pCisCtx->rxFtParamList.pHead->ftParam.pduRcved = TRUE;
|
||||
if (pCisCtx->rxFtParamList.pHead != NULL)
|
||||
{
|
||||
pCisCtx->rxFtParamList.pHead->ftParam.pduRcved = TRUE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -191,10 +197,9 @@ void lctrCisTxPduAck(lctrCisCtx_t *pCisCtx)
|
|||
/*************************************************************************************************/
|
||||
bool_t lctrCisProcessTxAck(lctrCisCtx_t *pCisCtx)
|
||||
{
|
||||
if (((pCisCtx->rxHdr.nesn ^ pCisCtx->txHdr.sn) & 1) == 1) /* bits are different */
|
||||
if (((pCisCtx->rxHdr.nesn ^ pCisCtx->dataSn) & 1) == 1) /* bits are different */
|
||||
{
|
||||
pCisCtx->txHdr.sn++;
|
||||
|
||||
pCisCtx->dataSn++;
|
||||
|
||||
if (pCisCtx->txBufPendAck)
|
||||
{
|
||||
|
@ -205,11 +210,13 @@ bool_t lctrCisProcessTxAck(lctrCisCtx_t *pCisCtx)
|
|||
else
|
||||
{
|
||||
/*** Peer ACK'ed an Empty PDU ***/
|
||||
|
||||
pCisCtx->txDataCounter++;
|
||||
}
|
||||
|
||||
pCisCtx->txFtParamList.pHead->ftParam.pduAcked = TRUE;
|
||||
if (pCisCtx->txFtParamList.pHead != NULL)
|
||||
{
|
||||
pCisCtx->txFtParamList.pHead->ftParam.pduAcked = TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -276,6 +283,7 @@ uint16_t lctrCisSetupForTx(lctrCigCtx_t *pCigCtx, uint8_t rxStatus, bool_t reqTx
|
|||
pCisCtx->txHdr.np = 0;
|
||||
pCisCtx->txHdr.len = 0;
|
||||
pCisCtx->txHdr.llid = LL_LLID_ISO_UNF_END_PDU;
|
||||
pCisCtx->txHdr.sn = pCisCtx->dataSn;
|
||||
|
||||
if ((rxStatus != BB_STATUS_SUCCESS) ||
|
||||
reqTx)
|
||||
|
@ -312,6 +320,7 @@ uint16_t lctrCisSetupForTx(lctrCigCtx_t *pCigCtx, uint8_t rxStatus, bool_t reqTx
|
|||
bbDesc[0].pBuf[0] ^= llTesterCb.pktLlId & 0x03;
|
||||
#endif
|
||||
|
||||
lctrSetBbCisPacketCounterTx(pCisCtx);
|
||||
BbBleCisTxData(&bbDesc[0], bbDescCnt);
|
||||
numTxBytes = LL_DATA_HDR_LEN + bbDesc[0].pBuf[LCTR_ISO_DATA_PDU_LEN_OFFSET];
|
||||
|
||||
|
@ -325,7 +334,10 @@ uint16_t lctrCisSetupForTx(lctrCigCtx_t *pCigCtx, uint8_t rxStatus, bool_t reqTx
|
|||
/*** Send Empty PDU ***/
|
||||
|
||||
lctrCisBuildEmptyPdu(pCisCtx);
|
||||
pFtParam->pduType[pFtParam->pduCounter] = LCTR_CIS_PDU_EMPTY;
|
||||
if (pFtParam != NULL)
|
||||
{
|
||||
pFtParam->pduType[pFtParam->pduCounter] = LCTR_CIS_PDU_EMPTY;
|
||||
}
|
||||
|
||||
PalBbBleTxBufDesc_t desc = {.pBuf = lctrCisIsr.emptyPdu, .len = sizeof(lctrCisIsr.emptyPdu)};
|
||||
BbBleCisTxData(&desc, 1);
|
||||
|
@ -347,12 +359,12 @@ uint16_t lctrCisSetupForTx(lctrCigCtx_t *pCigCtx, uint8_t rxStatus, bool_t reqTx
|
|||
/*************************************************************************************************/
|
||||
void lctrCisRxPostProcessing(lctrCisCtx_t *pCisCtx, uint8_t *pRxBuf)
|
||||
{
|
||||
if (pCisCtx->validRx) /* Another buffer ready to replace the received one. */
|
||||
{
|
||||
lctrCisRxEnq(pRxBuf, pCisCtx->cisEvtCounter, pCisCtx->cisHandle);
|
||||
}
|
||||
else
|
||||
if (!pCisCtx->validRx && (pRxBuf != NULL)) /* Another buffer ready to replace the received one. */
|
||||
{
|
||||
lctrCisRxPduFree(pRxBuf);
|
||||
pRxBuf = NULL;
|
||||
}
|
||||
|
||||
/* Notify the task */
|
||||
lctrCisRxEnq(pRxBuf, pCisCtx->cisEvtCounter, pCisCtx->cisHandle);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -70,16 +70,28 @@ static void lctrMstCisInitIsr(lctrCisCtx_t *pCisCtx)
|
|||
pCisCtx->txDataCounter = 0;
|
||||
pCisCtx->rxDataCounter = 0;
|
||||
|
||||
pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter = 0;
|
||||
pCisCtx->rxFtParamList.pHead->ftParam.subEvtCounter = 0;
|
||||
|
||||
if (pCisCtx->txFtParamList.pHead->ftParam.bn == 0)
|
||||
/* List may be empty if BN_S_To_M is 0 */
|
||||
if (pCisCtx->rxFtParamList.pHead != NULL)
|
||||
{
|
||||
pCisCtx->isTxDone = TRUE;
|
||||
pCisCtx->rxFtParamList.pHead->ftParam.subEvtCounter = 0;
|
||||
}
|
||||
|
||||
/* List may be empty if BN_M_To_S is 0 */
|
||||
if (pCisCtx->txFtParamList.pHead != NULL)
|
||||
{
|
||||
pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter = 0;
|
||||
if (pCisCtx->txFtParamList.pHead->ftParam.bn == 0)
|
||||
{
|
||||
pCisCtx->isTxDone = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pCisCtx->isTxDone = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pCisCtx->isTxDone = FALSE;
|
||||
pCisCtx->isTxDone = TRUE;
|
||||
}
|
||||
|
||||
/*** Setup for transmit ***/
|
||||
|
@ -115,7 +127,7 @@ static void lctrMstCisSetupRx(lctrCigCtx_t *pCigCtx, lctrCisCtx_t *pCisCtx)
|
|||
|
||||
/*** Setup for receive ***/
|
||||
|
||||
if ((pBuf = lctrCisRxPduAlloc(pCisCtx->localDataPdu.maxRxLen)) != NULL)
|
||||
if ((pBuf = lctrCisRxPduAlloc()) != NULL)
|
||||
{
|
||||
#if (LL_ENABLE_TESTER)
|
||||
/* Invalidate access address if trigger is set. */
|
||||
|
@ -136,12 +148,13 @@ static void lctrMstCisSetupRx(lctrCigCtx_t *pCigCtx, lctrCisCtx_t *pCisCtx)
|
|||
}
|
||||
#endif
|
||||
|
||||
lctrSetBbCisPacketCounterRx(pCisCtx);
|
||||
BbBleCisRxData(pBuf, LCTR_CIS_DATA_PDU_LEN(pCisCtx->localDataPdu.maxRxLen));
|
||||
/* Rx may fail; no more important statements in this code path */
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_ERR1("!!! OOM while initializing receive buffer at start of CE, cisHandle=%u", pCisCtx->cisHandle);
|
||||
LL_TRACE_ERR2("!!! OOM while initializing receive buffer at start of CE, cisHandle=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->cisEvtCounter);
|
||||
BbSetBodTerminateFlag();
|
||||
}
|
||||
}
|
||||
|
@ -196,7 +209,7 @@ static void lctrCisCheckTxFtAfterRx(lctrCisCtx_t *pCisCtx)
|
|||
if (pFtParam->subEvtCounter == pFtParam->lastSubEvtFt[pFtParam->pduCounter])
|
||||
{
|
||||
/* PDU needs to be flushed. */
|
||||
pCisCtx->txHdr.sn++;
|
||||
pCisCtx->dataSn++;
|
||||
pFtParam->isPduDone[pFtParam->pduCounter] = TRUE; /* The PDU is done. */
|
||||
|
||||
if (pFtParam->pduType[pFtParam->pduCounter] == LCTR_CIS_PDU_NON_EMPTY)
|
||||
|
@ -205,12 +218,17 @@ static void lctrCisCheckTxFtAfterRx(lctrCisCtx_t *pCisCtx)
|
|||
lctrCisTxPduAck(pCisCtx);
|
||||
pCisCtx->pduFlushed = TRUE; /* Set the flag, lctrCisProcessTxAckCleanup will be called to do the cleanup later in the lctrMstCisCigPostSubEvt. */
|
||||
}
|
||||
pFtParam->pduCounter++;
|
||||
|
||||
lctrCisIncPacketCounterTx(pCisCtx);
|
||||
pCisCtx->isoLinkQualStats.txUnAckPkt++;
|
||||
pFtParam->pduCounter++;
|
||||
}
|
||||
else /* Implies that a retransmit will happen. */
|
||||
{
|
||||
pCisCtx->isoLinkQualStats.retransmitPkt++;
|
||||
}
|
||||
}
|
||||
else /* Implies that a retransmit will happen. */
|
||||
else
|
||||
{
|
||||
pCisCtx->isoLinkQualStats.retransmitPkt++;
|
||||
}
|
||||
|
@ -253,12 +271,6 @@ static void lctrCisCheckRxFtAfterRx(lctrCisCtx_t *pCisCtx)
|
|||
return;
|
||||
}
|
||||
|
||||
if (pCisCtx->rxHdr.np)
|
||||
{
|
||||
/* NULL PDU doesn't need to be acked or flushed. */
|
||||
return;
|
||||
}
|
||||
|
||||
lctrFtParam_t *pFtParam = &pCisCtx->rxFtParamList.pHead->ftParam;
|
||||
|
||||
if (pFtParam->pduRcved)
|
||||
|
@ -282,6 +294,11 @@ static void lctrCisCheckRxFtAfterRx(lctrCisCtx_t *pCisCtx)
|
|||
pCisCtx->isoalRxCtx.pduFlushed = TRUE;
|
||||
pCisCtx->isoalRxCtx.packetSequence++;
|
||||
pCisCtx->numRxMissed++;
|
||||
if (pCisCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED)
|
||||
{
|
||||
/* Indicate SDU has missing data. */
|
||||
pCisCtx->isoalRxCtx.data.unframed.ps = LCTR_PS_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -317,12 +334,6 @@ static void lctrCisCheckTxFtAfterBod(lctrCisCtx_t *pCisCtx)
|
|||
return;
|
||||
}
|
||||
|
||||
if (pCisCtx->txHdr.np)
|
||||
{
|
||||
/* NULL PDU doesn't need to be acked or flushed. */
|
||||
return;
|
||||
}
|
||||
|
||||
lctrFtParamNode_t *pNode = pCisCtx->txFtParamList.pHead;
|
||||
|
||||
/* Increment interval counter for all the node in the list. */
|
||||
|
@ -340,7 +351,7 @@ static void lctrCisCheckTxFtAfterBod(lctrCisCtx_t *pCisCtx)
|
|||
pFtParam->intervalCounter == pFtParam->intervalTotal) /* Check if the PDU needs to be flush in this interval. */
|
||||
{
|
||||
pFtParam->isPduDone[i] = TRUE;
|
||||
pCisCtx->txHdr.sn++;
|
||||
pCisCtx->dataSn++;
|
||||
|
||||
if (pFtParam->pduType[i] == LCTR_CIS_PDU_NON_EMPTY)
|
||||
{
|
||||
|
@ -349,6 +360,8 @@ static void lctrCisCheckTxFtAfterBod(lctrCisCtx_t *pCisCtx)
|
|||
lctrCisTxQueuePopCleanup(pCisCtx);
|
||||
}
|
||||
pFtParam->pduCounter++;
|
||||
|
||||
lctrCisIncPacketCounterTx(pCisCtx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -403,7 +416,9 @@ static void lctrCisCheckRxFtAfterBod(lctrCisCtx_t *pCisCtx)
|
|||
{
|
||||
pFtParam->isPduDone[i] = TRUE;
|
||||
pCisCtx->txHdr.nesn++;
|
||||
lctrCisIncPacketCounterRx(pCisCtx);
|
||||
pFtParam->pduCounter++;
|
||||
pCisCtx->isoalRxCtx.pduFlushed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -453,6 +468,98 @@ static void lctrCisCheckFtAfterBod(lctrCisCtx_t *pCisCtx)
|
|||
External Functions
|
||||
**************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Check whether continue the current operation.
|
||||
*
|
||||
* \param pOp Operation.
|
||||
* \param pNewCisCtx A new CIS operation.
|
||||
*
|
||||
* \return zero
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint32_t lctrMstCisCheckContOpPostCback(BbOpDesc_t *pOp, bool_t *pNewCisCtx)
|
||||
{
|
||||
lctrCigCtx_t * const pCigCtx = pOp->pCtx;
|
||||
lctrCisCtx_t *pCisCtx = pCigCtx->pCisCtx;
|
||||
BbBleData_t *pBle = &pCisCtx->bleData;
|
||||
|
||||
if (*pNewCisCtx == FALSE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pCigCtx->packing == LL_PACKING_INTERLEAVED)
|
||||
{
|
||||
if ((pCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCisCtx)) == NULL)
|
||||
{
|
||||
/* End of the list, loop back to the head of the CIS. */
|
||||
pCisCtx = lctrCisGetHeadCis(&pCigCtx->list);
|
||||
pCigCtx->isLoopBack = TRUE;
|
||||
|
||||
pBle = &pCisCtx->bleData;
|
||||
|
||||
/* Point to the next CIS. */
|
||||
pOp->prot.pBle = pBle;
|
||||
pCigCtx->pCisCtx = pCisCtx;
|
||||
memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan));
|
||||
pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */
|
||||
|
||||
/* For interleaved CIS there is always a switch to a new CisCtx, so nextSubEvtChanIdx is not updated in bbMstCisRxCompCback()*/
|
||||
if (pCisCtx->subEvtCounter <= pCisCtx->nse)
|
||||
{
|
||||
lctrMstCisCigPostSubEvt(pOp, BB_STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO need to check whether this pCisCtx->rxHdr.cie || pCisCtx->txHdr.cie and no sending more PDU for this CIS. */
|
||||
|
||||
/* Get the next CIS in the list. */
|
||||
if (pCigCtx->isLoopBack == FALSE)
|
||||
{
|
||||
lctrFtParam_t txFtParam, rxFtParam;
|
||||
|
||||
if (pCisCtx->bnMToS)
|
||||
{
|
||||
lctrCisInitFtParam(&txFtParam, pCisCtx->bnMToS, pCisCtx->ftMToS, pCisCtx->nse);
|
||||
(void)lctrCisFtInsertTail(&pCisCtx->txFtParamList, &txFtParam); /* Assume there is memory. */
|
||||
}
|
||||
|
||||
if (pCisCtx->bnSToM)
|
||||
{
|
||||
lctrCisInitFtParam(&rxFtParam, pCisCtx->bnSToM, pCisCtx->ftSToM, pCisCtx->nse);
|
||||
(void)lctrCisFtInsertTail(&pCisCtx->rxFtParamList, &rxFtParam); /* Assume there is memory. */
|
||||
}
|
||||
|
||||
lctrMstCisInitIsr(pCisCtx);
|
||||
}
|
||||
|
||||
pBle = &pCisCtx->bleData;
|
||||
|
||||
/* Point to the next CIS. */
|
||||
pOp->prot.pBle = pBle;
|
||||
pCigCtx->pCisCtx = pCisCtx;
|
||||
memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan));
|
||||
if (pCigCtx->isLoopBack == FALSE)
|
||||
{
|
||||
pBle->chan.chanIdx = pCigCtx->pCisCtx->chIdx; /* Set the next channel to the first channel in the next CIS. */
|
||||
}
|
||||
else
|
||||
{
|
||||
pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */
|
||||
|
||||
/* For interleaved CIS there is always a switch to a new CisCtx, so nextSubEvtChanIdx is not updated in bbMstCisRxCompCback()*/
|
||||
if (pCisCtx->subEvtCounter <= pCisCtx->nse)
|
||||
{
|
||||
lctrMstCisCigPostSubEvt(pOp, BB_STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Check whether continue the current operation.
|
||||
|
@ -622,18 +729,8 @@ SwitchInt:
|
|||
goto Done;
|
||||
}
|
||||
|
||||
/* End of the list, loop back to the head of the CIS. */
|
||||
pCisCtx = lctrCisGetHeadCis(&pCigCtx->list);
|
||||
pCigCtx->isLoopBack = TRUE;
|
||||
|
||||
pBle = &pCisCtx->bleData;
|
||||
*pNewCisCtx = TRUE;
|
||||
|
||||
/* Point to the next CIS. */
|
||||
pOp->prot.pBle = pBle;
|
||||
pCigCtx->pCisCtx = pCisCtx;
|
||||
memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan));
|
||||
pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */
|
||||
/* Processing will continue in the lctrMstCisCheckContOpPostCback() */
|
||||
|
||||
return delayUsec; /* Return the offset from the old CIS */
|
||||
}
|
||||
|
@ -684,43 +781,8 @@ SwitchInt:
|
|||
return (subIntervUsec - addDelayUsec);
|
||||
}
|
||||
|
||||
/* TODO need to check whether this pCisCtx->rxHdr.cie || pCisCtx->txHdr.cie and no sending more PDU for this CIS. */
|
||||
|
||||
/* Get the next CIS in the list. */
|
||||
if (pCigCtx->isLoopBack == FALSE)
|
||||
{
|
||||
lctrFtParam_t txFtParam, rxFtParam;
|
||||
|
||||
if (pCisCtx->bnMToS)
|
||||
{
|
||||
lctrCisInitFtParam(&txFtParam, pCisCtx->bnMToS, pCisCtx->ftMToS, pCisCtx->nse);
|
||||
(void)lctrCisFtInsertTail(&pCisCtx->txFtParamList, &txFtParam); /* Assume there is memory. */
|
||||
}
|
||||
|
||||
if (pCisCtx->bnSToM)
|
||||
{
|
||||
lctrCisInitFtParam(&rxFtParam, pCisCtx->bnSToM, pCisCtx->ftSToM, pCisCtx->nse);
|
||||
(void)lctrCisFtInsertTail(&pCisCtx->rxFtParamList, &rxFtParam); /* Assume there is memory. */
|
||||
}
|
||||
|
||||
lctrMstCisInitIsr(pCisCtx);
|
||||
}
|
||||
|
||||
pBle = &pCisCtx->bleData;
|
||||
*pNewCisCtx = TRUE;
|
||||
|
||||
/* Point to the next CIS. */
|
||||
pOp->prot.pBle = pBle;
|
||||
pCigCtx->pCisCtx = pCisCtx;
|
||||
memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan));
|
||||
if (pCigCtx->isLoopBack == FALSE)
|
||||
{
|
||||
pBle->chan.chanIdx = pCigCtx->pCisCtx->chIdx; /* Set the next channel to the first channel in the next CIS. */
|
||||
}
|
||||
else
|
||||
{
|
||||
pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */
|
||||
}
|
||||
/* Processing will continue in the lctrMstCisCheckContOpPostCback() */
|
||||
|
||||
return delayUsec; /* Return the offset from the old CIS */
|
||||
}
|
||||
|
@ -850,6 +912,14 @@ void lctrMstCisCigEndOp(BbOpDesc_t *pOp)
|
|||
|
||||
while (pCisCtx)
|
||||
{
|
||||
/* Check for unframed flushed PDUs. */
|
||||
if ((pCisCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED) &&
|
||||
(pCisCtx->isoalRxCtx.pduFlushed == TRUE))
|
||||
{
|
||||
pCisCtx->isoalRxCtx.pduFlushed = FALSE;
|
||||
lctrCisCheckUnframedFlush(pCisCtx);
|
||||
}
|
||||
|
||||
pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle);
|
||||
|
||||
/* LL_CIS_TERMINATION case */
|
||||
|
@ -857,10 +927,20 @@ void lctrMstCisCigEndOp(BbOpDesc_t *pOp)
|
|||
(pConnCtx->enabled == FALSE) ||
|
||||
(lctrResetEnabled == TRUE))
|
||||
{
|
||||
/* This variable set to TRUE means it is a CIS disconnect that requires an event generation. */
|
||||
if (pCisCtx->isClosing == TRUE)
|
||||
/* Notify host when terminate happens unless reseted. */
|
||||
if (lctrResetEnabled == FALSE)
|
||||
{
|
||||
/* This was a host-initiated termination of the CIS. */
|
||||
if (pConnCtx->enabled == FALSE)
|
||||
{
|
||||
pCisCtx->reason = HCI_ERR_REMOTE_TERMINATED;
|
||||
}
|
||||
/* If host initiates the termination, the reason code shall be HCI_ERR_LOCAL_TERMINATED in the disconnect complete event. */
|
||||
else if (pCisCtx->hostInitTerm)
|
||||
{
|
||||
pCisCtx->reason = HCI_ERR_LOCAL_TERMINATED;
|
||||
pCisCtx->hostInitTerm = FALSE;
|
||||
}
|
||||
|
||||
lctrNotifyHostCisTerm(pCisCtx);
|
||||
}
|
||||
|
||||
|
@ -993,6 +1073,21 @@ void lctrMstCisCigEndOp(BbOpDesc_t *pOp)
|
|||
}
|
||||
}
|
||||
|
||||
if (pCisCtx->sduSizeMToS &&
|
||||
(pCisCtx->dataPathInCtx.id == LL_ISO_DATA_PATH_VS))
|
||||
{
|
||||
uint8_t *pSduBuf;
|
||||
if ((pSduBuf = lctrTxIsoDataPduAlloc()) != NULL)
|
||||
{
|
||||
WSF_ASSERT(lctrCodecHdlr.inReq);
|
||||
lctrCodecHdlr.inReq(pCisCtx->cisHandle, pSduBuf + HCI_ISO_HDR_LEN + HCI_ISO_DL_MAX_LEN, pCisCtx->sduSizeMToS);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_WARN1("!!! Out of memory; dropping input SDU, handle=%u", pCisCtx->cisHandle);
|
||||
}
|
||||
}
|
||||
|
||||
/* Assemble framed data. */
|
||||
if ((pCisCtx->framing == LL_ISO_PDU_TYPE_FRAMED) &&
|
||||
pCisCtx->isoalTxCtx.pendQueueSize)
|
||||
|
@ -1028,7 +1123,7 @@ void lctrMstCisCigEndOp(BbOpDesc_t *pOp)
|
|||
}
|
||||
|
||||
pCisCtx = lctrCisGetHeadCis(&pCigCtx->list);
|
||||
LL_TRACE_WARN1("!!! CIS master schedule conflict eventCounter=%u", pCisCtx->cisEvtCounter);
|
||||
LL_TRACE_WARN2("!!! CIS master schedule conflict handle=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->cisEvtCounter);
|
||||
}
|
||||
|
||||
if (lmgrCb.sendIsoCmplEvt)
|
||||
|
@ -1048,6 +1143,8 @@ void lctrMstCisCigAbortOp(BbOpDesc_t *pOp)
|
|||
{
|
||||
lctrCigCtx_t * const pCigCtx = pOp->pCtx;
|
||||
|
||||
LL_TRACE_WARN1("!!! CIG Master BOD aborted, cigHandle=%u", pCigCtx->cigHandle);
|
||||
|
||||
/* Need to setup Tx/Rx flush timeout parameter first since some field will be used in the lctrSlvCisInitIsr. */
|
||||
|
||||
if (pCigCtx->numCisEsted > 0)
|
||||
|
@ -1093,7 +1190,10 @@ void lctrMstCisCigTxCompletion(BbOpDesc_t *pOp, uint8_t status)
|
|||
lctrCigCtx_t * const pCigCtx = pOp->pCtx;
|
||||
lctrCisCtx_t *pCisCtx = pCigCtx->pCisCtx;
|
||||
|
||||
pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter++;
|
||||
if (pCisCtx->txFtParamList.pHead != NULL)
|
||||
{
|
||||
pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -1110,21 +1210,29 @@ void lctrMstCisCigRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status)
|
|||
lctrCigCtx_t * const pCigCtx = pOp->pCtx;
|
||||
lctrCisCtx_t *pCisCtx = pCigCtx->pCisCtx;
|
||||
lctrConnCtx_t *pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle);
|
||||
BbBleData_t * const pBle = &pCisCtx->bleData;
|
||||
|
||||
pCisCtx->txFtParamList.pHead->ftParam.pduAcked = FALSE;
|
||||
pCisCtx->rxFtParamList.pHead->ftParam.subEvtCounter++;
|
||||
pCisCtx->rxFtParamList.pHead->ftParam.pduRcved = FALSE;
|
||||
if (pCisCtx->txFtParamList.pHead != NULL)
|
||||
{
|
||||
pCisCtx->txFtParamList.pHead->ftParam.pduAcked = FALSE;
|
||||
}
|
||||
|
||||
if (pCisCtx->rxFtParamList.pHead != NULL)
|
||||
{
|
||||
pCisCtx->rxFtParamList.pHead->ftParam.subEvtCounter++;
|
||||
pCisCtx->rxFtParamList.pHead->ftParam.pduRcved = FALSE;
|
||||
}
|
||||
|
||||
pCisCtx->validRx = FALSE;
|
||||
pCisCtx->txPduIsAcked = FALSE;
|
||||
pCisCtx->pduFlushed = FALSE;
|
||||
pCisCtx->isoalRxCtx.pduFlushed = FALSE;
|
||||
|
||||
if (status == BB_STATUS_CRC_FAILED)
|
||||
{
|
||||
pCisCtx->isoLinkQualStats.crcErrPkt++;
|
||||
}
|
||||
|
||||
/*** Cancellation processing ***/
|
||||
/*** Cancelled processing ***/
|
||||
|
||||
if (status == BB_STATUS_CANCELED)
|
||||
{
|
||||
|
@ -1134,22 +1242,58 @@ void lctrMstCisCigRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status)
|
|||
|
||||
/*** Receive packet pre-processing ***/
|
||||
|
||||
if (status == BB_STATUS_SUCCESS)
|
||||
/* Add RSSI to average if monitoring power. */
|
||||
if ((pConnCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) &&
|
||||
(pConnCtx->powerMonitorScheme == LCTR_PC_MONITOR_AUTO))
|
||||
{
|
||||
int8_t rssi = (status == LL_SUCCESS) ? pOp->prot.pBle->op.mstCis.rssi : 0x80;
|
||||
|
||||
/* Calculations handled on timer expiration for tmrPowerCtrl. */
|
||||
/* Use a positive value to hold accumulated RSSI, as RSSI will never be positive. */
|
||||
pConnCtx->cisAccumulatedRssi += (uint32_t) -rssi;
|
||||
pConnCtx->cisTotalAccumulatedRssi++;
|
||||
}
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case BB_STATUS_SUCCESS:
|
||||
pCisCtx->firstFromPeer = TRUE;
|
||||
pCisCtx->data.mst.rxFromSlave = TRUE;
|
||||
}
|
||||
else if (status == BB_STATUS_CRC_FAILED ||
|
||||
status == BB_STATUS_RX_TIMEOUT ||
|
||||
status == BB_STATUS_FAILED)
|
||||
{
|
||||
LL_TRACE_WARN2("lctrMstCisCigRxCompletion: BB failed with status=%u, handle=%u", status, pCisCtx->cisHandle);
|
||||
LL_TRACE_WARN2("lctrMstCisCigRxCompletion: BB failed with cisEvtCounter=%d, bleChan=%u", pCisCtx->cisEvtCounter, pCisCtx->bleData.chan.chanIdx);
|
||||
break;
|
||||
|
||||
case BB_STATUS_CRC_FAILED:
|
||||
LL_TRACE_WARN3("lctrMstCisCigRxCompletion: BB failed with status=CRC_FAILED, handle=%u, bleChan=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->bleData.chan.chanIdx, pCisCtx->cisEvtCounter);
|
||||
goto PostProcessing;
|
||||
|
||||
case BB_STATUS_RX_TIMEOUT:
|
||||
LL_TRACE_WARN3("lctrMstCisCigRxCompletion: BB failed with status=RX_TIMEOUT, handle=%u, bleChan=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->bleData.chan.chanIdx, pCisCtx->cisEvtCounter);
|
||||
pCisCtx->validRx = FALSE;
|
||||
pCisCtx->txPduIsAcked = FALSE;
|
||||
goto PostProcessing;
|
||||
|
||||
case BB_STATUS_FAILED:
|
||||
LL_TRACE_WARN3("lctrMstCisCigRxCompletion: BB failed with status=FAILED, handle=%u, bleChan=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->bleData.chan.chanIdx, pCisCtx->cisEvtCounter);
|
||||
pCisCtx->validRx = FALSE;
|
||||
pCisCtx->txPduIsAcked = FALSE;
|
||||
goto PostProcessing;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
lctrCisUnpackDataPduHdr(&pCisCtx->rxHdr, pRxBuf);
|
||||
|
||||
/* Check for MIC failure and if this is not a re-transmission */
|
||||
if ((status == BB_STATUS_MIC_FAILED) &&
|
||||
((pCisCtx->rxHdr.sn ^ pCisCtx->txHdr.nesn) & 1) == 0)
|
||||
{
|
||||
LL_TRACE_WARN3("lctrMstCisCigRxCompletion: BB failed with MIC_FAILED, handle=%u, rxPacketNum=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->rxPktCounter, pCisCtx->cisEvtCounter);
|
||||
lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_TERM_MIC_FAILED);
|
||||
lctrCisRxPduFree(pRxBuf);
|
||||
BbSetBodTerminateFlag();
|
||||
goto Done;
|
||||
}
|
||||
|
||||
#if (LL_ENABLE_TESTER)
|
||||
if ((llTesterCb.cisAckMode != LL_TESTER_ACK_MODE_NORMAL) ||
|
||||
(llTesterCb.cisFwdPkt == TRUE))
|
||||
|
@ -1172,34 +1316,22 @@ void lctrMstCisCigRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status)
|
|||
/*** Packet post-processing ***/
|
||||
|
||||
PostProcessing:
|
||||
/* Save the Rx buffer and process in the lctrMstCisCigPostSubEvt. */
|
||||
pCisCtx->pRxBuf = pRxBuf;
|
||||
|
||||
/* Check rssi value if power monitoring. */
|
||||
if (pConnCtx->monitoringState == LCTR_PC_MONITOR_ENABLED)
|
||||
{
|
||||
lctrCisPowerMonitorCheckRssi(pOp->prot.pBle->op.mstCis.rssi,
|
||||
status,
|
||||
pCisCtx->phySToM +
|
||||
(((pCisCtx->phySToM == LL_PHY_LE_CODED) &&
|
||||
(pBle->chan.initTxPhyOptions == LL_PHY_OPTIONS_S2_PREFERRED)) ? 1 : 0),
|
||||
pConnCtx);
|
||||
}
|
||||
lctrCisCheckFtAfterRx(pCisCtx);
|
||||
|
||||
/* Tx post-processing. */
|
||||
lctrCisProcessTxAckCleanup(pCisCtx);
|
||||
|
||||
/* Rx post-processing. */
|
||||
lctrCisRxPostProcessing(pCisCtx, pRxBuf);
|
||||
|
||||
return;
|
||||
|
||||
/*** ISR complete ***/
|
||||
|
||||
Done:
|
||||
|
||||
lctrCisCheckFtAfterRx(pCisCtx);
|
||||
|
||||
if (status == BB_STATUS_SUCCESS ||
|
||||
status == BB_STATUS_RX_TIMEOUT ||
|
||||
status == BB_STATUS_CRC_FAILED ||
|
||||
status == BB_STATUS_FAILED)
|
||||
{
|
||||
|
||||
lctrCisProcessTxAckCleanup(pCisCtx);
|
||||
lctrCisRxPostProcessing(pCisCtx, pCisCtx->pRxBuf);
|
||||
}
|
||||
|
||||
return;
|
||||
lctrCisProcessTxAckCleanup(pCisCtx);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -72,16 +72,29 @@ static void lctrSlvCisInitIsr(lctrCisCtx_t *pCisCtx)
|
|||
pCisCtx->txDataCounter = 0;
|
||||
pCisCtx->rxDataCounter = 0;
|
||||
|
||||
pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter = 0;
|
||||
pCisCtx->rxFtParamList.pHead->ftParam.subEvtCounter = 0;
|
||||
|
||||
if (pCisCtx->txFtParamList.pHead->ftParam.bn == 0)
|
||||
/* List may be empty if BN M_S is 0 */
|
||||
if (pCisCtx->rxFtParamList.pHead != NULL)
|
||||
{
|
||||
pCisCtx->isTxDone = TRUE;
|
||||
pCisCtx->rxFtParamList.pHead->ftParam.subEvtCounter = 0;
|
||||
}
|
||||
|
||||
/* List may be empty if BN S_M is 0 */
|
||||
if (pCisCtx->txFtParamList.pHead != NULL)
|
||||
{
|
||||
pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter = 0;
|
||||
|
||||
if (pCisCtx->txFtParamList.pHead->ftParam.bn == 0)
|
||||
{
|
||||
pCisCtx->isTxDone = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pCisCtx->isTxDone = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pCisCtx->isTxDone = FALSE;
|
||||
pCisCtx->isTxDone = TRUE;
|
||||
}
|
||||
|
||||
/*** Setup for transmit ***/
|
||||
|
@ -116,7 +129,7 @@ static void lctrSlvCisCigExecOp(lctrCisCtx_t *pCisCtx)
|
|||
|
||||
/*** Setup receiver ***/
|
||||
|
||||
if ((pBuf = lctrCisRxPduAlloc(pCisCtx->localDataPdu.maxRxLen)) != NULL)
|
||||
if ((pBuf = lctrCisRxPduAlloc()) != NULL)
|
||||
{
|
||||
#if (LL_ENABLE_TESTER)
|
||||
if (llTesterCb.isoAccAddrSeTrigMask &&
|
||||
|
@ -136,6 +149,7 @@ static void lctrSlvCisCigExecOp(lctrCisCtx_t *pCisCtx)
|
|||
}
|
||||
#endif
|
||||
|
||||
lctrSetBbCisPacketCounterRx(pCisCtx);
|
||||
BbBleCisRxData(pBuf, LCTR_CIS_DATA_PDU_LEN(pCisCtx->localDataPdu.maxRxLen));
|
||||
/* Rx may fail; no more important statements in this code path */
|
||||
}
|
||||
|
@ -161,7 +175,7 @@ static void lctrCisCheckTxFtAfterRx(lctrCisCtx_t *pCisCtx)
|
|||
return;
|
||||
}
|
||||
|
||||
if (pCisCtx->txHdr.np)
|
||||
if (pCisCtx->data.slv.lastTxNull)
|
||||
{
|
||||
/* NULL PDU doesn't need to be acked or flushed. */
|
||||
return;
|
||||
|
@ -183,19 +197,23 @@ static void lctrCisCheckTxFtAfterRx(lctrCisCtx_t *pCisCtx)
|
|||
if (pFtParam->subEvtCounter == pFtParam->lastSubEvtFt[pFtParam->pduCounter])
|
||||
{
|
||||
/* PDU needs to be flushed. */
|
||||
pCisCtx->txHdr.sn++;
|
||||
pCisCtx->dataSn++;
|
||||
|
||||
lctrCisIncPacketCounterTx(pCisCtx);
|
||||
pFtParam->isPduDone[pFtParam->pduCounter] = TRUE; /* The PDU is done. */
|
||||
pFtParam->pduCounter++;
|
||||
pCisCtx->isoLinkQualStats.txUnAckPkt++;
|
||||
|
||||
if (pFtParam->pduType[pFtParam->pduCounter] == LCTR_CIS_PDU_NON_EMPTY)
|
||||
{
|
||||
/* Need to remove from ack queue if non-empty PDU. */
|
||||
lctrCisTxPduAck(pCisCtx);
|
||||
pCisCtx->pduFlushed = TRUE; /* Set the flag, lctrCisProcessTxAckCleanup will be called to do the cleanup later in the lctrMstCisCigPostSubEvt. */
|
||||
pCisCtx->pduFlushed = TRUE; /* Set the flag, lctrCisProcessTxAckCleanup will be called to do the cleanup later in the lctrSlvCisCigPostSubEvt. */
|
||||
}
|
||||
pFtParam->pduCounter++;
|
||||
pCisCtx->isoLinkQualStats.txUnAckPkt++;
|
||||
}
|
||||
else /* Implies that a retransmit will happen. */
|
||||
{
|
||||
pCisCtx->isoLinkQualStats.retransmitPkt++;
|
||||
}
|
||||
}
|
||||
else /* Implies that a retransmit will happen. */
|
||||
|
@ -241,12 +259,6 @@ static void lctrCisCheckRxFtAfterRx(lctrCisCtx_t *pCisCtx)
|
|||
return;
|
||||
}
|
||||
|
||||
if (pCisCtx->rxHdr.np)
|
||||
{
|
||||
/* NULL PDU doesn't need to be acked or flushed. */
|
||||
return;
|
||||
}
|
||||
|
||||
lctrFtParam_t *pFtParam = &pCisCtx->rxFtParamList.pHead->ftParam;
|
||||
|
||||
if (pFtParam->pduRcved)
|
||||
|
@ -270,6 +282,11 @@ static void lctrCisCheckRxFtAfterRx(lctrCisCtx_t *pCisCtx)
|
|||
pCisCtx->isoalRxCtx.pduFlushed = TRUE;
|
||||
pCisCtx->isoalRxCtx.packetSequence++;
|
||||
pCisCtx->numRxMissed++;
|
||||
if (pCisCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED)
|
||||
{
|
||||
/* Indicate SDU has missing data. */
|
||||
pCisCtx->isoalRxCtx.data.unframed.ps = LCTR_PS_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -305,12 +322,6 @@ static void lctrCisCheckTxFtAfterBod(lctrCisCtx_t *pCisCtx)
|
|||
return;
|
||||
}
|
||||
|
||||
if (pCisCtx->txHdr.np)
|
||||
{
|
||||
/* NULL PDU doesn't need to be acked or flushed. */
|
||||
return;
|
||||
}
|
||||
|
||||
lctrFtParamNode_t *pNode = pCisCtx->txFtParamList.pHead;
|
||||
|
||||
/* Increment interval counter for all the node in the list. */
|
||||
|
@ -328,16 +339,17 @@ static void lctrCisCheckTxFtAfterBod(lctrCisCtx_t *pCisCtx)
|
|||
pFtParam->intervalCounter == pFtParam->intervalTotal) /* Check if the PDU needs to be flush in this interval. */
|
||||
{
|
||||
pFtParam->isPduDone[i] = TRUE;
|
||||
pCisCtx->txHdr.sn++;
|
||||
pCisCtx->dataSn++;
|
||||
|
||||
PalBbBleTxBufDesc_t bbDesc[3];
|
||||
if (lctrCisTxQueuePeek(pCisCtx, &bbDesc[0]))
|
||||
if (pFtParam->pduType[i] == LCTR_CIS_PDU_NON_EMPTY)
|
||||
{
|
||||
/* Need to remove from ack queue if non-empty PDU. */
|
||||
lctrCisTxPduAck(pCisCtx);
|
||||
lctrCisTxQueuePopCleanup(pCisCtx);
|
||||
}
|
||||
pFtParam->pduCounter++;
|
||||
|
||||
lctrCisIncPacketCounterTx(pCisCtx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -393,6 +405,7 @@ static void lctrCisCheckRxFtAfterBod(lctrCisCtx_t *pCisCtx)
|
|||
pCisCtx->txHdr.nesn++;
|
||||
lctrCisIncPacketCounterRx(pCisCtx);
|
||||
pFtParam->pduCounter++;
|
||||
pCisCtx->isoalRxCtx.pduFlushed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -441,6 +454,95 @@ static void lctrCisCheckFtAfterBod(lctrCisCtx_t *pCisCtx)
|
|||
/**************************************************************************************************
|
||||
External Functions
|
||||
**************************************************************************************************/
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Setup for the next current operation.
|
||||
*
|
||||
* \param pOp Begin operation.
|
||||
* \param pNewCisCtx New CIS context to begin.
|
||||
*
|
||||
* \return zero.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint32_t lctrSlvCisCheckContOpPostCback(BbOpDesc_t *pOp, bool_t *pNewCisCtx)
|
||||
{
|
||||
lctrCigCtx_t * const pCigCtx = pOp->pCtx;
|
||||
lctrCisCtx_t *pCisCtx = pCigCtx->pCisCtx;
|
||||
BbBleData_t *pBle = &pCisCtx->bleData;
|
||||
|
||||
if (*pNewCisCtx == FALSE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pCigCtx->packing == LL_PACKING_INTERLEAVED)
|
||||
{
|
||||
if ((pCisCtx = lctrCisGetNextCis(&pCigCtx->list, pCisCtx)) == NULL)
|
||||
{
|
||||
/* End of the list, loop back to the head of the CIS. */
|
||||
pCisCtx = lctrCisGetHeadCis(&pCigCtx->list);
|
||||
pCigCtx->isLoopBack = TRUE;
|
||||
|
||||
pBle = &pCisCtx->bleData;
|
||||
|
||||
/* Point to the next CIS. */
|
||||
pOp->prot.pBle = pBle;
|
||||
pCigCtx->pCisCtx = pCisCtx;
|
||||
memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan));
|
||||
pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */
|
||||
|
||||
/* For interleaved CIS there is always a switch to a new CisCtx, so nextSubEvtChanIdx is not updated in bbMstCisRxCompCback()*/
|
||||
if (pCisCtx->subEvtCounter <= pCisCtx->nse)
|
||||
{
|
||||
lctrSlvCisCigPostSubEvt(pOp, BB_STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pCigCtx->isLoopBack == FALSE)
|
||||
{
|
||||
lctrFtParam_t txFtParam, rxFtParam;
|
||||
|
||||
if (pCisCtx->bnSToM)
|
||||
{
|
||||
lctrCisInitFtParam(&txFtParam, pCisCtx->bnSToM, pCisCtx->ftSToM, pCisCtx->nse);
|
||||
(void)lctrCisFtInsertTail(&pCisCtx->txFtParamList, &txFtParam); /* Assume there is memory. */
|
||||
}
|
||||
|
||||
if (pCisCtx->bnMToS)
|
||||
{
|
||||
lctrCisInitFtParam(&rxFtParam, pCisCtx->bnMToS, pCisCtx->ftMToS, pCisCtx->nse);
|
||||
(void)lctrCisFtInsertTail(&pCisCtx->rxFtParamList, &rxFtParam); /* Assume there is memory. */
|
||||
}
|
||||
|
||||
lctrSlvCisInitIsr(pCisCtx);
|
||||
}
|
||||
|
||||
pBle = &pCisCtx->bleData;
|
||||
|
||||
/* Point to the next CIS. */
|
||||
pOp->prot.pBle = pBle;
|
||||
pCigCtx->pCisCtx = pCisCtx;
|
||||
memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan));
|
||||
if (pCigCtx->isLoopBack == FALSE)
|
||||
{
|
||||
pBle->chan.chanIdx = pCigCtx->pCisCtx->chIdx; /* Set the next channel to the first channel in the next CIS. */
|
||||
}
|
||||
else
|
||||
{
|
||||
pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */
|
||||
|
||||
/* For interleaved CIS there is always a switch to a new CisCtx, so nextSubEvtChanIdx is not updated in bbMstCisRxCompCback()*/
|
||||
if (pCisCtx->subEvtCounter <= pCisCtx->nse)
|
||||
{
|
||||
lctrSlvCisCigPostSubEvt(pOp, BB_STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
|
@ -629,18 +731,8 @@ SwitchInt:
|
|||
goto Done;
|
||||
}
|
||||
|
||||
/* End of the list, loop back to the head of the CIS. */
|
||||
pCisCtx = lctrCisGetHeadCis(&pCigCtx->list);
|
||||
pCigCtx->isLoopBack = TRUE;
|
||||
|
||||
pBle = &pCisCtx->bleData;
|
||||
*pNewCisCtx = TRUE;
|
||||
|
||||
/* Point to the next CIS. */
|
||||
pOp->prot.pBle = pBle;
|
||||
pCigCtx->pCisCtx = pCisCtx;
|
||||
memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan));
|
||||
pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */
|
||||
/* Processing will continue in the lctrSlvCisCheckContOpPostCback() */
|
||||
|
||||
/* Only apply WW when rx success. */
|
||||
if (isSuccess)
|
||||
|
@ -715,40 +807,8 @@ SwitchInt:
|
|||
return (offsetUsec - addDelayUsec);
|
||||
}
|
||||
|
||||
if (pCigCtx->isLoopBack == FALSE)
|
||||
{
|
||||
lctrFtParam_t txFtParam, rxFtParam;
|
||||
|
||||
if (pCisCtx->bnSToM)
|
||||
{
|
||||
lctrCisInitFtParam(&txFtParam, pCisCtx->bnSToM, pCisCtx->ftSToM, pCisCtx->nse);
|
||||
(void)lctrCisFtInsertTail(&pCisCtx->txFtParamList, &txFtParam); /* Assume there is memory. */
|
||||
}
|
||||
|
||||
if (pCisCtx->bnMToS)
|
||||
{
|
||||
lctrCisInitFtParam(&rxFtParam, pCisCtx->bnMToS, pCisCtx->ftMToS, pCisCtx->nse);
|
||||
(void)lctrCisFtInsertTail(&pCisCtx->rxFtParamList, &rxFtParam); /* Assume there is memory. */
|
||||
}
|
||||
|
||||
lctrSlvCisInitIsr(pCisCtx);
|
||||
}
|
||||
|
||||
pBle = &pCisCtx->bleData;
|
||||
*pNewCisCtx = TRUE;
|
||||
|
||||
/* Point to the next CIS. */
|
||||
pOp->prot.pBle = pBle;
|
||||
pCigCtx->pCisCtx = pCisCtx;
|
||||
memcpy(&pBle->chan, &pCigCtx->pCisCtx->bleData.chan, sizeof(pBle->chan));
|
||||
if (pCigCtx->isLoopBack == FALSE)
|
||||
{
|
||||
pBle->chan.chanIdx = pCigCtx->pCisCtx->chIdx; /* Set the next channel to the first channel in the next CIS. */
|
||||
}
|
||||
else
|
||||
{
|
||||
pBle->chan.chanIdx = pCisCtx->nextSubEvtChanIdx; /* Next subevent channel index is pre-calculated. */
|
||||
}
|
||||
/* Processing will continue in the lctrSlvCisCheckContOpPostCback() */
|
||||
|
||||
/* Only apply WW when rx success. */
|
||||
if (isSuccess)
|
||||
|
@ -770,6 +830,7 @@ Done:
|
|||
pCigCtx->pCisCtx = lctrCisGetHeadCis(&pCigCtx->list);
|
||||
pOp->prot.pBle = &pCigCtx->pCisCtx->bleData;
|
||||
*pNewCisCtx = TRUE;
|
||||
|
||||
lctrCisClearCisDone(&pCigCtx->list);
|
||||
return 0;
|
||||
}
|
||||
|
@ -805,19 +866,40 @@ void lctrSlvCisCigEndOp(BbOpDesc_t *pOp)
|
|||
/* Re-sync to master's clock. */
|
||||
pCigCtx->roleData.slv.anchorPointUsec = pCisCtx->data.slv.firstRxStartTsUsec;
|
||||
pCigCtx->roleData.slv.lastActiveEvent = pCigCtx->roleData.slv.cigEvtCounter;
|
||||
|
||||
/* Reset ISR variables. */
|
||||
pCisCtx->data.slv.syncWithMaster = FALSE;
|
||||
}
|
||||
|
||||
while (pCisCtx)
|
||||
{
|
||||
/* Check for unframed flushed PDUs. */
|
||||
if ((pCisCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED) &&
|
||||
(pCisCtx->isoalRxCtx.pduFlushed == TRUE))
|
||||
{
|
||||
pCisCtx->isoalRxCtx.pduFlushed = FALSE;
|
||||
lctrCisCheckUnframedFlush(pCisCtx);
|
||||
}
|
||||
|
||||
/* LL_CIS_TERMINATION case */
|
||||
if ((pCisCtx->isClosing == TRUE) ||
|
||||
(pConnCtx->enabled == FALSE) ||
|
||||
(lctrResetEnabled == TRUE))
|
||||
{
|
||||
/* This variable set to TRUE means it is a CIS disconnect that requires an event generation. */
|
||||
if (pCisCtx->isClosing == TRUE)
|
||||
/* Notify host when terminate happens unless reset occurred. */
|
||||
if (lctrResetEnabled == FALSE)
|
||||
{
|
||||
/* This was a host-initiated termination of the CIS. */
|
||||
if (pConnCtx->enabled == FALSE)
|
||||
{
|
||||
pCisCtx->reason = pConnCtx->termReason;
|
||||
}
|
||||
/* If host initiates the termination, the reason code shall be HCI_ERR_LOCAL_TERMINATED in the disconnect complete event. */
|
||||
else if (pCisCtx->hostInitTerm)
|
||||
{
|
||||
pCisCtx->reason = HCI_ERR_LOCAL_TERMINATED;
|
||||
pCisCtx->hostInitTerm = FALSE;
|
||||
}
|
||||
|
||||
lctrNotifyHostCisTerm(pCisCtx);
|
||||
}
|
||||
|
||||
|
@ -934,6 +1016,21 @@ void lctrSlvCisCigEndOp(BbOpDesc_t *pOp)
|
|||
}
|
||||
}
|
||||
|
||||
if (pCisCtx->sduSizeSToM &&
|
||||
(pCisCtx->dataPathInCtx.id == LL_ISO_DATA_PATH_VS))
|
||||
{
|
||||
uint8_t *pSduBuf;
|
||||
if ((pSduBuf = WsfMsgAlloc(pLctrRtCfg->maxIsoSduLen + HCI_ISO_DL_MAX_LEN)) != NULL)
|
||||
{
|
||||
WSF_ASSERT(lctrCodecHdlr.inReq);
|
||||
lctrCodecHdlr.inReq(pCisCtx->cisHandle, pSduBuf + HCI_ISO_HDR_LEN + HCI_ISO_DL_MAX_LEN, pCisCtx->sduSizeSToM);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_WARN1("!!! Out of memory; dropping input SDU, handle=%u", pCisCtx->cisHandle);
|
||||
}
|
||||
}
|
||||
|
||||
/* Assemble framed data. */
|
||||
if ((pCisCtx->framing == LL_ISO_PDU_TYPE_FRAMED) &&
|
||||
pCisCtx->isoalTxCtx.pendQueueSize)
|
||||
|
@ -997,8 +1094,11 @@ void lctrSlvCisCigEndOp(BbOpDesc_t *pOp)
|
|||
/* Advance to next interval. */
|
||||
pOp->dueUsec = pCigCtx->roleData.slv.anchorPointUsec + unsyncTimeUsec - wwTotalUsec;
|
||||
|
||||
pOp->minDurUsec = pCigCtx->cigSyncDelayUsec + wwTotalUsec;
|
||||
pCigCtx->pCisCtx->bleData.op.slvCis.rxSyncDelayUsec = (wwTotalUsec << 1);
|
||||
/* Use small minDurUsec to improve scheduling. */
|
||||
pOp->minDurUsec = pCigCtx->list.pHead->pCisCtx->subIntervUsec + wwTotalUsec;
|
||||
|
||||
/* TODO: confirm extra rxTimeout time allocation. */
|
||||
pCigCtx->pCisCtx->bleData.op.slvCis.rxSyncDelayUsec = (wwTotalUsec << 1) + 10;
|
||||
|
||||
if (pCigCtx->headCisRmved == TRUE)
|
||||
{
|
||||
|
@ -1016,7 +1116,6 @@ void lctrSlvCisCigEndOp(BbOpDesc_t *pOp)
|
|||
LL_TRACE_WARN1("!!! CIG slave schedule conflict eventCounter=%u", pCisCtx->cisEvtCounter);
|
||||
}
|
||||
|
||||
|
||||
if (lmgrCb.sendIsoCmplEvt)
|
||||
{
|
||||
lctrNotifyHostIsoEventComplete(pCigCtx->cigHandle, (uint32_t) pCisCtx->cisEvtCounter);
|
||||
|
@ -1034,9 +1133,11 @@ void lctrSlvCisCigAbortOp(BbOpDesc_t *pOp)
|
|||
{
|
||||
lctrCigCtx_t * const pCigCtx = pOp->pCtx;
|
||||
|
||||
LL_TRACE_WARN1("!!! CIG Slave BOD aborted, cigHandle=%u", pCigCtx->cigHandle);
|
||||
|
||||
if (pCigCtx->numCisEsted > 0)
|
||||
{
|
||||
lctrCisCtx_t *pCisCtx = lctrCisGetHeadCis(&pCigCtx->list);
|
||||
lctrCisCtx_t *pCisCtx = lctrCisGetHeadCis(&pCigCtx->list);
|
||||
/* It is possible there is no CIS since it is aborting. */
|
||||
|
||||
while (pCisCtx)
|
||||
|
@ -1078,7 +1179,10 @@ void lctrSlvCisCigTxCompletion(BbOpDesc_t *pOp, uint8_t status)
|
|||
lctrCigCtx_t * const pCigCtx = pOp->pCtx;
|
||||
lctrCisCtx_t *pCisCtx = pCigCtx->pCisCtx;
|
||||
|
||||
pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter++;
|
||||
if (pCisCtx->txFtParamList.pHead != NULL)
|
||||
{
|
||||
pCisCtx->txFtParamList.pHead->ftParam.subEvtCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -1100,24 +1204,44 @@ void lctrSlvCisCigRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status)
|
|||
|
||||
pCisCtx->data.slv.rxStatus = status;
|
||||
|
||||
pCisCtx->rxFtParamList.pHead->ftParam.subEvtCounter++;
|
||||
pCisCtx->txFtParamList.pHead->ftParam.pduAcked = FALSE;
|
||||
pCisCtx->rxFtParamList.pHead->ftParam.pduRcved = FALSE;
|
||||
if (pCisCtx->rxFtParamList.pHead != NULL)
|
||||
{
|
||||
pCisCtx->rxFtParamList.pHead->ftParam.subEvtCounter++;
|
||||
pCisCtx->rxFtParamList.pHead->ftParam.pduRcved = FALSE;
|
||||
}
|
||||
|
||||
if (pCisCtx->txFtParamList.pHead != NULL)
|
||||
{
|
||||
pCisCtx->txFtParamList.pHead->ftParam.pduAcked = FALSE;
|
||||
}
|
||||
|
||||
pCisCtx->validRx = FALSE;
|
||||
pCisCtx->txPduIsAcked = FALSE;
|
||||
pCisCtx->pduFlushed = FALSE;
|
||||
pCisCtx->isoalRxCtx.pduFlushed = FALSE;
|
||||
|
||||
/*** Cancellation processing ***/
|
||||
/*** Cancelled processing ***/
|
||||
|
||||
if (status == BB_STATUS_CANCELED)
|
||||
{
|
||||
lctrCisRxPduFree(pRxBuf);
|
||||
|
||||
goto Done;
|
||||
}
|
||||
|
||||
/*** CIS event pre-processing ***/
|
||||
|
||||
/* Add RSSI to average if monitoring power. */
|
||||
if ((pConnCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) &&
|
||||
(pConnCtx->powerMonitorScheme == LCTR_PC_MONITOR_AUTO))
|
||||
{
|
||||
int8_t rssi = (status == LL_SUCCESS) ? pOp->prot.pBle->op.slvCis.rssi : 0x80;
|
||||
|
||||
/* Calculations handled on timer expiration for tmrPowerCtrl. */
|
||||
/* Use a positive value to hold accumulated RSSI, as RSSI will never be positive. */
|
||||
pConnCtx->cisAccumulatedRssi += (uint32_t) (-(rssi));
|
||||
pConnCtx->cisTotalAccumulatedRssi++;
|
||||
}
|
||||
|
||||
/* Save time stamp for the first Rx. */
|
||||
if (pCisCtx->data.slv.firstRxFromMaster == TRUE)
|
||||
{
|
||||
|
@ -1141,25 +1265,45 @@ void lctrSlvCisCigRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status)
|
|||
pCisCtx->data.slv.rxFromMaster = TRUE;
|
||||
pCisCtx->data.slv.consCrcFailed = 0;
|
||||
break;
|
||||
case BB_STATUS_CRC_FAILED:
|
||||
pCisCtx->isoLinkQualStats.crcErrPkt++;
|
||||
/* Fallthrough */
|
||||
case BB_STATUS_FAILED:
|
||||
case BB_STATUS_RX_TIMEOUT:
|
||||
LL_TRACE_WARN2("lctrSlvCisCigRxCompletion: BB failed with status=%u, handle=%u", status, pCisCtx->cisHandle);
|
||||
LL_TRACE_WARN2("lctrSlvCisCigRxCompletion: BB failed with cisEvtCounter=%d, bleChan=%u", pCisCtx->cisEvtCounter, pCisCtx->bleData.chan.chanIdx);
|
||||
|
||||
case BB_STATUS_CRC_FAILED:
|
||||
LL_TRACE_WARN3("lctrSlvCisCigRxCompletion: BB failed with status=CRC_FAILED, handle=%u, bleChan=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->bleData.chan.chanIdx, pCisCtx->cisEvtCounter);
|
||||
pCisCtx->isoLinkQualStats.crcErrPkt++;
|
||||
pCisCtx->validRx = FALSE;
|
||||
pCisCtx->txPduIsAcked = FALSE;
|
||||
|
||||
goto SetupTx;
|
||||
|
||||
case BB_STATUS_RX_TIMEOUT:
|
||||
LL_TRACE_WARN3("lctrSlvCisCigRxCompletion: BB failed with status=RX_TIMEOUT, handle=%u, bleChan=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->bleData.chan.chanIdx, pCisCtx->cisEvtCounter);
|
||||
pCisCtx->validRx = FALSE;
|
||||
pCisCtx->txPduIsAcked = FALSE;
|
||||
lctrCisRxPduFree(pRxBuf);
|
||||
goto Done;
|
||||
|
||||
case BB_STATUS_FAILED:
|
||||
LL_TRACE_WARN3("lctrSlvCisCigRxCompletion: BB failed with status=FAILED, handle=%u, bleChan=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->bleData.chan.chanIdx, pCisCtx->cisEvtCounter);
|
||||
pCisCtx->validRx = FALSE;
|
||||
pCisCtx->txPduIsAcked = FALSE;
|
||||
lctrCisRxPduFree(pRxBuf);
|
||||
goto Done;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
lctrCisUnpackDataPduHdr(&pCisCtx->rxHdr, pRxBuf);
|
||||
|
||||
/* Check for MIC failure and if this is not a re-transmission */
|
||||
if ((status == BB_STATUS_MIC_FAILED) &&
|
||||
((pCisCtx->rxHdr.sn ^ pCisCtx->txHdr.nesn) & 1) == 0)
|
||||
{
|
||||
LL_TRACE_WARN3("lctrSlvCisCigRxCompletion: BB failed with MIC_FAILED, handle=%u, rxPacketNum=%u, eventCounter=%u", pCisCtx->cisHandle, pCisCtx->rxPktCounter, pCisCtx->cisEvtCounter);
|
||||
lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_TERM_MIC_FAILED);
|
||||
lctrCisRxPduFree(pRxBuf);
|
||||
BbSetBodTerminateFlag();
|
||||
goto Done;
|
||||
}
|
||||
|
||||
#if (LL_ENABLE_TESTER)
|
||||
if ((llTesterCb.cisAckMode != LL_TESTER_ACK_MODE_NORMAL) ||
|
||||
(llTesterCb.cisFwdPkt == TRUE))
|
||||
|
@ -1187,6 +1331,7 @@ SetupTx:
|
|||
|
||||
/* Slave always transmits after receiving. */
|
||||
lctrCisSetupForTx(pCigCtx, status, TRUE);
|
||||
pCisCtx->data.slv.lastTxNull = pCisCtx->txHdr.np;
|
||||
|
||||
/* Tx post-processing. */
|
||||
lctrCisProcessTxAckCleanup(pCisCtx);
|
||||
|
@ -1194,28 +1339,17 @@ SetupTx:
|
|||
/* Rx post-processing. */
|
||||
lctrCisRxPostProcessing(pCisCtx, pRxBuf);
|
||||
|
||||
/* Check rssi value if power monitoring. */
|
||||
if (pConnCtx->monitoringState == LCTR_PC_MONITOR_ENABLED)
|
||||
{
|
||||
lctrCisPowerMonitorCheckRssi(pOp->prot.pBle->op.slvCis.rssi,
|
||||
status,
|
||||
pCisCtx->phySToM +
|
||||
(((pCisCtx->phySToM == LL_PHY_LE_CODED) &&
|
||||
(pBle->chan.initTxPhyOptions == LL_PHY_OPTIONS_S2_PREFERRED)) ? 1 : 0),
|
||||
pConnCtx);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
/*** ISR complete ***/
|
||||
|
||||
Done:
|
||||
|
||||
lctrCisCheckFtAfterRx(pCisCtx);
|
||||
|
||||
/* Tx post-processing. */
|
||||
lctrCisProcessTxAckCleanup(pCisCtx);
|
||||
pCisCtx->data.slv.lastTxNull = pCisCtx->isTxDone;
|
||||
|
||||
return;
|
||||
lctrCisProcessTxAckCleanup(pCisCtx);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
|
|
@ -164,10 +164,11 @@ uint8_t *lctrProcessRxAck(lctrConnCtx_t *pCtx)
|
|||
pCtx->txHdr.nesn++;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lctrIncPacketCounterRx(pCtx);
|
||||
}
|
||||
|
||||
pCtx->txHdr.nesn++;
|
||||
lctrIncPacketCounterRx(pCtx);
|
||||
return pNextRxBuf;
|
||||
}
|
||||
|
||||
|
@ -211,6 +212,12 @@ bool_t lctrProcessTxAck(lctrConnCtx_t *pCtx)
|
|||
|
||||
if (pCtx->txHdr.len) /* last packet from ARQ queue; zero length implies empty PDU */
|
||||
{
|
||||
if ((pCtx->txHdr.llid == LL_LLID_CTRL_PDU) &&
|
||||
(pCtx->numTxPendCtrlPdu > 0))
|
||||
{
|
||||
pCtx->numTxPendCtrlPdu--;
|
||||
}
|
||||
|
||||
/*** Peer ACK'ed a Data PDU ***/
|
||||
|
||||
lctrTxPduAck(pCtx);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -47,6 +47,8 @@ static struct
|
|||
{
|
||||
uint8_t consCrcFailed; /*!< Number of consecutive CRC failures. Used only by active operation. */
|
||||
bool_t rxFromSlave; /*!< At least one packet received from slave. */
|
||||
uint16_t numTxData; /*!< Number of Tx data PDU in a single CE. */
|
||||
uint16_t numRxData; /*!< Number of Rx data PDU in a single CE. */
|
||||
} lctrMstConnIsr;
|
||||
|
||||
/*! \brief Check BB meets data PDU requirements. */
|
||||
|
@ -216,10 +218,12 @@ void lctrMstConnBeginOp(BbOpDesc_t *pOp)
|
|||
pLctrVsHdlrs->ceSetup(LCTR_GET_CONN_HANDLE(pCtx));
|
||||
}
|
||||
|
||||
/*** Initialize connection event resources. ***/
|
||||
/*** Initialize connection event resources ***/
|
||||
|
||||
lctrMstConnIsr.consCrcFailed = 0;
|
||||
lctrMstConnIsr.rxFromSlave = FALSE;
|
||||
lctrMstConnIsr.numTxData = 0;
|
||||
lctrMstConnIsr.numRxData = 0;
|
||||
|
||||
/*** Setup for transmit ***/
|
||||
|
||||
|
@ -295,6 +299,14 @@ void lctrMstConnEndOp(BbOpDesc_t *pOp)
|
|||
lctrStoreConnTimeoutTerminateReason(pCtx);
|
||||
WsfTimerStartMs(&pCtx->tmrSupTimeout, pCtx->supTimeoutMs);
|
||||
|
||||
if (!lmgrGetOpFlag(LL_OP_MODE_FLAG_ENA_FEAT_LLCP_STARTUP) &&
|
||||
(pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) &&
|
||||
(pCtx->powerMonitorScheme == LCTR_PC_MONITOR_AUTO) &&
|
||||
!lmgrGetOpFlag(LL_OP_MODE_FLAG_DIS_POWER_MONITOR))
|
||||
{
|
||||
WsfTimerStartMs(&pCtx->tmrPowerCtrl, LL_PC_SERVICE_MS);
|
||||
}
|
||||
|
||||
pCtx->connEst = TRUE;
|
||||
}
|
||||
else if (lctrMstConnIsr.rxFromSlave)
|
||||
|
@ -304,13 +316,34 @@ void lctrMstConnEndOp(BbOpDesc_t *pOp)
|
|||
}
|
||||
|
||||
pCtx->rssi = pConn->rssi;
|
||||
|
||||
if ((pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) &&
|
||||
(pCtx->lastRxStatus == BB_STATUS_SUCCESS))
|
||||
if ((pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED))
|
||||
{
|
||||
if (lctrPcActTbl[pCtx->powerMonitorScheme])
|
||||
/* If a packet did not receive for whatever reason, add a datapoint with the lowest RSSI. */
|
||||
if (pCtx->lastRxStatus != BB_STATUS_SUCCESS)
|
||||
{
|
||||
lctrPcActTbl[pCtx->powerMonitorScheme](pCtx);
|
||||
pCtx->rssi = 0x80; /* Most negative 8 bit number. */
|
||||
}
|
||||
|
||||
switch (pCtx->powerMonitorScheme)
|
||||
{
|
||||
case LCTR_PC_MONITOR_AUTO:
|
||||
{
|
||||
/* Calculations handled on timer expiration for tmrPowerCtrl. */
|
||||
/* Use a positive value to hold accumulated RSSI, as RSSI will never be positive. */
|
||||
pCtx->pclMonitorParam.autoMonitor.accumulatedRssi += (uint32_t) (-(pCtx->rssi));
|
||||
pCtx->pclMonitorParam.autoMonitor.totalAccumulatedRssi++;
|
||||
break;
|
||||
}
|
||||
case LCTR_PC_MONITOR_PATH_LOSS:
|
||||
{
|
||||
/* Power control monitoring being enabled implies that this function exists. */
|
||||
lctrPathLossMonitorActFn(pCtx);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* Should not happen. */
|
||||
WSF_ASSERT(FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,6 +360,17 @@ void lctrMstConnEndOp(BbOpDesc_t *pOp)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Enhanced Connection Update. */
|
||||
uint16_t numIntervals = 0;
|
||||
if (lctrCalcSubrateConnEventsFn)
|
||||
{
|
||||
if ((numIntervals = lctrCalcSubrateConnEventsFn(pCtx, lctrMstConnIsr.numTxData + lctrMstConnIsr.numRxData)) > 0)
|
||||
{
|
||||
pCtx->eventCounter += numIntervals;
|
||||
lctrChSelHdlr[pCtx->usedChSel](pCtx, numIntervals - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (pCtx->data.mst.sendConnUpdInd)
|
||||
{
|
||||
uint8_t *pPdu;
|
||||
|
@ -344,8 +388,9 @@ void lctrMstConnEndOp(BbOpDesc_t *pOp)
|
|||
else
|
||||
#endif
|
||||
{
|
||||
ceOffset = LL_MIN_INSTANT + 1 + /* +1 for next CE */
|
||||
pCtx->maxLatency; /* ensure slave will listen this packet */
|
||||
ceOffset = ((LL_MIN_INSTANT + 1 + /* +1 for next CE */
|
||||
pCtx->maxLatency) * /* ensure slave will listen to this packet */
|
||||
pCtx->ecu.srFactor); /* include subrating factor */
|
||||
|
||||
/* TODO: accommodate pCtx->connParam.offset[]. */
|
||||
}
|
||||
|
@ -382,8 +427,7 @@ void lctrMstConnEndOp(BbOpDesc_t *pOp)
|
|||
|
||||
/*** Update for next operation ***/
|
||||
|
||||
uint32_t anchorPointUsec = pOp->dueUsec;
|
||||
uint16_t numIntervals = 0;
|
||||
uint32_t anchorPointUsec = pOp->dueUsec;
|
||||
|
||||
if (pBle->chan.tifsTxPhyOptions != BB_PHY_OPTIONS_DEFAULT)
|
||||
{
|
||||
|
@ -455,7 +499,7 @@ void lctrMstConnAbortOp(BbOpDesc_t *pOp)
|
|||
{
|
||||
lctrConnCtx_t * const pCtx = pOp->pCtx;
|
||||
|
||||
LL_TRACE_INFO2("!!! Connection Master BOD aborted, handle=%u, eventCounter=%u", LCTR_GET_CONN_HANDLE(pCtx), pCtx->eventCounter);
|
||||
LL_TRACE_WARN2("!!! Connection Master BOD aborted, handle=%u, eventCounter=%u", LCTR_GET_CONN_HANDLE(pCtx), pCtx->eventCounter);
|
||||
|
||||
/* Reset operation to state before BOD began */
|
||||
if (pCtx->emptyPduPend &&
|
||||
|
@ -470,6 +514,9 @@ void lctrMstConnAbortOp(BbOpDesc_t *pOp)
|
|||
return;
|
||||
}
|
||||
|
||||
lctrMstConnIsr.consCrcFailed = 0;
|
||||
lctrMstConnIsr.rxFromSlave = FALSE;
|
||||
|
||||
lctrMstConnEndOp(pOp);
|
||||
}
|
||||
|
||||
|
@ -488,6 +535,11 @@ void lctrMstConnTxCompletion(BbOpDesc_t *pOp, uint8_t status)
|
|||
lctrConnCtx_t * const pCtx = pOp->pCtx;
|
||||
|
||||
lctrSetControlPduAck(pCtx);
|
||||
|
||||
if (pCtx->txHdr.len)
|
||||
{
|
||||
lctrMstConnIsr.numTxData++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -571,6 +623,23 @@ void lctrMstConnRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status)
|
|||
|
||||
lctrUnpackDataPduHdr(&pCtx->rxHdr, pRxBuf);
|
||||
|
||||
/* Check for MIC failure and if this is not a re-transmission */
|
||||
if ((status == BB_STATUS_MIC_FAILED) &&
|
||||
((pCtx->rxHdr.sn ^ pCtx->txHdr.nesn) & 1) == 0)
|
||||
{
|
||||
LL_TRACE_WARN3("lctrMstConnRxCompletion: BB failed with status=MIC_FAILED, eventCounter=%u, bleChan=%u, handle=%u", pCtx->eventCounter, pCtx->bleData.chan.chanIdx, LCTR_GET_CONN_HANDLE(pCtx));
|
||||
lctrSendConnMsg(pCtx, LCTR_CONN_TERM_MIC_FAILED);
|
||||
/* Close connection event. */
|
||||
BbSetBodTerminateFlag();
|
||||
lctrRxPduFree(pRxBuf);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (pCtx->rxHdr.len)
|
||||
{
|
||||
lctrMstConnIsr.numRxData++;
|
||||
}
|
||||
|
||||
#if (LL_ENABLE_TESTER)
|
||||
if (llTesterCb.ackMode != LL_TESTER_ACK_MODE_NORMAL)
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -46,6 +46,13 @@
|
|||
WSF_CT_ASSERT((BB_FIXED_DATA_PKT_LEN == 0) ||
|
||||
(BB_FIXED_DATA_PKT_LEN >= LCTR_DATA_PDU_MAX_LEN));
|
||||
|
||||
/*! \brief Slave connection ISR control block. */
|
||||
static struct
|
||||
{
|
||||
uint16_t numTxData; /*!< Number of Tx data PDU in a single CE. */
|
||||
uint16_t numRxData; /*!< Number of Rx data PDU in a single CE. */
|
||||
} lctrSlvConnIsr;
|
||||
|
||||
/**************************************************************************************************
|
||||
Function Declarations
|
||||
**************************************************************************************************/
|
||||
|
@ -160,7 +167,7 @@ static void lctrSlvConnUpdateOp(lctrConnCtx_t *pCtx, bool_t ignoreOffset)
|
|||
pCtx->data.slv.txWinSizeUsec = txWinSizeUsec;
|
||||
|
||||
/* Add additional time due to Tx window size and WW due to Tx window offset. */
|
||||
pOp->minDurUsec += txWinSizeUsec + wwTxWinOffsetUsec;
|
||||
pOp->minDurUsec += wwTxWinOffsetUsec;
|
||||
|
||||
/*** BLE general setup ***/
|
||||
|
||||
|
@ -280,6 +287,25 @@ static void lctrSlvInitConnIsr(lctrConnCtx_t *pCtx)
|
|||
pCtx->data.slv.syncWithMaster = FALSE;
|
||||
pCtx->data.slv.rxFromMaster = FALSE;
|
||||
pCtx->data.slv.firstRxStartTsUsec = 0;
|
||||
|
||||
lctrSlvConnIsr.numTxData = 0;
|
||||
lctrSlvConnIsr.numRxData = 0;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Pack a channel status message.
|
||||
*
|
||||
* \param pBuf Packed buffer.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void lctrPackChannelStatusMsg(uint8_t *pBuf)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < LL_MAX_NUM_CHAN_DATA; i++)
|
||||
{
|
||||
UINT8_TO_BSTREAM(pBuf, (((UINT64_C(1) << i) & lmgrCb.chanClass) ? LL_CH_CLASS_UNKNOWN : LL_CH_CLASS_BAD));
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -308,7 +334,8 @@ void lctrSlvConnBeginOp(BbOpDesc_t *pOp)
|
|||
pLctrVsHdlrs->ceSetup(LCTR_GET_CONN_HANDLE(pCtx));
|
||||
}
|
||||
|
||||
/*** Initialize connection event resources. ***/
|
||||
/*** Initialize connection event resources ***/
|
||||
|
||||
lctrSlvInitConnIsr(pCtx);
|
||||
|
||||
/*** Setup receiver ***/
|
||||
|
@ -364,13 +391,35 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp)
|
|||
}
|
||||
|
||||
pCtx->rssi = pConn->rssi;
|
||||
|
||||
if ((pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) &&
|
||||
(pCtx->lastRxStatus == BB_STATUS_SUCCESS))
|
||||
if (pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED)
|
||||
{
|
||||
if (lctrPcActTbl[pCtx->powerMonitorScheme])
|
||||
|
||||
/* If a packet did not receive for whatever reason, add a datapoint with the lowest RSSI. */
|
||||
if (pCtx->lastRxStatus != BB_STATUS_SUCCESS)
|
||||
{
|
||||
lctrPcActTbl[pCtx->powerMonitorScheme](pCtx);
|
||||
pCtx->rssi = 0x80; /* Most negative 8 bit number. */
|
||||
}
|
||||
|
||||
switch (pCtx->powerMonitorScheme)
|
||||
{
|
||||
case LCTR_PC_MONITOR_AUTO:
|
||||
{
|
||||
/* Calculations handled on timer expiration for tmrPowerCtrl. */
|
||||
/* Use a positive value to hold accumulated RSSI, as RSSI will never be positive. */
|
||||
pCtx->pclMonitorParam.autoMonitor.accumulatedRssi += (uint32_t) (-(pCtx->rssi));
|
||||
pCtx->pclMonitorParam.autoMonitor.totalAccumulatedRssi++;
|
||||
break;
|
||||
}
|
||||
case LCTR_PC_MONITOR_PATH_LOSS:
|
||||
{
|
||||
/* Power control monitoring being enabled implies that this function exists. */
|
||||
lctrPathLossMonitorActFn(pCtx);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* Should not happen. */
|
||||
WSF_ASSERT(FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -393,6 +442,14 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp)
|
|||
lctrStoreConnTimeoutTerminateReason(pCtx);
|
||||
WsfTimerStartMs(&pCtx->tmrSupTimeout, pCtx->supTimeoutMs);
|
||||
|
||||
if (!lmgrGetOpFlag(LL_OP_MODE_FLAG_ENA_FEAT_LLCP_STARTUP) &&
|
||||
(pCtx->monitoringState == LCTR_PC_MONITOR_ENABLED) &&
|
||||
(pCtx->powerMonitorScheme == LCTR_PC_MONITOR_AUTO) &&
|
||||
!lmgrGetOpFlag(LL_OP_MODE_FLAG_DIS_POWER_MONITOR))
|
||||
{
|
||||
WsfTimerStartMs(&pCtx->tmrPowerCtrl, LL_PC_SERVICE_MS);
|
||||
}
|
||||
|
||||
pCtx->connEst = TRUE;
|
||||
}
|
||||
else if (pCtx->data.slv.rxFromMaster)
|
||||
|
@ -447,8 +504,7 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp)
|
|||
}
|
||||
}
|
||||
|
||||
/* Slave received connection update on the instant. */
|
||||
/* Immediately use that packet as the new anchor point and do not apply txWinOffset and txWinSize. */
|
||||
/* Check if channel status update is required. */
|
||||
if ((pCtx->llcpActiveProc == LCTR_PROC_CONN_UPD) && lctrSlvCheckConnUpdInstant(pCtx) &&
|
||||
(pCtx->eventCounter == pCtx->connUpd.instant))
|
||||
{
|
||||
|
@ -456,32 +512,68 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp)
|
|||
LL_TRACE_WARN1("Received connection update at instant, applying immediately at CE=%d", pCtx->eventCounter);
|
||||
}
|
||||
|
||||
/* If the channel map has changed since the last time, */
|
||||
/* Send master the status indication. */
|
||||
if (pCtx->chanStatRptEnable && pCtx->data.slv.queuedChanStatusTs &&
|
||||
(BbGetTargetTimeDelta(pOp->dueUsec, pCtx->data.slv.lastStatusSentTs) > pCtx->data.slv.chanStatMinIntUs))
|
||||
{
|
||||
/* Make sure that the report has not passed the max delay parameter. */
|
||||
if (BbGetTargetTimeDelta(pOp->dueUsec, pCtx->data.slv.queuedChanStatusTs) < pCtx->data.slv.chanStatMaxDelay)
|
||||
{
|
||||
pCtx->data.slv.lastStatusSentTs = pOp->dueUsec;
|
||||
|
||||
lctrMsgChStatusInd_t *pMsg;
|
||||
if ((pMsg = (lctrMsgChStatusInd_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL)
|
||||
{
|
||||
pMsg->hdr.handle = LCTR_GET_CONN_HANDLE(pCtx);
|
||||
pMsg->hdr.dispId = LCTR_DISP_CONN;
|
||||
pMsg->hdr.event = LCTR_CONN_LLCP_CHANNEL_STATUS;
|
||||
|
||||
lctrPackChannelStatusMsg(pMsg->chanStatus);
|
||||
|
||||
WsfMsgSend(lmgrPersistCb.handlerId, pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the timestamp to signal that there is no pending status report. */
|
||||
pCtx->data.slv.queuedChanStatusTs = 0;
|
||||
}
|
||||
|
||||
/*** Update for next operation ***/
|
||||
|
||||
uint16_t numUnsyncIntervals = pCtx->eventCounter - pCtx->data.slv.lastActiveEvent + 1;
|
||||
|
||||
uint16_t numSkipCe = 0;
|
||||
uint16_t numSkipSr = 0;
|
||||
uint16_t srLatency = pCtx->maxLatency;
|
||||
|
||||
/* Enhanced Connection Update. */
|
||||
if (lctrCalcSubrateConnEventsFn)
|
||||
{
|
||||
numSkipSr = lctrCalcSubrateConnEventsFn(pCtx, lctrSlvConnIsr.numTxData + lctrSlvConnIsr.numRxData);
|
||||
srLatency = (pCtx->maxLatency * pCtx->ecu.srFactor) + numSkipSr;
|
||||
}
|
||||
|
||||
if ((pCtx->data.slv.abortSlvLatency == FALSE) &&
|
||||
lctrGetConnOpFlag(pCtx, LL_OP_MODE_FLAG_ENA_SLV_LATENCY) &&
|
||||
(pCtx->maxLatency &&
|
||||
pCtx->data.slv.initAckRcvd &&
|
||||
pCtx->data.slv.rxFromMaster &&
|
||||
(WsfQueueEmpty(&pCtx->txArqQ)) &&
|
||||
(pCtx->state != LCTR_CONN_STATE_TERMINATING)))
|
||||
pCtx->maxLatency &&
|
||||
pCtx->data.slv.initAckRcvd &&
|
||||
pCtx->data.slv.rxFromMaster &&
|
||||
WsfQueueEmpty(&pCtx->txArqQ) &&
|
||||
(pCtx->state != LCTR_CONN_STATE_TERMINATING))
|
||||
{
|
||||
if (pCtx->llcpActiveProc == LCTR_PROC_INVALID)
|
||||
{
|
||||
numSkipCe = pCtx->maxLatency;
|
||||
numSkipCe = srLatency;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Still apply the slave latency if the instant is not reached for the following LLCPs. */
|
||||
if ((pCtx->llcpActiveProc == LCTR_PROC_CONN_UPD) && lctrSlvCheckConnUpdInstant(pCtx))
|
||||
{
|
||||
if ((uint16_t)(pCtx->connUpd.instant - pCtx->eventCounter) > (pCtx->maxLatency + 1))
|
||||
if ((uint16_t)(pCtx->connUpd.instant - pCtx->eventCounter) > (srLatency + 1))
|
||||
{
|
||||
numSkipCe = pCtx->maxLatency;
|
||||
numSkipCe = srLatency;
|
||||
}
|
||||
else if ((pCtx->connUpd.instant - pCtx->eventCounter) > 1)
|
||||
{
|
||||
|
@ -492,9 +584,9 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp)
|
|||
else if ((pCtx->llcpActiveProc == LCTR_PROC_CMN_CH_MAP_UPD) &&
|
||||
(pCtx->cmnState == LCTR_CMN_STATE_BUSY))
|
||||
{
|
||||
if ((uint16_t)(pCtx->chanMapUpd.instant - pCtx->eventCounter) > (pCtx->maxLatency + 1))
|
||||
if ((uint16_t)(pCtx->chanMapUpd.instant - pCtx->eventCounter) > (srLatency + 1))
|
||||
{
|
||||
numSkipCe = pCtx->maxLatency;
|
||||
numSkipCe = srLatency;
|
||||
}
|
||||
else if ((pCtx->chanMapUpd.instant - pCtx->eventCounter) > 1)
|
||||
{
|
||||
|
@ -504,9 +596,9 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp)
|
|||
}
|
||||
else if ((pCtx->llcpActiveProc == LCTR_PROC_PHY_UPD) && (pCtx->isSlvPhyUpdInstant == TRUE))
|
||||
{
|
||||
if ((uint16_t)(pCtx->phyUpd.instant - pCtx->eventCounter) > (pCtx->maxLatency + 1))
|
||||
if ((uint16_t)(pCtx->phyUpd.instant - pCtx->eventCounter) > (srLatency + 1))
|
||||
{
|
||||
numSkipCe = pCtx->maxLatency;
|
||||
numSkipCe = srLatency;
|
||||
}
|
||||
else if ((pCtx->phyUpd.instant - pCtx->eventCounter) > 1)
|
||||
{
|
||||
|
@ -516,15 +608,23 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp)
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No slave latency; listen at the next subrated connection events. */
|
||||
numSkipCe = numSkipSr;
|
||||
}
|
||||
|
||||
if (numSkipCe > 0)
|
||||
{
|
||||
if (numSkipCe > numSkipSr)
|
||||
{
|
||||
LL_TRACE_INFO2("Applying slave latency, last attended eventCounter=%u, wake up at eventCounter=%u", pCtx->eventCounter, pCtx->eventCounter + numSkipCe + 1);
|
||||
}
|
||||
|
||||
pCtx->eventCounter += numSkipCe;
|
||||
numUnsyncIntervals += numSkipCe;
|
||||
|
||||
lctrChSelHdlr[pCtx->usedChSel](pCtx, numSkipCe - 1);
|
||||
|
||||
LL_TRACE_INFO2("Applying slave latency, waking up at eventCounter=%u, numSkipCE=%u", pCtx->eventCounter + 1, numSkipCe);
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
|
@ -551,7 +651,9 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp)
|
|||
/* Advance to next interval. */
|
||||
pOp->dueUsec = pCtx->data.slv.anchorPointUsec + connInterUsec - wwTotalUsec;
|
||||
|
||||
pOp->minDurUsec = pCtx->data.slv.txWinSizeUsec + pCtx->effConnDurUsec + wwTotalUsec;
|
||||
/* Use small minDurUsec to improve scheduling. */
|
||||
pOp->minDurUsec = pCtx->data.slv.txWinSizeUsec + (2 * LL_MAX_DATA_TIME_MIN) + LL_BLE_TIFS_US + wwTotalUsec;
|
||||
|
||||
pConn->rxSyncDelayUsec = pCtx->data.slv.txWinSizeUsec + (wwTotalUsec << 1);
|
||||
|
||||
if ((pCtx->llcpActiveProc == LCTR_PROC_CONN_UPD) &&
|
||||
|
@ -568,12 +670,12 @@ void lctrSlvConnEndOp(BbOpDesc_t *pOp)
|
|||
lctrSlvConnUpdateOp(pCtx, FALSE);
|
||||
}
|
||||
else if ((pCtx->llcpActiveProc == LCTR_PROC_CMN_CH_MAP_UPD) &&
|
||||
(pCtx->eventCounter == pCtx->chanMapUpd.instant))
|
||||
(pCtx->eventCounter == pCtx->chanMapUpd.instant))
|
||||
{
|
||||
lctrSlvChanMapUpdateOp(pCtx);
|
||||
}
|
||||
else if ((pCtx->llcpActiveProc == LCTR_PROC_PHY_UPD) &&
|
||||
(pCtx->eventCounter == pCtx->phyUpd.instant))
|
||||
(pCtx->eventCounter == pCtx->phyUpd.instant))
|
||||
{
|
||||
lctrSlvPhyUpdateOp(pCtx);
|
||||
}
|
||||
|
@ -620,6 +722,8 @@ void lctrSlvConnAbortOp(BbOpDesc_t *pOp)
|
|||
{
|
||||
lctrConnCtx_t * const pCtx = pOp->pCtx;
|
||||
|
||||
LL_TRACE_WARN2("!!! Connection Slave BOD aborted, handle=%u, eventCounter=%u", LCTR_GET_CONN_HANDLE(pCtx), pCtx->eventCounter);
|
||||
|
||||
lctrSlvInitConnIsr(pCtx);
|
||||
lctrSlvConnEndOp(pOp);
|
||||
}
|
||||
|
@ -639,6 +743,11 @@ void lctrSlvConnTxCompletion(BbOpDesc_t *pOp, uint8_t status)
|
|||
lctrConnCtx_t * const pCtx = pOp->pCtx;
|
||||
|
||||
lctrSetControlPduAck(pCtx);
|
||||
|
||||
if (pCtx->txHdr.len)
|
||||
{
|
||||
lctrSlvConnIsr.numTxData++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -693,12 +802,12 @@ void lctrSlvConnRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status)
|
|||
{
|
||||
if (status == BB_STATUS_RX_TIMEOUT)
|
||||
{
|
||||
LL_TRACE_WARN3("lctrSlvConnRxCompletion: BB failed with status=RX_TIMEOUT, handle=%u, bleChan=%u, eventCounter=%u", LCTR_GET_CONN_HANDLE(pCtx), pBle->chan.chanIdx, pCtx->eventCounter);
|
||||
LL_TRACE_WARN3("lctrSlvConnRxCompletion: BB failed with status=RX_TIMEOUT, eventCounter=%u, bleChan=%u, handle=%u", pCtx->eventCounter, pCtx->bleData.chan.chanIdx, LCTR_GET_CONN_HANDLE(pCtx));
|
||||
}
|
||||
|
||||
if (status == BB_STATUS_FAILED)
|
||||
{
|
||||
LL_TRACE_ERR3("lctrSlvConnRxCompletion: BB failed with status=FAILED, handle=%u, bleChan=%u, eventCounter=%u", LCTR_GET_CONN_HANDLE(pCtx), pBle->chan.chanIdx, pCtx->eventCounter);
|
||||
LL_TRACE_ERR3("lctrSlvConnRxCompletion: BB failed with status=FAILED, eventCounter=%u, bleChan=%u, handle=%u", pCtx->eventCounter, pCtx->bleData.chan.chanIdx, LCTR_GET_CONN_HANDLE(pCtx));
|
||||
}
|
||||
|
||||
BbSetBodTerminateFlag();
|
||||
|
@ -741,6 +850,23 @@ void lctrSlvConnRxCompletion(BbOpDesc_t *pOp, uint8_t *pRxBuf, uint8_t status)
|
|||
|
||||
lctrUnpackDataPduHdr(&pCtx->rxHdr, pRxBuf);
|
||||
|
||||
/* Check for MIC failure and if this is not a re-transmission */
|
||||
if ((status == BB_STATUS_MIC_FAILED) &&
|
||||
((pCtx->rxHdr.sn ^ pCtx->txHdr.nesn) & 1) == 0)
|
||||
{
|
||||
LL_TRACE_WARN3("lctrSlvConnRxCompletion: BB failed with status=MIC_FAILED, eventCounter=%u, bleChan=%u, handle=%u", pCtx->eventCounter, pCtx->bleData.chan.chanIdx, LCTR_GET_CONN_HANDLE(pCtx));
|
||||
lctrSendConnMsg(pCtx, LCTR_CONN_TERM_MIC_FAILED);
|
||||
/* Close connection event. */
|
||||
BbSetBodTerminateFlag();
|
||||
lctrRxPduFree(pRxBuf);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (pCtx->rxHdr.len)
|
||||
{
|
||||
lctrSlvConnIsr.numRxData++;
|
||||
}
|
||||
|
||||
/* Check LLID from master. */
|
||||
if ((pCtx->isSlvReadySent == FALSE) &&
|
||||
(pCtx->rxHdr.llid != LL_LLID_CTRL_PDU) &&
|
||||
|
|
|
@ -414,6 +414,16 @@ void lctrRegisterChClassHandler(lctrChClassHdlr_t cback)
|
|||
{
|
||||
/* Ensure registration does not exceed limits. */
|
||||
WSF_ASSERT(lctrChClassHandlerCnt < LCTR_NUM_CH_CLASS_HANDLERS);
|
||||
|
||||
/* If callback is already registered, do nothing. */
|
||||
for (unsigned int i = 0; i < lctrChClassHandlerCnt; i++)
|
||||
{
|
||||
if (lctrChClassHandlerTbl[0] == cback)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
lctrChClassHandlerTbl[lctrChClassHandlerCnt++] = cback;
|
||||
}
|
||||
|
||||
|
@ -451,3 +461,42 @@ uint8_t LctrSetChannelClass(uint64_t chanMap)
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Get average RSSI of an averaging unit.
|
||||
*
|
||||
* \param pAvg Average block
|
||||
*
|
||||
* \return Average block average.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
int8_t lctrRssiGetAverage(lctrRssiRunAvg_t *pAvg)
|
||||
{
|
||||
WSF_ASSERT(pAvg->avgCount >= LL_PC_TBL_LEN);
|
||||
|
||||
int32_t total = 0;
|
||||
for (int i = 0; i < LL_PC_TBL_LEN; i++)
|
||||
{
|
||||
total += (int32_t) pAvg->averageRssi[i];
|
||||
}
|
||||
|
||||
return (int8_t) (total >> LL_PC_TBL_POW);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Add a value to the average block.
|
||||
*
|
||||
* \param pAvg Average block
|
||||
* \param value Value to add
|
||||
*
|
||||
* \note oldest value will be overwritten.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void lctrRssiAddAveragePoint(lctrRssiRunAvg_t *pAvg, int8_t value)
|
||||
{
|
||||
pAvg->averageRssi[pAvg->rssiIdx] = value;
|
||||
pAvg->rssiIdx = ((pAvg->rssiIdx + 1) == LL_PC_TBL_LEN) ? 0 : (pAvg->rssiIdx + 1);
|
||||
pAvg->avgCount++;
|
||||
}
|
||||
|
|
|
@ -275,6 +275,7 @@ void lctrMstDiscoverBuildOp(void)
|
|||
pOp->pCtx = &lctrMstScan;
|
||||
pOp->endCback = lctrMstDiscoverEndOp;
|
||||
pOp->abortCback = lctrMstDiscoverEndOp;
|
||||
pOp->recoverable = TRUE;
|
||||
|
||||
/*** BLE General Setup ***/
|
||||
|
||||
|
@ -415,6 +416,9 @@ void lctrMstDiscoverBuildOp(void)
|
|||
|
||||
SchInsertNextAvailable(pOp);
|
||||
lctrMstScan.scanWinStartUsec = pOp->dueUsec;
|
||||
|
||||
LL_TRACE_INFO1(" >>> Discover started, dueUsec=%u <<<", pOp->dueUsec);
|
||||
LL_TRACE_INFO1(" pBod=0x%08x", pOp);
|
||||
}
|
||||
|
||||
|
||||
|
@ -740,13 +744,13 @@ void LctrMstScanDefaults(void)
|
|||
/*************************************************************************************************/
|
||||
void lctrAdvReportsInc(void)
|
||||
{
|
||||
WSF_CS_INIT();
|
||||
WSF_CS_INIT(cs);
|
||||
|
||||
WSF_ASSERT(lmgrMstScanCb.numAdvReport < pLctrRtCfg->maxAdvReports);
|
||||
|
||||
WSF_CS_ENTER();
|
||||
WSF_CS_ENTER(cs);
|
||||
lmgrMstScanCb.numAdvReport++;
|
||||
WSF_CS_EXIT();
|
||||
WSF_CS_EXIT(cs);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -756,13 +760,13 @@ void lctrAdvReportsInc(void)
|
|||
/*************************************************************************************************/
|
||||
void lctrAdvReportsDec(void)
|
||||
{
|
||||
WSF_CS_INIT();
|
||||
WSF_CS_INIT(cs);
|
||||
|
||||
WSF_ASSERT(lmgrMstScanCb.numAdvReport > 0);
|
||||
|
||||
WSF_CS_ENTER();
|
||||
WSF_CS_ENTER(cs);
|
||||
lmgrMstScanCb.numAdvReport--;
|
||||
WSF_CS_EXIT();
|
||||
WSF_CS_EXIT(cs);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -437,6 +437,7 @@ uint8_t lctrMstExtDiscoverBuildOp(lctrExtScanCtx_t *pExtScanCtx)
|
|||
pOp->endCback = lctrMstExtDiscoverEndOp;
|
||||
pOp->abortCback = lctrMstExtDiscoverAbortOp;
|
||||
pOp->pCtx = pExtScanCtx;
|
||||
pOp->recoverable = TRUE;
|
||||
|
||||
/*** BLE General Setup ***/
|
||||
|
||||
|
@ -486,6 +487,9 @@ uint8_t lctrMstExtDiscoverBuildOp(lctrExtScanCtx_t *pExtScanCtx)
|
|||
|
||||
pScan->rxAdvCback = lctrMstDiscoverRxExtAdvPktHandler;
|
||||
pScan->rxAdvPostCback = lctrMstDiscoverRxExtAdvPktPostProcessHandler;
|
||||
pScan->auxScanCheckCback = lctrMstLinkAuxOffsetScanSetup;
|
||||
pScan->auxScanTxCompCback = BbMstAuxScanTxCompHandler;
|
||||
pScan->auxScanRxCompCback = BbMstAuxScanRxCompHandler;
|
||||
|
||||
if ((pScan->pRxAdvBuf = WsfMsgAlloc(LL_ADV_HDR_LEN + LL_EXT_ADV_HDR_MAX_LEN)) == NULL)
|
||||
{
|
||||
|
@ -607,6 +611,10 @@ uint8_t lctrMstExtDiscoverBuildOp(lctrExtScanCtx_t *pExtScanCtx)
|
|||
|
||||
lctrActiveExtScan.scanMask |= (1 << scanPhyIndex);
|
||||
|
||||
LL_TRACE_INFO1(" >>> ExtDiscover started, handle=%u <<<", LCTR_GET_EXT_SCAN_HANDLE(pExtScanCtx));
|
||||
LL_TRACE_INFO1(" dueUsec=%u, 0=deferred", pOp->dueUsec);
|
||||
LL_TRACE_INFO1(" pBod=0x%08x", pOp);
|
||||
|
||||
return LL_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -673,6 +681,7 @@ uint8_t lctrMstAuxDiscoverBuildOp(lctrExtScanCtx_t *pExtScanCtx)
|
|||
|
||||
pAuxScan->isInit = FALSE;
|
||||
pAuxScan->rxAuxAdvCback = lctrMstDiscoverRxAuxAdvPktHandler;
|
||||
pAuxScan->rxAuxAdvPostCback = lctrMstDiscoverRxAuxAdvPktPostProcessHandler;
|
||||
|
||||
/*** BLE Scan Setup: Tx scan request packet ***/
|
||||
|
||||
|
@ -731,7 +740,7 @@ uint8_t lctrMstAuxDiscoverBuildOp(lctrExtScanCtx_t *pExtScanCtx)
|
|||
|
||||
/*** Commit operation ***/
|
||||
|
||||
/* pOp->minDurUsec = 0; */ /* Defer assignment until AuxPtr is received. */
|
||||
/* pOp->minDurUsec = 0; */ /* Defer assignment until AuxPtr is received, lctrMstAuxDiscoverOpCommit(). */
|
||||
/* pOp->maxDurUsec = 0; */ /* Not used for aux scan. */
|
||||
|
||||
pExtScanCtx->selfTerm = FALSE;
|
||||
|
@ -740,6 +749,8 @@ uint8_t lctrMstAuxDiscoverBuildOp(lctrExtScanCtx_t *pExtScanCtx)
|
|||
|
||||
/* Defer scheduling until AuxPtr is received. */
|
||||
|
||||
LL_TRACE_INFO1(" >>> AuxDiscover ready, pBod=0x%08x <<<", pOp);
|
||||
|
||||
return LL_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -783,7 +794,12 @@ void lctrMstAuxDiscoverOpCommit(lctrExtScanCtx_t *pExtScanCtx, lctrAuxPtr_t *pAu
|
|||
pOp->dueUsec = startTs + auxOffsetUsec;
|
||||
SchBleCalcAdvOpDuration(pOp, 0);
|
||||
|
||||
if (SchInsertAtDueTime(pOp, NULL))
|
||||
if (auxOffsetUsec < BbGetSchSetupDelayUs())
|
||||
{
|
||||
/* Signal the lower layer to start Aux Scan ASAP, since the auxOffset is too small to run the scheduler. */
|
||||
pExtScanCtx->scheduleAuxAsap = TRUE;
|
||||
}
|
||||
else if (SchInsertAtDueTime(pOp, NULL))
|
||||
{
|
||||
pExtScanCtx->auxOpPending = TRUE;
|
||||
}
|
||||
|
@ -879,7 +895,7 @@ void LctrMstExtScanDefaults(void)
|
|||
uint16_t LctrInitExtScanMem(uint8_t *pFreeMem, uint32_t freeMemSize)
|
||||
{
|
||||
/* Extended Scanning requires receiving at least 251 bytes. */
|
||||
WSF_ASSERT(pLctrRtCfg->maxExtScanDataLen >= LL_EXT_ADVBU_MAX_LEN);
|
||||
WSF_ASSERT(pLctrRtCfg->maxExtScanDataLen >= WSF_MIN(LL_EXT_ADVBU_MAX_LEN, BB_ADV_PLD_MAX_LEN));
|
||||
|
||||
uint8_t *pAvailMem = pFreeMem;
|
||||
|
||||
|
@ -1307,7 +1323,7 @@ void lctrMstPerScanOpCommit(lctrExtScanCtx_t *pExtScanCtx, lctrAuxPtr_t *pAuxPtr
|
|||
pOp->dueUsec = startTs + syncOffsetUsec;
|
||||
|
||||
/* Ensure minimum packet is scheduled; allow PerAdv to schedule tight operations. */
|
||||
pPerScanCtx->minDurUsec = pOp->minDurUsec = SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, BB_PHY_OPTIONS_DEFAULT, LL_ADVB_MIN_LEN);
|
||||
pPerScanCtx->minDurUsec = pOp->minDurUsec = SchBleCalcAdvPktDurationUsec(pBle->chan.rxPhy, BB_PHY_OPTIONS_DEFAULT, LL_EXT_ADV_HDR_MIN_LEN);
|
||||
uint16_t numUnsyncIntervals = 0;
|
||||
|
||||
while (TRUE)
|
||||
|
@ -1315,7 +1331,6 @@ void lctrMstPerScanOpCommit(lctrExtScanCtx_t *pExtScanCtx, lctrAuxPtr_t *pAuxPtr
|
|||
if (SchInsertAtDueTime(pOp, lctrPerScanResolveConflict))
|
||||
{
|
||||
LL_TRACE_INFO1(" >>> Periodic scan started, handle=%u <<<", LCTR_GET_PER_SCAN_HANDLE(pPerScanCtx));
|
||||
LL_TRACE_INFO1(" pOp=%08x", pOp);
|
||||
LL_TRACE_INFO1(" dueUsec=%u", pOp->dueUsec);
|
||||
LL_TRACE_INFO1(" eventCounter=%u", pPerScanCtx->eventCounter);
|
||||
LL_TRACE_INFO1(" chanIdx=%u", pBle->chan.chanIdx);
|
||||
|
@ -1360,7 +1375,7 @@ void lctrMstPerScanTransferOpCommit(uint16_t connHandle)
|
|||
uint32_t refTime;
|
||||
uint16_t peC; /* paEventCounter for the AUX_SYNC_IND PDU that we are attempting to receive. */
|
||||
uint32_t startTs; /* Anchor point of the connection event. */
|
||||
uint16_t numInterval;
|
||||
uint32_t numInterval;
|
||||
|
||||
/* Pre-resolve common structures for efficient access. */
|
||||
lctrPerScanCtx_t *pPerScanCtx = lctrPerTransferSync.pPerScanCtx;
|
||||
|
@ -1373,6 +1388,12 @@ void lctrMstPerScanTransferOpCommit(uint16_t connHandle)
|
|||
pPerScanCtx->repDisabled = TRUE;
|
||||
}
|
||||
|
||||
if (pConnCtx->syncMode == LL_SYNC_TRSF_MODE_DUP_FILTERED)
|
||||
{
|
||||
pPerScanCtx->dupFilterEnable = TRUE;
|
||||
pPerScanCtx->lastDid = LL_DID_NOT_PRESENT;
|
||||
}
|
||||
|
||||
pPerScanCtx->syncTimeOutMs = LCTR_PER_SYNC_TIMEOUT_TO_MS(pConnCtx->syncTimeout);
|
||||
pPerScanCtx->skip = pConnCtx->syncSkip;
|
||||
pPerScanCtx->sca = trsfSyncInfo.sca;
|
||||
|
@ -1409,16 +1430,16 @@ void lctrMstPerScanTransferOpCommit(uint16_t connHandle)
|
|||
startTs = lctrConnGetAnchorPoint(pConnCtx, pConnCtx->eventCounter);
|
||||
peC = trsfSyncInfo.eventCounter;
|
||||
|
||||
if (BbGetTargetTimeDelta(refTime, startTs + pConnOp->minDurUsec) > 0)
|
||||
if ((uint16_t)(lctrPerTransferSync.ceRef - pConnCtx->eventCounter) < (uint16_t)LCTR_MAX_INSTANT) /* ceCounter is in the future. */
|
||||
{
|
||||
numInterval = BbGetTargetTimeDelta(refTime, startTs + pConnOp->minDurUsec) / pPerScanCtx->perInterUsec;
|
||||
numInterval = ((uint16_t)(lctrPerTransferSync.ceRef - pConnCtx->eventCounter) * LCTR_CONN_IND_US(pConnCtx->connInterval) + pConnOp->minDurUsec) / pPerScanCtx->perInterUsec;
|
||||
refTime -= numInterval * pPerScanCtx->perInterUsec;
|
||||
peC -= numInterval;
|
||||
offsetUsec = BbGetTargetTimeDelta(refTime , startTs);
|
||||
}
|
||||
else /* refTime is in the past. */
|
||||
{
|
||||
numInterval = 1 + BbGetTargetTimeDelta(startTs + pConnOp->minDurUsec, refTime)/ pPerScanCtx->perInterUsec;
|
||||
numInterval = 1 + ((uint16_t)(pConnCtx->eventCounter - lctrPerTransferSync.ceRef) * LCTR_CONN_IND_US(pConnCtx->connInterval) + pConnOp->minDurUsec) / pPerScanCtx->perInterUsec;
|
||||
refTime += numInterval * pPerScanCtx->perInterUsec;
|
||||
peC += numInterval;
|
||||
offsetUsec = BbGetTargetTimeDelta(refTime , startTs);
|
||||
|
@ -1463,7 +1484,6 @@ void lctrMstPerScanTransferOpCommit(uint16_t connHandle)
|
|||
if (SchInsertAtDueTime(pOp, lctrPerScanResolveConflict))
|
||||
{
|
||||
LL_TRACE_INFO1(" >>> Periodic scan from transfer started, handle=%u <<<", LCTR_GET_PER_SCAN_HANDLE(pPerScanCtx));
|
||||
LL_TRACE_INFO1(" pOp=%08x", pOp);
|
||||
LL_TRACE_INFO1(" dueUsec=%u", pOp->dueUsec);
|
||||
LL_TRACE_INFO1(" eventCounter=%u", pPerScanCtx->eventCounter);
|
||||
LL_TRACE_INFO1(" pBle->chan.chanIdx=%u", pBle->chan.chanIdx);
|
||||
|
@ -1568,6 +1588,9 @@ lctrPerScanCtx_t *lctrAllocPerScanCtx(void)
|
|||
/* Default PHY. */
|
||||
pCtx->rxPhys = lmgrConnCb.rxPhys;
|
||||
|
||||
/* ADI filtering. */
|
||||
pCtx->lastDid = LL_DID_NOT_PRESENT;
|
||||
|
||||
return pCtx;
|
||||
}
|
||||
}
|
||||
|
@ -1602,8 +1625,6 @@ BbOpDesc_t *lctrPerScanResolveConflict(BbOpDesc_t *pNewOp, BbOpDesc_t *pExistOp)
|
|||
}
|
||||
|
||||
/* Supervision timeout is imminent (2 PI). */
|
||||
LL_TRACE_WARN2("Exit timeout=%u, interval=%u", pExistCtx->tmrSupTimeout.ticks * WSF_MS_PER_TICK * 1000, (uint32_t)(pExistCtx->perInterUsec << 1));
|
||||
LL_TRACE_WARN2("New timeout=%u, interval=%u", pNewCtx->tmrSupTimeout.ticks * WSF_MS_PER_TICK * 1000, (uint32_t)(pExistCtx->perInterUsec << 1));
|
||||
if ((pExistCtx->tmrSupTimeout.ticks * WSF_MS_PER_TICK * 1000) < (uint32_t)(pExistCtx->perInterUsec << 1))
|
||||
{
|
||||
LL_TRACE_WARN2("!!! Scheduling conflict, imminent SVT: existing handle=%u prioritized over incoming handle=%u", LCTR_GET_PER_SCAN_HANDLE(pExistCtx), LCTR_GET_PER_SCAN_HANDLE(pNewCtx));
|
||||
|
@ -1617,7 +1638,6 @@ BbOpDesc_t *lctrPerScanResolveConflict(BbOpDesc_t *pNewOp, BbOpDesc_t *pExistOp)
|
|||
}
|
||||
|
||||
/* Less frequent perInterval (4x). */
|
||||
|
||||
if ((LCTR_PER_INTER_TO_MS(pExistCtx->perInterUsec) >> 2) > LCTR_PER_INTER_TO_MS(pNewCtx->perInterUsec))
|
||||
{
|
||||
LL_TRACE_WARN2("!!! Scheduling conflict, PI frequency: existing handle=%u prioritized over incoming handle=%u", LCTR_GET_PER_SCAN_HANDLE(pExistCtx), LCTR_GET_PER_SCAN_HANDLE(pNewCtx));
|
||||
|
@ -1698,13 +1718,17 @@ void LctrSendPerSyncTrsfRcvdEvt(uint8_t status, lctrPerScanCtx_t *pPerScanCtx)
|
|||
* \brief Enable or disable reports for the periodic advertising sync.
|
||||
*
|
||||
* \param syncHandle Periodic sync handle.
|
||||
* \param enable Enable or disable reporting.
|
||||
* \param enable Enable options.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void LctrMstPerSetRcvEnable(uint16_t syncHandle, bool_t enable)
|
||||
void LctrMstPerSetRcvEnable(uint16_t syncHandle, uint8_t enable)
|
||||
{
|
||||
WSF_ASSERT(syncHandle < LL_MAX_PER_SCAN);
|
||||
lctrPerScanCtx_t *pPerScanCtx = LCTR_GET_PER_SCAN_CTX(syncHandle);
|
||||
|
||||
pPerScanCtx->repDisabled = !enable;
|
||||
pPerScanCtx->repDisabled = !((bool_t) ((enable >> LCTR_PER_RECV_ENABLE_REPORT_BIT_POS) & 1));
|
||||
if (!pPerScanCtx->repDisabled)
|
||||
{
|
||||
pPerScanCtx->dupFilterEnable = (bool_t) ((enable >> LCTR_PER_RECV_ENABLE_FILTERING_BIT_POS) & 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -190,16 +190,18 @@ void lctrChooseAdvA(BbBleData_t * const pBle, lctrAdvbPduHdr_t *pPduHdr,
|
|||
void lctrChoosePeerAddr(BbBleData_t * const pBle, uint8_t ownAddrType,
|
||||
uint8_t peerAddrType, uint64_t peerAddr, uint64_t *pPeerRpa)
|
||||
{
|
||||
/* Attempt to generate RPA for peer. */
|
||||
BbBleResListGeneratePeer(peerAddrType, peerAddr, pPeerRpa);
|
||||
|
||||
/* Resolve peer RPAs whether or not a RPA was generated for peer, unless address resolution is disabled. */
|
||||
if (lmgrCb.addrResEna)
|
||||
{
|
||||
/* Attempt to generate RPA for peer. */
|
||||
if (ownAddrType & LL_ADDR_IDENTITY_BIT)
|
||||
{
|
||||
BbBleResListGeneratePeer(peerAddrType, peerAddr, pPeerRpa);
|
||||
}
|
||||
/* Resolve peer RPAs whether or not a RPA was generated for peer. */
|
||||
BB_BLE_PDU_FILT_SET_FLAG(&pBle->pduFilt, PEER_ADDR_RES_ENA);
|
||||
}
|
||||
else
|
||||
{
|
||||
BB_BLE_PDU_FILT_CLR_FLAG(&pBle->pduFilt, PEER_ADDR_RES_ENA);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -451,57 +451,23 @@ static uint8_t lctrSetExtAdvDataSm(lctrAdvSet_t *pAdvSet, lctrAdvDataBuf_t *pDat
|
|||
/*** Complete single fragment buffer (no reassembly required) while advertising is enabled. ***/
|
||||
if (pAdvSet->state == LCTR_EXT_ADV_STATE_ENABLED)
|
||||
{
|
||||
bool_t isCancelled = FALSE;
|
||||
/* BOD's are already running. Data will be updated in the end callback of the BOD's. */
|
||||
pDataBuf->alt.ext.len = fragLen;
|
||||
memcpy(pDataBuf->alt.ext.buf, pFragBuf, fragLen);
|
||||
pDataBuf->alt.ext.did = lctrCalcDID(pFragBuf, fragLen);
|
||||
pDataBuf->alt.ext.fragPref = fragPref;
|
||||
pDataBuf->alt.ext.modified = TRUE;
|
||||
|
||||
WSF_CS_ENTER();
|
||||
/* Renew BOD's to make the data updated immediately if possible. */
|
||||
if (SchIsBodCancellable(&pAdvSet->advBod) &&
|
||||
((pAdvSet->auxBodUsed == FALSE) || SchIsBodCancellable(&pAdvSet->auxAdvBod)))
|
||||
{
|
||||
/* Temporarily disable abort callbacks. */
|
||||
pAdvSet->advBod.abortCback = NULL;
|
||||
pAdvSet->auxAdvBod.abortCback = NULL;
|
||||
|
||||
/* Remove BOD's */
|
||||
SchRemove(&pAdvSet->advBod);
|
||||
/* Remove BOD's; remove completes in abortCback(). */
|
||||
if (pAdvSet->auxBodUsed)
|
||||
{
|
||||
SchRemove(&pAdvSet->auxAdvBod);
|
||||
}
|
||||
|
||||
isCancelled = TRUE;
|
||||
}
|
||||
WSF_CS_EXIT();
|
||||
|
||||
if (isCancelled)
|
||||
{
|
||||
pAdvSet->advData.len = fragLen;
|
||||
memcpy(pAdvSet->advData.pBuf, pFragBuf, fragLen);
|
||||
pAdvSet->param.advDID = lctrCalcDID(pFragBuf, fragLen);
|
||||
pAdvSet->advData.fragPref = fragPref;
|
||||
|
||||
/* Update superior PDU. */
|
||||
BbBleSlvAdvEvent_t * const pAdv = &pAdvSet->bleData.op.slvAdv;
|
||||
pAdv->txAdvLen = lctrPackAdvExtIndPdu(pAdvSet, pAdvSet->advHdrBuf, FALSE);
|
||||
|
||||
/* Re-insert BOD's */
|
||||
pAdvSet->advBod.abortCback = lctrSlvExtAdvAbortOp;
|
||||
(void)SchInsertAtDueTime(&pAdvSet->advBod, NULL);
|
||||
|
||||
if (pAdvSet->auxBodUsed)
|
||||
{
|
||||
pAdvSet->auxAdvBod.abortCback = lctrSlvAuxAdvEndOp;
|
||||
(void)SchInsertAtDueTime(&pAdvSet->auxAdvBod, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* BOD's are already running. Data will be updated in the end callback of the BOD's. */
|
||||
pDataBuf->alt.ext.len = fragLen;
|
||||
memcpy(pDataBuf->alt.ext.buf, pFragBuf, fragLen);
|
||||
pDataBuf->alt.ext.did = lctrCalcDID(pFragBuf, fragLen);
|
||||
pDataBuf->alt.ext.fragPref = fragPref;
|
||||
pDataBuf->alt.ext.modified = TRUE;
|
||||
SchRemove(&pAdvSet->advBod);
|
||||
}
|
||||
|
||||
return LL_SUCCESS;
|
||||
|
@ -629,6 +595,7 @@ static uint8_t lctrSetPerAdvDataSm(lctrAdvSet_t *pAdvSet, lctrAdvDataBuf_t *pDat
|
|||
{
|
||||
pDataBuf->alt.ext.len = fragLen;
|
||||
memcpy(pDataBuf->alt.ext.buf, pFragBuf, fragLen);
|
||||
pDataBuf->alt.ext.did = lctrCalcDID(pFragBuf, fragLen);
|
||||
pDataBuf->alt.ext.modified = TRUE;
|
||||
|
||||
return LL_SUCCESS;
|
||||
|
@ -676,16 +643,19 @@ static uint8_t lctrSetPerAdvDataSm(lctrAdvSet_t *pAdvSet, lctrAdvDataBuf_t *pDat
|
|||
/* Append buffer. */
|
||||
memcpy(pDataBuf->pBuf + pDataBuf->len, pFragBuf, fragLen);
|
||||
pDataBuf->len += fragLen;
|
||||
pAdvSet->perParam.advDID = lctrCalcDID(pFragBuf, fragLen);
|
||||
pDataBuf->ready = TRUE;
|
||||
break;
|
||||
case LL_ADV_DATA_OP_COMP:
|
||||
/* New buffer (discard old buffer). */
|
||||
memcpy(pDataBuf->pBuf, pFragBuf, fragLen);
|
||||
pDataBuf->len = fragLen;
|
||||
pAdvSet->perParam.advDID = lctrCalcDID(pFragBuf, fragLen);
|
||||
pDataBuf->ready = TRUE;
|
||||
break;
|
||||
case LL_ADV_DATA_OP_UNCHANGED:
|
||||
/* Same buffer. */
|
||||
pAdvSet->perParam.advDID = lctrCalcDID(pFragBuf, fragLen);
|
||||
pDataBuf->ready = TRUE;
|
||||
break;
|
||||
default:
|
||||
|
@ -931,8 +901,6 @@ uint8_t lctrSlvExtAdvBuildOp(lctrAdvSet_t *pAdvSet, uint32_t maxStartMs)
|
|||
SchInsertNextAvailable(pOp);
|
||||
}
|
||||
|
||||
LL_TRACE_INFO1("### ExtAdvEvent ### Advertising enabled, dueUsec=%u", pOp->dueUsec);
|
||||
|
||||
/* Advertising offloading to auxiliary channel. */
|
||||
if (pAdvSet->pExtAdvAuxPtr)
|
||||
{
|
||||
|
@ -971,6 +939,13 @@ uint8_t lctrSlvExtAdvBuildOp(lctrAdvSet_t *pAdvSet, uint32_t maxStartMs)
|
|||
lctrSlvTxSetupExtAdvHandler(pOp, pOp->dueUsec);
|
||||
}
|
||||
|
||||
LL_TRACE_INFO1(" >>> ExtAdv started, handle=%u <<<", pAdvSet->handle);
|
||||
LL_TRACE_INFO1(" priAdvInterMinUsec=%u", pAdvSet->param.priAdvInterMinUsec);
|
||||
LL_TRACE_INFO1(" priAdvInterMaxUsec=%u", pAdvSet->param.priAdvInterMaxUsec);
|
||||
LL_TRACE_INFO1(" dueUsec=%u", pOp->dueUsec);
|
||||
LL_TRACE_INFO1(" pAdvBod=0x%08x", pOp);
|
||||
LL_TRACE_INFO1(" pAuxAdvBod=0x%08x", &pAdvSet->auxAdvBod);
|
||||
|
||||
return LL_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -985,8 +960,8 @@ uint8_t lctrSlvExtAdvBuildOp(lctrAdvSet_t *pAdvSet, uint32_t maxStartMs)
|
|||
void lctrSlvAuxRescheduleOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pOp)
|
||||
{
|
||||
uint32_t auxOffsUsec = pAdvSet->advBod.minDurUsec +
|
||||
WSF_MAX(BbGetSchSetupDelayUs(), LL_BLE_MAFS_US) +
|
||||
WSF_MAX(pAdvSet->auxDelayUsec, pLctrRtCfg->auxDelayUsec);
|
||||
WSF_MAX(BbGetSchSetupDelayUs(), LL_BLE_MAFS_US) +
|
||||
WSF_MAX(pAdvSet->auxDelayUsec, pLctrRtCfg->auxDelayUsec);
|
||||
|
||||
auxOffsUsec = WSF_MIN(auxOffsUsec, LL_AUX_PTR_MAX_USEC);
|
||||
|
||||
|
@ -996,14 +971,14 @@ void lctrSlvAuxRescheduleOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pOp)
|
|||
/* Update BOD duration because extended header length might have been updated. */
|
||||
SchBleCalcAdvOpDuration(pOp, (pAdvSet->advData.fragPref == LL_ADV_DATA_FRAG_ALLOW) ? pAdvSet->advDataFragLen : 0);
|
||||
|
||||
pOp->dueUsec = pAdvSet->advBod.dueUsec + auxOffsUsec + pLctrRtCfg->auxPtrOffsetUsec;
|
||||
|
||||
if (pAdvSet->auxSkipInterUsec == 0)
|
||||
{
|
||||
pOp->dueUsec = pAdvSet->advBod.dueUsec;
|
||||
|
||||
do
|
||||
{
|
||||
/* No delay after primary channel operation. */
|
||||
if (SchInsertAtDueTime(pOp, NULL))
|
||||
if (SchInsertEarlyAsPossible(pOp, auxOffsUsec + pLctrRtCfg->auxPtrOffsetUsec, pAdvSet->param.priAdvInterMaxUsec))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -1017,10 +992,13 @@ void lctrSlvAuxRescheduleOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pOp)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Using EXT_ADV_IND due time as a reference ensures AuxOffset value does not overflow. */
|
||||
pOp->dueUsec = pAdvSet->advBod.dueUsec;
|
||||
|
||||
do
|
||||
{
|
||||
/* Link multiple primary channel operations. */
|
||||
if (SchInsertLateAsPossible(pOp, 0, pAdvSet->auxSkipInterUsec))
|
||||
if (SchInsertLateAsPossible(pOp, auxOffsUsec + pLctrRtCfg->auxPtrOffsetUsec, pAdvSet->auxSkipInterUsec))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -1054,13 +1032,13 @@ static void lctrSlvAuxCommitOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pOp)
|
|||
uint32_t advEvtDurUsec = pAdvSet->advBod.minDurUsec;
|
||||
|
||||
uint32_t skipTimeUsec = pAdvSet->param.secAdvMaxSkip * /* number of skip events */
|
||||
(pAdvSet->param.priAdvInterMinUsec + /* minimum interval */
|
||||
(pAdvSet->param.priAdvInterMinUsec + /* minimum interval */
|
||||
((LL_MAX_ADV_DLY_MS >> 1) * 1000)) + /* average advDelay */
|
||||
(LL_MAX_ADV_DLY_MS * 1000); /* ensure no overlap due to advDelay */
|
||||
skipTimeUsec = WSF_MIN(skipTimeUsec,
|
||||
LCTR_AUX_PTR_MAX_OFFSET * 300); /* limit maximum */
|
||||
skipTimeUsec = WSF_MIN(skipTimeUsec, (LCTR_AUX_PTR_MAX_OFFSET * 300)); /* limit maximum */
|
||||
|
||||
pAdvSet->auxSkipInterUsec = WSF_MAX(skipTimeUsec, advEvtDurUsec); /* ensure minimum */
|
||||
|
||||
pAdvSet->auxSkipInterUsec = WSF_MAX(skipTimeUsec, advEvtDurUsec); /* ensure minimum */
|
||||
}
|
||||
|
||||
lctrSlvAuxRescheduleOp(pAdvSet, pOp);
|
||||
|
@ -2156,13 +2134,23 @@ uint8_t LctrSetPeriodicAdvData(uint8_t handle, uint8_t op, uint8_t len, const ui
|
|||
return LL_ERROR_CODE_UNKNOWN_ADV_ID;
|
||||
}
|
||||
|
||||
if ((pAdvSet->perParam.advParamReady == FALSE) || /* Adv set is not configured for periodic adv. */
|
||||
(pAdvSet->perParam.perAdvEnabled == TRUE && op != LL_ADV_DATA_OP_COMP) || /* When periodic adv is enabled, complete data shall be provided. Never gonna happen. */
|
||||
(len == 0 && op != LL_ADV_DATA_OP_COMP)) /* Existing data shall be deleted and no new data provided. */
|
||||
if (pAdvSet->perParam.advParamReady == FALSE) /* AdvSet is not configured for Periodic Advertising. */
|
||||
{
|
||||
return LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
if ((op != LL_ADV_DATA_OP_COMP) && (op != LL_ADV_DATA_OP_UNCHANGED))
|
||||
{
|
||||
if (len == 0)
|
||||
{
|
||||
return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS;
|
||||
}
|
||||
|
||||
if (pAdvSet->perParam.perAdvEnabled)
|
||||
{
|
||||
return LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t worstCaseUsec;
|
||||
uint16_t mafOffset = WSF_MAX(pAdvSet->auxDelayUsec, pLctrRtCfg->auxDelayUsec);
|
||||
|
@ -2213,6 +2201,15 @@ uint8_t LctrSetPeriodicAdvData(uint8_t handle, uint8_t op, uint8_t len, const ui
|
|||
void LctrSetPeriodicAdvEnable(uint8_t handle, bool_t enable)
|
||||
{
|
||||
lctrAdvSet_t *pAdvSet;
|
||||
bool_t enableAdv = enable & LL_PER_ADV_ENABLE_ADV_ENABLE_BIT;
|
||||
bool_t enableAdi = (enable & LL_PER_ADV_ENABLE_ADI_ENABLE_BIT) >> 1;
|
||||
|
||||
if ((enableAdv == TRUE) && (enableAdi == TRUE) &&
|
||||
!(lmgrCb.features & LL_FEAT_PER_ADV_ADI_SUP))
|
||||
{
|
||||
LmgrSendPeriodicAdvEnableCnf(handle, LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((pAdvSet = lctrFindAdvSet(handle)) == NULL)
|
||||
{
|
||||
|
@ -2221,7 +2218,7 @@ void LctrSetPeriodicAdvEnable(uint8_t handle, bool_t enable)
|
|||
}
|
||||
|
||||
if ((pAdvSet->perParam.advParamReady == FALSE) || /* Periodic advertising parameters shall be set. */
|
||||
((enable == TRUE) && (pAdvSet->perAdvData.ready == FALSE)) || /* Periodic advertising data shall be complete. */
|
||||
((enableAdv == TRUE) && (pAdvSet->perAdvData.ready == FALSE)) || /* Periodic advertising data shall be complete. */
|
||||
(pAdvSet->param.advEventProp & (LL_ADV_EVT_PROP_CONN_ADV_BIT | LL_ADV_EVT_PROP_SCAN_ADV_BIT | /* Only non-connectable and non-scannable is allowed. */
|
||||
LL_ADV_EVT_PROP_HIGH_DUTY_ADV_BIT | LL_ADV_EVT_PROP_OMIT_AA_BIT)))/* No high duty cycle, No anonymous advertising. */
|
||||
{
|
||||
|
@ -2229,13 +2226,15 @@ void LctrSetPeriodicAdvEnable(uint8_t handle, bool_t enable)
|
|||
return;
|
||||
}
|
||||
|
||||
pAdvSet->perParam.enableAdi = enableAdi;
|
||||
|
||||
LctrPerAdvEnableMsg_t *pMsg;
|
||||
|
||||
if ((pMsg = WsfMsgAlloc(sizeof(*pMsg))) != NULL)
|
||||
{
|
||||
pMsg->hdr.handle = handle;
|
||||
pMsg->hdr.dispId = LCTR_DISP_PER_ADV;
|
||||
pMsg->hdr.event = enable ? LCTR_PER_ADV_MSG_START : LCTR_PER_ADV_MSG_STOP;
|
||||
pMsg->hdr.event = enableAdv ? LCTR_PER_ADV_MSG_START : LCTR_PER_ADV_MSG_STOP;
|
||||
|
||||
WsfMsgSend(lmgrPersistCb.handlerId, pMsg);
|
||||
}
|
||||
|
@ -2596,6 +2595,11 @@ void LctrSlvPeriodicAdvInit(void)
|
|||
{
|
||||
lmgrPersistCb.featuresDefault |= LL_FEAT_LE_PER_ADV;
|
||||
}
|
||||
|
||||
if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_SYDNEY)
|
||||
{
|
||||
lmgrPersistCb.featuresDefault |= LL_FEAT_PER_ADV_ADI_SUP;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -2635,8 +2639,6 @@ static void lctrSlvPeriodicCommitOp(lctrAdvSet_t *pAdvSet, BbOpDesc_t * const pO
|
|||
/* Advance to next interval. */
|
||||
pOp->dueUsec = anchorPointUsec + perInterUsec;
|
||||
}
|
||||
|
||||
LL_TRACE_INFO1("### ExtAdvEvent ### Periodic advertising enabled, dueUsec=%u", pOp->dueUsec);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -2753,6 +2755,11 @@ uint8_t lctrSlvPeriodicAdvBuildOp(lctrAdvSet_t *pAdvSet)
|
|||
pAdvSet->perParam.perAdvInterUsec = perInterUsec;
|
||||
lctrSlvPeriodicCommitOp(pAdvSet, pOp);
|
||||
|
||||
LL_TRACE_INFO2(" >>> PerAdv started, AdvSet.handle=%u perChHopInc=%u <<<", pAdvSet->handle, pAdvSet->perParam.perChHopInc);
|
||||
LL_TRACE_INFO1(" perInterUsec=%u", perInterUsec);
|
||||
LL_TRACE_INFO1(" perAccessAddr=0x%08x", pAdvSet->perParam.perAccessAddr);
|
||||
LL_TRACE_INFO1(" pPerAdvBod=0x%08x", pOp);
|
||||
|
||||
return LL_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -133,12 +133,6 @@ static void lctrBisFragmentIsoSdu(lctrBisCtx_t *pBisCtx, lctrIsoHdr_t *pIsoHdr,
|
|||
uint64_t pktCtr = (pBisCtx->pBigCtx->eventCounter * pBisCtx->pBigCtx->bn) + pDesc->fragCnt;
|
||||
pBisCtx->chan.enc.pTxPktCounter = &pktCtr;
|
||||
|
||||
/* Set the new packet counter for inline encryption. */
|
||||
if (lctrSetEncryptPktCountHdlr)
|
||||
{
|
||||
lctrSetEncryptPktCountHdlr(&pBisCtx->chan.enc, pktCtr);
|
||||
}
|
||||
|
||||
if (lctrPktEncryptHdlr &&
|
||||
lctrPktEncryptHdlr(&pBisCtx->chan.enc,
|
||||
pDesc->frag[pDesc->fragCnt].hdr,
|
||||
|
@ -221,14 +215,19 @@ void lctrFreeBigCtx(lctrBigCtx_t *pBigCtx)
|
|||
{
|
||||
lctrBisCtx_t *pBisCtx = pBigCtx->pBisCtx[i];
|
||||
|
||||
if (pBisCtx == NULL)
|
||||
{
|
||||
/* Filtered BIS. */
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (pBigCtx->role)
|
||||
{
|
||||
case LL_ROLE_SLAVE:
|
||||
lctrBisSetDataPath(pBisCtx, LL_ISO_DATA_DIR_INPUT, LL_ISO_DATA_PATH_DISABLED);
|
||||
lctrNotifyIsoTxComplete(pBigCtx);
|
||||
LctrRemoveIsoDataPath(pBisCtx->handle, LL_ISO_DATA_PATH_INPUT_BIT);
|
||||
break;
|
||||
case LL_ROLE_MASTER:
|
||||
lctrBisSetDataPath(pBisCtx, LL_ISO_DATA_DIR_OUTPUT, LL_ISO_DATA_PATH_DISABLED);
|
||||
LctrRemoveIsoDataPath(pBisCtx->handle, LL_ISO_DATA_PATH_OUTPUT_BIT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -269,7 +268,8 @@ uint8_t lctrBigIsPerAdvUsed(uint8_t advHandle)
|
|||
|
||||
if ((pBigCtx->enabled) &&
|
||||
(pBigCtx->role == LL_ROLE_SLAVE) &&
|
||||
(pBigCtx->roleData.slv.pAdvSet))
|
||||
(pBigCtx->roleData.slv.pAdvSet) &&
|
||||
(pBigCtx->roleData.slv.pAdvSet->handle == advHandle))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -372,7 +372,14 @@ lctrBisCtx_t *lctrAllocBisCtx(lctrBigCtx_t *pBigCtx)
|
|||
pBisCtx->pBigCtx = pBigCtx;
|
||||
pBisCtx->bisNum = pBigCtx->numBis + 1;
|
||||
|
||||
pBisCtx->path = LL_ISO_DATA_PATH_DISABLED;
|
||||
if (pBigCtx->role == LL_ROLE_MASTER)
|
||||
{
|
||||
pBisCtx->roleData.mst.dataPathOutCtx.id = LL_ISO_DATA_PATH_DISABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBisCtx->roleData.slv.dataPathInCtx.id = LL_ISO_DATA_PATH_DISABLED;
|
||||
}
|
||||
|
||||
/* Parent context. */
|
||||
pBigCtx->pBisCtx[pBigCtx->numBis++] = pBisCtx;
|
||||
|
@ -384,17 +391,6 @@ lctrBisCtx_t *lctrAllocBisCtx(lctrBigCtx_t *pBigCtx)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Cleanup BIS context, clean BIG context if necessary for slave.
|
||||
*
|
||||
* \param pBisCtx BIS context to free.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void lctrCleanupBisCtx(lctrBisCtx_t *pBisCtx)
|
||||
{
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Free a BIS context.
|
||||
|
@ -413,11 +409,18 @@ void lctrFreeBisCtx(lctrBisCtx_t *pBisCtx)
|
|||
switch (pBisCtx->pBigCtx->role)
|
||||
{
|
||||
case LL_ROLE_MASTER:
|
||||
while ((pPdu = lctrBisDequeueRxDataPdu(pBisCtx, NULL)) != NULL)
|
||||
while ((pPdu = lctrBisDequeueRxDataPduTop(pBisCtx)) != NULL)
|
||||
{
|
||||
lctrBisRxIsoDataPduFree(pPdu);
|
||||
}
|
||||
|
||||
uint8_t *pIsoSdu;
|
||||
while ((pIsoSdu = lctrBisRxIsoSduDeq(pBisCtx)) != NULL)
|
||||
{
|
||||
WsfMsgFree(pIsoSdu);
|
||||
lctrIsoDataRxIncAvailBuf(1);
|
||||
}
|
||||
|
||||
lctrIsoalRxDataPathClear(&pBisCtx->roleData.mst.isoalRxCtx, pBisCtx->pBigCtx->framing);
|
||||
break;
|
||||
case LL_ROLE_SLAVE:
|
||||
|
@ -585,7 +588,10 @@ void lctrSetupBisContext(lctrBisCtx_t *pBisCtx, uint32_t seedAccAddr, uint16_t b
|
|||
pBisCtx->chan.enc.dir = 1;
|
||||
pBisCtx->chan.enc.type = PAL_BB_TYPE_BIS;
|
||||
|
||||
lctrInitCipherBlkHdlr(&pBisCtx->chan.enc, pBisCtx->handle, 1);
|
||||
if (lctrInitCipherBlkHdlr)
|
||||
{
|
||||
lctrInitCipherBlkHdlr(&pBisCtx->chan.enc, pBisCtx->handle, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -602,15 +608,25 @@ void lctrSelectBigChannels(lctrBigCtx_t *pBigCtx)
|
|||
for (unsigned int i = 0; i < pBigCtx->numBis; i++)
|
||||
{
|
||||
lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[i];
|
||||
pBisCtx->chan.chanIdx = LmgrSelectNextChannel(&pBisCtx->chSelInfo, pBigCtx->eventCounter, 0, TRUE);
|
||||
|
||||
if (pBisCtx)
|
||||
{
|
||||
pBisCtx->chan.chanIdx = LmgrSelectNextChannel(&pBisCtx->chSelInfo, pBigCtx->eventCounter, 0, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Select BIG Control channel. */
|
||||
pBigCtx->ctrChan.chanIdx = LmgrSelectNextChannel(&pBigCtx->ctrChSelInfo, pBigCtx->eventCounter, 0, TRUE);
|
||||
|
||||
/* Setup BOD for next BIG Event. */
|
||||
pBigCtx->bleData.chan.chanIdx = pBigCtx->pBisCtx[0]->chan.chanIdx;
|
||||
|
||||
if (pBigCtx->role == LL_ROLE_SLAVE)
|
||||
{
|
||||
pBigCtx->bleData.chan.chanIdx = pBigCtx->pBisCtx[0]->chan.chanIdx;
|
||||
}
|
||||
else /* LL_ROLE_MASTER */
|
||||
{
|
||||
pBigCtx->bleData.chan.chanIdx = pBigCtx->roleData.mst.pFirstBisCtx->chan.chanIdx;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -627,8 +643,12 @@ void lctrRemapBigChannels(lctrBigCtx_t *pBigCtx, uint64_t chanMap)
|
|||
for (unsigned int i = 0; i < pBigCtx->numBis; i++)
|
||||
{
|
||||
lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[i];
|
||||
pBisCtx->chSelInfo.chanMask = chanMap;
|
||||
LmgrBuildRemapTable(&pBisCtx->chSelInfo);
|
||||
|
||||
if (pBisCtx)
|
||||
{
|
||||
pBisCtx->chSelInfo.chanMask = chanMap;
|
||||
LmgrBuildRemapTable(&pBisCtx->chSelInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/* Select BIG Control channel. */
|
||||
|
@ -653,7 +673,8 @@ void lctrBisTxIsoPduQueue(lctrBisCtx_t *pBisCtx, lctrIsoHdr_t *pIsoHdr, uint8_t
|
|||
{
|
||||
LL_TRACE_ERR1("Failed to allocate transmit buffer descriptor: bisHandle=%u", pIsoHdr->handle);
|
||||
WsfMsgFree(pIsoSdu);
|
||||
if (!pBisCtx->test.enabled)
|
||||
if (lmgrPersistCb.sendIsoCompCback &&
|
||||
!pBisCtx->test.enabled)
|
||||
{
|
||||
uint16_t handle = pIsoHdr->handle;
|
||||
uint16_t numSdu = 1;
|
||||
|
@ -773,7 +794,7 @@ void lctrBisTxQueuePopCleanup(lctrBisCtx_t *pBisCtx, uint8_t numFrag)
|
|||
lctrFreeIsoTxBufDesc(pDesc);
|
||||
lctrIsoSduTxIncAvailBuf();
|
||||
|
||||
if (pBisCtx->path == LL_ISO_DATA_PATH_HCI)
|
||||
if (pBisCtx->roleData.slv.dataPathInCtx.id == LL_ISO_DATA_PATH_HCI)
|
||||
{
|
||||
/* ISO Test does not send Tx Complete notifications. */
|
||||
if (!pBisCtx->test.enabled)
|
||||
|
@ -931,8 +952,8 @@ uint8_t *lctrBisRxIsoDataPduAlloc(void)
|
|||
/* Return start of ISO Data PDU. */
|
||||
pPdu += LCTR_ISO_SDU_START_OFFSET;
|
||||
|
||||
/* Do not claim buffer until committed. */
|
||||
/* lctrIsoDataRxDecAvailBuf(); */
|
||||
/* Do not claim buffer until SDU is committed. */
|
||||
/* lctrIsoDataRxDecAvailBuf(); */ /* SDU committed in lctrBisRxIsoSduEnq(). */
|
||||
}
|
||||
|
||||
return pPdu;
|
||||
|
@ -952,25 +973,29 @@ uint8_t *lctrBisRxIsoDataPduAlloc(void)
|
|||
uint8_t *lctrBisRxIsoSduDeq(lctrBisCtx_t *pBisCtx)
|
||||
{
|
||||
wsfHandlerId_t bisHandle;
|
||||
uint8_t *pSdu = NULL;
|
||||
|
||||
uint8_t *pSdu = WsfMsgDeq(&pBisCtx->roleData.mst.rxIsoSduQ, &bisHandle);
|
||||
if (pBisCtx->test.enabled)
|
||||
{
|
||||
pSdu = WsfMsgDeq(&pBisCtx->roleData.mst.dataPathOutCtx.cfg.hci.rxDataQ, &bisHandle);
|
||||
return pSdu;
|
||||
}
|
||||
|
||||
switch (pBisCtx->roleData.mst.dataPathOutCtx.id)
|
||||
{
|
||||
case LL_ISO_DATA_PATH_HCI:
|
||||
pSdu = WsfMsgDeq(&pBisCtx->roleData.mst.dataPathOutCtx.cfg.hci.rxDataQ, &bisHandle);
|
||||
break;
|
||||
case LL_ISO_DATA_PATH_VS:
|
||||
pSdu = WsfMsgDeq(&pBisCtx->roleData.mst.dataPathOutCtx.cfg.codec.rxDataQ, &bisHandle);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return pSdu;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Enqueue a received ISO SDU buffer.
|
||||
*
|
||||
* \param pBisCtx BIS context.
|
||||
* \param pSdu BIS Data SDU buffer.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void lctrBisRxIsoSduEnq(lctrBisCtx_t *pBisCtx, uint8_t *pSdu)
|
||||
{
|
||||
WsfMsgEnq(&pBisCtx->roleData.mst.rxIsoSduQ, pBisCtx->handle, pSdu);
|
||||
lctrIsoDataRxDecAvailBuf();
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
|
@ -991,12 +1016,43 @@ void lctrBisRxIsoDataPduFree(uint8_t *pPdu)
|
|||
*
|
||||
* \param pBisCtx BIS context.
|
||||
* \param pRxBuf Received PDU data buffer to queue.
|
||||
* \param evtCtr Event counter when packet was received.
|
||||
* \param burstIdx Burst index.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void lctrBisEnqueueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t *pRxBuf, uint64_t evtCtr)
|
||||
void lctrBisEnqueueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t *pRxBuf, uint8_t burstIdx)
|
||||
{
|
||||
WsfMsgEnq(&pBisCtx->roleData.mst.rxDataQ, (uint8_t)evtCtr, pRxBuf - LCTR_ISO_SDU_START_OFFSET);
|
||||
WsfMsgEnq(&pBisCtx->roleData.mst.rxDataQ, burstIdx, pRxBuf - LCTR_ISO_SDU_START_OFFSET);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Pop top element from Tx queue if it matches given \a bnIdx.
|
||||
*
|
||||
* \param pBisCtx BIS context.
|
||||
* \param bnIdx Burst Number index.
|
||||
*
|
||||
* \return Pointer to ISO Data PDU.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t *lctrBisDequeueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t burstIdx)
|
||||
{
|
||||
uint8_t *pBuf;
|
||||
|
||||
uint8_t actBurstIdx;
|
||||
|
||||
if (WsfMsgPeek(&pBisCtx->roleData.mst.rxDataQ, &actBurstIdx) == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (actBurstIdx != burstIdx)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pBuf = WsfMsgDeq(&pBisCtx->roleData.mst.rxDataQ, &actBurstIdx);
|
||||
|
||||
return pBuf + LCTR_ISO_SDU_START_OFFSET;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -1004,22 +1060,16 @@ void lctrBisEnqueueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t *pRxBuf, uint64_t ev
|
|||
* \brief Pop top element from Tx queue.
|
||||
*
|
||||
* \param pBisCtx BIS context.
|
||||
* \param pEvtCtrLsb Least significant byte of the event counter.
|
||||
*
|
||||
* \return Pointer to ISO Data PDU.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t *lctrBisDequeueRxDataPdu(lctrBisCtx_t *pBisCtx, uint8_t *pEvtCtrLsb)
|
||||
uint8_t *lctrBisDequeueRxDataPduTop(lctrBisCtx_t *pBisCtx)
|
||||
{
|
||||
uint8_t *pBuf;
|
||||
uint8_t temp8;
|
||||
|
||||
if (pEvtCtrLsb == NULL)
|
||||
{
|
||||
pEvtCtrLsb = &temp8;
|
||||
}
|
||||
|
||||
if ((pBuf = WsfMsgDeq(&pBisCtx->roleData.mst.rxDataQ, pEvtCtrLsb)) == NULL)
|
||||
if ((pBuf = WsfMsgDeq(&pBisCtx->roleData.mst.rxDataQ, &temp8)) == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1074,6 +1124,7 @@ uint8_t lctrBisTxTest(lctrBisCtx_t *pBisCtx, uint8_t pldType)
|
|||
* \param pldType Payload length type.
|
||||
*
|
||||
* \return Status error code.
|
||||
*
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t lctrBisRxTest(lctrBisCtx_t *pBisCtx, uint8_t pldType)
|
||||
|
@ -1189,7 +1240,8 @@ void lctrNotifyIsoTxComplete(lctrBigCtx_t *pBigCtx)
|
|||
{
|
||||
lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[i];
|
||||
|
||||
if (pBisCtx->path == LL_ISO_DATA_PATH_HCI)
|
||||
if (pBisCtx &&
|
||||
(pBisCtx->roleData.slv.dataPathInCtx.id == LL_ISO_DATA_PATH_HCI))
|
||||
{
|
||||
if (pBisCtx->roleData.slv.numTxSduComp)
|
||||
{
|
||||
|
@ -1201,7 +1253,7 @@ void lctrNotifyIsoTxComplete(lctrBigCtx_t *pBigCtx)
|
|||
}
|
||||
}
|
||||
|
||||
if (numHandles)
|
||||
if (lmgrPersistCb.sendIsoCompCback && numHandles)
|
||||
{
|
||||
/* Notify host completed SDUs. */
|
||||
lmgrPersistCb.sendIsoCompCback(numHandles, handle, numSdu);
|
||||
|
@ -1237,86 +1289,6 @@ void lctrBisCalcGroupSessionKey(const uint8_t *pGSKD, const uint8_t *pBC, uint8_
|
|||
PalCryptoAesCmac(ik, pGSK, big3, 4);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Set the BIS data path.
|
||||
*
|
||||
* \param pBisCtx BIS context.
|
||||
* \param dpDir Data path direction.
|
||||
* \param dpId Data path ID.
|
||||
*
|
||||
* \return Status error code.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t lctrBisSetDataPath(lctrBisCtx_t *pBisCtx, LlIsoDataPathDir_t dpDir, LlIsoDataPath_t dpId)
|
||||
{
|
||||
if (pBisCtx->path == dpId)
|
||||
{
|
||||
/* No change. */
|
||||
return LL_SUCCESS;
|
||||
}
|
||||
|
||||
/*** Stop current data path. ***/
|
||||
|
||||
switch (pBisCtx->path)
|
||||
{
|
||||
case LL_ISO_DATA_PATH_VS:
|
||||
if (!lctrCodecHdlr.stop)
|
||||
{
|
||||
return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS;
|
||||
}
|
||||
lctrCodecHdlr.stop(pBisCtx->handle);
|
||||
break;
|
||||
case LL_ISO_DATA_PATH_DISABLED:
|
||||
case LL_ISO_DATA_PATH_HCI:
|
||||
default:
|
||||
/* No action required. */
|
||||
break;
|
||||
}
|
||||
|
||||
/*** Start new data path. ***/
|
||||
|
||||
pBisCtx->path = dpId;
|
||||
|
||||
switch (dpId)
|
||||
{
|
||||
case LL_ISO_DATA_PATH_VS:
|
||||
if (lctrCodecHdlr.start)
|
||||
{
|
||||
PalCodecSreamParam_t param =
|
||||
{
|
||||
.dir = (dpDir == LL_ISO_DATA_DIR_INPUT) ? PAL_CODEC_DIR_INPUT : PAL_CODEC_DIR_OUTPUT,
|
||||
.chMask = PAL_CODEC_CH_LEFT_BIT | PAL_CODEC_CH_RIGHT_BIT,
|
||||
.intervalUsec = pBisCtx->pBigCtx->isoInterUsec,
|
||||
.pktCtr = (pBisCtx->pBigCtx->eventCounter + 1) * pBisCtx->pBigCtx->bn,
|
||||
.rdyCback = lctrIsoSendCodecSdu
|
||||
};
|
||||
|
||||
if (!lctrCodecHdlr.start(pBisCtx->handle, ¶m))
|
||||
{
|
||||
LL_TRACE_WARN1("Failed to start the codec, dpId=%u", dpId);
|
||||
pBisCtx->path = LL_ISO_DATA_PATH_DISABLED;
|
||||
return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_WARN1("Codec not found, dpId=%u", dpId);
|
||||
return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS;
|
||||
}
|
||||
break;
|
||||
case LL_ISO_DATA_PATH_DISABLED:
|
||||
case LL_ISO_DATA_PATH_HCI:
|
||||
/* No action required. */
|
||||
break;
|
||||
default:
|
||||
LL_TRACE_WARN1("Unknown Data Path, dpId=%u", dpId);
|
||||
return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS;
|
||||
}
|
||||
|
||||
return LL_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Calculate next subevent index values, using sequential packing.
|
||||
|
@ -1328,7 +1300,7 @@ uint8_t lctrBisSetDataPath(lctrBisCtx_t *pBisCtx, LlIsoDataPathDir_t dpDir, LlIs
|
|||
* \return TRUE if more subevents pending, FALSE otherwise.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t lctrSlvBisCalcNextIdxSequential(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts)
|
||||
bool_t lctrBisCalcNextIdxSequential(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts)
|
||||
{
|
||||
/* Burst loop. */
|
||||
|
||||
|
@ -1382,7 +1354,7 @@ bool_t lctrSlvBisCalcNextIdxSequential(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCt
|
|||
* \return TRUE if more subevents pending, FALSE otherwise.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t lctrSlvBisCalcNextIdxInterleaved(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts)
|
||||
bool_t lctrBisCalcNextIdxInterleaved(lctrBigCtx_t *pBigCtx, lctrSeCtx_t *pSeCtx, uint8_t numSePkts)
|
||||
{
|
||||
/* BIS loop. */
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -122,7 +122,7 @@ void LctrMstBisInit(void)
|
|||
/* Set supported features. */
|
||||
if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_5_1)
|
||||
{
|
||||
lmgrPersistCb.featuresDefault |= LL_FEAT_ISO_BROADCASTER;
|
||||
lmgrPersistCb.featuresDefault |= LL_FEAT_ISO_SYNC;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,7 @@ uint8_t LctrMstBigCreateSync(LlBigCreateSync_t *pParam)
|
|||
if (lctrFindBigByHandle(pParam->bigHandle) != NULL)
|
||||
{
|
||||
LL_TRACE_WARN1("LctrMstBigCreateSync: bigHandle=%u already in use", pParam->bigHandle);
|
||||
return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE;
|
||||
return LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
pPerScanCtx = LCTR_GET_PER_SCAN_CTX(pParam->syncHandle);
|
||||
|
@ -175,6 +175,17 @@ uint8_t LctrMstBigCreateSync(LlBigCreateSync_t *pParam)
|
|||
}
|
||||
|
||||
pBigInfo = &pPerScanCtx->acadParams[LCTR_ACAD_ID_BIG_INFO].bigInfo;
|
||||
if (pParam->numBis > pBigInfo->numBis)
|
||||
{
|
||||
LL_TRACE_WARN2("LctrMstBigCreateSync: invalid value for numBis=%u for this sync handle, validRange=1..%u", pParam->numBis, pBigInfo->numBis);
|
||||
return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE;
|
||||
}
|
||||
|
||||
if (pParam->numBis > LL_MAX_BIS)
|
||||
{
|
||||
LL_TRACE_WARN2("LctrMstBigCreateSync: invalid value for numBis=%u, validRange=1..%u", pParam->numBis, LL_MAX_BIS);
|
||||
return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES;
|
||||
}
|
||||
|
||||
if (pParam->numBis > lctrGetNumAvailBisCtx())
|
||||
{
|
||||
|
@ -182,12 +193,6 @@ uint8_t LctrMstBigCreateSync(LlBigCreateSync_t *pParam)
|
|||
return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES;
|
||||
}
|
||||
|
||||
if (pParam->numBis > WSF_MIN(pBigInfo->numBis, LL_MAX_BIS))
|
||||
{
|
||||
LL_TRACE_WARN2("LctrMstBigCreateSync: invalid value for numBis=%u, validRange=1..%u", pParam->numBis, WSF_MIN(pBigInfo->numBis, LL_MAX_BIS));
|
||||
return LL_ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < pParam->numBis; i++)
|
||||
{
|
||||
if ((pParam->bis[i] < LL_MIN_BIS) ||
|
||||
|
@ -286,7 +291,7 @@ void LctrMstBigTerminateSync(uint8_t bigHandle)
|
|||
/*************************************************************************************************/
|
||||
void lctrMstBigBuildOp(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo)
|
||||
{
|
||||
lctrBisCtx_t * const pBisCtx = pBigCtx->pBisCtx[0];
|
||||
lctrBisCtx_t * const pBisCtx = pBigCtx->roleData.mst.pFirstBisCtx;
|
||||
|
||||
BbOpDesc_t * const pOp = &pBigCtx->bod;
|
||||
BbBleData_t * const pBle = &pBigCtx->bleData;
|
||||
|
@ -302,7 +307,7 @@ void lctrMstBigBuildOp(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo)
|
|||
pOp->protId = BB_PROT_BLE;
|
||||
pOp->prot.pBle = pBle;
|
||||
pOp->endCback = lctrMstBigEndOp;
|
||||
pOp->abortCback = lctrMstBigEndOp;
|
||||
pOp->abortCback = lctrMstBigAbortOp;
|
||||
pOp->pCtx = pBigCtx;
|
||||
|
||||
/*** BLE General Setup ***/
|
||||
|
@ -337,17 +342,18 @@ void lctrMstBigBuildOp(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo)
|
|||
pBigCtx->roleData.mst.anchorPoint = pBigInfo->bigAnchorPoint;
|
||||
pBigCtx->roleData.mst.rxSyncTime = pBigCtx->roleData.mst.anchorPoint - pBigCtx->isoInterUsec;
|
||||
/* Expand receive window for initial synchronization due to resolution uncertainty. */
|
||||
pBigCtx->roleData.mst.extraWwUsec = (pBigInfo->bigOffsUnits == 0) ? 30 : 300;
|
||||
pBigCtx->roleData.mst.initWwUsec = (pBigInfo->bigOffsUnits == 0) ? 30 : 300;
|
||||
uint32_t unsyncTimeUsec = 0;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
uint32_t wwTotalUsec = lctrCalcWindowWideningUsec(unsyncTimeUsec, pBigCtx->roleData.mst.totalAcc);
|
||||
uint32_t wwTotalUsec = lctrCalcWindowWideningUsec(unsyncTimeUsec, pBigCtx->roleData.mst.totalAcc)
|
||||
+ pBigCtx->roleData.mst.initWwUsec;
|
||||
/* TODO Limit to half the ISO Interval size */
|
||||
|
||||
pOp->dueUsec = pBigCtx->roleData.mst.anchorPoint - wwTotalUsec;
|
||||
pOp->dueUsec = pBigCtx->roleData.mst.anchorPoint + pBigCtx->roleData.mst.firstBisOffsUsec - wwTotalUsec;
|
||||
/* Multiply 2 for before and after BIG Anchor Point. */
|
||||
pBis->rxSyncDelayUsec = (wwTotalUsec << 1) + pBigCtx->roleData.mst.extraWwUsec;
|
||||
pBis->rxSyncDelayUsec = (wwTotalUsec << 1);
|
||||
|
||||
lctrSelectBigChannels(pBigCtx);
|
||||
|
||||
|
@ -356,7 +362,7 @@ void lctrMstBigBuildOp(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo)
|
|||
break;
|
||||
}
|
||||
|
||||
LL_TRACE_WARN1("!!! BIG schedule conflict handle=%u", pBigCtx->handle);
|
||||
LL_TRACE_WARN2("!!! BIG schedule conflict handle=%u, ec[15:0]=%u", pBigCtx->handle, pBigCtx->eventCounter);
|
||||
|
||||
/* Advance to next interval. */
|
||||
pBigCtx->eventCounter += 1;
|
||||
|
@ -443,14 +449,15 @@ void lctrMstSetupBigContext(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo)
|
|||
/*************************************************************************************************/
|
||||
void lctrMstSetupBigChannel(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo)
|
||||
{
|
||||
pBigCtx->ctrChSelInfo.chanMask = pBigInfo->chanMap;
|
||||
pBigCtx->ctrChSelInfo.usedChSel = LL_CH_SEL_2;
|
||||
pBigCtx->ctrChSelInfo.chIdentifier = (uint16_t)(LL_BIG_CONTROL_ACCESS_ADDR >> 16) ^
|
||||
(uint16_t)(LL_BIG_CONTROL_ACCESS_ADDR >> 0);
|
||||
LmgrBuildRemapTable(&pBigCtx->ctrChSelInfo);
|
||||
|
||||
pBigCtx->ctrChan.opType = BB_BLE_OP_MST_BIS_EVENT;
|
||||
pBigCtx->ctrChan.accAddr = lctrComputeBisAccessAddr(pBigInfo->seedAccAddr, 0);
|
||||
|
||||
pBigCtx->ctrChSelInfo.chanMask = pBigInfo->chanMap;
|
||||
pBigCtx->ctrChSelInfo.usedChSel = LL_CH_SEL_2;
|
||||
pBigCtx->ctrChSelInfo.chIdentifier = (uint16_t)(pBigCtx->ctrChan.accAddr >> 16) ^
|
||||
(uint16_t)(pBigCtx->ctrChan.accAddr >> 0);
|
||||
LmgrBuildRemapTable(&pBigCtx->ctrChSelInfo);
|
||||
|
||||
pBigCtx->ctrChan.crcInit = (pBigCtx->baseCrcInit << 8) | 0;
|
||||
pBigCtx->ctrChan.rxPhy = pBigCtx->phy;
|
||||
|
||||
|
@ -468,10 +475,10 @@ void lctrMstSetupBigChannel(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo)
|
|||
pBigCtx->ctrChan.enc.nonceMode = PAL_BB_NONCE_MODE_EXT64_CNTR;
|
||||
|
||||
memcpy(pBigCtx->ctrChan.enc.iv, pBigCtx->giv, LL_IV_LEN);
|
||||
pBigCtx->ctrChan.enc.iv[0] ^= LL_BIG_CONTROL_ACCESS_ADDR >> 0;
|
||||
pBigCtx->ctrChan.enc.iv[1] ^= LL_BIG_CONTROL_ACCESS_ADDR >> 8;
|
||||
pBigCtx->ctrChan.enc.iv[2] ^= LL_BIG_CONTROL_ACCESS_ADDR >> 16;
|
||||
pBigCtx->ctrChan.enc.iv[3] ^= LL_BIG_CONTROL_ACCESS_ADDR >> 24;
|
||||
pBigCtx->ctrChan.enc.iv[0] ^= pBigCtx->ctrChan.accAddr >> 0;
|
||||
pBigCtx->ctrChan.enc.iv[1] ^= pBigCtx->ctrChan.accAddr >> 8;
|
||||
pBigCtx->ctrChan.enc.iv[2] ^= pBigCtx->ctrChan.accAddr >> 16;
|
||||
pBigCtx->ctrChan.enc.iv[3] ^= pBigCtx->ctrChan.accAddr >> 24;
|
||||
|
||||
memcpy(pBigCtx->ctrChan.enc.sk, pBigCtx->bleData.chan.enc.sk, PAL_CRYPTO_LL_KEY_LEN);
|
||||
|
||||
|
@ -479,7 +486,10 @@ void lctrMstSetupBigChannel(lctrBigCtx_t *pBigCtx, LctrAcadBigInfo_t *pBigInfo)
|
|||
pBigCtx->ctrChan.enc.dir = 1;
|
||||
pBigCtx->ctrChan.enc.type = PAL_BB_TYPE_BIS;
|
||||
|
||||
lctrInitCipherBlkHdlr(&pBigCtx->ctrChan.enc, LCTR_BIG_CTRL_ENC_ID(pBigCtx), 1);
|
||||
if (lctrInitCipherBlkHdlr)
|
||||
{
|
||||
lctrInitCipherBlkHdlr(&pBigCtx->ctrChan.enc, LCTR_BIG_CTRL_ENC_ID(pBigCtx), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -124,8 +124,8 @@ static void lctrSlvSetupBigContext(lctrBigCtx_t *pBigCtx, LlCreateBig_t *pCreate
|
|||
case LL_PACKING_INTERLEAVED:
|
||||
{
|
||||
pBigCtx->bisSpaceUsec = lctrBisCalcMaxPduTimeUsec(pBigCtx->phy, pBigCtx->maxPdu, pCreateBig->encrypt);
|
||||
pBigCtx->subInterUsec = pBigCtx->bisSpaceUsec * pBigCtx->nse;
|
||||
pBigCtx->syncDelayUsec = pCreateBig->numBis * pBigCtx->subInterUsec;
|
||||
pBigCtx->subInterUsec = pBigCtx->bisSpaceUsec * pCreateBig->numBis;
|
||||
pBigCtx->syncDelayUsec = (pCreateBig->numBis * pBigCtx->subInterUsec) - LL_BLE_TMSS_US;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ static void lctrSlvSetupBigContext(lctrBigCtx_t *pBigCtx, LlCreateBig_t *pCreate
|
|||
{
|
||||
pBigCtx->subInterUsec = lctrBisCalcMaxPduTimeUsec(pBigCtx->phy, pBigCtx->maxPdu, pCreateBig->encrypt);
|
||||
pBigCtx->bisSpaceUsec = pBigCtx->subInterUsec * pBigCtx->nse;
|
||||
pBigCtx->syncDelayUsec = pCreateBig->numBis * pBigCtx->bisSpaceUsec;
|
||||
pBigCtx->syncDelayUsec = (pCreateBig->numBis * pBigCtx->bisSpaceUsec) - LL_BLE_TMSS_US;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -142,9 +142,18 @@ static void lctrSlvSetupBigContext(lctrBigCtx_t *pBigCtx, LlCreateBig_t *pCreate
|
|||
/* Ensure successful divide. */
|
||||
if (pBigCtx->bn || pBigCtx->sduInterUsec)
|
||||
{
|
||||
pBigCtx->transLatUsec = pBigCtx->syncDelayUsec +
|
||||
pBigCtx->pto * (pBigCtx->nse / pBigCtx->bn - pBigCtx->irc) * pBigCtx->isoInterUsec +
|
||||
((pBigCtx->isoInterUsec / pBigCtx->sduInterUsec) - 1) * pBigCtx->sduInterUsec;
|
||||
if (pBigCtx->framing == LL_ISO_PDU_TYPE_FRAMED)
|
||||
{
|
||||
pBigCtx->transLatUsec = pBigCtx->syncDelayUsec +
|
||||
pBigCtx->pto * (pBigCtx->nse / pBigCtx->bn - pBigCtx->irc) * pBigCtx->isoInterUsec +
|
||||
pBigCtx->isoInterUsec + pBigCtx->sduInterUsec;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBigCtx->transLatUsec = pBigCtx->syncDelayUsec +
|
||||
pBigCtx->pto * (pBigCtx->nse / pBigCtx->bn - pBigCtx->irc) * pBigCtx->isoInterUsec +
|
||||
((pBigCtx->isoInterUsec / pBigCtx->sduInterUsec) - 1) * pBigCtx->sduInterUsec;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -188,15 +197,15 @@ static void lctrSlvSetupBigTestContext(lctrBigCtx_t *pBigCtx, LlCreateBigTest_t
|
|||
pBigCtx->bn = pCreateBigTest->bn;
|
||||
pBigCtx->irc = pCreateBigTest->irc;
|
||||
pBigCtx->pto = pCreateBigTest->pto;
|
||||
pBigCtx->nse = (pBigCtx->bn + pBigCtx->pto) * pBigCtx->irc;
|
||||
pBigCtx->nse = pCreateBigTest->nse;
|
||||
|
||||
switch (pBigCtx->packing)
|
||||
{
|
||||
case LL_PACKING_INTERLEAVED:
|
||||
{
|
||||
pBigCtx->bisSpaceUsec = lctrBisCalcMaxPduTimeUsec(pBigCtx->phy, pBigCtx->maxPdu, pCreateBigTest->encrypt);
|
||||
pBigCtx->subInterUsec = pBigCtx->bisSpaceUsec * pBigCtx->nse;
|
||||
pBigCtx->syncDelayUsec = pCreateBigTest->numBis * pBigCtx->subInterUsec;
|
||||
pBigCtx->subInterUsec = pBigCtx->bisSpaceUsec * pCreateBigTest->numBis;
|
||||
pBigCtx->syncDelayUsec = (pCreateBigTest->numBis * pBigCtx->subInterUsec) - LL_BLE_TMSS_US;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -205,7 +214,7 @@ static void lctrSlvSetupBigTestContext(lctrBigCtx_t *pBigCtx, LlCreateBigTest_t
|
|||
{
|
||||
pBigCtx->subInterUsec = lctrBisCalcMaxPduTimeUsec(pBigCtx->phy, pBigCtx->maxPdu, pCreateBigTest->encrypt);
|
||||
pBigCtx->bisSpaceUsec = pBigCtx->subInterUsec * pBigCtx->nse;
|
||||
pBigCtx->syncDelayUsec = pCreateBigTest->numBis * pBigCtx->bisSpaceUsec;
|
||||
pBigCtx->syncDelayUsec = (pCreateBigTest->numBis * pBigCtx->bisSpaceUsec) - LL_BLE_TMSS_US;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -213,9 +222,18 @@ static void lctrSlvSetupBigTestContext(lctrBigCtx_t *pBigCtx, LlCreateBigTest_t
|
|||
/* Ensure successful divide. */
|
||||
if (pBigCtx->bn || pBigCtx->sduInterUsec)
|
||||
{
|
||||
pBigCtx->transLatUsec = pBigCtx->syncDelayUsec +
|
||||
pBigCtx->pto * (pBigCtx->nse / pBigCtx->bn - pBigCtx->irc) * pBigCtx->isoInterUsec +
|
||||
((pBigCtx->isoInterUsec / pBigCtx->sduInterUsec) - 1) * pBigCtx->sduInterUsec;
|
||||
if (pBigCtx->framing == LL_ISO_PDU_TYPE_FRAMED)
|
||||
{
|
||||
pBigCtx->transLatUsec = pBigCtx->syncDelayUsec +
|
||||
pBigCtx->pto * (pBigCtx->nse / pBigCtx->bn - pBigCtx->irc) * pBigCtx->isoInterUsec +
|
||||
pBigCtx->isoInterUsec + pBigCtx->sduInterUsec;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBigCtx->transLatUsec = pBigCtx->syncDelayUsec +
|
||||
pBigCtx->pto * (pBigCtx->nse / pBigCtx->bn - pBigCtx->irc) * pBigCtx->isoInterUsec +
|
||||
((pBigCtx->isoInterUsec / pBigCtx->sduInterUsec) - 1) * pBigCtx->sduInterUsec;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -236,15 +254,15 @@ static void lctrSlvSetupBigChannel(lctrBigCtx_t *pBigCtx)
|
|||
pBigCtx->seedAccAddr = lctrComputeSeedAccessAddr();
|
||||
pBigCtx->baseCrcInit = lctrComputeCrcInit() >> 8;
|
||||
|
||||
pBigCtx->ctrChSelInfo.chanMask = lmgrCb.chanClass;
|
||||
pBigCtx->ctrChSelInfo.usedChSel = LL_CH_SEL_2;
|
||||
pBigCtx->ctrChSelInfo.chIdentifier = (uint16_t)(LL_BIG_CONTROL_ACCESS_ADDR >> 16) ^
|
||||
(uint16_t)(LL_BIG_CONTROL_ACCESS_ADDR >> 0);
|
||||
LmgrBuildRemapTable(&pBigCtx->ctrChSelInfo);
|
||||
|
||||
pBigCtx->ctrChan.opType = BB_BLE_OP_SLV_BIS_EVENT;
|
||||
pBigCtx->ctrChan.accAddr = lctrComputeBisAccessAddr(pBigCtx->seedAccAddr, 0);
|
||||
|
||||
pBigCtx->ctrChSelInfo.chanMask = lmgrCb.chanClass;
|
||||
pBigCtx->ctrChSelInfo.usedChSel = LL_CH_SEL_2;
|
||||
pBigCtx->ctrChSelInfo.chIdentifier = (uint16_t)(pBigCtx->ctrChan.accAddr >> 16) ^
|
||||
(uint16_t)(pBigCtx->ctrChan.accAddr >> 0);
|
||||
LmgrBuildRemapTable(&pBigCtx->ctrChSelInfo);
|
||||
|
||||
pBigCtx->ctrChan.crcInit = (pBigCtx->baseCrcInit << 8) | 0;
|
||||
pBigCtx->ctrChan.txPower = lmgrCb.advTxPwr;
|
||||
pBigCtx->ctrChan.txPhy = pBigCtx->phy;
|
||||
|
@ -266,10 +284,10 @@ static void lctrSlvSetupBigChannel(lctrBigCtx_t *pBigCtx)
|
|||
pBigCtx->ctrChan.enc.nonceMode = PAL_BB_NONCE_MODE_EXT64_CNTR;
|
||||
|
||||
memcpy(pBigCtx->ctrChan.enc.iv, pBigCtx->giv, LL_IV_LEN);
|
||||
pBigCtx->ctrChan.enc.iv[0] ^= LL_BIG_CONTROL_ACCESS_ADDR >> 0;
|
||||
pBigCtx->ctrChan.enc.iv[1] ^= LL_BIG_CONTROL_ACCESS_ADDR >> 8;
|
||||
pBigCtx->ctrChan.enc.iv[2] ^= LL_BIG_CONTROL_ACCESS_ADDR >> 16;
|
||||
pBigCtx->ctrChan.enc.iv[3] ^= LL_BIG_CONTROL_ACCESS_ADDR >> 24;
|
||||
pBigCtx->ctrChan.enc.iv[0] ^= pBigCtx->ctrChan.accAddr >> 0;
|
||||
pBigCtx->ctrChan.enc.iv[1] ^= pBigCtx->ctrChan.accAddr >> 8;
|
||||
pBigCtx->ctrChan.enc.iv[2] ^= pBigCtx->ctrChan.accAddr >> 16;
|
||||
pBigCtx->ctrChan.enc.iv[3] ^= pBigCtx->ctrChan.accAddr >> 24;
|
||||
|
||||
memcpy(pBigCtx->ctrChan.enc.sk, pBigCtx->bleData.chan.enc.sk, PAL_CRYPTO_LL_KEY_LEN);
|
||||
|
||||
|
@ -277,7 +295,10 @@ static void lctrSlvSetupBigChannel(lctrBigCtx_t *pBigCtx)
|
|||
pBigCtx->ctrChan.enc.dir = 1;
|
||||
pBigCtx->ctrChan.enc.type = PAL_BB_TYPE_BIS;
|
||||
|
||||
lctrInitCipherBlkHdlr(&pBigCtx->ctrChan.enc, LCTR_BIG_CTRL_ENC_ID(pBigCtx), 1);
|
||||
if (lctrInitCipherBlkHdlr)
|
||||
{
|
||||
lctrInitCipherBlkHdlr(&pBigCtx->ctrChan.enc, LCTR_BIG_CTRL_ENC_ID(pBigCtx), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -508,7 +529,7 @@ void LctrSlvBisInit(void)
|
|||
/* Set supported features. */
|
||||
if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_5_1)
|
||||
{
|
||||
lmgrPersistCb.featuresDefault |= LL_FEAT_ISO_BROADCASTER;
|
||||
lmgrPersistCb.featuresDefault |= LL_FEAT_ISO_SYNC;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -574,7 +595,8 @@ uint8_t LctrSlvBisCreateBig(LlCreateBig_t *pCreateBig)
|
|||
|
||||
if (pBisCtx)
|
||||
{
|
||||
lctrSetupBisContext(pBisCtx, pBigCtx->seedAccAddr, pBigCtx->baseCrcInit, lmgrCb.chanClass, pBigCtx->phy);
|
||||
lctrSetupBisContext(pBisCtx, pBigCtx->seedAccAddr, pBigCtx->baseCrcInit, lmgrCb.chanClass,
|
||||
(LlPhy_t)pBigCtx->phy);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -663,7 +685,8 @@ uint8_t LctrSlvBisCreateBigTest(LlCreateBigTest_t *pCreateBigTest)
|
|||
|
||||
if (pBisCtx)
|
||||
{
|
||||
lctrSetupBisContext(pBisCtx, pBigCtx->seedAccAddr, pBigCtx->baseCrcInit, lmgrCb.chanClass, pBigCtx->phy);
|
||||
lctrSetupBisContext(pBisCtx, pBigCtx->seedAccAddr, pBigCtx->baseCrcInit, lmgrCb.chanClass,
|
||||
(LlPhy_t)pBigCtx->phy);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -932,10 +955,10 @@ uint8_t lctrSlvBigBuildOp(lctrBigCtx_t *pBigCtx)
|
|||
return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES;
|
||||
}
|
||||
|
||||
const uint32_t curTime = PalBbGetCurrentTime();
|
||||
uint32_t offsetUsec = SchRmGetOffsetUsec(pOp->minDurUsec,
|
||||
LCTR_BIG_TO_RM_HANDLE(pBigCtx), curTime);
|
||||
pOp->dueUsec = curTime + offsetUsec;
|
||||
const uint32_t refTime = pBigCtx->roleData.slv.pAdvSet->advBod.dueUsec;
|
||||
uint32_t offsetUsec = SchRmGetOffsetUsec(pBigCtx->isoInterUsec,
|
||||
LCTR_BIG_TO_RM_HANDLE(pBigCtx), refTime);
|
||||
pOp->dueUsec = refTime + offsetUsec;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -143,6 +143,38 @@ void lctrCleanupCtx(lctrCisCtx_t *pCisCtx)
|
|||
lctrCigCtx_t *pCigCtx = lctrFindCigById(pCisCtx->cigId);
|
||||
WSF_ASSERT(pCigCtx);
|
||||
|
||||
uint8_t *pBuf;
|
||||
uint8_t numTxBufs;
|
||||
wsfHandlerId_t handlerId;
|
||||
|
||||
pCisCtx->cisEvtCounter = 0;
|
||||
pCisCtx->firstFromPeer = FALSE;
|
||||
pCisCtx->connEst = FALSE;
|
||||
|
||||
/* Must do one at a time in case one datapath is not used. */
|
||||
LctrRemoveIsoDataPath(pCisCtx->cisHandle, LL_ISO_DATA_PATH_INPUT_BIT);
|
||||
LctrRemoveIsoDataPath(pCisCtx->cisHandle, LL_ISO_DATA_PATH_OUTPUT_BIT);
|
||||
|
||||
/* Flush remaining transmit packets. */
|
||||
numTxBufs = lctrCisTxQueueClear(pCisCtx);
|
||||
|
||||
/* Flush remaining transmit packets. */
|
||||
while ((pBuf = WsfMsgDeq(&pCisCtx->txIsoQ, &handlerId)) != NULL)
|
||||
{
|
||||
lctrDataTxIncAvailBuf();
|
||||
numTxBufs++;
|
||||
|
||||
WsfMsgFree(pBuf);
|
||||
}
|
||||
|
||||
/* Flush remaining Tx/Rx flush timeout list. */
|
||||
lctrCisFtListClear(&pCisCtx->txFtParamList);
|
||||
lctrCisFtListClear(&pCisCtx->rxFtParamList);
|
||||
|
||||
/* Cleanup timers. */
|
||||
WsfTimerStop(&pCisCtx->tmrSupTimeout);
|
||||
WsfTimerStop(&pCisCtx->tmrProcRsp);
|
||||
|
||||
if (lctrCisIsHeadCis(&pCigCtx->list, pCisCtx) == TRUE)
|
||||
{
|
||||
pCigCtx->headCisRmved = TRUE;
|
||||
|
@ -177,6 +209,11 @@ void lctrCleanupCtx(lctrCisCtx_t *pCisCtx)
|
|||
|
||||
if (lctrCisIsListEmpty(&pCigCtx->list))
|
||||
{
|
||||
/* Refresh CIG context to get ready for re-starting CIS. */
|
||||
pCigCtx->headCisRmved = FALSE;
|
||||
pCigCtx->isBodBuilt = FALSE;
|
||||
pCigCtx->isBodStarted = FALSE;
|
||||
|
||||
if (pCigCtx->isRmAdded == TRUE)
|
||||
{
|
||||
SchRmRemove(LCTR_GET_CIG_RM_HANDLE(pCigCtx));
|
||||
|
@ -204,7 +241,6 @@ void lctrCleanupCtx(lctrCisCtx_t *pCisCtx)
|
|||
}
|
||||
|
||||
void *pIsoBuf;
|
||||
uint8_t handlerId;
|
||||
while ((pIsoBuf = WsfMsgDeq(&pCisCtx->isoalTxCtx.pendingSduQ, &handlerId)) != NULL)
|
||||
{
|
||||
WsfMsgFree(pIsoBuf);
|
||||
|
@ -222,36 +258,8 @@ void lctrCleanupCtx(lctrCisCtx_t *pCisCtx)
|
|||
/*************************************************************************************************/
|
||||
void lctrFreeCisCtx(lctrCisCtx_t *pCisCtx)
|
||||
{
|
||||
uint8_t *pBuf;
|
||||
uint8_t numTxBufs;
|
||||
wsfHandlerId_t handlerId;
|
||||
|
||||
WSF_ASSERT(pCisCtx->enabled);
|
||||
pCisCtx->enabled = FALSE;
|
||||
|
||||
/* Clean up receive context. */
|
||||
lctrIsoOutDataPathClear(&pCisCtx->dataPathOutCtx);
|
||||
|
||||
/* Flush remaining transmit packets. */
|
||||
numTxBufs = lctrCisTxQueueClear(pCisCtx);
|
||||
|
||||
/* Flush remaining transmit packets. */
|
||||
while ((pBuf = WsfMsgDeq(&pCisCtx->txIsoQ, &handlerId)) != NULL)
|
||||
{
|
||||
lctrDataTxIncAvailBuf();
|
||||
numTxBufs++;
|
||||
|
||||
WsfMsgFree(pBuf);
|
||||
}
|
||||
|
||||
/* Flush remaining Tx/Rx flush timeout list. */
|
||||
lctrCisFtListClear(&pCisCtx->txFtParamList);
|
||||
lctrCisFtListClear(&pCisCtx->rxFtParamList);
|
||||
|
||||
/* Cleanup timers. */
|
||||
WsfTimerStop(&pCisCtx->tmrSupTimeout);
|
||||
WsfTimerStop(&pCisCtx->tmrProcRsp);
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -444,7 +452,6 @@ uint16_t LctrInitCisMem(uint8_t *pFreeMem, uint32_t freeMemSize)
|
|||
pLctrCisTbl = (lctrCisCtx_t *)pAvailMem;
|
||||
pAvailMem += sizeof(lctrCisCtx_t) * pLctrRtCfg->maxCis;
|
||||
|
||||
|
||||
if (((uint32_t)pAvailMem) & 3)
|
||||
{
|
||||
/* Align to next word. */
|
||||
|
@ -493,7 +500,7 @@ void lctrCisInitFtParam(lctrFtParam_t *pFtParam, uint8_t bn, uint8_t ft, uint8_t
|
|||
if (bn == 1)
|
||||
{
|
||||
/* BN = 1, numSubEvtFt[0] = BN * NSE */
|
||||
pFtParam->lastSubEvtFt[0] = bn * nse;
|
||||
pFtParam->lastSubEvtFt[0] = nse;
|
||||
pFtParam->isPduDone[0] = FALSE;
|
||||
pFtParam->pduType[0] = LCTR_CIS_PDU_DEFAULT;
|
||||
}
|
||||
|
@ -784,7 +791,6 @@ void lctrCisSetupEncrypt(lctrCisCtx_t *pCisCtx)
|
|||
|
||||
PalCryptoAesEcb(pCtx->ltk, pEnc->sk, pCtx->skd);
|
||||
|
||||
WSF_ASSERT(lctrInitCipherBlkHdlr);
|
||||
memcpy(pEnc->iv, pCtx->iv, sizeof(pEnc->iv));
|
||||
uint8_t *pTemp, accAddr[4];
|
||||
pTemp = accAddr;
|
||||
|
@ -796,7 +802,10 @@ void lctrCisSetupEncrypt(lctrCisCtx_t *pCisCtx)
|
|||
pEnc->dir = (pCisCtx->role == LL_ROLE_MASTER) ? 1 : 0; /* master = 1; slave = 0 */
|
||||
pEnc->type = PAL_BB_TYPE_CIS;
|
||||
|
||||
lctrInitCipherBlkHdlr(pEnc, pCisCtx->cisHandle, pEnc->dir);
|
||||
if (lctrInitCipherBlkHdlr)
|
||||
{
|
||||
lctrInitCipherBlkHdlr(pEnc, pCisCtx->cisHandle, pEnc->dir);
|
||||
}
|
||||
|
||||
pEnc->enaEncrypt = pCtx->bleData.chan.enc.enaEncrypt;
|
||||
pEnc->enaDecrypt = pCtx->bleData.chan.enc.enaDecrypt;
|
||||
|
@ -1638,7 +1647,14 @@ uint32_t lctrCisCalcSubEvtDurationUsecSeq(uint8_t phyMToS, uint8_t phySToM, uint
|
|||
duration += LL_DATA_LEN_TO_TIME_2M(plMToS, TRUE);
|
||||
break;
|
||||
case BB_PHY_BLE_CODED:
|
||||
duration += LL_DATA_LEN_TO_TIME_CODED_S8(plMToS, TRUE);
|
||||
if (lmgrGetOpFlag(LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2))
|
||||
{
|
||||
duration += LL_DATA_LEN_TO_TIME_CODED_S2(plMToS, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
duration += LL_DATA_LEN_TO_TIME_CODED_S8(plMToS, TRUE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1655,7 +1671,14 @@ uint32_t lctrCisCalcSubEvtDurationUsecSeq(uint8_t phyMToS, uint8_t phySToM, uint
|
|||
duration += LL_DATA_LEN_TO_TIME_2M(plSToM, TRUE);
|
||||
break;
|
||||
case BB_PHY_BLE_CODED:
|
||||
duration += LL_DATA_LEN_TO_TIME_CODED_S8(plSToM, TRUE);
|
||||
if (lmgrGetOpFlag(LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2))
|
||||
{
|
||||
duration += LL_DATA_LEN_TO_TIME_CODED_S2(plSToM, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
duration += LL_DATA_LEN_TO_TIME_CODED_S8(plSToM, TRUE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1745,65 +1768,168 @@ void lctrCisTxTestPayloadHandler(lctrCisCtx_t * pCisCtx)
|
|||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Action function for cis power monitoring.
|
||||
* \brief Generate a lost/invalid SDU in case of flushed SDU.
|
||||
*
|
||||
* \param rssi CIS RX RSSI.
|
||||
* \param status rx status.
|
||||
* \param phy phy.
|
||||
* \param pConnCtx Connection context.
|
||||
*************************************************************************************************/
|
||||
void lctrCisPowerMonitorCheckRssi(int8_t rssi, uint8_t status, uint8_t phy, lctrConnCtx_t *pConnCtx)
|
||||
* \param pCisCtx CIS context.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void lctrCisCheckUnframedFlush(lctrCisCtx_t *pCisCtx)
|
||||
{
|
||||
if (!(pConnCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST))
|
||||
/*** Send up error SDU ***/
|
||||
uint8_t handlerId;
|
||||
uint8_t *pSdu;
|
||||
uint8_t numHandles = 0;
|
||||
uint16_t handles[1] = { pCisCtx->cisHandle };
|
||||
uint16_t numSdu[1] = { 0 };
|
||||
|
||||
/* NULL signals lost PDU; release previously stored fragments. */
|
||||
if (lctrRecombineRxUnframedSdu(&pCisCtx->isoalRxCtx, NULL))
|
||||
{
|
||||
while ((pSdu = WsfMsgDeq(&pCisCtx->isoalRxCtx.data.unframed.pendSduQ, &handlerId)) != NULL)
|
||||
{
|
||||
/* Enqueue SDU for processing. */
|
||||
if (!lctrIsoRxConnEnq(&pCisCtx->dataPathOutCtx, pCisCtx->cisHandle,
|
||||
pCisCtx->rxPktCounter, pSdu))
|
||||
{
|
||||
/* The buffer was not freed, so free it now. */
|
||||
WsfMsgFree(pSdu);
|
||||
}
|
||||
|
||||
numHandles = 1;
|
||||
numSdu[0]++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lmgrGetOpFlag(LL_OP_MODE_FLAG_ENA_ISO_LOST_NOTIFY) &&
|
||||
(((pCisCtx->role == LL_ROLE_SLAVE) && (pCisCtx->data.slv.rxFromMaster == FALSE)) ||
|
||||
((pCisCtx->role == LL_ROLE_MASTER) && (pCisCtx->data.mst.rxFromSlave == FALSE))))
|
||||
{
|
||||
/* No prior fragments; send lost SDU. */
|
||||
if ((pSdu = lctrRxSduAlloc()) != NULL)
|
||||
{
|
||||
/* TODO: This code path increases this twice: once in lctrRxSduAlloc and lctrIsoRxConnEnq.
|
||||
* Change to only increase once.
|
||||
*/
|
||||
lctrIsoDataRxIncAvailBuf(1);
|
||||
|
||||
lctrIsoHdr_t isoHdr =
|
||||
{
|
||||
/* ISO header */
|
||||
.handle = pCisCtx->cisHandle,
|
||||
.pb = LCTR_PB_COMP,
|
||||
.tsFlag = FALSE,
|
||||
.len = 0,
|
||||
|
||||
/* Data load */
|
||||
.ts = 0,
|
||||
.pktSn = pCisCtx->rxPktCounter,
|
||||
.sduLen = 0,
|
||||
.ps = LCTR_PS_LOST
|
||||
};
|
||||
|
||||
lctrIsoPackHdr(pSdu, &isoHdr);
|
||||
|
||||
/* Enqueue SDU for processing. */
|
||||
if (!lctrIsoRxConnEnq(&pCisCtx->dataPathOutCtx, pCisCtx->cisHandle,
|
||||
pCisCtx->rxPktCounter, pSdu))
|
||||
{
|
||||
/* The buffer was not freed, so free it now. */
|
||||
WsfMsgFree(pSdu);
|
||||
}
|
||||
numHandles = 1;
|
||||
numSdu[0]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_WARN0("SDU Could not be allocated.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lmgrPersistCb.recvIsoPendCback && numHandles)
|
||||
{
|
||||
/* Notify host received SDUs. */
|
||||
lmgrPersistCb.recvIsoPendCback(numHandles, handles, numSdu);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Service function for CIS power control.
|
||||
*
|
||||
* \param pConnCtx Connection context.
|
||||
*
|
||||
*************************************************************************************************/
|
||||
void lctrCisServicePowerMonitor(lctrConnCtx_t *pConnCtx)
|
||||
{
|
||||
if (!(pConnCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST) ||
|
||||
lmgrGetOpFlag(LL_OP_MODE_FLAG_DIS_POWER_MONITOR))
|
||||
{
|
||||
pConnCtx->monitoringState = LCTR_PC_MONITOR_DISABLED;
|
||||
return;
|
||||
}
|
||||
|
||||
if (lmgrCb.opModeFlags & LL_OP_MODE_DISABLE_POWER_MONITOR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int8_t sendReqDelta = 0;
|
||||
lctrCisCtx_t *pCisCtx = NULL;
|
||||
|
||||
if ((rssi < pConnCtx->pclMonitorParam.autoMonitor.lowThreshold) ||
|
||||
(status != BB_STATUS_SUCCESS))
|
||||
for (unsigned int i = 0; i < pLctrRtCfg->maxCis; i++)
|
||||
{
|
||||
pConnCtx->cisRssiExtremeTimeSpent++;
|
||||
pCisCtx = &pLctrCisTbl[i];
|
||||
|
||||
if (pConnCtx->cisRssiExtremeTimeSpent >= pConnCtx->pclMonitorParam.autoMonitor.minTimeSpent)
|
||||
if ((pCisCtx->aclHandle == LCTR_GET_CONN_HANDLE(pConnCtx)) &&
|
||||
(pCisCtx->enabled) && (pCisCtx->connEst))
|
||||
{
|
||||
if (!(pConnCtx->peerPwrLimits & LL_PWR_CONTROL_LIMIT_MAX_BIT))
|
||||
if (((pCisCtx->role == LL_ROLE_SLAVE) && (pCisCtx->phyMToS == pConnCtx->bleData.chan.rxPhy)) ||
|
||||
((pCisCtx->role == LL_ROLE_MASTER) && (pCisCtx->phySToM == pConnCtx->bleData.chan.rxPhy)))
|
||||
{
|
||||
LL_TRACE_INFO1("RSSI too low, requesting increase in power. phy=%u", phy);
|
||||
sendReqDelta = pConnCtx->pclMonitorParam.autoMonitor.requestVal;
|
||||
/* This power is already managed by ACL, so no need to run management on CIS. */
|
||||
return;
|
||||
}
|
||||
pConnCtx->cisRssiExtremeTimeSpent = 0;
|
||||
|
||||
goto CisManageRssiPower;
|
||||
}
|
||||
}
|
||||
else if (rssi > pConnCtx->pclMonitorParam.autoMonitor.highThreshold)
|
||||
{
|
||||
pConnCtx->cisRssiExtremeTimeSpent++;
|
||||
return;
|
||||
|
||||
if (pConnCtx->cisRssiExtremeTimeSpent >= pConnCtx->pclMonitorParam.autoMonitor.minTimeSpent)
|
||||
{
|
||||
if (!(pConnCtx->peerPwrLimits & LL_PWR_CONTROL_LIMIT_MIN_BIT))
|
||||
{
|
||||
LL_TRACE_INFO1("RSSI too high, requesting decrease in power. phy=%u", phy);
|
||||
sendReqDelta = -(pConnCtx->pclMonitorParam.autoMonitor.requestVal);
|
||||
}
|
||||
pConnCtx->cisRssiExtremeTimeSpent = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
CisManageRssiPower:
|
||||
|
||||
lctrRssiAddAveragePoint(&pConnCtx->cisRunAvg, -((int8_t) (pConnCtx->cisAccumulatedRssi / pConnCtx->cisTotalAccumulatedRssi)));
|
||||
pConnCtx->cisAccumulatedRssi = 0;
|
||||
pConnCtx->cisTotalAccumulatedRssi = 0;
|
||||
|
||||
if (pConnCtx->cisRunAvg.avgCount >= LL_PC_TBL_LEN)
|
||||
{
|
||||
pConnCtx->cisRssiExtremeTimeSpent = 0;
|
||||
int8_t averageRunning = lctrRssiGetAverage(&pConnCtx->cisRunAvg);
|
||||
|
||||
if ((averageRunning > pConnCtx->pclMonitorParam.autoMonitor.highThreshold) &&
|
||||
!(pConnCtx->peerPwrLimits & LL_PWR_CONTROL_LIMIT_MIN_BIT))
|
||||
{
|
||||
sendReqDelta = -(pConnCtx->pclMonitorParam.autoMonitor.requestVal);
|
||||
}
|
||||
else if ((averageRunning < pConnCtx->pclMonitorParam.autoMonitor.lowThreshold) &&
|
||||
!(pConnCtx->peerPwrLimits & LL_PWR_CONTROL_LIMIT_MAX_BIT))
|
||||
{
|
||||
sendReqDelta = pConnCtx->pclMonitorParam.autoMonitor.requestVal;
|
||||
}
|
||||
}
|
||||
|
||||
if (sendReqDelta != 0)
|
||||
{
|
||||
if ((pConnCtx->llcpActiveProc == LCTR_PROC_PWR_CTRL) ||
|
||||
(pConnCtx->llcpPendMask & (1 << LCTR_PROC_PWR_CTRL)))
|
||||
{
|
||||
LL_TRACE_WARN0("Power control LLCP already ongoing or pended upon attempt to start new power control process.");
|
||||
return;
|
||||
}
|
||||
|
||||
lctrMsgPwrCtrlReq_t *pMsg;
|
||||
uint8_t phy = ((pCisCtx->role == LL_ROLE_MASTER) ? pCisCtx->phySToM : pCisCtx->phyMToS);
|
||||
|
||||
/* Decide to request S8 or S2 PHY. */
|
||||
phy += (((phy == LL_PHY_LE_CODED) &&
|
||||
(pCisCtx->bleData.chan.initTxPhyOptions == LL_PHY_OPTIONS_S2_PREFERRED)) ? 1 : 0);
|
||||
|
||||
if ((pMsg = (lctrMsgPwrCtrlReq_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL)
|
||||
{
|
||||
pMsg->hdr.handle = LCTR_GET_CONN_HANDLE(pConnCtx);
|
||||
|
@ -1814,6 +1940,8 @@ void lctrCisPowerMonitorCheckRssi(int8_t rssi, uint8_t status, uint8_t phy, lctr
|
|||
|
||||
WsfMsgSend(lmgrPersistCb.handlerId, pMsg);
|
||||
}
|
||||
|
||||
pConnCtx->cisRunAvg.avgCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -207,7 +207,11 @@ static void lctrSetCis(lctrCisCtx_t *pCisCtx, LlCisCigParams_t *pSetCigParam, Ll
|
|||
pCisCtx->ftMToS = LlMathDivideUint32(pSetCigParam->transLatMToS * 1000, LCTR_ISO_INT_TO_US(pCisCtx->isoInterval));
|
||||
pCisCtx->ftSToM = LlMathDivideUint32(pSetCigParam->transLatSToM * 1000, LCTR_ISO_INT_TO_US(pCisCtx->isoInterval));
|
||||
|
||||
if (pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen * pCisCtx->localDataPdu.maxTxLen < pCisCtx->sduSizeMToS)
|
||||
if (pCisCtx->localDataPdu.maxTxLen == 0)
|
||||
{
|
||||
pCisCtx->bnMToS = 0;
|
||||
}
|
||||
else if (pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen * pCisCtx->localDataPdu.maxTxLen < pCisCtx->sduSizeMToS)
|
||||
{
|
||||
pCisCtx->bnMToS = pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen + 1;
|
||||
}
|
||||
|
@ -216,7 +220,11 @@ static void lctrSetCis(lctrCisCtx_t *pCisCtx, LlCisCigParams_t *pSetCigParam, Ll
|
|||
pCisCtx->bnMToS = pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen;
|
||||
}
|
||||
|
||||
if (pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen * pCisCtx->localDataPdu.maxRxLen < pCisCtx->sduSizeSToM)
|
||||
if (pCisCtx->localDataPdu.maxRxLen == 0)
|
||||
{
|
||||
pCisCtx->bnSToM = 0;
|
||||
}
|
||||
else if (pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen * pCisCtx->localDataPdu.maxRxLen < pCisCtx->sduSizeSToM)
|
||||
{
|
||||
pCisCtx->bnSToM = pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen + 1;
|
||||
}
|
||||
|
@ -255,7 +263,11 @@ static void lctrSetCis(lctrCisCtx_t *pCisCtx, LlCisCigParams_t *pSetCigParam, Ll
|
|||
pCisCtx->ftMToS = LlMathDivideUint32(pSetCigParam->transLatMToS * 1000, LCTR_ISO_INT_TO_US(pCisCtx->isoInterval));
|
||||
pCisCtx->ftSToM = LlMathDivideUint32(pSetCigParam->transLatSToM * 1000, LCTR_ISO_INT_TO_US(pCisCtx->isoInterval));
|
||||
|
||||
if (pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen * pCisCtx->localDataPdu.maxTxLen < pCisCtx->sduSizeMToS)
|
||||
if (pCisCtx->localDataPdu.maxTxLen == 0)
|
||||
{
|
||||
pCisCtx->bnMToS = 0;
|
||||
}
|
||||
else if (pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen * pCisCtx->localDataPdu.maxTxLen < pCisCtx->sduSizeMToS)
|
||||
{
|
||||
pCisCtx->bnMToS = pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen + 1;
|
||||
}
|
||||
|
@ -264,7 +276,11 @@ static void lctrSetCis(lctrCisCtx_t *pCisCtx, LlCisCigParams_t *pSetCigParam, Ll
|
|||
pCisCtx->bnMToS = pCisCtx->sduSizeMToS / pCisCtx->localDataPdu.maxTxLen;
|
||||
}
|
||||
|
||||
if (pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen * pCisCtx->localDataPdu.maxRxLen < pCisCtx->sduSizeSToM)
|
||||
if (pCisCtx->localDataPdu.maxRxLen == 0)
|
||||
{
|
||||
pCisCtx->bnSToM = 0;
|
||||
}
|
||||
else if (pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen * pCisCtx->localDataPdu.maxRxLen < pCisCtx->sduSizeSToM)
|
||||
{
|
||||
pCisCtx->bnSToM = pCisCtx->sduSizeSToM / pCisCtx->localDataPdu.maxRxLen + 1;
|
||||
}
|
||||
|
@ -359,6 +375,7 @@ static void lctrSetCig(lctrCigCtx_t *pCigCtx, LlCisCigParams_t *pSetCigParam)
|
|||
pCisCtx = lctrFindCisById(pSetCigParam->cigId, pSetCigParam->pCisParam[i].cisId);
|
||||
|
||||
WSF_ASSERT(pCisCtx);
|
||||
pCisCtx->cisSyncDelayUsec = 0;
|
||||
|
||||
for (unsigned int j = i; j < pSetCigParam->numCis; j++)
|
||||
{
|
||||
|
@ -569,6 +586,40 @@ uint8_t LctrSetCigParam(LlCisCigParams_t *pSetCigParam, uint16_t *pCisHandles)
|
|||
pCisHandles[i] = pCisCtx->cisHandle;
|
||||
}
|
||||
lctrSetCig(pCigCtx, pSetCigParam);
|
||||
|
||||
/* Invalid CIG parameters. Attempt adjusting of CIG parameters. */
|
||||
bool_t paramsChanged = TRUE;
|
||||
if (pCigCtx->isValid == FALSE)
|
||||
{
|
||||
LL_TRACE_WARN1("LctrSetCigParam, invalid parameters in cigID=%u; adjust parameters", pSetCigParam->cigId);
|
||||
}
|
||||
while ((pCigCtx->isValid == FALSE) && (paramsChanged == TRUE))
|
||||
{
|
||||
paramsChanged = FALSE;
|
||||
for (unsigned int i = 0; i < pSetCigParam->numCis; i++)
|
||||
{
|
||||
/* Try to adjust CIS RTE to lower than host-reccomended value. */
|
||||
pCisCtx = lctrFindCisByHandle(pCisHandles[i]);
|
||||
if (pSetCigParam->pCisParam[i].rteMToS > 0)
|
||||
{
|
||||
pSetCigParam->pCisParam[i].rteMToS--;
|
||||
paramsChanged = TRUE;
|
||||
}
|
||||
if (pSetCigParam->pCisParam[i].rteSToM > 0)
|
||||
{
|
||||
pSetCigParam->pCisParam[i].rteSToM--;
|
||||
paramsChanged = TRUE;
|
||||
}
|
||||
|
||||
/* Re-apply parameters. */
|
||||
lctrSetCis(pCisCtx, pSetCigParam, &pSetCigParam->pCisParam[i]);
|
||||
lctrSetCig(pCigCtx, pSetCigParam);
|
||||
if (pCigCtx->isValid)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -597,6 +648,40 @@ uint8_t LctrSetCigParam(LlCisCigParams_t *pSetCigParam, uint16_t *pCisHandles)
|
|||
}
|
||||
lctrSetCig(pCigCtx, pSetCigParam);
|
||||
}
|
||||
|
||||
/* Invalid CIG parameters. Attempt adjusting of CIG parameters. */
|
||||
bool_t paramsChanged = TRUE;
|
||||
if (pCigCtx->isValid == FALSE)
|
||||
{
|
||||
LL_TRACE_WARN1("LctrSetCigParam: invalid parameters in cigID=%u; adjust parameters", pSetCigParam->cigId);
|
||||
}
|
||||
while ((pCigCtx->isValid == FALSE) && (paramsChanged == TRUE))
|
||||
{
|
||||
paramsChanged = FALSE;
|
||||
for (unsigned int i = 0; i < pSetCigParam->numCis; i++)
|
||||
{
|
||||
/* Try to adjust CIS RTE to lower than host-reccomended value. */
|
||||
pCisCtx = lctrFindCisByHandle(pCisHandles[i]);
|
||||
if (pSetCigParam->pCisParam[i].rteMToS > 0)
|
||||
{
|
||||
pSetCigParam->pCisParam[i].rteMToS--;
|
||||
paramsChanged = TRUE;
|
||||
}
|
||||
if (pSetCigParam->pCisParam[i].rteSToM > 0)
|
||||
{
|
||||
pSetCigParam->pCisParam[i].rteSToM--;
|
||||
paramsChanged = TRUE;
|
||||
}
|
||||
|
||||
/* Re-apply parameters. */
|
||||
lctrSetCis(pCisCtx, pSetCigParam, &pSetCigParam->pCisParam[i]);
|
||||
lctrSetCig(pCigCtx, pSetCigParam);
|
||||
if (pCigCtx->isValid)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pCigCtx->roleData.mst.numCis = pSetCigParam->numCis;
|
||||
|
@ -772,6 +857,7 @@ void LctrMstCisInit(void)
|
|||
/* Add CIS function pointers */
|
||||
LctrUpdateCisChanMapFn = LctrCisUpdateChanMap;
|
||||
lctrRegisterChClassHandler(lctrMstCisChClassUpdate);
|
||||
lctrCisServicePowerMonitorFn = lctrCisServicePowerMonitor;
|
||||
|
||||
/* Add CIS event handlers. */
|
||||
lctrEventHdlrTbl[LCTR_EVENT_CIS_TX_PENDING] = lctrIsoTxPendingHandler;
|
||||
|
@ -826,6 +912,8 @@ uint8_t LctrCreateCis(uint8_t numCis, LlCisCreateCisParams_t *pCreateCisParam)
|
|||
LL_TRACE_WARN0("LctrCreateCis, CIS is already established");
|
||||
return LL_ERROR_CODE_ACL_CONN_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
pCisCtx->isClosing = FALSE;
|
||||
}
|
||||
|
||||
lmgrCisMstCb.createCisPend = TRUE;
|
||||
|
@ -873,6 +961,7 @@ void lctrMstCisBuildCigOp(lctrCigCtx_t *pCigCtx)
|
|||
|
||||
BbBleData_t * const pBle = &pCisCtx->bleData;
|
||||
BbBleMstCisEvent_t * const pCis = &pBle->op.mstCis;
|
||||
lctrConnCtx_t * pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle);
|
||||
|
||||
memset(pOp, 0, sizeof(BbOpDesc_t));
|
||||
memset(pBle, 0, sizeof(BbBleData_t));
|
||||
|
@ -897,8 +986,18 @@ void lctrMstCisBuildCigOp(lctrCigCtx_t *pCigCtx)
|
|||
pBle->chan.peerTxStableModIdx = TRUE;
|
||||
pBle->chan.peerRxStableModIdx = TRUE;
|
||||
|
||||
/* Set PHY options to mirror acl connection option. */
|
||||
pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S8;
|
||||
if (lmgrGetOpFlag(LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2))
|
||||
{
|
||||
/* Force Coded PHY option to S2. */
|
||||
pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S2;
|
||||
pBle->chan.tifsTxPhyOptions = BB_PHY_OPTIONS_BLE_S2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set PHY options to mirror ACL connection option. */
|
||||
pBle->chan.initTxPhyOptions = pConnCtx->bleData.chan.initTxPhyOptions;
|
||||
pBle->chan.tifsTxPhyOptions = pConnCtx->bleData.chan.tifsTxPhyOptions;
|
||||
}
|
||||
|
||||
#if (LL_ENABLE_TESTER)
|
||||
pBle->chan.accAddrRx = pCisCtx->accessAddr ^ llTesterCb.cisAccessAddrRx;
|
||||
|
@ -916,8 +1015,7 @@ void lctrMstCisBuildCigOp(lctrCigCtx_t *pCigCtx)
|
|||
|
||||
/*** General setup ***/
|
||||
|
||||
/* pOp->minDurUsec = pFirstCisCtx->subIntervUsec * WSF_MAX(pFirstCisCtx->bnMToS, pFirstCisCtx->bnSToM); */ /* Guarantee at least Max BN */
|
||||
pOp->minDurUsec = pCigCtx->cigSyncDelayUsec;
|
||||
pOp->minDurUsec = pCisCtx->subIntervUsec * WSF_MAX(pCisCtx->bnMToS, pCisCtx->bnSToM); /* Guarantee at least Max BN */
|
||||
pOp->maxDurUsec = pCigCtx->cigSyncDelayUsec;
|
||||
|
||||
/* pOp->due = 0 */ /* set in lctrMstCisCigOpCommit() */
|
||||
|
@ -931,6 +1029,7 @@ void lctrMstCisBuildCigOp(lctrCigCtx_t *pCigCtx)
|
|||
/*** BLE stream setup ***/
|
||||
|
||||
pCis->checkContOpCback = lctrMstCisCheckContOp;
|
||||
pCis->checkContOpPostCback = lctrMstCisCheckContOpPostCback;
|
||||
pCis->execCback = lctrMstCisCigBeginOp;
|
||||
pCis->contExecCback = lctrMstCisCigContOp;
|
||||
pCis->postSubEvtCback = lctrMstCisCigPostSubEvt;
|
||||
|
@ -979,15 +1078,17 @@ void lctrMstCisBuildCisData(lctrCisCtx_t *pCisCtx)
|
|||
pBle->chan.peerTxStableModIdx = TRUE;
|
||||
pBle->chan.peerRxStableModIdx = TRUE;
|
||||
|
||||
/* Set PHY options to mirror acl connection option. */
|
||||
if (pConnCtx->bleData.chan.tifsTxPhyOptions != BB_PHY_OPTIONS_DEFAULT)
|
||||
if (lmgrGetOpFlag(LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2))
|
||||
{
|
||||
/* Set PHY options to host defined behavior. */
|
||||
pBle->chan.initTxPhyOptions = pConnCtx->bleData.chan.tifsTxPhyOptions;
|
||||
/* Force Coded PHY option to S2. */
|
||||
pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S2;
|
||||
pBle->chan.tifsTxPhyOptions = BB_PHY_OPTIONS_BLE_S2;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S8;
|
||||
/* Set PHY options to mirror ACL connection option. */
|
||||
pBle->chan.initTxPhyOptions = pConnCtx->bleData.chan.initTxPhyOptions;
|
||||
pBle->chan.tifsTxPhyOptions = pConnCtx->bleData.chan.tifsTxPhyOptions;
|
||||
}
|
||||
|
||||
#if (LL_ENABLE_TESTER)
|
||||
|
@ -1007,6 +1108,7 @@ void lctrMstCisBuildCisData(lctrCisCtx_t *pCisCtx)
|
|||
/*** BLE stream setup ***/
|
||||
|
||||
pCis->checkContOpCback = lctrMstCisCheckContOp;
|
||||
pCis->checkContOpPostCback = lctrMstCisCheckContOpPostCback;
|
||||
pCis->execCback = lctrMstCisCigBeginOp;
|
||||
pCis->contExecCback = lctrMstCisCigContOp;
|
||||
pCis->postSubEvtCback = lctrMstCisCigPostSubEvt;
|
||||
|
@ -1034,8 +1136,9 @@ void lctrMstCisCigOpCommit(lctrCigCtx_t *pCigCtx, lctrConnCtx_t *pCtx, lctrCisCt
|
|||
{
|
||||
/* Recalculate the CE ref if it is already past. */
|
||||
pCisCtx->ceRef = pCtx->eventCounter +
|
||||
LL_MIN_INSTANT + 1 + /* +1 for next CE */
|
||||
pCtx->maxLatency; /* ensure slave will listen to this packet */
|
||||
((LL_MIN_INSTANT + 1 + /* +1 for next CE */
|
||||
pCtx->maxLatency) * /* ensure slave will listen to this packet */
|
||||
pCtx->ecu.srFactor); /* include subrating factor */
|
||||
|
||||
refTime = pConnBod->dueUsec + (pCisCtx->ceRef - pCtx->eventCounter) * LCTR_CONN_IND_US(pCtx->connInterval);
|
||||
|
||||
|
|
|
@ -71,12 +71,11 @@ void LctrCisSlvInit(void)
|
|||
lctrResetHdlrTbl[LCTR_DISP_CIS] = lctrSlvCisResetHandler;
|
||||
|
||||
/* Add connection message dispatcher. */
|
||||
if (lctrMsgDispTbl[LCTR_DISP_CIS] != NULL)
|
||||
{
|
||||
lctrMsgDispTbl[LCTR_DISP_CIS] = (LctrMsgDisp_t)lctrCisDisp;
|
||||
}
|
||||
lctrMsgDispTbl[LCTR_DISP_CIS] = (LctrMsgDisp_t)lctrCisDisp;
|
||||
|
||||
lctrCisDefaults();
|
||||
/* Add CIS function pointers */
|
||||
LctrUpdateCisChanMapFn = LctrCisUpdateChanMap;
|
||||
lctrCisServicePowerMonitorFn = lctrCisServicePowerMonitor;
|
||||
|
||||
/* Add connection event handlers. */
|
||||
lctrEventHdlrTbl[LCTR_EVENT_CIS_RX_PENDING] = lctrCisRxPendingHandler;
|
||||
|
@ -86,6 +85,8 @@ void LctrCisSlvInit(void)
|
|||
lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_EST] = lctrSlvLlcpExecuteCisEstSm;
|
||||
lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM] = lctrLlcpExecuteCisTermSm;
|
||||
|
||||
lctrCisDefaults();
|
||||
|
||||
/* Set supported features. */
|
||||
if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_5_1)
|
||||
{
|
||||
|
@ -207,6 +208,7 @@ void lctrSlvCisBuildCigOp(lctrCigCtx_t *pCigCtx)
|
|||
|
||||
BbBleData_t * const pBle = &pCisCtx->bleData;
|
||||
BbBleSlvCisEvent_t * const pCis = &pBle->op.slvCis;
|
||||
lctrConnCtx_t * const pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle);
|
||||
|
||||
memset(pOp, 0, sizeof(BbOpDesc_t));
|
||||
memset(pBle, 0, sizeof(BbBleData_t));
|
||||
|
@ -235,8 +237,18 @@ void lctrSlvCisBuildCigOp(lctrCigCtx_t *pCigCtx)
|
|||
pBle->chan.peerTxStableModIdx = TRUE;
|
||||
pBle->chan.peerRxStableModIdx = TRUE;
|
||||
|
||||
/* Set PHY options to mirror acl connection option. */
|
||||
pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S8;
|
||||
if (lmgrGetOpFlag(LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2))
|
||||
{
|
||||
/* Force Coded PHY option to S2. */
|
||||
pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S2;
|
||||
pBle->chan.tifsTxPhyOptions = BB_PHY_OPTIONS_BLE_S2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set PHY options to mirror ACL connection option. */
|
||||
pBle->chan.initTxPhyOptions = pConnCtx->bleData.chan.initTxPhyOptions;
|
||||
pBle->chan.tifsTxPhyOptions = pConnCtx->bleData.chan.tifsTxPhyOptions;
|
||||
}
|
||||
|
||||
#if (LL_ENABLE_TESTER)
|
||||
pBle->chan.accAddrRx = pCisCtx->accessAddr ^ llTesterCb.cisAccessAddrRx;
|
||||
|
@ -254,7 +266,8 @@ void lctrSlvCisBuildCigOp(lctrCigCtx_t *pCigCtx)
|
|||
|
||||
/*** General setup ***/
|
||||
|
||||
pOp->minDurUsec = pCisCtx->subIntervUsec * WSF_MAX(pCisCtx->bnMToS, pCisCtx->bnSToM); /* Guarantee at least Max BN */
|
||||
/* Use small minDurUsec to improve scheduling. */
|
||||
pOp->minDurUsec = pCisCtx->subIntervUsec;
|
||||
pOp->maxDurUsec = pCigCtx->cigSyncDelayUsec;
|
||||
|
||||
/* pOp->due = 0 */ /* set in lctrCisMstCigOpCommit() */
|
||||
|
@ -268,6 +281,7 @@ void lctrSlvCisBuildCigOp(lctrCigCtx_t *pCigCtx)
|
|||
/*** BLE stream setup ***/
|
||||
|
||||
pCis->checkContOpCback = lctrSlvCisCheckContOp;
|
||||
pCis->checkContOpPostCback = lctrSlvCisCheckContOpPostCback;
|
||||
pCis->execCback = lctrSlvCisCigBeginOp;
|
||||
pCis->contExecCback = lctrSlvCisCigContOp;
|
||||
pCis->postSubEvtCback = lctrSlvCisCigPostSubEvt;
|
||||
|
@ -292,7 +306,7 @@ void lctrSlvCisBuildCisData(lctrCisCtx_t *pCisCtx)
|
|||
{
|
||||
BbBleData_t * const pBle = &pCisCtx->bleData;
|
||||
BbBleSlvCisEvent_t * const pCis = &pBle->op.slvCis;
|
||||
lctrConnCtx_t * pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle);
|
||||
lctrConnCtx_t * const pConnCtx = LCTR_GET_CONN_CTX(pCisCtx->aclHandle);
|
||||
|
||||
memset(pBle, 0, sizeof(BbBleData_t));
|
||||
memset(pCis, 0, sizeof(BbBleMstCisEvent_t));
|
||||
|
@ -316,15 +330,17 @@ void lctrSlvCisBuildCisData(lctrCisCtx_t *pCisCtx)
|
|||
pBle->chan.peerTxStableModIdx = TRUE;
|
||||
pBle->chan.peerRxStableModIdx = TRUE;
|
||||
|
||||
/* Set PHY options to mirror acl connection option. */
|
||||
if (pConnCtx->bleData.chan.tifsTxPhyOptions != BB_PHY_OPTIONS_DEFAULT)
|
||||
if (lmgrGetOpFlag(LL_OP_MODE_FLAG_FORCE_CIS_CODED_PHY_S2))
|
||||
{
|
||||
/* Set PHY options to host defined behavior. */
|
||||
pBle->chan.initTxPhyOptions = pConnCtx->bleData.chan.tifsTxPhyOptions;
|
||||
/* Force Coded PHY option to S2. */
|
||||
pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S2;
|
||||
pBle->chan.tifsTxPhyOptions = BB_PHY_OPTIONS_BLE_S2;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBle->chan.initTxPhyOptions = BB_PHY_OPTIONS_BLE_S8;
|
||||
/* Set PHY options to mirror ACL connection option. */
|
||||
pBle->chan.initTxPhyOptions = pConnCtx->bleData.chan.initTxPhyOptions;
|
||||
pBle->chan.tifsTxPhyOptions = pConnCtx->bleData.chan.tifsTxPhyOptions;
|
||||
}
|
||||
|
||||
#if (LL_ENABLE_TESTER)
|
||||
|
@ -344,6 +360,7 @@ void lctrSlvCisBuildCisData(lctrCisCtx_t *pCisCtx)
|
|||
/*** BLE stream setup ***/
|
||||
|
||||
pCis->checkContOpCback = lctrSlvCisCheckContOp;
|
||||
pCis->checkContOpPostCback = lctrSlvCisCheckContOpPostCback;
|
||||
pCis->execCback = lctrSlvCisCigBeginOp;
|
||||
pCis->contExecCback = lctrSlvCisCigContOp;
|
||||
pCis->postSubEvtCback = lctrSlvCisCigPostSubEvt;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -91,8 +91,8 @@ lctrLlcpEh_t lctrStorePeriodicSyncTrsfFn = NULL;
|
|||
/*! \brief Pointer to lctrReceivePeriodicSyncInd function. */
|
||||
lctrLlcpEh_t lctrReceivePeriodicSyncIndFn = NULL;
|
||||
|
||||
/*! \brief Power monitoring scheme action table. */
|
||||
lctrPcMonAct_t lctrPcActTbl[LCTR_PC_MONITOR_SCHEME_TOTAL];
|
||||
/*! \brief Pointer to path lctrPathLossMonitorAct function. */
|
||||
lctrPcMonAct_t lctrPathLossMonitorActFn = NULL;
|
||||
|
||||
/*! \brief Pointer to lctrSendPowerChangeInd function. */
|
||||
lctrPcPowInd_t lctrSendPowerChangeIndCback = NULL;
|
||||
|
@ -100,6 +100,18 @@ lctrPcPowInd_t lctrSendPowerChangeIndCback = NULL;
|
|||
/*! \brief Pointer to lctrNotifyPowerReportInd function. */
|
||||
lctrPcNotifyPwr_t lctrNotifyPowerReportIndCback = NULL;
|
||||
|
||||
/*! \brief Pointer to lctrCisServicePowerMonitor Function. */
|
||||
lctrCisServicePowerMonitor_t lctrCisServicePowerMonitorFn = NULL;
|
||||
|
||||
/*! \brief Last channel class map since host update (Used for slave channel status indications). */
|
||||
static uint64_t lastChanClassMap = LL_CHAN_DATA_ALL;
|
||||
|
||||
/*! \brief Calculate number of subrated connection events. */
|
||||
lctrCalcSubrateConnEvents_t lctrCalcSubrateConnEventsFn = NULL;
|
||||
|
||||
/*! \brief Calculate number of subrated connection events. */
|
||||
lctrCheckLlcpOverride_t lctrSlvCheckEncOverridePhyUpdateFn = NULL;
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Return PHYs supported by LL.
|
||||
|
@ -287,6 +299,44 @@ bool_t LctrIsProcActPended(uint16_t handle, uint8_t event)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Check whether a feature exchange procedure was host-initiated, or initiated as a result of connection startup.
|
||||
*
|
||||
* \param handle Connection handle.
|
||||
*
|
||||
* \return TRUE if the procedure was host-initiated. FALSE if not.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t LctrIsFeatExchHostInit(uint16_t handle)
|
||||
{
|
||||
lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(handle);
|
||||
|
||||
if (!pCtx->enabled)
|
||||
{
|
||||
/* Should not happen. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return (pCtx->llcpNotifyMask & (1 << LCTR_PROC_CMN_FEAT_EXCH)) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Set controller to notify host when feature exchange completes.
|
||||
*
|
||||
* \param handle Connection handle.
|
||||
*
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void LctrSetHostNotifyFeatExch(uint16_t handle)
|
||||
{
|
||||
|
||||
lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(handle);
|
||||
|
||||
pCtx->llcpNotifyMask |= (1 << LCTR_PROC_CMN_FEAT_EXCH);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Get encryption mode used in a connection.
|
||||
|
@ -415,6 +465,13 @@ lctrConnCtx_t *lctrAllocConnCtx(void)
|
|||
pMsg->dispId = LCTR_DISP_CONN;
|
||||
pMsg->event = LCTR_CONN_TMR_AUTH_PAYLOAD_EXP;
|
||||
|
||||
/* Setup power control timer. */
|
||||
pCtx->tmrPowerCtrl.handlerId = lmgrPersistCb.handlerId;
|
||||
pMsg = (lctrMsgHdr_t *)&pCtx->tmrPowerCtrl.msg;
|
||||
pMsg->handle = connIdx;
|
||||
pMsg->dispId = LCTR_DISP_CONN;
|
||||
pMsg->event = LCTR_CONN_LLCP_PWR_CTRL_SERVICE;
|
||||
|
||||
/* Default packet lengths. */
|
||||
pCtx->localDataPdu.maxTxLen = lmgrConnCb.maxTxLen;
|
||||
pCtx->localDataPdu.maxRxLen = WSF_MIN(LCTR_MAX_DATA_LEN_MAX, pLctrRtCfg->maxAclLen);
|
||||
|
@ -457,17 +514,33 @@ lctrConnCtx_t *lctrAllocConnCtx(void)
|
|||
}
|
||||
|
||||
/* Power control initialization. */
|
||||
if (pCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST)
|
||||
if ((pCtx->usedFeatSet & LL_FEAT_POWER_CONTROL_REQUEST) &&
|
||||
!lmgrGetOpFlag(LL_OP_MODE_FLAG_DIS_POWER_MONITOR))
|
||||
{
|
||||
pCtx->powerMonitorScheme = LCTR_PC_MONITOR_AUTO;
|
||||
pCtx->monitoringState = LCTR_PC_MONITOR_ENABLED;
|
||||
pCtx->pclMonitorParam.autoMonitor.highThreshold = LCTR_RSSI_HIGH_THRESHOLD;
|
||||
pCtx->pclMonitorParam.autoMonitor.lowThreshold = LCTR_RSSI_LOW_THRESHOLD;
|
||||
pCtx->pclMonitorParam.autoMonitor.minTimeSpent = LCTR_PC_MIN_TIME;
|
||||
pCtx->pclMonitorParam.autoMonitor.requestVal = LCTR_PC_REQUEST_VAL;
|
||||
pCtx->pclMonitorParam.autoMonitor.curTimeSpent = 0;
|
||||
pCtx->pclMonitorParam.autoMonitor.highThreshold = pLctrRtCfg->pcHighThreshold;
|
||||
pCtx->pclMonitorParam.autoMonitor.lowThreshold = pLctrRtCfg->pcLowThreshold;
|
||||
pCtx->pclMonitorParam.autoMonitor.requestVal = LL_PC_REQ_CHANGE_DBM;
|
||||
|
||||
/* Reset average counters. */
|
||||
pCtx->pclMonitorParam.autoMonitor.accumulatedRssi = 0;
|
||||
pCtx->pclMonitorParam.autoMonitor.totalAccumulatedRssi = 0;
|
||||
pCtx->pclMonitorParam.autoMonitor.rssiRunAvg.avgCount = 0;
|
||||
pCtx->cisAccumulatedRssi = 0;
|
||||
pCtx->cisTotalAccumulatedRssi = 0;
|
||||
pCtx->cisRunAvg.avgCount = 0;
|
||||
}
|
||||
|
||||
/* Default Enhanced Connection Update. */
|
||||
pCtx->ecu.srFactor = 1;
|
||||
/* pCtx->ecu.contNum = 0; */
|
||||
pCtx->ecu.defSrMin = lmgrConnCb.defSrMin;
|
||||
pCtx->ecu.defSrMax = lmgrConnCb.defSrMax;
|
||||
pCtx->ecu.defMaxLatency = lmgrConnCb.defMaxLatency;
|
||||
pCtx->ecu.defContNum = lmgrConnCb.defContNum;
|
||||
pCtx->ecu.defSvt = lmgrConnCb.defSvt;
|
||||
|
||||
LmgrIncResetRefCount();
|
||||
lmgrCb.numConnEnabled++;
|
||||
|
||||
|
@ -519,6 +592,7 @@ void lctrFreeConnCtx(lctrConnCtx_t *pCtx)
|
|||
WsfTimerStop(&pCtx->tmrProcRsp);
|
||||
WsfTimerStop(&pCtx->tmrPingTimeout);
|
||||
WsfTimerStop(&pCtx->tmrAuthTimeout);
|
||||
WsfTimerStop(&pCtx->tmrPowerCtrl);
|
||||
|
||||
uint16_t handle = LCTR_GET_CONN_HANDLE(pCtx);
|
||||
|
||||
|
@ -695,18 +769,10 @@ void lctrConnRxPendingHandler(void)
|
|||
lctrUnpackDataPduHdr(&rxHdr, pRxBuf);
|
||||
|
||||
/* Decrypt PDU. */
|
||||
if (lctrPktDecryptHdlr)
|
||||
if (pCtx->bleData.chan.enc.enaDecrypt)
|
||||
{
|
||||
if (lctrPktDecryptHdlr(&pCtx->bleData.chan.enc, pRxBuf))
|
||||
{
|
||||
if (pCtx->bleData.chan.enc.enaDecrypt)
|
||||
{
|
||||
/* Restart authentication timers. */
|
||||
WsfTimerStartMs(&pCtx->tmrAuthTimeout, pCtx->authTimeoutMs);
|
||||
WsfTimerStartMs(&pCtx->tmrPingTimeout, pCtx->pingPeriodMs);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (lctrPktDecryptHdlr &&
|
||||
(!lctrPktDecryptHdlr(&pCtx->bleData.chan.enc, pRxBuf)))
|
||||
{
|
||||
LL_TRACE_ERR1("!!! MIC verification failed on connHandle=%u", connHandle);
|
||||
lctrRxPduFree(pRxBuf);
|
||||
|
@ -714,6 +780,10 @@ void lctrConnRxPendingHandler(void)
|
|||
lctrSendConnMsg(pCtx, LCTR_CONN_TERM_MIC_FAILED);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Restart authentication timers. */
|
||||
WsfTimerStartMs(&pCtx->tmrAuthTimeout, pCtx->authTimeoutMs);
|
||||
WsfTimerStartMs(&pCtx->tmrPingTimeout, pCtx->pingPeriodMs);
|
||||
}
|
||||
|
||||
/* Demux PDU. */
|
||||
|
@ -1076,7 +1146,7 @@ void LctrSetTxPowerLevel(uint16_t handle, int8_t level)
|
|||
{
|
||||
if (lctrNotifyPowerReportIndCback)
|
||||
{
|
||||
lctrNotifyPowerReportIndCback(pCtx, LL_POWER_REPORT_REASON_LOCAL, phy, adjustedLevel,
|
||||
lctrNotifyPowerReportIndCback(pCtx, LL_SUCCESS, LL_POWER_REPORT_REASON_LOCAL, phy, adjustedLevel,
|
||||
lctrGetPowerLimits(adjustedLevel),
|
||||
adjustedLevel - txPwrOld[phy]);
|
||||
}
|
||||
|
@ -1144,7 +1214,7 @@ void LctrSetPhyTxPowerLevel(uint16_t handle, int8_t level, uint8_t phy)
|
|||
{
|
||||
if (lctrNotifyPowerReportIndCback)
|
||||
{
|
||||
lctrNotifyPowerReportIndCback(pCtx, LL_POWER_REPORT_REASON_LOCAL, pBle->chan.txPhy, adjustedLevel,
|
||||
lctrNotifyPowerReportIndCback(pCtx, LL_SUCCESS, LL_POWER_REPORT_REASON_LOCAL, pBle->chan.txPhy, adjustedLevel,
|
||||
lctrGetPowerLimits(pBle->chan.txPower),
|
||||
delta);
|
||||
}
|
||||
|
@ -1211,6 +1281,30 @@ uint8_t LctrGetRxPhy(uint16_t handle)
|
|||
return pLctrConnTbl[handle].bleData.chan.rxPhy;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Get status of CIS termination procedure.
|
||||
*
|
||||
* \param handle Connection handle.
|
||||
*
|
||||
* \return TRUE if termination is currently pending, FALSE if not.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t LctrCisTerminationInProgress(uint16_t handle)
|
||||
{
|
||||
WSF_ASSERT(handle < pLctrRtCfg->maxConn);
|
||||
|
||||
lctrConnCtx_t *pCtx = &pLctrConnTbl[handle];
|
||||
|
||||
if ((pCtx->llcpActiveProc == LCTR_PROC_CIS_TERM) ||
|
||||
(pCtx->llcpPendMask & (1 << LCTR_PROC_CIS_TERM)))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Get peer minimum number of used channels.
|
||||
|
@ -1327,7 +1421,7 @@ BbOpDesc_t *lctrConnResolveConflict(BbOpDesc_t *pNewOp, BbOpDesc_t *pExistOp)
|
|||
!((pExistOp->prot.pBle->chan.opType == BB_BLE_OP_SLV_CONN_EVENT) ||
|
||||
(pExistOp->prot.pBle->chan.opType == BB_BLE_OP_MST_CONN_EVENT)))
|
||||
{
|
||||
LL_TRACE_WARN1("!!! Scheduling conflict, BLE connections: incoming handle=%u prioritized over non-BLE operation", LCTR_GET_CONN_HANDLE(pNewCtx));
|
||||
LL_TRACE_WARN1("!!! Scheduling conflict, BLE connections: incoming handle=%u prioritized over non-connection operation", LCTR_GET_CONN_HANDLE(pNewCtx));
|
||||
return pNewOp;
|
||||
}
|
||||
|
||||
|
@ -1603,11 +1697,17 @@ uint8_t lctrSetPowerMonitorEnable(uint16_t handle, bool_t enable)
|
|||
|
||||
pCtx->powerMonitorScheme = LCTR_PC_MONITOR_AUTO;
|
||||
pCtx->monitoringState = enable;
|
||||
pCtx->pclMonitorParam.autoMonitor.highThreshold = LCTR_RSSI_HIGH_THRESHOLD;
|
||||
pCtx->pclMonitorParam.autoMonitor.lowThreshold = LCTR_RSSI_LOW_THRESHOLD;
|
||||
pCtx->pclMonitorParam.autoMonitor.minTimeSpent = LCTR_PC_MIN_TIME;
|
||||
pCtx->pclMonitorParam.autoMonitor.requestVal = LCTR_PC_REQUEST_VAL;
|
||||
pCtx->pclMonitorParam.autoMonitor.curTimeSpent = 0;
|
||||
pCtx->pclMonitorParam.autoMonitor.highThreshold = pLctrRtCfg->pcHighThreshold;
|
||||
pCtx->pclMonitorParam.autoMonitor.lowThreshold = pLctrRtCfg->pcLowThreshold;
|
||||
pCtx->pclMonitorParam.autoMonitor.requestVal = LL_PC_REQ_CHANGE_DBM;
|
||||
|
||||
/* Initialize average function. */
|
||||
pCtx->pclMonitorParam.autoMonitor.accumulatedRssi = 0;
|
||||
pCtx->pclMonitorParam.autoMonitor.totalAccumulatedRssi = 0;
|
||||
pCtx->pclMonitorParam.autoMonitor.rssiRunAvg.avgCount = 0;
|
||||
pCtx->cisAccumulatedRssi = 0;
|
||||
pCtx->cisTotalAccumulatedRssi = 0;
|
||||
pCtx->cisRunAvg.avgCount = 0;
|
||||
|
||||
return LL_SUCCESS;
|
||||
}
|
||||
|
@ -1648,3 +1748,75 @@ uint8_t lctrGetPowerLimits(int8_t txPower)
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Host channel class update handler for connections.
|
||||
*
|
||||
* \param chanMap Updated channel map.
|
||||
*
|
||||
* \return Status code.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t lctrConnChClassUpdate(uint64_t chanMap)
|
||||
{
|
||||
lctrChanMapUpdate_t *pMsg;
|
||||
lctrConnCtx_t *pCtx;
|
||||
uint16_t handle;
|
||||
uint8_t status = LL_SUCCESS;
|
||||
|
||||
/* Update for connections */
|
||||
for (handle = 0; handle < pLctrRtCfg->maxConn; handle++)
|
||||
{
|
||||
if (LctrIsConnHandleEnabled(handle))
|
||||
{
|
||||
if (LctrGetRole(handle) == LL_ROLE_MASTER)
|
||||
{
|
||||
/* Update the channel map for CIS master as well. */
|
||||
if (LctrUpdateCisChanMapFn)
|
||||
{
|
||||
LctrUpdateCisChanMapFn(handle);
|
||||
}
|
||||
|
||||
if (LctrIsProcActPended(handle, LCTR_CONN_MSG_API_CHAN_MAP_UPDATE) == TRUE)
|
||||
{
|
||||
status = LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
if ((pMsg = (lctrChanMapUpdate_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL)
|
||||
{
|
||||
pMsg->hdr.handle = handle;
|
||||
pMsg->hdr.dispId = LCTR_DISP_CONN;
|
||||
pMsg->hdr.event = LCTR_CONN_MSG_API_CHAN_MAP_UPDATE;
|
||||
|
||||
pMsg->chanMap = chanMap;
|
||||
|
||||
WsfMsgSend(lmgrPersistCb.handlerId, pMsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_ERR0("lctrConnChClassUpdate: out of message buffers");
|
||||
return LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
}
|
||||
}
|
||||
else /* LL_ROLE_SLAVE */
|
||||
{
|
||||
if (lastChanClassMap != chanMap)
|
||||
{
|
||||
pCtx = LCTR_GET_CONN_CTX(handle);
|
||||
|
||||
if ((pCtx->usedFeatSet & LL_FEAT_CHANNEL_CLASSIFICATION) &&
|
||||
pCtx->chanStatRptEnable)
|
||||
{
|
||||
pCtx->data.slv.queuedChanStatusTs = PalBbGetCurrentTime();
|
||||
/* Update is sent to host in lctrSlvConnEndOp(). */
|
||||
}
|
||||
|
||||
lastChanClassMap = chanMap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -606,6 +606,8 @@ void lctrTxDataPduQueue(lctrConnCtx_t *pCtx, uint16_t fragLen, lctrAclHdr_t *pAc
|
|||
/*************************************************************************************************/
|
||||
void lctrTxCtrlPduQueue(lctrConnCtx_t *pCtx, uint8_t *pBuf)
|
||||
{
|
||||
pCtx->numTxPendCtrlPdu++;
|
||||
|
||||
#if (LL_ENABLE_TESTER)
|
||||
uint16_t connHandle = LCTR_GET_CONN_HANDLE(pCtx);
|
||||
#endif
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -192,59 +192,6 @@ static void lctrMstConnDisp(lctrConnMsg_t *pMsg)
|
|||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Host channel class update handler for connections.
|
||||
*
|
||||
* \param chanMap Updated channel map.
|
||||
*
|
||||
* \return Status code.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t lctrConnChClassUpdate(uint64_t chanMap)
|
||||
{
|
||||
lctrChanMapUpdate_t *pMsg;
|
||||
uint16_t handle;
|
||||
uint8_t status = LL_SUCCESS;
|
||||
|
||||
/* Update for connections */
|
||||
for (handle = 0; handle < pLctrRtCfg->maxConn; handle++)
|
||||
{
|
||||
if ((LctrIsConnHandleEnabled(handle)) &&
|
||||
(LctrGetRole(handle) == LL_ROLE_MASTER))
|
||||
{
|
||||
/* Update the channel map for CIS master as well. */
|
||||
if (LctrUpdateCisChanMapFn)
|
||||
{
|
||||
LctrUpdateCisChanMapFn(handle);
|
||||
}
|
||||
|
||||
if (LctrIsProcActPended(handle, LCTR_CONN_MSG_API_CHAN_MAP_UPDATE) == TRUE)
|
||||
{
|
||||
status = LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
if ((pMsg = (lctrChanMapUpdate_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL)
|
||||
{
|
||||
pMsg->hdr.handle = handle;
|
||||
pMsg->hdr.dispId = LCTR_DISP_CONN;
|
||||
pMsg->hdr.event = LCTR_CONN_MSG_API_CHAN_MAP_UPDATE;
|
||||
|
||||
pMsg->chanMap = chanMap;
|
||||
|
||||
WsfMsgSend(lmgrPersistCb.handlerId, pMsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_ERR0("lctrConnChClassUpdate: out of message buffers");
|
||||
return LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Build a connection operation.
|
||||
|
@ -357,8 +304,10 @@ void lctrMstSetEstablishConn(lctrConnCtx_t *pCtx)
|
|||
const uint16_t txWinOffsetCnt = pConnInd->txWinOffset + LCTR_DATA_CHAN_DLY;
|
||||
|
||||
/* Initially use fast termination. */
|
||||
/* The first CE starts after transmitWindowDelay + transmitWindowOffset + transmitWindowSize.
|
||||
Then an additional 5 CI are required + the duration of the last connection event. */
|
||||
uint32_t fastTermCnt = txWinOffsetCnt + pConnInd->txWinSize +
|
||||
(LCTR_FAST_TERM_CNT * pConnInd->interval);
|
||||
((LCTR_FAST_TERM_CNT - 1) * pConnInd->interval) + (pConnInd->interval >> 1);
|
||||
WsfTimerStartMs(&pCtx->tmrSupTimeout, LCTR_CONN_IND_MS(fastTermCnt));
|
||||
|
||||
/* Set initial channel. */
|
||||
|
@ -371,6 +320,7 @@ void lctrMstSetEstablishConn(lctrConnCtx_t *pCtx)
|
|||
LL_TRACE_INFO1(" >>> Connection established, handle=%u <<<", LCTR_GET_CONN_HANDLE(pCtx));
|
||||
LL_TRACE_INFO1(" connIntervalUsec=%u", LCTR_CONN_IND_US(pCtx->connInterval));
|
||||
LL_TRACE_INFO1(" dueUsec=%u", pCtx->connBod.dueUsec);
|
||||
LL_TRACE_INFO1(" pBod=0x%08x", &pCtx->connBod);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -401,6 +351,7 @@ void LctrMstConnInit(void)
|
|||
/* Add channel selection handler. */
|
||||
lctrChSelHdlr[LL_CH_SEL_1] = lctrSelectNextDataChannel;
|
||||
|
||||
/* Register channel class update handler. */
|
||||
lctrRegisterChClassHandler(lctrConnChClassUpdate);
|
||||
|
||||
lctrConnDefaults();
|
||||
|
@ -426,7 +377,13 @@ void LctrMstConnInit(void)
|
|||
if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_5_1)
|
||||
{
|
||||
lmgrPersistCb.featuresDefault |=
|
||||
(LL_FEAT_PAST_SENDER | LL_FEAT_SCA_UPDATE);
|
||||
LL_FEAT_PAST_SENDER |
|
||||
LL_FEAT_SCA_UPDATE;
|
||||
}
|
||||
if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_SYDNEY)
|
||||
{
|
||||
lmgrPersistCb.featuresDefault |=
|
||||
LL_FEAT_CHANNEL_CLASSIFICATION;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -375,6 +375,7 @@ void lctrSlvConnBuildOp(lctrConnCtx_t *pCtx)
|
|||
LL_TRACE_INFO1(" connIntervalUsec=%u", LCTR_CONN_IND_US(pCtx->connInterval));
|
||||
LL_TRACE_INFO1(" dueUsec=%u", pOp->dueUsec);
|
||||
LL_TRACE_INFO1(" minDurUsec=%u", pOp->minDurUsec);
|
||||
LL_TRACE_INFO1(" pBod=0x%08x", pOp);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -432,6 +433,9 @@ void LctrSlvConnInit(void)
|
|||
/* Add channel selection handler. */
|
||||
lctrChSelHdlr[LL_CH_SEL_1] = lctrSelectNextDataChannel;
|
||||
|
||||
/* Register channel class update handler. */
|
||||
lctrRegisterChClassHandler(lctrConnChClassUpdate);
|
||||
|
||||
lctrConnDefaults();
|
||||
|
||||
/* Set supported features. */
|
||||
|
@ -455,7 +459,13 @@ void LctrSlvConnInit(void)
|
|||
if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_5_1)
|
||||
{
|
||||
lmgrPersistCb.featuresDefault |=
|
||||
(LL_FEAT_PAST_SENDER | LL_FEAT_SCA_UPDATE);
|
||||
LL_FEAT_PAST_SENDER |
|
||||
LL_FEAT_SCA_UPDATE;
|
||||
}
|
||||
if (pLctrRtCfg->btVer >= LL_VER_BT_CORE_SPEC_SYDNEY)
|
||||
{
|
||||
lmgrPersistCb.featuresDefault |=
|
||||
LL_FEAT_CHANNEL_CLASSIFICATION;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -105,16 +105,18 @@ void LctrMstConnEncInit(void)
|
|||
lctrCtrlPduHdlr = lctrMstEncProcessDataPdu;
|
||||
|
||||
/* Add packet encryption handlers. */
|
||||
#if (!(BB_ENABLE_INLINE_ENC_TX && BB_ENABLE_INLINE_DEC_RX))
|
||||
lctrInitCipherBlkHdlr = PalCryptoAesEnable;
|
||||
#endif
|
||||
#if (!BB_ENABLE_INLINE_ENC_TX)
|
||||
lctrPktEncryptHdlr = PalCryptoAesCcmEncrypt;
|
||||
#else
|
||||
lctrSetEncryptPktCountHdlr = PalCryptoSetEncryptPacketCount;
|
||||
lctrSetEncryptPktCountHdlr = PalBbBleSetInlineEncryptPacketCount;
|
||||
#endif
|
||||
#if (!BB_ENABLE_INLINE_DEC_RX)
|
||||
lctrPktDecryptHdlr = PalCryptoAesCcmDecrypt;
|
||||
#else
|
||||
lctrSetDecryptPktCountHdlr = PalCryptoSetDecryptPacketCount;
|
||||
lctrSetDecryptPktCountHdlr = PalBbBleSetInlineDecryptPacketCount;
|
||||
#endif
|
||||
|
||||
/* Set supported features. */
|
||||
|
|
|
@ -84,16 +84,18 @@ void LctrSlvConnEncInit(void)
|
|||
}
|
||||
|
||||
/* Add packet encryption handlers. */
|
||||
#if (!(BB_ENABLE_INLINE_ENC_TX && BB_ENABLE_INLINE_DEC_RX))
|
||||
lctrInitCipherBlkHdlr = PalCryptoAesEnable;
|
||||
#endif
|
||||
#if (!BB_ENABLE_INLINE_ENC_TX)
|
||||
lctrPktEncryptHdlr = PalCryptoAesCcmEncrypt;
|
||||
#else
|
||||
lctrSetEncryptPktCountHdlr = PalCryptoSetEncryptPacketCount;
|
||||
lctrSetEncryptPktCountHdlr = PalBbBleSetInlineEncryptPacketCount;
|
||||
#endif
|
||||
#if (!BB_ENABLE_INLINE_DEC_RX)
|
||||
lctrPktDecryptHdlr = PalCryptoAesCcmDecrypt;
|
||||
#else
|
||||
lctrSetDecryptPktCountHdlr = PalCryptoSetDecryptPacketCount;
|
||||
lctrSetDecryptPktCountHdlr = PalBbBleSetInlineDecryptPacketCount;
|
||||
#endif
|
||||
|
||||
/* Set supported features. */
|
||||
|
|
|
@ -242,6 +242,9 @@ void lctrMstInitiateOpCommit(void)
|
|||
|
||||
SchInsertNextAvailable(pOp);
|
||||
lctrMstInit.scanWinStartUsec = pOp->dueUsec;
|
||||
|
||||
LL_TRACE_INFO1(" >>> Initiate started, dueUsec=%u <<<", pOp->dueUsec);
|
||||
LL_TRACE_INFO1(" pBod=0x%08x", pOp);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
|
|
@ -398,6 +398,9 @@ void lctrMstExtInitiateOpCommit(lctrExtScanCtx_t *pExtInitCtx)
|
|||
|
||||
SchInsertNextAvailable(pOp);
|
||||
pExtInitCtx->data.init.scanWinStartUsec = pOp->dueUsec;
|
||||
|
||||
LL_TRACE_INFO1(" >>> ExtInitiate started, dueUsec=%u <<<", pOp->dueUsec);
|
||||
LL_TRACE_INFO1(" pBod=0x%08x", pOp);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -460,6 +463,7 @@ uint8_t lctrMstAuxInitiateBuildOp(lctrExtScanCtx_t *pExtInitCtx, LlConnSpec_t *p
|
|||
/*** BLE Scan Setup: Rx packets ***/
|
||||
pAuxScan->isInit = TRUE;
|
||||
pAuxScan->rxAuxAdvCback = lctrMstInitiateRxAuxAdvPktHandler;
|
||||
pAuxScan->rxAuxAdvPostCback = NULL;
|
||||
|
||||
/*** BLE Scan Setup: Tx connect request packet ***/
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -58,7 +58,7 @@ static void lctrIsoProcessRxTestData(lctrCisCtx_t *pCisCtx, uint8_t *pDataBuf, u
|
|||
uint16_t pldType = 0;
|
||||
uint64_t plTestCounter = pCisCtx->rxPktCounter;
|
||||
|
||||
if (pCisCtx->rxPendInit)
|
||||
if (pCisCtx->rxPendInit && (dataLen >= LL_ISO_TEST_VAR_MIN_LEN))
|
||||
{
|
||||
memcpy(&pCisCtx->expectedPkt, pDataBuf, 4);
|
||||
pCisCtx->rxPendInit = FALSE;
|
||||
|
@ -94,12 +94,15 @@ static void lctrIsoProcessRxTestData(lctrCisCtx_t *pCisCtx, uint8_t *pDataBuf, u
|
|||
if ((dataLen == pldType) &&
|
||||
(pktNum == pCisCtx->expectedPkt))
|
||||
{
|
||||
pCisCtx->expectedPkt++;
|
||||
pCisCtx->numRxSuccess++;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
pCisCtx->expectedPkt = pktNum + 1;
|
||||
pCisCtx->numRxFailed++;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -107,7 +110,8 @@ static void lctrIsoProcessRxTestData(lctrCisCtx_t *pCisCtx, uint8_t *pDataBuf, u
|
|||
if ((dataLen >= LL_ISO_TEST_VAR_MIN_LEN) &&
|
||||
(pktNum == pCisCtx->expectedPkt))
|
||||
{
|
||||
pCisCtx->numRxSuccess++;
|
||||
pCisCtx->numRxSuccess++;
|
||||
pCisCtx->expectedPkt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -224,7 +228,7 @@ void LctrInitCodec(void)
|
|||
/* Add codec. */
|
||||
lctrCodecHdlr.start = PalCodecDataStartStream;
|
||||
lctrCodecHdlr.stop = PalCodecDataStopStream;
|
||||
lctrCodecHdlr.in = PalCodecDataStreamIn;
|
||||
lctrCodecHdlr.inReq = PalCodecDataStreamIn;
|
||||
lctrCodecHdlr.out = PalCodecDataStreamOut;
|
||||
}
|
||||
|
||||
|
@ -269,9 +273,8 @@ void lctrIsoTxCompletedHandler(void)
|
|||
|
||||
WSF_CS_EXIT(cs);
|
||||
|
||||
if (numHandles)
|
||||
if (lmgrPersistCb.sendIsoCompCback && numHandles)
|
||||
{
|
||||
/* Notify host. */
|
||||
lmgrPersistCb.sendIsoCompCback(numHandles, handle, numSdu);
|
||||
}
|
||||
}
|
||||
|
@ -285,14 +288,14 @@ void lctrCisRxPendingHandler(void)
|
|||
{
|
||||
uint16_t cisHandle = 0;
|
||||
uint8_t *pRxBuf;
|
||||
lctrCisCtx_t *pCisCtx;
|
||||
|
||||
/* Route and demux received Data PDUs. */
|
||||
|
||||
while ((pRxBuf = lctrCisRxDeq(&cisHandle)) != NULL)
|
||||
{
|
||||
WSF_ASSERT(pRxBuf);
|
||||
|
||||
lctrCisCtx_t *pCisCtx = lctrFindCisByHandle(cisHandle);
|
||||
pCisCtx = lctrFindCisByHandle(cisHandle);
|
||||
lctrIsoalRxCtx_t *pRxCtx = &pCisCtx->isoalRxCtx;
|
||||
|
||||
if (!pCisCtx->enabled)
|
||||
|
@ -317,18 +320,31 @@ void lctrCisRxPendingHandler(void)
|
|||
lctrSendCisMsg(pCisCtx, LCTR_CIS_MSG_CIS_TERM_MIC_FAILED);
|
||||
continue;
|
||||
}
|
||||
/* Increase packet counter after decryption. */
|
||||
lctrCisIncPacketCounterRx(pCisCtx);
|
||||
}
|
||||
|
||||
/* Increase packet counter after decryption. */
|
||||
lctrCisIncPacketCounterRx(pCisCtx);
|
||||
|
||||
lctrCisDataPduHdr_t cisDataHdr;
|
||||
lctrCisUnpackDataPduHdr(&cisDataHdr, pRxBuf);
|
||||
|
||||
/* Demux PDU. */
|
||||
if (pCisCtx->framing == LL_ISO_PDU_TYPE_UNFRAMED)
|
||||
{
|
||||
lctrIsoHdr_t isoHdr = { 0 };
|
||||
lctrIsoHdr_t isoHdr =
|
||||
{
|
||||
/* ISO header */
|
||||
.handle = cisHandle,
|
||||
.len = pRxBuf[LCTR_ISO_DATA_PDU_LEN_OFFSET],
|
||||
/* .pb = 0, */ /* assigned below */
|
||||
.tsFlag = FALSE,
|
||||
|
||||
/* Data load */
|
||||
.ts = 0,
|
||||
/* .pktSn = 0, */ /* assigned below */
|
||||
.sduLen = pRxBuf[LCTR_ISO_DATA_PDU_LEN_OFFSET],
|
||||
.ps = LCTR_PS_VALID
|
||||
};
|
||||
|
||||
switch (rxHdr.llid)
|
||||
{
|
||||
/* Received a end/complete PDU. */
|
||||
|
@ -346,6 +362,7 @@ void lctrCisRxPendingHandler(void)
|
|||
lctrCisRxPduFree(pRxBuf);
|
||||
LL_TRACE_ERR2("!!! Invalid rxState; dropping Rx data PDU, connHandle=%u, rxState=%u", cisHandle, pRxCtx->rxState);
|
||||
pRxCtx->rxState = LL_ISO_SDU_STATE_NEW;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -359,24 +376,7 @@ void lctrCisRxPendingHandler(void)
|
|||
default:
|
||||
lctrCisRxPduFree(pRxBuf);
|
||||
LL_TRACE_ERR2("!!! Invalid LLID; dropping Rx data PDU, connHandle=%u llid=%u", cisHandle, rxHdr.llid);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the packet was flushed, change the packet status flag to warn host of errors. */
|
||||
if (pRxCtx->pduFlushed)
|
||||
{
|
||||
switch (pRxCtx->rxState)
|
||||
{
|
||||
case LL_ISO_SDU_STATE_CONT:
|
||||
/* Lost data since last transfer; invalidate packet. */
|
||||
pRxCtx->data.unframed.ps = LCTR_PS_INVALID;
|
||||
break;
|
||||
case LL_ISO_SDU_STATE_NEW:
|
||||
/* This may be a fragmented packet with the end fragment, but no way to tell, so process as normal. */
|
||||
pRxCtx->data.unframed.ps = (rxHdr.llid == LL_LLID_ISO_UNF_END_PDU) ? LCTR_PS_INVALID : LCTR_PS_LOST;
|
||||
break;
|
||||
}
|
||||
pRxCtx->pduFlushed = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Pack isoHdr and queue PDU. */
|
||||
|
@ -384,34 +384,34 @@ void lctrCisRxPendingHandler(void)
|
|||
{
|
||||
uint8_t * pSduBuf = pRxBuf - LCTR_CIS_DATA_PDU_START_OFFSET - HCI_ISO_DL_MAX_LEN;
|
||||
|
||||
/* Pack current packet. */
|
||||
isoHdr.handle = cisHandle;
|
||||
isoHdr.tsFlag = ((isoHdr.pb == LCTR_PB_COMP) || (isoHdr.pb == LCTR_PB_FIRST)) ? 1 : 0;
|
||||
if (isoHdr.tsFlag)
|
||||
if ((isoHdr.pb == LCTR_PB_COMP) || (isoHdr.pb == LCTR_PB_FIRST))
|
||||
{
|
||||
isoHdr.ts = 0xFF;
|
||||
}
|
||||
isoHdr.len = pRxBuf[LCTR_ISO_DATA_PDU_LEN_OFFSET];
|
||||
/* isoHdr.pktSn = 0; */
|
||||
isoHdr.tsFlag = TRUE;
|
||||
isoHdr.ts = PalBbGetCurrentTime();
|
||||
|
||||
/* LCTR_PB_COMP and LCTR_PB_FIRST will have their headers re-packed in lctrIsoUnframedRxSduPendQueue. */
|
||||
pRxCtx->packetSequence++;
|
||||
}
|
||||
isoHdr.pktSn = pRxCtx->packetSequence;
|
||||
|
||||
/* LCTR_PB_COMP and LCTR_PB_FIRST will have their headers re-packed in lctrRecombineRxUnframedSdu(). */
|
||||
uint8_t headerOffset = lctrIsoPackHdr(pSduBuf, &isoHdr);
|
||||
|
||||
/* Process received buffer for Rx testing purpose. */
|
||||
/* TODO: Optimize test packet dataflow. */
|
||||
if (pCisCtx->rxTestEnabled == TRUE)
|
||||
{
|
||||
lctrIsoProcessRxTestData(pCisCtx, pRxBuf + LL_DATA_HDR_LEN, rxHdr.len);
|
||||
}
|
||||
|
||||
/* TODO optimize memory layout */
|
||||
/* Move payload next to header. */
|
||||
if (LCTR_CIS_DATA_PDU_START_OFFSET + LL_ISO_DATA_HDR_LEN > HCI_ISO_HDR_LEN)
|
||||
if ((LCTR_CIS_DATA_PDU_START_OFFSET + LL_ISO_DATA_HDR_LEN) > HCI_ISO_HDR_LEN)
|
||||
{
|
||||
/* TODO optimize memory layout */
|
||||
memmove(pSduBuf + headerOffset , pRxBuf + LL_DATA_HDR_LEN, rxHdr.len);
|
||||
}
|
||||
|
||||
/* Put onto pending queue until whole SDU is ready to be sent. */
|
||||
if (!lctrIsoUnframedRxSduPendQueue(pRxCtx, pSduBuf, cisHandle, rxHdr.len, rxHdr.llid))
|
||||
if (!lctrRecombineRxUnframedSdu(pRxCtx, pSduBuf))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -421,7 +421,8 @@ void lctrCisRxPendingHandler(void)
|
|||
while ((pSduBuf = WsfMsgDeq(&pRxCtx->data.unframed.pendSduQ, &handlerId)) != NULL)
|
||||
{
|
||||
/* Enqueue SDU for processing. */
|
||||
if (!lctrIsoRxConnEnq(&pCisCtx->dataPathOutCtx, pCisCtx->cisHandle, pSduBuf))
|
||||
if (!lctrIsoRxConnEnq(&pCisCtx->dataPathOutCtx, pCisCtx->cisHandle,
|
||||
pCisCtx->rxPktCounter - 1, pSduBuf))
|
||||
{
|
||||
/* The buffer was not freed, so free it now. */
|
||||
WsfMsgFree(pSduBuf);
|
||||
|
@ -437,12 +438,13 @@ void lctrCisRxPendingHandler(void)
|
|||
{
|
||||
pCisCtx->dataPathOutCtx.cfg.hci.numRxPend += lctrAssembleRxFramedSdu(pRxCtx, &pCisCtx->dataPathOutCtx.cfg.hci.rxDataQ, pCisCtx->cisHandle, pRxBuf, cisDataHdr.len);
|
||||
|
||||
/* Consume and process packets for iso test mode */
|
||||
/* Consume packets if needed */
|
||||
lctrIsoHdr_t isoHdr;
|
||||
/* ISO test mode. */
|
||||
if (pCisCtx->rxTestEnabled == TRUE)
|
||||
{
|
||||
while (pCisCtx->dataPathOutCtx.cfg.hci.numRxPend)
|
||||
{
|
||||
lctrIsoHdr_t isoHdr;
|
||||
uint8_t *pTestRxBuf = lctrIsoRxConnDeq(&pCisCtx->dataPathOutCtx);
|
||||
lctrIsoUnpackHdr(&isoHdr, pTestRxBuf);
|
||||
lctrIsoProcessRxTestData(pCisCtx, pTestRxBuf+ HCI_ISO_HDR_LEN + HCI_ISO_DL_MAX_LEN, isoHdr.sduLen);
|
||||
|
@ -451,6 +453,19 @@ void lctrCisRxPendingHandler(void)
|
|||
pCisCtx->dataPathOutCtx.cfg.hci.numRxPend--;
|
||||
}
|
||||
}
|
||||
/* Codec output */
|
||||
else if (pCisCtx->dataPathOutCtx.id == LL_ISO_DATA_PATH_VS)
|
||||
{
|
||||
while (pCisCtx->dataPathOutCtx.cfg.hci.numRxPend)
|
||||
{
|
||||
uint8_t *pSduBuf = lctrIsoRxConnDeq(&pCisCtx->dataPathOutCtx);
|
||||
lctrIsoUnpackHdr(&isoHdr, pSduBuf);
|
||||
lctrCodecHdlr.out(pCisCtx->dataPathOutCtx.cfg.codec.streamId, isoHdr.pSdu, isoHdr.sduLen, isoHdr.ts);
|
||||
WsfMsgFree(pSduBuf);
|
||||
LctrRxIsoComplete(1);
|
||||
}
|
||||
}
|
||||
|
||||
lctrCisRxPduFree(pRxBuf);
|
||||
break;
|
||||
}
|
||||
|
@ -473,23 +488,21 @@ void lctrCisRxPendingHandler(void)
|
|||
WSF_CS_ENTER(cs);
|
||||
for (unsigned int i = 0; i < pLctrRtCfg->maxCis; i++)
|
||||
{
|
||||
lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i];
|
||||
pCisCtx = &pLctrCisTbl[i];
|
||||
|
||||
if (pCisCtx->enabled &&
|
||||
(pCisCtx->dataPathOutCtx.id == LL_ISO_DATA_PATH_HCI) &&
|
||||
pCisCtx->dataPathOutCtx.cfg.hci.numRxPend)
|
||||
{
|
||||
if (pCisCtx->dataPathOutCtx.id == LL_ISO_DATA_PATH_HCI)
|
||||
{
|
||||
handle[numHandles] = pCisCtx->cisHandle;
|
||||
numSdu[numHandles] = pCisCtx->dataPathOutCtx.cfg.hci.numRxPend;
|
||||
pCisCtx->dataPathOutCtx.cfg.hci.numRxPend = 0;
|
||||
numHandles++;
|
||||
}
|
||||
handle[numHandles] = pCisCtx->cisHandle;
|
||||
numSdu[numHandles] = pCisCtx->dataPathOutCtx.cfg.hci.numRxPend;
|
||||
pCisCtx->dataPathOutCtx.cfg.hci.numRxPend = 0;
|
||||
numHandles++;
|
||||
}
|
||||
}
|
||||
WSF_CS_EXIT(cs);
|
||||
|
||||
if (numHandles)
|
||||
if (lmgrPersistCb.recvIsoPendCback && numHandles)
|
||||
{
|
||||
/* Notify host. */
|
||||
lmgrPersistCb.recvIsoPendCback(numHandles, handle, numSdu);
|
||||
|
@ -551,7 +564,10 @@ void LctrTxIso(uint8_t *pIsoBuf)
|
|||
{
|
||||
LL_TRACE_ERR2("Invalid ISO header: invalid packet length, actLen=%u, maxLen=%u", isoHdr.sduLen, pLctrRtCfg->maxIsoSduLen);
|
||||
WsfMsgFree(pIsoBuf);
|
||||
lmgrPersistCb.sendCompCback(isoHdr.handle, 1);
|
||||
if (lmgrPersistCb.sendCompCback)
|
||||
{
|
||||
lmgrPersistCb.sendCompCback(isoHdr.handle, 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -559,16 +575,22 @@ void LctrTxIso(uint8_t *pIsoBuf)
|
|||
{
|
||||
LL_TRACE_ERR1("ISO Tx path flow controlled, handle=%u", isoHdr.handle);
|
||||
WsfMsgFree(pIsoBuf);
|
||||
lmgrPersistCb.sendCompCback(isoHdr.handle, 1);
|
||||
if (lmgrPersistCb.sendCompCback)
|
||||
{
|
||||
lmgrPersistCb.sendCompCback(isoHdr.handle, 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t expIsoLen = isoHdr.len - HCI_ISO_DL_MIN_LEN + ((isoHdr.tsFlag) ? HCI_ISO_TS_LEN : 0);
|
||||
uint16_t expIsoLen = isoHdr.len - HCI_ISO_DL_MIN_LEN - ((isoHdr.tsFlag) ? HCI_ISO_TS_LEN : 0);
|
||||
if (isoHdr.sduLen != expIsoLen)
|
||||
{
|
||||
LL_TRACE_ERR2("Invalid ISO header: packet length mismatch, expSduLen=%u, actSduLen=%u", expIsoLen, isoHdr.sduLen);
|
||||
WsfMsgFree(pIsoBuf);
|
||||
lmgrPersistCb.sendCompCback(isoHdr.handle, 1);
|
||||
if (lmgrPersistCb.sendCompCback)
|
||||
{
|
||||
lmgrPersistCb.sendCompCback(isoHdr.handle, 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -582,7 +604,10 @@ void LctrTxIso(uint8_t *pIsoBuf)
|
|||
if (!lctrCheckIsCisEstCis(pCisCtx->cisHandle))
|
||||
{
|
||||
LL_TRACE_ERR1("Invalid ISO handle: link not established cisHandle=%u; dropping packet", isoHdr.handle);
|
||||
lmgrPersistCb.sendCompCback(isoHdr.handle, 1);
|
||||
if (lmgrPersistCb.sendCompCback)
|
||||
{
|
||||
lmgrPersistCb.sendCompCback(isoHdr.handle, 1);
|
||||
}
|
||||
WsfMsgFree(pIsoBuf);
|
||||
return;
|
||||
}
|
||||
|
@ -593,7 +618,10 @@ void LctrTxIso(uint8_t *pIsoBuf)
|
|||
{
|
||||
LL_TRACE_ERR1("Invalid CIS state: handle=%u does not accept transmissions; dropping packet", isoHdr.handle);
|
||||
WsfMsgFree(pIsoBuf);
|
||||
lmgrPersistCb.sendCompCback(isoHdr.handle, 1);
|
||||
if (lmgrPersistCb.sendCompCback)
|
||||
{
|
||||
lmgrPersistCb.sendCompCback(isoHdr.handle, 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -620,7 +648,10 @@ void LctrTxIso(uint8_t *pIsoBuf)
|
|||
{
|
||||
LL_TRACE_ERR2("Invalid ISO header: invalid packet length, actLen=%u, maxSdu=%u", isoHdr.sduLen, pBisCtx->pBigCtx->maxSdu);
|
||||
WsfMsgFree(pIsoBuf);
|
||||
lmgrPersistCb.sendCompCback(isoHdr.handle, 1);
|
||||
if (lmgrPersistCb.sendCompCback)
|
||||
{
|
||||
lmgrPersistCb.sendCompCback(isoHdr.handle, 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -662,7 +693,7 @@ uint8_t *LctrRxIso(void)
|
|||
{
|
||||
lctrCisCtx_t *pCisCtx = &pLctrCisTbl[i];
|
||||
|
||||
if ((pCisCtx->enabled) &&
|
||||
if ((pCisCtx->enabled) && (pCisCtx->dataPathOutCtx.id == LL_ISO_DATA_PATH_HCI) &&
|
||||
((pBuf = lctrIsoRxConnDeq(&pCisCtx->dataPathOutCtx)) != NULL))
|
||||
{
|
||||
return pBuf;
|
||||
|
@ -677,6 +708,7 @@ uint8_t *LctrRxIso(void)
|
|||
(pBisCtx->pBigCtx->role == LL_ROLE_MASTER) &&
|
||||
((pBuf = lctrBisRxIsoSduDeq(pBisCtx)) != NULL))
|
||||
{
|
||||
/* Postpone lctrIsoDataRxIncAvailBuf() until client consumes buffer, cf. LctrRxIsoComplete(). */
|
||||
return pBuf;
|
||||
}
|
||||
}
|
||||
|
@ -742,7 +774,37 @@ uint8_t LctrReadIsoTxSync(uint16_t handle, uint16_t *pPktSn, uint32_t *pTs, uint
|
|||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Used to identify and enable the isochronous data path between the host and the controller for each connected isochronous stream or broadcast isochronous stream.
|
||||
* \brief Used to request the Controller to configure the data transport path in a given
|
||||
* direction between the Controller and the Host.
|
||||
*
|
||||
* \param pConfigDataPath Parameters for configure data path.
|
||||
*
|
||||
* \return Status error code.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t LctrConfigureDataPath(LlIsoConfigDataPath_t *pConfigDataPath)
|
||||
{
|
||||
switch (pConfigDataPath->dpId)
|
||||
{
|
||||
case LL_ISO_DATA_PATH_DISABLED:
|
||||
case LL_ISO_DATA_PATH_HCI:
|
||||
/* No action required. */
|
||||
break;
|
||||
case LL_ISO_DATA_PATH_VS:
|
||||
/* No action required. */
|
||||
break;
|
||||
default:
|
||||
LL_TRACE_WARN2("LlConfigureDataPath: unknown data path, dpDir=%u, dpId=%u", pConfigDataPath->dpDir, pConfigDataPath->dpId);
|
||||
return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS;
|
||||
}
|
||||
|
||||
return LL_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Used to identify and enable the isochronous data path between the host and the
|
||||
* controller for each connected isochronous stream or broadcast isochronous stream.
|
||||
*
|
||||
* \param pSetupDataPath Parameters for setup ISO data path.
|
||||
*
|
||||
|
@ -751,65 +813,76 @@ uint8_t LctrReadIsoTxSync(uint16_t handle, uint16_t *pPktSn, uint32_t *pTs, uint
|
|||
/*************************************************************************************************/
|
||||
uint8_t LctrSetupIsoDataPath(LlIsoSetupDataPath_t *pSetupDataPath)
|
||||
{
|
||||
uint8_t status = LL_SUCCESS;
|
||||
lctrCisCtx_t *pCisCtx;
|
||||
lctrBisCtx_t *pBisCtx;
|
||||
lctrDataPathCtx_t *pDataPathDir;
|
||||
lctrDpParams_t dpParam;
|
||||
|
||||
if ((pCisCtx = lctrFindCisByHandle(pSetupDataPath->handle)) != NULL)
|
||||
{
|
||||
dpParam.handle = pCisCtx->cisHandle;
|
||||
dpParam.isoInt = (pCisCtx->role == LL_ROLE_SLAVE) ? pCisCtx->sduIntervalSToM : pCisCtx->sduIntervalMToS;
|
||||
dpParam.pktCtr = pCisCtx->txPktCounter + 1;
|
||||
dpParam.dpDir = pSetupDataPath->dpDir;
|
||||
|
||||
switch (pSetupDataPath->dpDir)
|
||||
{
|
||||
case LL_ISO_DATA_DIR_INPUT:
|
||||
pDataPathDir = (lctrDataPathCtx_t *) (&pCisCtx->dataPathInCtx);
|
||||
dpParam.pDataPathCtx = (lctrDataPathCtx_t *) (&pCisCtx->dataPathInCtx);
|
||||
break;
|
||||
case LL_ISO_DATA_DIR_OUTPUT:
|
||||
pDataPathDir = (lctrDataPathCtx_t *) (&pCisCtx->dataPathOutCtx);
|
||||
dpParam.pDataPathCtx = (lctrDataPathCtx_t *) (&pCisCtx->dataPathOutCtx);
|
||||
break;
|
||||
default:
|
||||
LL_TRACE_WARN2("LctrSetupIsoDataPath: handle=%u invalid direction dpDir=%u", pSetupDataPath->handle, pSetupDataPath->dpDir);
|
||||
return LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
}
|
||||
return lctrSetupIsoDataPath(pSetupDataPath, pDataPathDir);
|
||||
}
|
||||
|
||||
else if ((pBisCtx = lctrFindBisByHandle(pSetupDataPath->handle)) != NULL)
|
||||
{
|
||||
dpParam.handle = pBisCtx->handle;
|
||||
dpParam.isoInt = pBisCtx->pBigCtx->isoInterUsec;
|
||||
dpParam.pktCtr = (pBisCtx->pBigCtx->eventCounter + 1) * pBisCtx->pBigCtx->bn;
|
||||
dpParam.dpDir = pSetupDataPath->dpDir;
|
||||
|
||||
switch (pSetupDataPath->dpDir)
|
||||
{
|
||||
case LL_ISO_DATA_DIR_INPUT:
|
||||
if (pBisCtx->pBigCtx->role == LL_ROLE_SLAVE)
|
||||
{
|
||||
status = lctrBisSetDataPath(pBisCtx, pSetupDataPath->dpDir, pSetupDataPath->dpId);
|
||||
dpParam.pDataPathCtx = (lctrDataPathCtx_t *) (&pBisCtx->roleData.slv.dataPathInCtx);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_WARN1("LctrSetupIsoDataPath: handle=%u invalid input direction for master", pSetupDataPath->handle);
|
||||
status = LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
return LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
}
|
||||
break;
|
||||
case LL_ISO_DATA_DIR_OUTPUT:
|
||||
if (pBisCtx->pBigCtx->role == LL_ROLE_MASTER)
|
||||
{
|
||||
status = lctrBisSetDataPath(pBisCtx, pSetupDataPath->dpDir, pSetupDataPath->dpId);
|
||||
dpParam.pDataPathCtx = (lctrDataPathCtx_t *) (&pBisCtx->roleData.mst.dataPathOutCtx);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_WARN1("LctrSetupIsoDataPath: handle=%u invalid output direction for slave", pSetupDataPath->handle);
|
||||
status = LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
return LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LL_TRACE_WARN2("LctrSetupIsoDataPath: handle=%u invalid direction dpDir=%u", pSetupDataPath->handle, pSetupDataPath->dpDir);
|
||||
return LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
LL_TRACE_WARN1("LctrSetupIsoDataPath: handle=%u not found", pSetupDataPath->handle);
|
||||
status = LL_ERROR_CODE_UNKNOWN_CONN_ID;
|
||||
return LL_ERROR_CODE_UNKNOWN_CONN_ID;
|
||||
}
|
||||
|
||||
return status;
|
||||
return lctrIsoSetupDataPath(&dpParam, pSetupDataPath);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -828,18 +901,27 @@ uint8_t LctrRemoveIsoDataPath(uint16_t handle, uint8_t dpDir)
|
|||
uint8_t status = LL_SUCCESS;
|
||||
lctrCisCtx_t *pCisCtx;
|
||||
lctrBisCtx_t *pBisCtx;
|
||||
lctrDpParams_t dpParam;
|
||||
|
||||
if ((pCisCtx = lctrFindCisByHandle(handle)) != NULL)
|
||||
{
|
||||
/* Check to make sure parameters are valid. */
|
||||
if ((dpDir & ~(LL_ISO_DATA_PATH_INPUT_BIT | LL_ISO_DATA_PATH_OUTPUT_BIT)) ||
|
||||
(dpDir == 0))
|
||||
{
|
||||
LL_TRACE_WARN2("LctrRemoveIsoDataPath: handle=%u invalid direction dpDir=0x%08x", handle, dpDir);
|
||||
return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS;
|
||||
}
|
||||
|
||||
/* Check for validity of parameters before operating on them. */
|
||||
if (dpDir | LL_ISO_DATA_PATH_INPUT_BIT)
|
||||
if (dpDir & LL_ISO_DATA_PATH_INPUT_BIT)
|
||||
{
|
||||
if (pCisCtx->dataPathInCtx.id == LL_ISO_DATA_PATH_DISABLED)
|
||||
{
|
||||
return LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
}
|
||||
}
|
||||
if (dpDir | LL_ISO_DATA_PATH_OUTPUT_BIT)
|
||||
if (dpDir & LL_ISO_DATA_PATH_OUTPUT_BIT)
|
||||
{
|
||||
if (pCisCtx->dataPathOutCtx.id == LL_ISO_DATA_PATH_DISABLED)
|
||||
{
|
||||
|
@ -847,18 +929,70 @@ uint8_t LctrRemoveIsoDataPath(uint16_t handle, uint8_t dpDir)
|
|||
}
|
||||
}
|
||||
|
||||
if (dpDir | LL_ISO_DATA_PATH_INPUT_BIT)
|
||||
if (dpDir & LL_ISO_DATA_PATH_INPUT_BIT)
|
||||
{
|
||||
/* Stop input data path. */
|
||||
dpParam.handle = pCisCtx->cisHandle;
|
||||
dpParam.pDataPathCtx = (lctrDataPathCtx_t *)&pCisCtx->dataPathInCtx;
|
||||
/* Other parameters are unused in data path clearing. */
|
||||
lctrIsoInDataPathClear(&dpParam);
|
||||
|
||||
pCisCtx->dataPathInCtx.id = LL_ISO_DATA_PATH_DISABLED;
|
||||
}
|
||||
if (dpDir | LL_ISO_DATA_PATH_OUTPUT_BIT)
|
||||
if (dpDir & LL_ISO_DATA_PATH_OUTPUT_BIT)
|
||||
{
|
||||
/* Stop output data path. */
|
||||
dpParam.handle = pCisCtx->cisHandle;
|
||||
dpParam.pDataPathCtx = (lctrDataPathCtx_t *)&pCisCtx->dataPathOutCtx;
|
||||
/* Other parameters are unused in data path clearing. */
|
||||
lctrIsoOutDataPathClear(&dpParam);
|
||||
|
||||
pCisCtx->dataPathOutCtx.id = LL_ISO_DATA_PATH_DISABLED;
|
||||
}
|
||||
}
|
||||
else if ((pBisCtx = lctrFindBisByHandle(handle)) != NULL)
|
||||
{
|
||||
pBisCtx->path = LL_ISO_DATA_PATH_DISABLED;
|
||||
if (dpDir & LL_ISO_DATA_PATH_INPUT_BIT)
|
||||
{
|
||||
if (pBisCtx->roleData.slv.dataPathInCtx.id == LL_ISO_DATA_PATH_DISABLED)
|
||||
{
|
||||
return LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
}
|
||||
}
|
||||
if (dpDir & LL_ISO_DATA_PATH_OUTPUT_BIT)
|
||||
{
|
||||
if (pBisCtx->roleData.mst.dataPathOutCtx.id == LL_ISO_DATA_PATH_DISABLED)
|
||||
{
|
||||
return LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
}
|
||||
}
|
||||
|
||||
dpParam.handle = pBisCtx->handle;
|
||||
|
||||
if (pBisCtx->pBigCtx->role == LL_ROLE_MASTER)
|
||||
{
|
||||
if (pBisCtx->roleData.mst.dataPathOutCtx.id == LL_ISO_DATA_PATH_DISABLED)
|
||||
{
|
||||
return LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
dpParam.pDataPathCtx = (lctrDataPathCtx_t *)&pBisCtx->roleData.mst.dataPathOutCtx;
|
||||
/* Other parameters are unused in data path clearing. */
|
||||
lctrIsoOutDataPathClear(&dpParam);
|
||||
pBisCtx->roleData.mst.dataPathOutCtx.id = LL_ISO_DATA_PATH_DISABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pBisCtx->roleData.slv.dataPathInCtx.id == LL_ISO_DATA_PATH_DISABLED)
|
||||
{
|
||||
return LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
dpParam.pDataPathCtx = (lctrDataPathCtx_t *)&pBisCtx->roleData.slv.dataPathInCtx;
|
||||
/* Other parameters are unused in data path clearing. */
|
||||
lctrIsoInDataPathClear(&dpParam);
|
||||
pBisCtx->roleData.slv.dataPathInCtx.id = LL_ISO_DATA_PATH_DISABLED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1100,48 +1234,23 @@ void lctrNotifyHostIsoEventComplete(uint8_t handle, uint32_t evtCtr)
|
|||
/*!
|
||||
* \brief Send Codec SDU data.
|
||||
*
|
||||
* \param handle Stream ID.
|
||||
* \param handle ISO Handle.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void lctrIsoSendCodecSdu(uint16_t handle)
|
||||
void lctrIsoSendCodecSdu(uint16_t id, uint32_t pktCtr, uint32_t ts, uint8_t *pData, uint16_t actLen)
|
||||
{
|
||||
lctrBisCtx_t *pBisCtx;
|
||||
|
||||
if ((pBisCtx = lctrFindBisByHandle(handle)) == NULL)
|
||||
{
|
||||
LL_TRACE_WARN1("lctrIsoSendCodecSdu: handle=%u not found", handle);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *pSduBuf;
|
||||
|
||||
if ((pSduBuf = WsfMsgAlloc(pLctrRtCfg->maxIsoSduLen + HCI_ISO_DL_MAX_LEN)) == NULL)
|
||||
{
|
||||
LL_TRACE_ERR1("!!! Out of memory; dropping input SDU, stream=%u", handle);
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t len;
|
||||
uint32_t pktCtr;
|
||||
|
||||
WSF_ASSERT(lctrCodecHdlr.in);
|
||||
if ((len = lctrCodecHdlr.in(handle, pSduBuf + HCI_ISO_HDR_LEN + HCI_ISO_DL_MAX_LEN,
|
||||
pBisCtx->pBigCtx->maxSdu, &pktCtr)) == 0)
|
||||
{
|
||||
LL_TRACE_WARN1("ISO audio stream data not available, stream=%u", handle);
|
||||
WsfMsgFree(pSduBuf);
|
||||
return;
|
||||
}
|
||||
/* Recover SDU buffer. */
|
||||
uint8_t *pSduBuf = pData - HCI_ISO_HDR_LEN - HCI_ISO_DL_MAX_LEN;
|
||||
|
||||
lctrIsoHdr_t hdr =
|
||||
{
|
||||
.handle = handle,
|
||||
.handle = id,
|
||||
.pb = LCTR_PB_COMP,
|
||||
.tsFlag = TRUE,
|
||||
.len = len,
|
||||
.len = actLen,
|
||||
.ts = 0,
|
||||
.pktSn = pktCtr,
|
||||
.sduLen = len,
|
||||
.sduLen = actLen,
|
||||
.ps = LCTR_PS_VALID
|
||||
};
|
||||
|
||||
|
@ -1153,37 +1262,42 @@ void lctrIsoSendCodecSdu(uint16_t handle)
|
|||
/*!
|
||||
* \brief Setup ISO data path.
|
||||
*
|
||||
* \param pDpParam Parameters to set up data path.
|
||||
* \param pSetupDataPath Data path setup parameters.
|
||||
* \param pDataPathCtx Generic data path context.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t lctrSetupIsoDataPath(LlIsoSetupDataPath_t *pSetupDataPath, lctrDataPathCtx_t *pDataPathCtx)
|
||||
uint8_t lctrIsoSetupDataPath(lctrDpParams_t *pDpParam, LlIsoSetupDataPath_t *pSetupDataPath)
|
||||
{
|
||||
uint8_t status = LL_SUCCESS;
|
||||
|
||||
switch (pSetupDataPath->dpDir)
|
||||
{
|
||||
case LL_ISO_DATA_DIR_INPUT:
|
||||
{
|
||||
if (pSetupDataPath->dpId == pDataPathCtx->in.id)
|
||||
if (pSetupDataPath->dpId == pDpParam->pDataPathCtx->in.id)
|
||||
{
|
||||
/* No change. */
|
||||
return LL_SUCCESS;
|
||||
}
|
||||
|
||||
/* No teardown needed. */
|
||||
pDataPathCtx->in.id = pSetupDataPath->dpId;
|
||||
/* No setup needed. */
|
||||
lctrIsoInDataPathClear(pDpParam);
|
||||
pDpParam->pDataPathCtx->in.id = pSetupDataPath->dpId;
|
||||
status = lctrIsoInDataPathSetup(pDpParam, pSetupDataPath);
|
||||
break;
|
||||
}
|
||||
|
||||
case LL_ISO_DATA_DIR_OUTPUT:
|
||||
{
|
||||
if (pSetupDataPath->dpId == pDataPathCtx->out.id)
|
||||
if (pSetupDataPath->dpId == pDpParam->pDataPathCtx->out.id)
|
||||
{
|
||||
/* No change. */
|
||||
return LL_SUCCESS;
|
||||
}
|
||||
|
||||
lctrIsoOutDataPathClear(&pDataPathCtx->out);
|
||||
pDataPathCtx->out.id = pSetupDataPath->dpId;
|
||||
lctrIsoOutDataPathSetup(&pDataPathCtx->out);
|
||||
lctrIsoOutDataPathClear(pDpParam);
|
||||
pDpParam->pDataPathCtx->out.id = pSetupDataPath->dpId;
|
||||
status = lctrIsoOutDataPathSetup(pDpParam, pSetupDataPath);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1192,5 +1306,5 @@ uint8_t lctrSetupIsoDataPath(LlIsoSetupDataPath_t *pSetupDataPath, lctrDataPathC
|
|||
break;
|
||||
}
|
||||
|
||||
return LL_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -69,7 +69,6 @@ static void lctrAssembleCisDataPdu(lctrIsoHdr_t *pIsoHdr, uint8_t *pBuf, uint8_t
|
|||
lctrCisPackDataPduHdr(pBuf, &dataHdr);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Initialize the transmit memory resources.
|
||||
|
@ -181,7 +180,8 @@ void lctrCisTxDataPduQueue(lctrCisCtx_t *pCisCtx, lctrIsoHdr_t *pIsoHdr, uint8_t
|
|||
{
|
||||
LL_TRACE_ERR1("Failed to allocate transmit buffer descriptor: cisHandle=%u", pIsoHdr->handle);
|
||||
WsfMsgFree(pIsoBuf);
|
||||
if (pCisCtx->txTestEnabled == FALSE)
|
||||
if (lmgrPersistCb.sendIsoCompCback &&
|
||||
(pCisCtx->txTestEnabled == FALSE))
|
||||
{
|
||||
uint16_t handle = pIsoHdr->handle;
|
||||
uint16_t numSdu = 1;
|
||||
|
@ -411,15 +411,15 @@ uint8_t lctrCisTxQueueClear(lctrCisCtx_t *pCisCtx)
|
|||
* \return Pointer to the start of the PDU data buffer.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t *lctrCisRxPduAlloc(uint16_t maxRxLen)
|
||||
uint8_t *lctrCisRxPduAlloc()
|
||||
{
|
||||
/* LCTR_DATA_PDU_MAX_LEN includes LL_DATA_MIC_LEN if required. */
|
||||
const uint16_t allocLen = WSF_MAX(BB_FIXED_DATA_PKT_LEN, LCTR_CIS_DATA_PDU_LEN(maxRxLen)) + LCTR_CIS_DATA_PDU_START_OFFSET;
|
||||
const uint16_t allocLen = LCTR_CIS_DATA_PDU_START_OFFSET + HCI_ISO_DL_MAX_LEN + pLctrRtCfg->maxIsoSduLen + BB_DATA_PDU_TAILROOM;
|
||||
|
||||
uint8_t *pBuf;
|
||||
|
||||
/* Include ISO header. */
|
||||
if ((pBuf = WsfMsgAlloc(HCI_ISO_DL_MAX_LEN + allocLen)) != NULL)
|
||||
if ((pBuf = WsfMsgAlloc(allocLen)) != NULL)
|
||||
{
|
||||
/* Return start of data PDU. */
|
||||
pBuf += LCTR_CIS_DATA_PDU_START_OFFSET + HCI_ISO_DL_MAX_LEN;
|
||||
|
@ -454,12 +454,16 @@ void lctrCisRxPduFree(uint8_t *pBuf)
|
|||
/*************************************************************************************************/
|
||||
void lctrCisRxEnq(uint8_t *pBuf, uint16_t eventCounter, uint16_t cisHandle)
|
||||
{
|
||||
/* Stamp packet with event counter. */
|
||||
pBuf -= LCTR_CIS_DATA_PDU_START_OFFSET;
|
||||
UINT16_TO_BUF(pBuf, eventCounter);
|
||||
if (pBuf != NULL)
|
||||
{
|
||||
/* Stamp packet with event counter. */
|
||||
pBuf -= LCTR_CIS_DATA_PDU_START_OFFSET;
|
||||
UINT16_TO_BUF(pBuf, eventCounter);
|
||||
|
||||
/* Queue LE Data PDU. */
|
||||
WsfMsgEnq(&lmgrIsoCb.rxDataQ, cisHandle, pBuf);
|
||||
}
|
||||
|
||||
/* Queue LE Data PDU. */
|
||||
WsfMsgEnq(&lmgrIsoCb.rxDataQ, cisHandle, pBuf);
|
||||
WsfSetEvent(lmgrPersistCb.handlerId, (1 << LCTR_EVENT_CIS_RX_PENDING));
|
||||
}
|
||||
|
||||
|
@ -497,12 +501,15 @@ uint8_t *lctrCisRxDeq(uint16_t *pCisHandle)
|
|||
* \param pBuf SDU buffer.
|
||||
*
|
||||
* \return TRUE if buffer successfully handled and will be used.
|
||||
* FALSE if buffer was not handled and needs to be disposed.
|
||||
* FALSE needs to be disposed.
|
||||
*
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t lctrIsoRxConnEnq(lctrOutDataPathCtx_t *pOutDataPathCtx, uint16_t handle, uint8_t *pBuf)
|
||||
bool_t lctrIsoRxConnEnq(lctrOutDataPathCtx_t *pOutDataPathCtx, uint16_t handle, uint32_t pktCtr, uint8_t *pBuf)
|
||||
{
|
||||
lctrIsoHdr_t isoHdr;
|
||||
lctrIsoUnpackHdr(&isoHdr, pBuf);
|
||||
|
||||
switch (pOutDataPathCtx->id)
|
||||
{
|
||||
case LL_ISO_DATA_PATH_HCI:
|
||||
|
@ -513,6 +520,10 @@ bool_t lctrIsoRxConnEnq(lctrOutDataPathCtx_t *pOutDataPathCtx, uint16_t handle,
|
|||
return TRUE;
|
||||
|
||||
case LL_ISO_DATA_PATH_VS:
|
||||
WSF_ASSERT(lctrCodecHdlr.out);
|
||||
lctrCodecHdlr.out(pOutDataPathCtx->cfg.codec.streamId, isoHdr.pSdu, isoHdr.sduLen, isoHdr.ts);
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -533,34 +544,84 @@ uint8_t *lctrIsoRxConnDeq(lctrOutDataPathCtx_t *pOutCtx)
|
|||
{
|
||||
wsfHandlerId_t handle;
|
||||
|
||||
if (pOutCtx->id != LL_ISO_DATA_PATH_HCI)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return WsfMsgDeq(&pOutCtx->cfg.hci.rxDataQ, &handle);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Setup a datapath context.
|
||||
* \brief Setup an input data path context.
|
||||
*
|
||||
* \param pOutCtx Output datapath context.
|
||||
* \param pDpParam Data path parameters.
|
||||
* \param pSetupDataPath Data path setup parameters.
|
||||
*
|
||||
* \return Status error code.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void lctrIsoOutDataPathSetup(lctrOutDataPathCtx_t *pOutCtx)
|
||||
uint8_t lctrIsoInDataPathSetup(lctrDpParams_t *pDpParam, LlIsoSetupDataPath_t *pSetupDataPath)
|
||||
{
|
||||
switch (pOutCtx->id)
|
||||
lctrInDataPathCtx_t *pInCtx = &pDpParam->pDataPathCtx->in;
|
||||
|
||||
switch (pInCtx->id)
|
||||
{
|
||||
case LL_ISO_DATA_PATH_HCI:
|
||||
pOutCtx->cfg.hci.numRxPend = 0;
|
||||
WSF_QUEUE_INIT(&pOutCtx->cfg.hci.rxDataQ);
|
||||
break;
|
||||
|
||||
case LL_ISO_DATA_PATH_VS:
|
||||
/* No action. */
|
||||
pInCtx->cfg.codec.streamId = pDpParam->handle;
|
||||
|
||||
if (lctrCodecHdlr.start)
|
||||
{
|
||||
PalCodecStreamParam_t param =
|
||||
{
|
||||
.dir = PAL_CODEC_DIR_INPUT,
|
||||
.pktCtr = pDpParam->pktCtr,
|
||||
.codecId = pSetupDataPath->codecId,
|
||||
.inCback = lctrIsoSendCodecSdu
|
||||
};
|
||||
|
||||
if (!lctrCodecHdlr.start(pInCtx->cfg.codec.streamId, ¶m))
|
||||
{
|
||||
LL_TRACE_WARN1("Failed to start the codec, dpId=%u", pInCtx->id);
|
||||
pInCtx->id = LL_ISO_DATA_PATH_DISABLED;
|
||||
return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_WARN1("Codec not found, dpId=%u", pInCtx->id);
|
||||
return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS;
|
||||
}
|
||||
break;
|
||||
|
||||
case LL_ISO_DATA_PATH_DISABLED:
|
||||
case LL_ISO_DATA_PATH_HCI:
|
||||
/* No action required. */
|
||||
break;
|
||||
|
||||
default:
|
||||
LL_TRACE_WARN1("Unknown Data Path, dpId=%u", pInCtx->id);
|
||||
return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS;
|
||||
}
|
||||
|
||||
return LL_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Clear an input data path context.
|
||||
*
|
||||
* \param pOutCtx Output data path context.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void lctrIsoInDataPathClear(lctrDpParams_t *pDpParam)
|
||||
{
|
||||
lctrInDataPathCtx_t *pInCtx = &pDpParam->pDataPathCtx->in;
|
||||
|
||||
switch (pInCtx->id)
|
||||
{
|
||||
case LL_ISO_DATA_PATH_VS:
|
||||
WSF_ASSERT(lctrCodecHdlr.stop);
|
||||
lctrCodecHdlr.stop(pInCtx->cfg.codec.streamId, PAL_CODEC_DIR_INPUT);
|
||||
break;
|
||||
|
||||
case LL_ISO_DATA_PATH_HCI:
|
||||
default:
|
||||
/* No action. */
|
||||
break;
|
||||
|
@ -569,19 +630,81 @@ void lctrIsoOutDataPathSetup(lctrOutDataPathCtx_t *pOutCtx)
|
|||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Clear a datapath context.
|
||||
* \brief Setup a data path context.
|
||||
*
|
||||
* \param pOutCtx Output datapath context.
|
||||
* \param pDpParam Data path parameters.
|
||||
* \param pSetupDataPath Data path setup parameters.
|
||||
*
|
||||
* \return Status error code.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void lctrIsoOutDataPathClear(lctrOutDataPathCtx_t *pOutCtx)
|
||||
uint8_t lctrIsoOutDataPathSetup(lctrDpParams_t *pDpParam, LlIsoSetupDataPath_t *pSetupDataPath)
|
||||
{
|
||||
lctrOutDataPathCtx_t *pOutCtx = &pDpParam->pDataPathCtx->out;
|
||||
|
||||
switch (pOutCtx->id)
|
||||
{
|
||||
case LL_ISO_DATA_PATH_VS:
|
||||
pOutCtx->cfg.codec.streamId = pDpParam->handle;
|
||||
|
||||
if (lctrCodecHdlr.start)
|
||||
{
|
||||
PalCodecStreamParam_t param =
|
||||
{
|
||||
.dir = PAL_CODEC_DIR_OUTPUT,
|
||||
.pktCtr = pDpParam->pktCtr,
|
||||
.codecId = pSetupDataPath->codecId
|
||||
};
|
||||
|
||||
if (!lctrCodecHdlr.start(pOutCtx->cfg.codec.streamId, ¶m))
|
||||
{
|
||||
LL_TRACE_WARN1("Failed to start the codec, dpId=%u", pOutCtx->id);
|
||||
pOutCtx->id = LL_ISO_DATA_PATH_DISABLED;
|
||||
return LL_ERROR_CODE_CONN_REJ_LIMITED_RESOURCES;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_TRACE_WARN1("Codec not found, dpId=%u", pOutCtx->id);
|
||||
return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS;
|
||||
}
|
||||
break;
|
||||
|
||||
case LL_ISO_DATA_PATH_HCI:
|
||||
pOutCtx->cfg.hci.numRxPend = 0;
|
||||
WSF_QUEUE_INIT(&pOutCtx->cfg.hci.rxDataQ);
|
||||
break;
|
||||
|
||||
case LL_ISO_DATA_PATH_DISABLED:
|
||||
/* No action required. */
|
||||
break;
|
||||
|
||||
default:
|
||||
LL_TRACE_WARN1("Unknown Data Path, dpId=%u", pOutCtx->id);
|
||||
return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS;
|
||||
}
|
||||
|
||||
return LL_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Clear a data path context.
|
||||
*
|
||||
* \param pOutCtx Output data path context.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void lctrIsoOutDataPathClear(lctrDpParams_t *pDpParam)
|
||||
{
|
||||
lctrOutDataPathCtx_t *pOutCtx = &pDpParam->pDataPathCtx->out;
|
||||
|
||||
switch (pOutCtx->id)
|
||||
{
|
||||
case LL_ISO_DATA_PATH_HCI:
|
||||
{
|
||||
uint8_t *pBuf;
|
||||
wsfHandlerId_t handlerId;
|
||||
|
||||
while ((pBuf = WsfMsgDeq(&pOutCtx->cfg.hci.rxDataQ, &handlerId)) != NULL)
|
||||
{
|
||||
WsfMsgFree(pBuf);
|
||||
|
@ -591,8 +714,20 @@ void lctrIsoOutDataPathClear(lctrOutDataPathCtx_t *pOutCtx)
|
|||
}
|
||||
|
||||
case LL_ISO_DATA_PATH_VS:
|
||||
/* No action. */
|
||||
{
|
||||
WSF_ASSERT(lctrCodecHdlr.stop);
|
||||
lctrCodecHdlr.stop(pOutCtx->cfg.codec.streamId, PAL_CODEC_DIR_OUTPUT);
|
||||
|
||||
uint8_t *pBuf;
|
||||
wsfHandlerId_t handlerId;
|
||||
|
||||
while ((pBuf = WsfMsgDeq(&pOutCtx->cfg.codec.rxDataQ, &handlerId)) != NULL)
|
||||
{
|
||||
WsfMsgFree(pBuf);
|
||||
lctrIsoDataRxIncAvailBuf(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
/* No action. */
|
||||
|
@ -678,11 +813,9 @@ uint8_t *lctrGenerateIsoTestData(uint16_t handle, LlIsoPldType_t pldType, uint16
|
|||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
LL_TRACE_ERR1("Invalid value pldType=%u", pldType);
|
||||
len = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Pack ISO header. */
|
||||
|
@ -810,7 +943,7 @@ uint8_t *lctrTxIsoDataPduAlloc(void)
|
|||
/* Use LL_ISO_PDU_MAX_LEN to ensure use of data buffers located in the large pool. */
|
||||
if ((pPdu = (uint8_t*)WsfMsgAlloc(allocLen)) == NULL)
|
||||
{
|
||||
LL_TRACE_WARN1("lctrTxIsoDataPduAlloc: Unable to allocate framed Tx buffer, allocSize=%u", allocLen);
|
||||
LL_TRACE_WARN1("lctrTxIsoDataPduAlloc: Unable to allocate Tx buffer, allocSize=%u", allocLen);
|
||||
}
|
||||
|
||||
return pPdu;
|
||||
|
@ -841,13 +974,12 @@ uint8_t lctrAssembleTxFramedPdu(lctrIsoalTxCtx_t *pIsoalTxCtx, uint8_t *pPduBuf,
|
|||
/* Set offset of pPduBuf */
|
||||
pPduBuf += HCI_ISO_HDR_LEN + HCI_ISO_DL_MIN_LEN;
|
||||
|
||||
/*** Loop through and pack SDUs. ***/
|
||||
|
||||
/* Loop through and pack SDUs. */
|
||||
while (remLen)
|
||||
{
|
||||
uint8_t *pSduBuf = WsfMsgPeek(pSduQ, &handlerId);
|
||||
|
||||
/* The buffer is empty, process the completed PDU */
|
||||
/* The buffer is empty, process the completed PDU. */
|
||||
if (pSduBuf == NULL)
|
||||
{
|
||||
break;
|
||||
|
@ -855,7 +987,7 @@ uint8_t lctrAssembleTxFramedPdu(lctrIsoalTxCtx_t *pIsoalTxCtx, uint8_t *pPduBuf,
|
|||
|
||||
lctrIsoHdr_t isoHdr;
|
||||
|
||||
/*** Disassemble ISO packet. ***/
|
||||
/*** Disassemble ISO packet ***/
|
||||
|
||||
lctrIsoUnpackHdr(&isoHdr, pSduBuf);
|
||||
|
||||
|
@ -878,7 +1010,7 @@ uint8_t lctrAssembleTxFramedPdu(lctrIsoalTxCtx_t *pIsoalTxCtx, uint8_t *pPduBuf,
|
|||
segHdrLen += LL_ISO_SEG_TO_LEN;
|
||||
}
|
||||
|
||||
/*** Compute segment parameters. ***/
|
||||
/*** Compute segment parameters ***/
|
||||
|
||||
/* There is enough room for the entire SDU. */
|
||||
if (remLen >= (isoHdr.sduLen + segHdrLen))
|
||||
|
@ -951,7 +1083,7 @@ uint8_t lctrAssembleTxFramedPdu(lctrIsoalTxCtx_t *pIsoalTxCtx, uint8_t *pPduBuf,
|
|||
* \return Pointer to the start of the ISO Data PDU buffer, NULL if allocation failed.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t *lctrRxSduAlloc(void)
|
||||
uint8_t *lctrRxSduAlloc(void)
|
||||
{
|
||||
uint8_t *pSdu;
|
||||
|
||||
|
@ -971,59 +1103,102 @@ static uint8_t *lctrRxSduAlloc(void)
|
|||
* \brief Queue the received SDU into the pending queue.
|
||||
*
|
||||
* \param pRxCtx ISOAL receive context.
|
||||
* \param pSdu SDU buffer.
|
||||
* \param pSdu SDU fragment.
|
||||
* \param handle CIS connection handle.
|
||||
* \param dataLen Data length.
|
||||
* \param llid Rx LLID.
|
||||
*
|
||||
* \return TRUE if pending queue ready to be sent to host.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t lctrIsoUnframedRxSduPendQueue(lctrIsoalRxCtx_t *pRxCtx, uint8_t *pSdu, uint16_t handle,
|
||||
uint16_t dataLen, uint8_t llid)
|
||||
bool_t lctrRecombineRxUnframedSdu(lctrIsoalRxCtx_t *pRxCtx, uint8_t *pSduFrag)
|
||||
{
|
||||
/* Save data for head packet. */
|
||||
/* pRxCtx->data.unframed.pendSduIsoHdr.ps = 0; */ /* Should be done in calling function. */
|
||||
pRxCtx->data.unframed.curLen += dataLen;
|
||||
bool_t result = FALSE;
|
||||
|
||||
WsfMsgEnq(&pRxCtx->data.unframed.pendSduQ, handle, pSdu);
|
||||
uint8_t handlerId;
|
||||
uint8_t *pSdu = WsfMsgPeek(&pRxCtx->data.unframed.pendSduQ, &handlerId);
|
||||
|
||||
/* If we received the last PDU, pack the head packet with the packet status and sdu length. */
|
||||
if (llid == LL_LLID_ISO_UNF_END_PDU)
|
||||
if (pSduFrag)
|
||||
{
|
||||
uint8_t *pHeadPkt;
|
||||
uint8_t handlerId;
|
||||
lctrIsoHdr_t isoHdr = {0};
|
||||
lctrIsoHdr_t fragHdr;
|
||||
lctrIsoUnpackHdr(&fragHdr, pSduFrag);
|
||||
|
||||
pHeadPkt = WsfMsgPeek(&pRxCtx->data.unframed.pendSduQ, &handlerId);
|
||||
WSF_ASSERT(pHeadPkt);
|
||||
switch (fragHdr.pb)
|
||||
{
|
||||
case LCTR_PB_COMP:
|
||||
result = TRUE;
|
||||
/* Fallthrough */
|
||||
case LCTR_PB_FIRST:
|
||||
if (pSdu)
|
||||
{
|
||||
LL_TRACE_ERR1("Previous SDU was not flushed, dropping SDU, handle=%u", fragHdr.handle);
|
||||
|
||||
lctrIsoUnpackHdr(&isoHdr, pHeadPkt);
|
||||
isoHdr.pktSn = pRxCtx->packetSequence++;
|
||||
pSdu = WsfMsgDeq(&pRxCtx->data.unframed.pendSduQ, &handlerId);
|
||||
WsfMsgFree(pSdu);
|
||||
|
||||
pSdu = NULL;
|
||||
}
|
||||
|
||||
/* Store first fragment. */
|
||||
pRxCtx->data.unframed.curLen = fragHdr.sduLen;
|
||||
WsfMsgEnq(&pRxCtx->data.unframed.pendSduQ, fragHdr.handle, pSduFrag);
|
||||
break;
|
||||
|
||||
case LCTR_PB_LAST:
|
||||
result = TRUE;
|
||||
/* Fallthrough */
|
||||
case LCTR_PB_CONT:
|
||||
if (pSdu == NULL)
|
||||
{
|
||||
/* Store first fragment. */
|
||||
pRxCtx->data.unframed.curLen = fragHdr.len;
|
||||
WsfMsgEnq(&pRxCtx->data.unframed.pendSduQ, fragHdr.handle, pSduFrag);
|
||||
|
||||
/* Missing first fragment. */
|
||||
pRxCtx->data.unframed.ps = LCTR_PS_INVALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
lctrIsoHdr_t isoHdr;
|
||||
lctrIsoUnpackHdr(&isoHdr, pSdu);
|
||||
|
||||
/* Append continuation fragment (recombine). */
|
||||
memcpy(isoHdr.pSdu + pRxCtx->data.unframed.curLen, fragHdr.pSdu, fragHdr.len);
|
||||
WsfMsgFree(pSduFrag);
|
||||
pRxCtx->data.unframed.curLen += fragHdr.len;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NULL fragment indicates unexpected flush. */
|
||||
if (pSdu)
|
||||
{
|
||||
/* Complete pending SDU fragment. */
|
||||
pRxCtx->data.unframed.ps = LCTR_PS_INVALID;
|
||||
result = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (result && pSdu)
|
||||
{
|
||||
/* Update ISO header. */
|
||||
lctrIsoHdr_t isoHdr;
|
||||
lctrIsoUnpackHdr(&isoHdr, pSdu);
|
||||
isoHdr.pb = LCTR_PB_COMP;
|
||||
isoHdr.len = pRxCtx->data.unframed.curLen;
|
||||
isoHdr.sduLen = pRxCtx->data.unframed.curLen;
|
||||
isoHdr.ps = pRxCtx->data.unframed.ps;
|
||||
isoHdr.len -= + HCI_ISO_DL_MAX_LEN;
|
||||
|
||||
/* Reset the packet boundary in case a missed packet leaves it undefined. */
|
||||
uint8_t rfu; /* Used to peek into msg queue. */
|
||||
if (WsfMsgNPeek(&pRxCtx->data.unframed.pendSduQ, 1, &rfu))
|
||||
{
|
||||
isoHdr.pb = LCTR_PB_FIRST;
|
||||
}
|
||||
else
|
||||
{
|
||||
isoHdr.pb = LCTR_PB_COMP;
|
||||
}
|
||||
|
||||
lctrIsoPackHdr(pHeadPkt, &isoHdr);
|
||||
lctrIsoPackHdr(pSdu, &isoHdr);
|
||||
|
||||
/* Clean up context */
|
||||
pRxCtx->data.unframed.curLen = 0;
|
||||
pRxCtx->data.unframed.ps = 0;
|
||||
return TRUE;
|
||||
pRxCtx->data.unframed.ps = LCTR_PS_VALID;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -1044,17 +1219,19 @@ uint8_t lctrAssembleRxFramedSdu(lctrIsoalRxCtx_t *pIsoalRxCtx, wsfQueue_t *pRxQu
|
|||
{
|
||||
uint8_t totalSduQueued = 0;
|
||||
|
||||
/* Last PDU was flushed. SDU data is lost and will be flushed. */
|
||||
/* Last PDU was flushed. */
|
||||
if (pIsoalRxCtx->pduFlushed)
|
||||
{
|
||||
pIsoalRxCtx->pduFlushed = FALSE;
|
||||
|
||||
/* There was a lost SDU due to a fragment being flushed. */
|
||||
if (pIsoalRxCtx->pPendSduBuf)
|
||||
{
|
||||
/* Flush SDU. */
|
||||
WsfMsgFree(pIsoalRxCtx->pPendSduBuf);
|
||||
pIsoalRxCtx->pPendSduBuf = NULL;
|
||||
return 0;
|
||||
}
|
||||
pIsoalRxCtx->pduFlushed = FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *pDataBuf = pIsoBuf + LL_DATA_HDR_LEN;
|
||||
|
@ -1160,6 +1337,7 @@ uint8_t lctrAssembleRxFramedSdu(lctrIsoalRxCtx_t *pIsoalRxCtx, wsfQueue_t *pRxQu
|
|||
uint8_t *pIsoHdrBuf = (pIsoalRxCtx->pPendSduBuf);
|
||||
lctrIsoPackHdr(pIsoHdrBuf, &isoHdr);
|
||||
|
||||
/* TODO: when adding codec data path, change this to enque or consume based on data path. */
|
||||
/* Queue SDU. */
|
||||
WsfMsgEnq(pRxQueue, handle, pIsoalRxCtx->pPendSduBuf);
|
||||
/* lctrIsoDataRxDecAvailBuf(); */ /* Handled in lctrRxSduAlloc. */
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* \brief Link layer controller power control implementation file.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -42,11 +42,10 @@ void LctrPowerControlInit(void)
|
|||
{
|
||||
/* Initialize power control. */
|
||||
lmgrPersistCb.featuresDefault |= (LL_FEAT_POWER_CHANGE_IND | LL_FEAT_POWER_CONTROL_REQUEST);
|
||||
lctrPcActTbl[LCTR_PC_MONITOR_AUTO] = lctrAutoPowerMonitorAct;
|
||||
|
||||
/* Initialize path loss. */
|
||||
lmgrPersistCb.featuresDefault |= (LL_FEAT_PATH_LOSS_MONITOR);
|
||||
lctrPcActTbl[LCTR_PC_MONITOR_PATH_LOSS] = lctrPathLossMonitorAct;
|
||||
lctrPathLossMonitorActFn = lctrPathLossMonitorAct;
|
||||
|
||||
/* Initialize state machines. */
|
||||
lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PC] = lctrLlcpExecutePclSm;
|
||||
|
@ -209,7 +208,6 @@ uint8_t lctrSetPathLossReportingEnable(uint16_t handle, uint8_t enable)
|
|||
return LL_ERROR_CODE_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
|
||||
/* If peer Tx power is unavailable, read the peer tx power. */
|
||||
if (pCtx->peerTxPower == LL_PWR_CTRL_TXPOWER_UNAVAILABLE)
|
||||
{
|
||||
|
@ -255,7 +253,7 @@ void lctrNotifyHostPathLossRpt(lctrConnCtx_t *pCtx)
|
|||
const uint16_t handle = LCTR_GET_CONN_HANDLE(pCtx);
|
||||
uint8_t curPathLoss = lctrCalcPathLoss(pCtx);
|
||||
|
||||
LlPathLossThresholdEvt_t evt =
|
||||
LlPathLossThresholdInd_t evt =
|
||||
{
|
||||
.hdr =
|
||||
{
|
||||
|
@ -311,7 +309,7 @@ void lctrPathLossMonitorAct(lctrConnCtx_t *pCtx)
|
|||
if (pCtx->pclMonitorParam.pathLoss.curTimeSpent >=
|
||||
pCtx->pclMonitorParam.pathLoss.minTimeSpent)
|
||||
{
|
||||
LL_TRACE_INFO2("lctrPathLossMonitorAct, New zone entered. newZone=%u, pathLoss=%u", newZone, lctrCalcPathLoss(pCtx));
|
||||
LL_TRACE_INFO2("lctrPathLossMonitorAct: new zone entered. newZone=%u, pathLoss=%u", newZone, lctrCalcPathLoss(pCtx));
|
||||
pCtx->pclMonitorParam.pathLoss.curTimeSpent = 0;
|
||||
pCtx->pclMonitorParam.pathLoss.curZone = newZone;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -30,10 +30,18 @@
|
|||
#include "wsf_assert.h"
|
||||
#include "ll_math.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "uECC_ll.h"
|
||||
#include "pal_bb_ble.h"
|
||||
#include <string.h>
|
||||
|
||||
#if ENABLE_UECC
|
||||
#include "uECC_ll.h"
|
||||
#endif
|
||||
|
||||
#if ENABLE_UECC_TINYCRYPT
|
||||
#include "tinycrypt/ecc.h"
|
||||
#include "tinycrypt/ecc_dh.h"
|
||||
#endif
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Baseband driver ECC service function.
|
||||
|
@ -117,6 +125,34 @@ static void lctrReverse(uint8_t *p, uint16_t len)
|
|||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Notify host of key generation.
|
||||
*
|
||||
* \param pDhKey Diffie-Hellman key.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void lctrNotifyGenerateDhKeyInd(const uint8_t *pDhKey)
|
||||
{
|
||||
LlGenerateDhKeyInd_t evt =
|
||||
{
|
||||
.hdr =
|
||||
{
|
||||
.param = 0,
|
||||
.event = LL_GENERATE_DHKEY_CMPL_IND,
|
||||
.status = LL_SUCCESS
|
||||
}
|
||||
};
|
||||
|
||||
evt.status = lmgrScCb.pubKeyValid ? LL_SUCCESS : LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS;
|
||||
memcpy(evt.dhKey, pDhKey, sizeof(evt.dhKey));
|
||||
|
||||
LL_TRACE_INFO0("### LlEvent ### LL_GENERATE_DHKEY_CMPL_IND, status=LL_SUCCESS");
|
||||
|
||||
LmgrSendEvent((LlEvt_t *)&evt);
|
||||
}
|
||||
|
||||
#if ENABLE_UECC
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Start generating P-256 key pair.
|
||||
|
@ -193,6 +229,7 @@ void lctrGenerateP256KeyPairComplete(uint8_t *pPubKey, uint8_t *pPrivKey)
|
|||
lctrReverse(pPubKey + LL_ECC_KEY_LEN, LL_ECC_KEY_LEN);
|
||||
lctrReverse(pPrivKey, LL_ECC_KEY_LEN);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
|
@ -213,12 +250,30 @@ void lctrGenerateDhKeyStart(const uint8_t *pPubKey, const uint8_t *pPrivKey)
|
|||
lctrReverseCopy(privKey, pPrivKey, LL_ECC_KEY_LEN);
|
||||
|
||||
/* Start shared secret generation. */
|
||||
#if ENABLE_UECC
|
||||
uECC_set_rng_ll(lctrRng);
|
||||
uECC_shared_secret_start(pubKey, privKey);
|
||||
|
||||
lctrScBbDrvEcc(LL_MATH_ECC_OP_GENERATE_DH_KEY);
|
||||
#endif
|
||||
|
||||
#if ENABLE_UECC_TINYCRYPT
|
||||
uint8_t dhKey[LL_ECC_KEY_LEN];
|
||||
uECC_set_rng(lctrRng);
|
||||
const struct uECC_Curve_t* pCurve = uECC_secp256r1();
|
||||
uECC_shared_secret(pPubKey, pPrivKey, dhKey, pCurve);
|
||||
|
||||
/* Reverse shared secret (to little endian). */
|
||||
lctrReverse(dhKey, LL_ECC_KEY_LEN);
|
||||
|
||||
/* Notify host that the key was generated. */
|
||||
lctrNotifyGenerateDhKeyInd(dhKey);
|
||||
|
||||
lmgrScCb.eccOpActive = FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_UECC
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Continue generating Diffie-Hellman key.
|
||||
|
@ -252,6 +307,7 @@ void lctrGenerateDhKeyComplete(uint8_t *pDhKey)
|
|||
/* Reverse shared secret (to little endian). */
|
||||
lctrReverse(pDhKey, LL_ECC_KEY_LEN);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
|
@ -272,7 +328,14 @@ bool_t lctrValidatePublicKey(const uint8_t *pPubKey, bool_t generateKey)
|
|||
lctrReverseCopy(pubKey, pPubKey, LL_ECC_KEY_LEN);
|
||||
lctrReverseCopy(pubKey + LL_ECC_KEY_LEN, pPubKey + LL_ECC_KEY_LEN, LL_ECC_KEY_LEN);
|
||||
|
||||
#if ENABLE_UECC
|
||||
pubKeyValid = (bool_t)uECC_valid_public_key_ll(pubKey);
|
||||
#endif
|
||||
|
||||
#if ENABLE_UECC_TINYCRYPT
|
||||
const struct uECC_Curve_t* pCurve = uECC_secp256r1();
|
||||
pubKeyValid = (bool_t)uECC_valid_public_key(pubKey, pCurve);
|
||||
#endif
|
||||
|
||||
if (!pubKeyValid && generateKey)
|
||||
{
|
||||
|
@ -310,33 +373,7 @@ static void lctrNotifyReadLocalP256PubKeyInd(const uint8_t *pPubKey)
|
|||
LmgrSendEvent((LlEvt_t *)&evt);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Notify host of key generation.
|
||||
*
|
||||
* \param pDhKey Diffie-Hellman key.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void lctrNotifyGenerateDhKeyInd(const uint8_t *pDhKey)
|
||||
{
|
||||
LlGenerateDhKeyInd_t evt =
|
||||
{
|
||||
.hdr =
|
||||
{
|
||||
.param = 0,
|
||||
.event = LL_GENERATE_DHKEY_CMPL_IND,
|
||||
.status = LL_SUCCESS
|
||||
}
|
||||
};
|
||||
|
||||
evt.status = lmgrScCb.pubKeyValid ? LL_SUCCESS : LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS;
|
||||
memcpy(evt.dhKey, pDhKey, sizeof(evt.dhKey));
|
||||
|
||||
LL_TRACE_INFO0("### LlEvent ### LL_GENERATE_DHKEY_CMPL_IND, status=LL_SUCCESS");
|
||||
|
||||
LmgrSendEvent((LlEvt_t *)&evt);
|
||||
}
|
||||
|
||||
#if ENABLE_UECC
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief P-256 key pair generation.
|
||||
|
@ -388,6 +425,7 @@ static void lctrScGenerateDhKeyContinue(void)
|
|||
lmgrScCb.eccOpActive = FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
|
@ -409,6 +447,8 @@ uint8_t LctrGenerateP256KeyPair(void)
|
|||
|
||||
/* Start operation. */
|
||||
lmgrScCb.eccOpActive = TRUE;
|
||||
|
||||
#if ENABLE_UECC
|
||||
if (lmgrScCb.privKeySet)
|
||||
{
|
||||
lctrGenerateP256PublicKeyStart(lmgrScCb.privKey);
|
||||
|
@ -417,6 +457,37 @@ uint8_t LctrGenerateP256KeyPair(void)
|
|||
{
|
||||
lctrGenerateP256KeyPairStart();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_UECC_TINYCRYPT
|
||||
uint8_t pubKey[LL_ECC_KEY_LEN * 2];
|
||||
uint8_t privKey[LL_ECC_KEY_LEN];
|
||||
|
||||
if (lmgrScCb.privKeySet)
|
||||
{
|
||||
/* Reverse private key (to big endian). */
|
||||
lctrReverseCopy(privKey, lmgrScCb.privKey, LL_ECC_KEY_LEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Generate private key. */
|
||||
lctrRng(privKey, sizeof(privKey));
|
||||
}
|
||||
|
||||
uECC_set_rng(lctrRng);
|
||||
const struct uECC_Curve_t* pCurve = uECC_secp256r1();
|
||||
uECC_make_key(pubKey, privKey, pCurve);
|
||||
|
||||
/* Reverse keys (to little endian). */
|
||||
lctrReverse(pubKey, LL_ECC_KEY_LEN);
|
||||
lctrReverse(pubKey + LL_ECC_KEY_LEN, LL_ECC_KEY_LEN);
|
||||
lctrReverseCopy(lmgrScCb.privKey, privKey, LL_ECC_KEY_LEN);
|
||||
|
||||
/* Notify host that the key was generated. */
|
||||
lctrNotifyReadLocalP256PubKeyInd(pubKey);
|
||||
|
||||
lmgrScCb.eccOpActive = FALSE;
|
||||
#endif
|
||||
|
||||
return LL_SUCCESS;
|
||||
}
|
||||
|
@ -471,23 +542,23 @@ uint8_t LctrGenerateDhKey(const uint8_t *pPubKey, const uint8_t *pPrivKey)
|
|||
uint8_t LctrGenerateDebugDhKey()
|
||||
{
|
||||
const uint8_t privKey[LL_ECC_KEY_LEN] = {
|
||||
0xbd, 0x1a, 0x3c, 0xcd, 0xa6, 0xb8, 0x99, 0x58,
|
||||
0x99, 0xb7, 0x40, 0xeb, 0x7b, 0x60, 0xff, 0x4a,
|
||||
0x50, 0x3f, 0x10, 0xd2, 0xe3, 0xb3, 0xc9, 0x74,
|
||||
0x38, 0x5f, 0xc5, 0xa3, 0xd4, 0xf6, 0x49, 0x3f
|
||||
0xbd, 0x1a, 0x3c, 0xcd, 0xa6, 0xb8, 0x99, 0x58,
|
||||
0x99, 0xb7, 0x40, 0xeb, 0x7b, 0x60, 0xff, 0x4a,
|
||||
0x50, 0x3f, 0x10, 0xd2, 0xe3, 0xb3, 0xc9, 0x74,
|
||||
0x38, 0x5f, 0xc5, 0xa3, 0xd4, 0xf6, 0x49, 0x3f
|
||||
};
|
||||
|
||||
const uint8_t pubKey[LL_ECC_KEY_LEN * 2] = {
|
||||
/* pubDebugKey_x */
|
||||
0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
|
||||
0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
|
||||
0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
|
||||
0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20,
|
||||
/* pubDebuKey_y */
|
||||
0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74,
|
||||
0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
|
||||
0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63,
|
||||
0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc
|
||||
/* pubDebugKey_x */
|
||||
0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
|
||||
0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
|
||||
0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
|
||||
0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20,
|
||||
/* pubDebuKey_y */
|
||||
0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74,
|
||||
0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
|
||||
0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63,
|
||||
0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc
|
||||
};
|
||||
|
||||
/* Allow only one key pair generation at a time. */
|
||||
|
@ -529,8 +600,10 @@ uint8_t LctrSetValidatePublicKeyMode(uint8_t validateMode)
|
|||
/*************************************************************************************************/
|
||||
void LctrScInit(void)
|
||||
{
|
||||
#if ENABLE_UECC
|
||||
lctrEventHdlrTbl[LCTR_EVENT_SC_GENERATE_P256_KEY_PAIR] = lctrScGenerateP256KeyPairContinue;
|
||||
lctrEventHdlrTbl[LCTR_EVENT_SC_GENERATE_DHKEY] = lctrScGenerateDhKeyContinue;
|
||||
#endif
|
||||
|
||||
lmgrPersistCb.featuresDefault |= LL_FEAT_REMOTE_PUB_KEY_VALIDATION;
|
||||
lmgrScCb.validatePubKeyMode = KEY_VALIDATE_MODE_ALT2;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -36,4 +36,6 @@ void LctrSlvPhyConnInit(void)
|
|||
{
|
||||
/* Add LLCP SM handler. */
|
||||
lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD] = lctrSlvLlcpExecutePhyUpdateSm;
|
||||
|
||||
lctrSlvCheckEncOverridePhyUpdateFn = lctrSlvCheckEncOverridePhyUpdate;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#include "ll_api.h"
|
||||
#include "lctr_pdu_adv_ae.h"
|
||||
#include "lctr_pdu_adv.h"
|
||||
#include "lctr_int_adv_slave.h"
|
||||
|
@ -190,11 +191,13 @@ static uint8_t lctrPackExtAdvHeader(lctrAdvSet_t *pAdvSet, uint8_t manExtHdrFlag
|
|||
}
|
||||
|
||||
if ((manExtHdrFlags & LL_EXT_HDR_ADI_BIT) ||
|
||||
((optExtHdrFlags & LL_EXT_HDR_ADI_BIT) && (!(pAdvSet->extHdrFlags & LL_EXT_HDR_ADI_BIT))))
|
||||
((optExtHdrFlags & LL_EXT_HDR_ADI_BIT) &&
|
||||
(!(pAdvSet->extHdrFlags & LL_EXT_HDR_ADI_BIT) || (isPeriodic && pAdvSet->perParam.enableAdi))))
|
||||
{
|
||||
/* Pack AdvDataInfo */
|
||||
extHdrFlags |= LL_EXT_HDR_ADI_BIT;
|
||||
UINT16_TO_BSTREAM(pBuf, (pAdvSet->param.advSID << 12) | ((pAdvSet->param.advDID & 0x0FFF) << 0));
|
||||
uint8_t did = isPeriodic ? pAdvSet->perParam.advDID : pAdvSet->param.advDID;
|
||||
UINT16_TO_BSTREAM(pBuf, (pAdvSet->param.advSID << 12) | ((did & 0x0FFF) << 0));
|
||||
|
||||
#if (LL_ENABLE_TESTER == TRUE)
|
||||
if ((llTesterCb.extHdr.pduMatchMask & (1 << pPduHdr->pduType)) &&
|
||||
|
@ -610,6 +613,7 @@ uint8_t lctrPackAuxAdvIndPdu(lctrAdvSet_t *pAdvSet, uint8_t *pPduBuf, lctrAdvDat
|
|||
}
|
||||
|
||||
/*** Host allowed options ***/
|
||||
|
||||
lctrChooseSetAdvA(&pduHdr, pBle, pAdvSet);
|
||||
lctrChooseSetPeerA(&pduHdr, pBle, pAdvSet);
|
||||
|
||||
|
@ -744,6 +748,11 @@ void lctrPackAuxPtr(lctrAdvSet_t const *pAdvSet, uint32_t offsUsec, uint8_t chId
|
|||
auxOffset = LL_MATH_DIV_300(offsUsec);
|
||||
}
|
||||
|
||||
if (auxOffset > LCTR_AUX_PTR_MAX_OFFSET)
|
||||
{
|
||||
LL_TRACE_ERR1("AUX Offset exceeds max allowed value: %u", auxOffset);
|
||||
}
|
||||
|
||||
pAuxPtr[0] = chIdx | /* LL Channel */
|
||||
(ca << 6) | /* CA */
|
||||
(offsUnits << 7); /* Offset Units */
|
||||
|
@ -932,6 +941,7 @@ uint8_t lctrPackSyncIndPdu(lctrAdvSet_t *pAdvSet, uint8_t *pPduBuf, lctrAdvDataB
|
|||
|
||||
uint8_t manExtHdrFlags = 0;
|
||||
uint8_t optExtHdrFlags = LL_EXT_HDR_AUX_PTR_BIT |
|
||||
((lmgrCb.features & LL_FEAT_PER_ADV_ADI_SUP) ? LL_EXT_HDR_ADI_BIT : 0) |
|
||||
((pAdvSet->perParam.advEventProp & LL_EXT_HDR_TX_PWR_BIT) ? LL_EXT_HDR_TX_PWR_BIT : 0);
|
||||
|
||||
return lctrPackExtAdvHeader(pAdvSet, manExtHdrFlags, optExtHdrFlags,
|
||||
|
|
|
@ -129,6 +129,57 @@ static inline bool_t lctrIsSetMinUsedChanParamValid(lctrMinUsedChanInd_t *pParam
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Check whether the subrate request parameters are valid.
|
||||
*
|
||||
* \param pParam Subrate request parameter.
|
||||
*
|
||||
* \return TRUE if parameters are valid, FALSE otherwise.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static inline bool_t lctrIsSubrateReqParamValid(lctrSubrateReq_t *pParam)
|
||||
{
|
||||
if ((pParam->srMin < LCTR_MIN_SUBRATE) ||
|
||||
(pParam->srMin > LCTR_MAX_SUBRATE) ||
|
||||
(pParam->srMax < LCTR_MIN_SUBRATE) ||
|
||||
(pParam->srMax > LCTR_MAX_SUBRATE) ||
|
||||
(pParam->srMin > pParam->srMax) ||
|
||||
(pParam->maxLatency > (LCTR_MAX_SUBRATE - 1)) ||
|
||||
(pParam->contNum > (LCTR_MAX_SUBRATE - 1)) ||
|
||||
(pParam->svt < LL_MIN_SUP_TIMEOUT) ||
|
||||
(pParam->svt > LL_MAX_SUP_TIMEOUT))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Check whether the subrate indication parameters are valid.
|
||||
*
|
||||
* \param pParam Subrate indication parameter.
|
||||
*
|
||||
* \return TRUE if parameters are valid, FALSE otherwise.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static inline bool_t lctrIsSubrateIndParamValid(lctrSubrateInd_t *pParam)
|
||||
{
|
||||
if ((pParam->srFactor < LCTR_MIN_SUBRATE) ||
|
||||
(pParam->srFactor > LCTR_MAX_SUBRATE) ||
|
||||
(pParam->latency > (LCTR_MAX_SUBRATE - 1)) ||
|
||||
(pParam->contNum > (LCTR_MAX_SUBRATE - 1)) ||
|
||||
(pParam->svt < LL_MIN_SUP_TIMEOUT) ||
|
||||
(pParam->svt > LL_MAX_SUP_TIMEOUT))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Pack an ACL header.
|
||||
|
@ -745,7 +796,7 @@ uint8_t lctrUnpackCisTermPdu(lctrCisTermInd_t *pPdu, const uint8_t *pBuf)
|
|||
/*************************************************************************************************/
|
||||
static uint8_t lctrUnpackPwrChngIndPdu(lctrPwrChngInd_t *pPdu, const uint8_t *pBuf)
|
||||
{
|
||||
const uint8_t len = LL_PWR_CHNG_IND_LEN;
|
||||
const uint8_t len = LL_PWR_CHANGE_IND_LEN;
|
||||
|
||||
pBuf += 1; /* skip opcode */
|
||||
BSTREAM_TO_UINT8 (pPdu->phy, pBuf);
|
||||
|
@ -800,6 +851,103 @@ static uint8_t lctrUnpackPwrCtrlRspPdu(lctrPwrCtrlRsp_t *pPdu, const uint8_t *pB
|
|||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Unpack a subrate request PDU.
|
||||
*
|
||||
* \param pPdu Subrate request PDU.
|
||||
* \param pBuf Packed packet buffer.
|
||||
*
|
||||
* \return PDU length.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t lctrUnpackSubrateReqPdu(lctrSubrateReq_t *pPdu, const uint8_t *pBuf)
|
||||
{
|
||||
const uint8_t len = LL_SUBRATE_REQ_LEN;
|
||||
|
||||
pBuf += 1; /* skip opcode */
|
||||
BSTREAM_TO_UINT16(pPdu->srMin, pBuf);
|
||||
BSTREAM_TO_UINT16(pPdu->srMax, pBuf);
|
||||
BSTREAM_TO_UINT16(pPdu->maxLatency, pBuf);
|
||||
BSTREAM_TO_UINT16(pPdu->contNum, pBuf);
|
||||
BSTREAM_TO_UINT16(pPdu->svt, pBuf);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Unpack a subrate indication PDU.
|
||||
*
|
||||
* \param pPdu Subrate indication PDU.
|
||||
* \param pBuf Packed packet buffer.
|
||||
*
|
||||
* \return PDU length.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t lctrUnpackSubrateIndPdu(lctrSubrateInd_t *pPdu, const uint8_t *pBuf)
|
||||
{
|
||||
const uint8_t len = LL_SUBRATE_IND_LEN;
|
||||
|
||||
pBuf += 1; /* skip opcode */
|
||||
BSTREAM_TO_UINT16(pPdu->srFactor, pBuf);
|
||||
BSTREAM_TO_UINT16(pPdu->srBaseEvent, pBuf);
|
||||
BSTREAM_TO_UINT16(pPdu->latency, pBuf);
|
||||
BSTREAM_TO_UINT16(pPdu->contNum, pBuf);
|
||||
BSTREAM_TO_UINT16(pPdu->svt, pBuf);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Unpack a channel reporting indication pdu
|
||||
*
|
||||
* \param pPdu Channel reporting indication PDU.
|
||||
* \param pBuf Packed packet buffer.
|
||||
*
|
||||
* \return PDU length.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t lctrUnpackChanRptIndPdu(lctrChanRptInd_t *pPdu, const uint8_t *pBuf)
|
||||
{
|
||||
const uint8_t len = LL_CH_REPORTING_LEN;
|
||||
|
||||
pBuf += 1; /* skip opcode */
|
||||
BSTREAM_TO_UINT8 (pPdu->enable, pBuf);
|
||||
BSTREAM_TO_UINT8 (pPdu->minSpacing, pBuf);
|
||||
BSTREAM_TO_UINT8 (pPdu->maxDelay, pBuf);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Unpack a channel status indication pdu
|
||||
*
|
||||
* \param pPdu Channel status indication PDU.
|
||||
* \param pBuf Packed packet buffer.
|
||||
*
|
||||
* \return PDU length.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t lctrUnpackChanStatusIndPdu(lctrChanStatusInd_t *pPdu, const uint8_t *pBuf)
|
||||
{
|
||||
const uint8_t len = LL_CH_STATUS_LEN;
|
||||
|
||||
uint8_t i = 0;
|
||||
|
||||
pBuf += 1; /* skip opcode */
|
||||
for (i = 0; i < (LL_CH_STATUS_LEN - 1); i++)
|
||||
{
|
||||
/* Leave channel status map packed, unpack as needed. */
|
||||
BSTREAM_TO_UINT8 (pPdu->chanStatusMap[i], pBuf);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Decode an LE-C channel buffer.
|
||||
|
@ -1051,7 +1199,7 @@ uint8_t lctrDecodeCtrlPdu(lctrDataPdu_t *pPdu, const uint8_t *pBuf, uint8_t role
|
|||
return LL_ERROR_CODE_UNKNOWN_LMP_PDU;
|
||||
}
|
||||
break;
|
||||
case LL_PDU_PWR_CHNG_IND:
|
||||
case LL_PDU_PWR_CHANGE_IND:
|
||||
if ((lmgrCb.features & LL_FEAT_POWER_CHANGE_IND) == 0)
|
||||
{
|
||||
return LL_ERROR_CODE_UNKNOWN_LMP_PDU;
|
||||
|
@ -1081,6 +1229,54 @@ uint8_t lctrDecodeCtrlPdu(lctrDataPdu_t *pPdu, const uint8_t *pBuf, uint8_t role
|
|||
return LL_ERROR_CODE_UNKNOWN_LMP_PDU;
|
||||
}
|
||||
break;
|
||||
case LL_PDU_SUBRATE_REQ:
|
||||
if ((lmgrCb.features & LL_FEAT_CONN_SUBRATE) == 0)
|
||||
{
|
||||
return LL_ERROR_CODE_UNKNOWN_LMP_PDU;
|
||||
}
|
||||
if (lctrUnpackSubrateReqPdu(&pPdu->pld.subrateReq, pBuf) != pPdu->hdr.len)
|
||||
{
|
||||
return LL_ERROR_CODE_UNKNOWN_LMP_PDU;
|
||||
}
|
||||
if (lctrIsSubrateReqParamValid(&pPdu->pld.subrateReq) == FALSE)
|
||||
{
|
||||
return LL_ERROR_CODE_INVALID_LMP_PARAMS;
|
||||
}
|
||||
break;
|
||||
case LL_PDU_SUBRATE_IND:
|
||||
if ((lmgrCb.features & LL_FEAT_CONN_SUBRATE) == 0)
|
||||
{
|
||||
return LL_ERROR_CODE_UNKNOWN_LMP_PDU;
|
||||
}
|
||||
if (lctrUnpackSubrateIndPdu(&pPdu->pld.subrateInd, pBuf) != pPdu->hdr.len)
|
||||
{
|
||||
return LL_ERROR_CODE_UNKNOWN_LMP_PDU;
|
||||
}
|
||||
if (lctrIsSubrateIndParamValid(&pPdu->pld.subrateInd) == FALSE)
|
||||
{
|
||||
return LL_ERROR_CODE_INVALID_LMP_PARAMS;
|
||||
}
|
||||
break;
|
||||
case LL_PDU_CH_REPORTING_IND:
|
||||
if ((lmgrCb.features & LL_FEAT_CHANNEL_CLASSIFICATION) == 0)
|
||||
{
|
||||
return LL_ERROR_CODE_UNKNOWN_LMP_PDU;
|
||||
}
|
||||
if (lctrUnpackChanRptIndPdu(&pPdu->pld.chanRptInd, pBuf) != pPdu->hdr.len)
|
||||
{
|
||||
return LL_ERROR_CODE_UNKNOWN_LMP_PDU;
|
||||
}
|
||||
break;
|
||||
case LL_PDU_CH_STATUS_IND:
|
||||
if ((lmgrCb.features & LL_FEAT_CHANNEL_CLASSIFICATION) == 0)
|
||||
{
|
||||
return LL_ERROR_CODE_UNKNOWN_LMP_PDU;
|
||||
}
|
||||
if (lctrUnpackChanStatusIndPdu(&pPdu->pld.chanStatusInd, pBuf) != pPdu->hdr.len)
|
||||
{
|
||||
return LL_ERROR_CODE_UNKNOWN_LMP_PDU;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
result = LL_ERROR_CODE_UNKNOWN_LMP_PDU;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -154,32 +154,32 @@ typedef struct
|
|||
/*! \brief Data length request or response PDU. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t maxRxLen; /*!< Maximum receive length. */
|
||||
uint16_t maxRxTime; /*!< Maximum receive time. */
|
||||
uint16_t maxTxLen; /*!< Maximum transmit length. */
|
||||
uint16_t maxTxTime; /*!< Maximum transmit time. */
|
||||
uint16_t maxRxLen; /*!< Maximum receive length. */
|
||||
uint16_t maxRxTime; /*!< Maximum receive time. */
|
||||
uint16_t maxTxLen; /*!< Maximum transmit length. */
|
||||
uint16_t maxTxTime; /*!< Maximum transmit time. */
|
||||
} lctrDataLen_t;
|
||||
|
||||
/*! \brief PHY request or response PDU. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t txPhys; /*!< Transmitter PHYs. */
|
||||
uint8_t rxPhys; /*!< Receiver PHYs. */
|
||||
uint8_t txPhys; /*!< Transmitter PHYs. */
|
||||
uint8_t rxPhys; /*!< Receiver PHYs. */
|
||||
} lctrPhy_t;
|
||||
|
||||
/*! \brief PHY update indication PDU. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t masterToSlavePhy; /*!< Master-to-slave PHY. */
|
||||
uint8_t slaveToMasterPhy; /*!< Slave-to-master PHY. */
|
||||
uint16_t instant; /*!< Instant. */
|
||||
uint8_t masterToSlavePhy; /*!< Master-to-slave PHY. */
|
||||
uint8_t slaveToMasterPhy; /*!< Slave-to-master PHY. */
|
||||
uint16_t instant; /*!< Instant. */
|
||||
} lctrPhyUpdInd_t;
|
||||
|
||||
/*! \brief Minimum number of used channels indication PDU. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t phys; /*!< Bitmask for the affected PHYs. */
|
||||
uint8_t minUsedChan; /*!< Minimum number of used channels. */
|
||||
uint8_t phys; /*!< Bitmask for the affected PHYs. */
|
||||
uint8_t minUsedChan; /*!< Minimum number of used channels. */
|
||||
} lctrMinUsedChanInd_t;
|
||||
|
||||
/*! \brief Periodic sync indication PDU. */
|
||||
|
@ -200,61 +200,81 @@ typedef struct
|
|||
/*! \brief Peer SCA response PDU. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t sca; /*!< Peer SCA. */
|
||||
uint8_t sca; /*!< Peer SCA. */
|
||||
} lctrPeerSca_t;
|
||||
|
||||
/*! \brief CIS request PDU. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t cigId; /*!< CIG identifier. */
|
||||
uint8_t cisId; /*!< CIS identifier. */
|
||||
uint8_t phyMToS; /*!< Master to slave PHY. */
|
||||
uint8_t phySToM; /*!< Slave to Master PHY. */
|
||||
uint8_t framing; /*!< PDU framing type. */
|
||||
uint16_t sduSizeMToS; /*!< Maximum SDU size from the master Host. */
|
||||
uint16_t sduSizeSToM; /*!< Maximum SDU size from the slave Host. */
|
||||
uint32_t sduIntervalMToS; /*!< Time interval between the start of consecutive SDUs from the master Host */
|
||||
uint32_t sduIntervalSToM; /*!< Time interval between the start of consecutive SDUs from the master Host */
|
||||
uint16_t plMToS; /*!< Master to slave payload. */
|
||||
uint16_t plSToM; /*!< Slave to master payload. */
|
||||
uint8_t nse; /*!< Number of subevent. */
|
||||
uint32_t subIntervUsec; /*!< Contain the time between the start of a subevent and the start of the next subevent, 24 significant bits. */
|
||||
uint8_t bnMToS; /*!< Master to slave burst number, 4 significant bits. */
|
||||
uint8_t bnSToM; /*!< Slave to master burst number, 4 significant bits. */
|
||||
uint8_t ftMToS; /*!< Master to slave flush time. */
|
||||
uint8_t ftSToM; /*!< Slave to master flush time. */
|
||||
uint16_t isoInterval; /*!< Contain the time between two CIS anchor points in 1.25msec unit. */
|
||||
uint32_t cisOffMinUsec; /*!< Contain the minimum time between the CE and the first CIS anchor point. */
|
||||
uint32_t cisOffMaxUsec; /*!< Contain the maximum time between the CE and the first CIS anchor point. */
|
||||
uint16_t ceRef; /*!< Contain the reference CE where offsets are applied. */
|
||||
uint8_t cigId; /*!< CIG identifier. */
|
||||
uint8_t cisId; /*!< CIS identifier. */
|
||||
uint8_t phyMToS; /*!< Master to slave PHY. */
|
||||
uint8_t phySToM; /*!< Slave to Master PHY. */
|
||||
uint8_t framing; /*!< PDU framing type. */
|
||||
uint16_t sduSizeMToS; /*!< Maximum SDU size from the master Host. */
|
||||
uint16_t sduSizeSToM; /*!< Maximum SDU size from the slave Host. */
|
||||
uint32_t sduIntervalMToS; /*!< Time interval between the start of consecutive SDUs from the master Host */
|
||||
uint32_t sduIntervalSToM; /*!< Time interval between the start of consecutive SDUs from the master Host */
|
||||
uint16_t plMToS; /*!< Master to slave payload. */
|
||||
uint16_t plSToM; /*!< Slave to master payload. */
|
||||
uint8_t nse; /*!< Number of subevent. */
|
||||
uint32_t subIntervUsec; /*!< Contain the time between the start of a subevent and the start of the next subevent, 24 significant bits. */
|
||||
uint8_t bnMToS; /*!< Master to slave burst number, 4 significant bits. */
|
||||
uint8_t bnSToM; /*!< Slave to master burst number, 4 significant bits. */
|
||||
uint8_t ftMToS; /*!< Master to slave flush time. */
|
||||
uint8_t ftSToM; /*!< Slave to master flush time. */
|
||||
uint16_t isoInterval; /*!< Contain the time between two CIS anchor points in 1.25msec unit. */
|
||||
uint32_t cisOffMinUsec; /*!< Contain the minimum time between the CE and the first CIS anchor point. */
|
||||
uint32_t cisOffMaxUsec; /*!< Contain the maximum time between the CE and the first CIS anchor point. */
|
||||
uint16_t ceRef; /*!< Contain the reference CE where offsets are applied. */
|
||||
} lctrCisReq_t;
|
||||
|
||||
/*! \brief CIS response PDU. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t cisOffMinUsec; /*!< Contain the minimum time between the CE and the first CIS anchor point. */
|
||||
uint32_t cisOffMaxUsec; /*!< Contain the maximum time between the CE and the first CIS anchor point. */
|
||||
uint16_t ceRef; /*!< Contain the reference CE where offsets are applied. */
|
||||
uint32_t cisOffMinUsec; /*!< Contain the minimum time between the CE and the first CIS anchor point. */
|
||||
uint32_t cisOffMaxUsec; /*!< Contain the maximum time between the CE and the first CIS anchor point. */
|
||||
uint16_t ceRef; /*!< Contain the reference CE where offsets are applied. */
|
||||
} lctrCisRsp_t;
|
||||
|
||||
/*! \brief CIS indication PDU. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t accessAddr; /*!< Contain the access address of the CIS. */
|
||||
uint32_t cisOffUsec; /*!< Contain the time from the start of the referenced CE to the first CIS anchor point. */
|
||||
uint32_t cigSyncDelayUsec; /*!< CIG synchronization delay in usec. */
|
||||
uint32_t cisSyncDelayUsec; /*!< CIG synchronization delay in usec. */
|
||||
uint16_t ceRef; /*!< Contain the reference CE where offsets are applied. */
|
||||
uint32_t accessAddr; /*!< Contain the access address of the CIS. */
|
||||
uint32_t cisOffUsec; /*!< Contain the time from the start of the referenced CE to the first CIS anchor point. */
|
||||
uint32_t cigSyncDelayUsec; /*!< CIG synchronization delay in usec. */
|
||||
uint32_t cisSyncDelayUsec; /*!< CIG synchronization delay in usec. */
|
||||
uint16_t ceRef; /*!< Contain the reference CE where offsets are applied. */
|
||||
} lctrCisInd_t;
|
||||
|
||||
/*! \brief CIS terminate PDU. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t cigId; /*!< CIG identifier. */
|
||||
uint8_t cisId; /*!< CIS identifier. */
|
||||
uint8_t reason; /*!< Reason for termination. */
|
||||
uint8_t cigId; /*!< CIG identifier. */
|
||||
uint8_t cisId; /*!< CIS identifier. */
|
||||
uint8_t reason; /*!< Reason for termination. */
|
||||
} lctrCisTermInd_t;
|
||||
|
||||
/*! \brief Subrate request PDU. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t srMin; /*!< Subrate minimum value. */
|
||||
uint16_t srMax; /*!< Subrate maximum value. */
|
||||
uint16_t maxLatency; /*!< Maximum latency. */
|
||||
uint16_t contNum; /*!< Continuation number. */
|
||||
uint16_t svt; /*!< Supervision timeout in 10ms units. */
|
||||
} lctrSubrateReq_t;
|
||||
|
||||
/*! \brief Subrate indication PDU. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t srFactor; /*!< Subrate factor. */
|
||||
uint16_t srBaseEvent; /*!< Subrate base event. */
|
||||
uint16_t latency; /*!< Latency. */
|
||||
uint16_t contNum; /*!< Continuation number. */
|
||||
uint16_t svt; /*!< Supervision timeout in 10ms units. */
|
||||
} lctrSubrateInd_t;
|
||||
|
||||
/*! \brief Power control request PDU. */
|
||||
typedef struct
|
||||
{
|
||||
|
@ -281,6 +301,21 @@ typedef struct
|
|||
int8_t txPower; /*!< Local txPower. */
|
||||
} lctrPwrChngInd_t;
|
||||
|
||||
/*! \brief Channel reporting indication PDU. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t enable; /*!< Enable. */
|
||||
uint8_t minSpacing; /*!< Minimum spacing. */
|
||||
uint8_t maxDelay; /*!< Maximum delay. */
|
||||
} lctrChanRptInd_t;
|
||||
|
||||
/*! \brief Channel status indication PDU. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t chanStatusMap[LL_CH_STATUS_LEN - 1];
|
||||
/*!< Map of current peer channel status. */
|
||||
} lctrChanStatusInd_t;
|
||||
|
||||
/*! \brief Data channel control PDU. */
|
||||
typedef struct
|
||||
{
|
||||
|
@ -314,6 +349,11 @@ typedef struct
|
|||
lctrPwrCtrlReq_t pwrCtrlReq; /*!< Power control request. */
|
||||
lctrPwrCtrlRsp_t pwrCtrlRsp; /*!< Power control response. */
|
||||
lctrPwrChngInd_t pwrChngInd; /*!< Power change indication. */
|
||||
lctrChanRptInd_t chanRptInd; /*!< Channel report indication. */
|
||||
lctrChanStatusInd_t chanStatusInd;
|
||||
/*!< Channel status indication. */
|
||||
lctrSubrateReq_t subrateReq; /*!< Subrate request. */
|
||||
lctrSubrateInd_t subrateInd; /*!< Subrate indication. */
|
||||
} pld; /*!< Unpacked PDU payload. */
|
||||
} lctrDataPdu_t;
|
||||
|
||||
|
|
|
@ -37,9 +37,9 @@
|
|||
* \return Header length.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t lctrIsoUnpackHdr(lctrIsoHdr_t *pHdr, const uint8_t *pBuf)
|
||||
uint8_t lctrIsoUnpackHdr(lctrIsoHdr_t *pHdr, uint8_t *pBuf)
|
||||
{
|
||||
uint8_t len = HCI_ISO_HDR_LEN + HCI_ISO_DL_MIN_LEN;
|
||||
uint8_t len = HCI_ISO_HDR_LEN;
|
||||
|
||||
uint16_t field16;
|
||||
|
||||
|
@ -50,21 +50,34 @@ uint8_t lctrIsoUnpackHdr(lctrIsoHdr_t *pHdr, const uint8_t *pBuf)
|
|||
|
||||
BSTREAM_TO_UINT16(pHdr->len, pBuf);
|
||||
|
||||
if (pHdr->tsFlag)
|
||||
switch (pHdr->pb)
|
||||
{
|
||||
BSTREAM_TO_UINT32(pHdr->ts, pBuf);
|
||||
len += HCI_ISO_TS_LEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
pHdr->ts = 0;
|
||||
}
|
||||
case LCTR_PB_COMP:
|
||||
case LCTR_PB_FIRST:
|
||||
len += HCI_ISO_DL_MIN_LEN;
|
||||
if (pHdr->tsFlag)
|
||||
{
|
||||
BSTREAM_TO_UINT32(pHdr->ts, pBuf);
|
||||
len += HCI_ISO_TS_LEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
pHdr->ts = 0;
|
||||
}
|
||||
|
||||
BSTREAM_TO_UINT16(pHdr->pktSn, pBuf);
|
||||
BSTREAM_TO_UINT16(field16, pBuf);
|
||||
BSTREAM_TO_UINT16(pHdr->pktSn, pBuf);
|
||||
BSTREAM_TO_UINT16(field16, pBuf);
|
||||
|
||||
pHdr->sduLen = (field16 >> 0) & 0x0FFF;
|
||||
pHdr->ps = (field16 >> 14) & 0x03;
|
||||
pHdr->sduLen = (field16 >> 0) & 0x0FFF;
|
||||
pHdr->ps = (field16 >> 14) & 0x03;
|
||||
break;
|
||||
|
||||
default:
|
||||
pHdr->ts = 0;
|
||||
pHdr->sduLen = 0;
|
||||
pHdr->ps = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
pHdr->pSdu = pBuf;
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ typedef struct
|
|||
uint16_t pktSn; /*!< Packet sequence number. */
|
||||
uint16_t sduLen; /*!< SDU length. */
|
||||
lctrPktStatus_t ps:8; /*!< Packet status. */
|
||||
const uint8_t *pSdu; /*!< First byte of ISO SDU. */
|
||||
uint8_t *pSdu; /*!< First byte of ISO SDU. */
|
||||
} lctrIsoHdr_t;
|
||||
|
||||
/*! \brief ISO SDU descriptor. */
|
||||
|
@ -136,7 +136,7 @@ uint8_t lctrBisPackBigChannelMapInd(uint8_t *pBuf, uint64_t chanMap, uint16_t in
|
|||
uint8_t lctrBisPackBigTerminateInd(uint8_t *pBuf, uint8_t reason, uint16_t instance);
|
||||
|
||||
/* Unpack */
|
||||
uint8_t lctrIsoUnpackHdr(lctrIsoHdr_t *pHdr, const uint8_t *pBuf);
|
||||
uint8_t lctrIsoUnpackHdr(lctrIsoHdr_t *pHdr, uint8_t *pBuf);
|
||||
uint8_t lctrCisUnpackDataPduHdr(lctrCisDataPduHdr_t *pHdr, const uint8_t *pBuf);
|
||||
uint8_t lctrBisUnpackDataPduHdr(lctrBisDataPduHdr_t *pHdr, const uint8_t *pBuf);
|
||||
uint8_t lctrBisUnpackBigChannelMapInd(uint64_t *pChanMap, uint16_t *pInstance, const uint8_t *pBuf);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -60,6 +60,7 @@ static uint8_t lctrRemapEvent(lctrCisCtx_t *pCisCtx, uint8_t event)
|
|||
|
||||
case LCTR_CONN_MSG_API_DISCONNECT:
|
||||
{
|
||||
pCisCtx->hostInitTerm = TRUE;
|
||||
lctrCisStoreDisconnectReason(pCisCtx);
|
||||
return LCTR_CIS_MSG_CIS_DISC;
|
||||
}
|
||||
|
|
|
@ -249,7 +249,12 @@ bool_t lctrMstLlcpExecuteCisEstSm(lctrConnCtx_t *pCtx, uint8_t event)
|
|||
}
|
||||
|
||||
lctrCisCtx_t *pCisCtx = lctrFindCisByHandle(pCtx->llcpCisHandle);
|
||||
WSF_ASSERT(pCisCtx != NULL)
|
||||
if (pCisCtx == NULL)
|
||||
{
|
||||
LL_TRACE_WARN1("lctrMstLlcpExecuteCisEstSm: CIS context not found cis_handle=%u", pCtx->llcpCisHandle);
|
||||
/* TRUE to prevent further processing of this message. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
switch (pCtx->llcpState)
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -38,6 +38,7 @@
|
|||
|
||||
#include "lctr_int_conn.h"
|
||||
#include "lctr_int_conn_slave.h"
|
||||
#include "ll_init_api.h"
|
||||
#include "lmgr_api.h"
|
||||
#include "util/bstream.h"
|
||||
#include "wsf_trace.h"
|
||||
|
@ -142,6 +143,24 @@ const lctrLlcpEh_t lctrCmnProcTbl[LCTR_PROC_CMN_TOTAL][LCTR_PROC_CMN_ACT_TOTAL]
|
|||
lctrStorePeerSca, /* LCTR_PROC_CMN_ACT_RECV_REQ */
|
||||
lctrSendPeerScaRsp, /* LCTR_PROC_CMN_ACT_SEND_RSP */
|
||||
lctrStorePeerSca, /* LCTR_PROC_CMN_ACT_RECV_RSP */
|
||||
},
|
||||
/* LCTR_PROC_CMN_CH_CLASS_REPORTING */
|
||||
{
|
||||
NULL, /* LCTR_PROC_CMN_ACT_API_PARAM */
|
||||
lctrSendChannelReportingInd,
|
||||
/* LCTR_PROC_CMN_ACT_SEND_REQ */
|
||||
lctrStoreChannelReportingInd,
|
||||
/* LCTR_PROC_CMN_ACT_RECV_REQ */
|
||||
NULL, /* LCTR_PROC_CMN_ACT_SEND_RSP */
|
||||
NULL /* LCTR_PROC_CMN_ACT_RECV_RSP */
|
||||
},
|
||||
/* LCTR_PROC_CMN_CH_STATUS_REPORT */
|
||||
{
|
||||
NULL, /* LCTR_PROC_CMN_ACT_API_PARAM */
|
||||
lctrSendChannelStatusInd, /* LCTR_PROC_CMN_ACT_SEND_REQ */
|
||||
lctrStoreChannelStatusInd, /* LCTR_PROC_CMN_ACT_RECV_REQ */
|
||||
NULL, /* LCTR_PROC_CMN_ACT_SEND_RSP */
|
||||
NULL /* LCTR_PROC_CMN_ACT_RECV_RSP */
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -270,6 +289,12 @@ static uint8_t lctrGetCmnProcId(lctrConnCtx_t *pCtx, uint8_t event)
|
|||
case LCTR_CONN_LLCP_LENGTH_EXCH:
|
||||
return LCTR_PROC_CMN_DATA_LEN_UPD;
|
||||
|
||||
case LCTR_CONN_LLCP_CHANNEL_STATUS:
|
||||
return LCTR_PROC_CMN_CH_STATUS_REPORT;
|
||||
|
||||
case LCTR_CONN_LLCP_CHANNEL_REPORTING:
|
||||
return LCTR_PROC_CMN_CH_CLASS_REPORTING;
|
||||
|
||||
case LCTR_CONN_LLCP_PROC_CMPL:
|
||||
return pCtx->llcpActiveProc;
|
||||
|
||||
|
@ -304,6 +329,12 @@ static uint8_t lctrGetCmnProcId(lctrConnCtx_t *pCtx, uint8_t event)
|
|||
case LL_PDU_PEER_SCA_RSP:
|
||||
return LCTR_PROC_CMN_REQ_PEER_SCA;
|
||||
|
||||
case LL_PDU_CH_REPORTING_IND:
|
||||
return LCTR_PROC_CMN_CH_CLASS_REPORTING;
|
||||
|
||||
case LL_PDU_CH_STATUS_IND:
|
||||
return LCTR_PROC_CMN_CH_STATUS_REPORT;
|
||||
|
||||
case LL_PDU_UNKNOWN_RSP:
|
||||
switch (lctrDataPdu.pld.unknownRsp.unknownType)
|
||||
{
|
||||
|
@ -325,6 +356,19 @@ static uint8_t lctrGetCmnProcId(lctrConnCtx_t *pCtx, uint8_t event)
|
|||
case LL_PDU_LENGTH_RSP:
|
||||
return LCTR_PROC_CMN_DATA_LEN_UPD;
|
||||
|
||||
case LL_PDU_PWR_CHANGE_IND:
|
||||
return LCTR_PROC_PWR_IND;
|
||||
|
||||
case LL_PDU_PWR_CTRL_RSP:
|
||||
case LL_PDU_PWR_CTRL_REQ:
|
||||
return LCTR_PROC_PWR_CTRL;
|
||||
|
||||
case LL_PDU_CH_REPORTING_IND:
|
||||
return LCTR_PROC_CMN_CH_CLASS_REPORTING;
|
||||
|
||||
case LL_PDU_CH_STATUS_IND:
|
||||
return LCTR_PROC_CMN_CH_STATUS_REPORT;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -381,6 +425,8 @@ static uint8_t lctrRemapCmnProcEvent(lctrConnCtx_t *pCtx, uint8_t event)
|
|||
case LCTR_CONN_LLCP_VERSION_EXCH:
|
||||
case LCTR_CONN_LLCP_LENGTH_EXCH:
|
||||
case LCTR_CONN_LLCP_TERM:
|
||||
case LCTR_CONN_LLCP_CHANNEL_STATUS:
|
||||
case LCTR_CONN_LLCP_CHANNEL_REPORTING:
|
||||
return LCTR_PROC_CMN_EVT_INT_START;
|
||||
|
||||
case LCTR_CONN_LLCP_PROC_CMPL:
|
||||
|
@ -397,6 +443,8 @@ static uint8_t lctrRemapCmnProcEvent(lctrConnCtx_t *pCtx, uint8_t event)
|
|||
case LL_PDU_SLV_FEATURE_REQ:
|
||||
case LL_PDU_LENGTH_REQ:
|
||||
case LL_PDU_PEER_SCA_REQ:
|
||||
case LL_PDU_CH_REPORTING_IND:
|
||||
case LL_PDU_CH_STATUS_IND:
|
||||
return LCTR_PROC_CMN_EVT_RECV_REQ;
|
||||
|
||||
case LL_PDU_TERMINATE_IND:
|
||||
|
@ -541,6 +589,14 @@ static bool_t lctrFeatureAvail(lctrConnCtx_t *pCtx, uint8_t proc, uint8_t event)
|
|||
result = FALSE;
|
||||
}
|
||||
break;
|
||||
case LCTR_PROC_CMN_CH_CLASS_REPORTING:
|
||||
case LCTR_PROC_CMN_CH_STATUS_REPORT:
|
||||
if ((pCtx->usedFeatSet & LL_FEAT_CHANNEL_CLASSIFICATION) == 0)
|
||||
{
|
||||
LL_TRACE_WARN1("Requested LL_FEAT_CHANNEL_CLASSIFICATION not available, usedFeatSet=0x%08x", pCtx->usedFeatSet);
|
||||
result = FALSE;
|
||||
}
|
||||
break;
|
||||
case LCTR_PROC_CMN_TERM:
|
||||
default:
|
||||
break;
|
||||
|
@ -575,7 +631,14 @@ static void lctrNotifyHostReadRemoteFeatCnf(lctrConnCtx_t *pCtx, uint8_t status)
|
|||
};
|
||||
|
||||
uint8_t *pBuf = evt.features;
|
||||
UINT64_TO_BSTREAM(pBuf, pCtx->usedFeatSet);
|
||||
if (BT_VER < LL_VER_BT_CORE_SPEC_5_0)
|
||||
{
|
||||
UINT64_TO_BSTREAM(pBuf, pCtx->usedFeatSet);
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT64_TO_BSTREAM(pBuf, pCtx->peerFeatures);
|
||||
}
|
||||
|
||||
LL_TRACE_INFO2("### LlEvent ### LL_READ_REMOTE_FEAT_CNF, handle=%u, status=%u", handle, status);
|
||||
|
||||
|
|
|
@ -53,13 +53,13 @@ enum
|
|||
LCTR_CU_EVENT_HOST_NEG_REPLY, /*!< Received host connection parameter negative reply. */
|
||||
LCTR_CU_EVENT_PEER_CONN_PARAM_REQ, /*!< Received peer LL_CONN_PARAM_REQ. */
|
||||
LCTR_CU_EVENT_PEER_CONN_PARAM_RSP, /*!< Received peer LL_CONN_PARAM_RSP. */
|
||||
LCTR_CU_EVENT_PEER_REJECT, /*!< Received peer LL_REJECT_IND OR LL_UNKNOWN_RSP. */
|
||||
LCTR_CU_EVENT_PEER_REJECT, /*!< Received peer LL_REJECT_IND or LL_UNKNOWN_RSP. */
|
||||
LCTR_CU_EVENT_INT_PROC_COMP, /*!< Procedure completion event. */
|
||||
LCTR_CU_EVENT_INT_SKIP_CONN_PARAM, /*!< Skip connection parameter procedure. */
|
||||
LCTR_CU_EVENT_INT_START_CONN_UPD, /*!< Start pending host connection update procedure. */
|
||||
LCTR_CU_EVENT_INT_START_CONN_PARAM, /*!< Start pending peer connection parameter procedure. */
|
||||
LCTR_CU_EVENT_INT_REJECT_CONN_UPD, /*!< Reject connection update procedure. */
|
||||
LCTR_CU_EVENT_TOTAL, /*!< Total connection parameter/update states. */
|
||||
LCTR_CU_EVENT_TOTAL, /*!< Total connection parameter/update events. */
|
||||
LCTR_CU_EVENT_INVALID = 0xFF /*!< Invalid event. */
|
||||
};
|
||||
|
||||
|
@ -638,14 +638,15 @@ void lctrMstLlcpExecuteSm(lctrConnCtx_t *pCtx, uint8_t event)
|
|||
break;
|
||||
}
|
||||
|
||||
if (!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_ENCRYPT] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_ENCRYPT](pCtx, event)) &&
|
||||
!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_PING] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_PING](pCtx, event)) &&
|
||||
!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_CONN_UPD] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_CONN_UPD](pCtx, event)) &&
|
||||
!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD](pCtx, event)) &&
|
||||
!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_EST] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_EST](pCtx, event)) &&
|
||||
!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM](pCtx, event)) &&
|
||||
!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_PC] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_PC](pCtx, event)) &&
|
||||
!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_CMN] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_CMN](pCtx, event)))
|
||||
if (!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_ENCRYPT] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_ENCRYPT](pCtx, event)) &&
|
||||
!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_PING] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_PING](pCtx, event)) &&
|
||||
!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_ENH_CONN_UPD] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_ENH_CONN_UPD](pCtx, event)) &&
|
||||
!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_CONN_UPD] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_CONN_UPD](pCtx, event)) &&
|
||||
!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD](pCtx, event)) &&
|
||||
!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_EST] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_EST](pCtx, event)) &&
|
||||
!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM](pCtx, event)) &&
|
||||
!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_PC] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_PC](pCtx, event)) &&
|
||||
!(lctrMstLlcpSmTbl[LCTR_LLCP_SM_CMN] && lctrMstLlcpSmTbl[LCTR_LLCP_SM_CMN](pCtx, event)))
|
||||
{
|
||||
lctrLlcpStatelessEventHandler(pCtx, event);
|
||||
}
|
||||
|
|
|
@ -50,10 +50,10 @@ enum
|
|||
LCTR_CU_EVENT_HOST_REPLY, /*!< Received host connection parameter reply. */
|
||||
LCTR_CU_EVENT_HOST_NEG_REPLY, /*!< Received host connection parameter negative reply. */
|
||||
LCTR_CU_EVENT_PEER_CONN_UPD_IND, /*!< Received peer LL_CONN_UPD_IND. */
|
||||
LCTR_CU_EVENT_PEER_REJECT, /*!< Received peer LL_REJECT_IND OR LL_UNKNOWN_RSP. */
|
||||
LCTR_CU_EVENT_PEER_REJECT, /*!< Received peer LL_REJECT_IND or LL_UNKNOWN_RSP. */
|
||||
LCTR_CU_EVENT_INT_PROC_COMP, /*!< Procedure completion event. */
|
||||
LCTR_CU_EVENT_INT_START_CONN_UPD, /*!< Start pending connection update procedure. */
|
||||
LCTR_CU_EVENT_TOTAL, /*!< Total connection parameter/update states. */
|
||||
LCTR_CU_EVENT_TOTAL, /*!< Total connection parameter/update events. */
|
||||
LCTR_CU_EVENT_INVALID = 0xFF /*!< Invalid event. */
|
||||
};
|
||||
|
||||
|
@ -670,14 +670,15 @@ void lctrSlvLlcpExecuteSm(lctrConnCtx_t *pCtx, uint8_t event)
|
|||
break;
|
||||
}
|
||||
|
||||
if (!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_ENCRYPT] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_ENCRYPT](pCtx, event)) &&
|
||||
!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PING] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PING](pCtx, event)) &&
|
||||
!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CONN_UPD] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CONN_UPD](pCtx, event)) &&
|
||||
!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD](pCtx, event)) &&
|
||||
!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_EST] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_EST](pCtx, event)) &&
|
||||
!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM](pCtx, event)) &&
|
||||
!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PC] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PC](pCtx, event)) &&
|
||||
!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CMN] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CMN](pCtx, event)) )
|
||||
if (!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_ENCRYPT] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_ENCRYPT](pCtx, event)) &&
|
||||
!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PING] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PING](pCtx, event)) &&
|
||||
!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_ENH_CONN_UPD] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_ENH_CONN_UPD](pCtx, event)) &&
|
||||
!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CONN_UPD] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CONN_UPD](pCtx, event)) &&
|
||||
!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PHY_UPD](pCtx, event)) &&
|
||||
!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_EST] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_EST](pCtx, event)) &&
|
||||
!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CIS_TERM](pCtx, event)) &&
|
||||
!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PC] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_PC](pCtx, event)) &&
|
||||
!(lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CMN] && lctrSlvLlcpSmTbl[LCTR_LLCP_SM_CMN](pCtx, event)) )
|
||||
{
|
||||
lctrLlcpStatelessEventHandler(pCtx, event);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
||||
* Copyright (c) 2019-2021 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -25,6 +25,7 @@
|
|||
#include "lctr_int_enc_slave.h"
|
||||
#include "lctr_int_conn.h"
|
||||
#include "lctr_int_conn_slave.h"
|
||||
#include "lctr_int_slave_phy.h"
|
||||
#include "lmgr_api.h"
|
||||
#include "wsf_trace.h"
|
||||
|
||||
|
@ -428,7 +429,8 @@ static void lctrSlvCheckProcOverride(lctrConnCtx_t *pCtx, uint8_t event)
|
|||
{
|
||||
case LCTR_ENC_EVENT_PEER_ENC_REQ:
|
||||
if (lctrSlvCheckEncOverrideConnParam(pCtx) ||
|
||||
lctrSlvCheckEncOverrideCommonParam(pCtx))
|
||||
lctrSlvCheckEncOverrideCommonParam(pCtx) ||
|
||||
((lctrSlvCheckEncOverridePhyUpdateFn == NULL) || lctrSlvCheckEncOverridePhyUpdateFn(pCtx)))
|
||||
{
|
||||
pCtx->llcpPendMask |= 1 << pCtx->llcpActiveProc;
|
||||
pCtx->llcpActiveProc = LCTR_PROC_ENCRYPT;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue