Exemple #1
0
void smpActMaxAttempts(smpCcb_t *pCcb, smpMsg_t *pMsg)
{
  uint32_t timeout;

  /* send paring failed packet; note this stops the timer so call this first */
  smpActPairingCancel(pCcb, pMsg);

  /* Check SMP device DB to determine time to wait before pairing can happen again */
  timeout = SmpDbMaxAttemptReached(pCcb->connId);

  /* start repeated attempts timer */
  pCcb->smpTimer.msg.event = SMP_MSG_INT_TIMEOUT;
  WsfTimerStartMs(&pCcb->smpTimer, timeout);

  /* clear attempts count */
  pCcb->attempts = 0;
}
Exemple #2
0
static void lctrMstConnUpdateOp(lctrConnCtx_t *pCtx)
{
  /* Pre-resolve common structures for efficient access. */
  BbOpDesc_t * const pOp = &pCtx->connBod;
  lctrConnUpdInd_t * const pConnUpdInd = &pCtx->connUpd;

  /*** Connection context setup ***/

  const uint16_t connIntervalOld = pCtx->connInterval;
  const uint16_t latencyOld      = pCtx->maxLatency;
  const uint16_t supTimeoutMsOld = pCtx->supTimeoutMs;

  pCtx->connInterval = pConnUpdInd->interval;
  pCtx->maxLatency   = pConnUpdInd->latency;
  pCtx->supTimeoutMs = LCTR_CONN_IND_TO_MS(pConnUpdInd->timeout);

  SchRmCommitUpdate(LCTR_GET_CONN_HANDLE(pCtx));

  /*** General setup ***/

  const uint32_t txWinOffset = BB_BLE_TO_BB_TICKS(LCTR_CONN_IND_TICKS(pConnUpdInd->txWinOffset));

  pOp->due += txWinOffset;
  pOp->maxDurUsec = LCTR_CONN_IND_US(pCtx->connInterval);

  /* Unconditionally reset supervision timer with transitional value.
   *     connIntervalOld + supervisionTimeoutNew */
  WsfTimerStartMs(&pCtx->tmrSupTimeout, LCTR_CONN_IND_MS(connIntervalOld) + pCtx->supTimeoutMs);

  /*** Notifications ***/

  /* Notify host only if connection parameters changed. */
  if ((connIntervalOld != pCtx->connInterval) ||
      (latencyOld      != pCtx->maxLatency) ||
      (supTimeoutMsOld != pCtx->supTimeoutMs))
  {
    pCtx->llcpNotifyMask |= 1 << LCTR_PROC_CONN_UPD;
  }

  /* Delay notification until CE starts. */
  pCtx->llcpInstantComp = TRUE;

  LL_TRACE_INFO2("    >>> Connection updated, handle=%u, eventCounter=%u <<<", LCTR_GET_CONN_HANDLE(pCtx), pCtx->eventCounter);
  LL_TRACE_INFO1("                            connIntervalUsec=%u", LCTR_CONN_IND_US(pCtx->connInterval));
}
Exemple #3
0
static void smpResumeAttemptsState(dmConnId_t connId)
{
  smpCcb_t *pCcb = smpCcbByConnId(connId);
  uint32_t timeMs = SmpDbGetPairingDisabledTime(connId);

  if (timeMs)
  {
    if (smpCb.lescSupported)
    {
      pCcb->state = DmConnRole(connId) == DM_ROLE_SLAVE? SMPR_SC_SM_ST_ATTEMPTS : SMPI_SC_SM_ST_ATTEMPTS;
    }
    else
    {
      pCcb->state = DmConnRole(connId) == DM_ROLE_SLAVE? SMPR_SM_ST_ATTEMPTS : SMPI_SM_ST_ATTEMPTS;
    }

    /* Start smp timer indicating the time to prevent pairing in the attempts state */
    pCcb->waitTimer.msg.event = SMP_MSG_INT_WI_TIMEOUT;
    WsfTimerStartMs(&pCcb->waitTimer, timeMs);
  }
}
Exemple #4
0
void lctrMstConnEndOp(BbOpDesc_t *pOp)
{
  /* Pre-resolve common structures for efficient access. */
  BbBleData_t * const pBle = pOp->prot.pBle;
  BbBleMstConnEvent_t * const pConn = &pBle->op.mstConn;
  lctrConnCtx_t * const pCtx = pOp->pCtx;

  /* Process event completion */

  if (!pCtx->connEst && (lctrMstConnIsr.rxFromSlave || (lctrMstConnIsr.consCrcFailed > 0)))
  {
    lctrStoreConnTimeoutTerminateReason(pCtx);
    WsfTimerStartMs(&pCtx->tmrSupTimeout, pCtx->supTimeoutMs);

    pCtx->connEst = TRUE;
  }
  else if (lctrMstConnIsr.rxFromSlave)
  {
    /* Reset supervision timer. */
    WsfTimerStartMs(&pCtx->tmrSupTimeout, pCtx->supTimeoutMs);
  }

  pCtx->rssi = pConn->rssi;

  SchRmSetReference(LCTR_GET_CONN_HANDLE(pCtx));

  /* Terminate connection */
  if (lctrCheckForLinkTerm(pCtx))
  {
    lctrSendConnMsg(pCtx, LCTR_CONN_TERMINATED);
    WsfTimerStop(&pCtx->tmrSupTimeout);
    return;
  }

  if (pCtx->data.mst.sendConnUpdInd)
  {
    uint8_t *pPdu;

    if ((pPdu = lctrTxCtrlPduAlloc(LL_CONN_UPD_IND_PDU_LEN)) != NULL)
    {
      pCtx->data.mst.sendConnUpdInd = FALSE;

      uint16_t ceOffset;
#if (LL_ENABLE_TESTER)
      if (llTesterCb.eventCounterOffset)
      {
        ceOffset = pCtx->eventCounter +
                   llTesterCb.eventCounterOffset + 1;          /* +1 for next CE */
      }
      else
#endif
      {
        ceOffset = LL_MIN_INSTANT + 1 +          /* +1 for next CE */
                   pCtx->maxLatency;             /* ensure slave will listen this packet */

        /* TODO: accommodate pCtx->connParam.offset[]. */
      }
      pCtx->connUpd.instant = pCtx->eventCounter + ceOffset;

      uint32_t rsvnOffs[SCH_RM_MAX_RSVN];
      memset(&rsvnOffs[0], 0, sizeof(rsvnOffs));
      if (lctrGetConnOffsetsCback)
      {
        lctrGetConnOffsetsCback(rsvnOffs, pOp->due);
      }
      if (lctrGetPerOffsetsCback)
      {
        lctrGetPerOffsetsCback(&rsvnOffs[LL_MAX_CONN], pOp->due);
      }
      /* Use smallest txWindowOffset (i.e. 0) to minimize data loss. */
      uint32_t txWinOffsetUsec = SchRmGetOffsetUsec(rsvnOffs, 0, LCTR_GET_CONN_HANDLE(pCtx));
      pCtx->connUpd.txWinOffset = LCTR_US_TO_CONN_IND(txWinOffsetUsec);

      lctrPackConnUpdInd(pPdu, &pCtx->connUpd);
      lctrTxCtrlPduQueue(pCtx, pPdu);
    }
    /* else retry at next lctrMstConnEndOp() event. */
  }

  /*** Update for next operation ***/

  uint32_t anchorPoint           = pOp->due;
  uint16_t anchorPointOffsetUsec = pOp->dueOffsetUsec;
  uint16_t numIntervals          = 0;

  if (pBle->chan.tifsTxPhyOptions != BB_PHY_OPTIONS_DEFAULT)
  {
    /* Set PHY options to host defined behavior. */
    pBle->chan.initTxPhyOptions = pBle->chan.tifsTxPhyOptions;
  }
  else
  {
    /* Set PHY options to RX PHY Options*/
    pBle->chan.initTxPhyOptions = pConn->rxPhyOptions;
  }

  while (TRUE)
  {
    numIntervals += 1;
    pCtx->eventCounter += 1;

    uint32_t connInterUsec = LCTR_CONN_IND_US(numIntervals * pCtx->connInterval) + anchorPointOffsetUsec;
    uint32_t connInter     = BB_US_TO_BB_TICKS(connInterUsec);
    int16_t  dueOffsetUsec = connInterUsec - BB_TICKS_TO_US(connInter);
#if (LL_ENABLE_TESTER)
    if (llTesterCb.connIntervalUs)
    {
      connInter     = BB_US_TO_BB_TICKS(llTesterCb.connIntervalUs);
      dueOffsetUsec = llTesterCb.connIntervalUs - BB_TICKS_TO_US(connInter);
    }
#endif

    /* Advance to next interval. */
    pOp->due           = anchorPoint + connInter;
    pOp->dueOffsetUsec = WSF_MAX(dueOffsetUsec, 0);
#if (LL_ENABLE_TESTER)
    if (llTesterCb.connIntervalUs)
    {
      pOp->due = anchorPoint + BB_US_TO_BB_TICKS(llTesterCb.connIntervalUs);
      pOp->dueOffsetUsec = 0;
    }
#endif

    if ((pCtx->llcpActiveProc == LCTR_PROC_CONN_UPD) &&
        (pCtx->eventCounter == pCtx->connUpd.instant))
    {
      lctrMstConnUpdateOp(pCtx);
    }
    else if ((pCtx->llcpActiveProc == LCTR_PROC_CMN_CH_MAP_UPD) &&
             (pCtx->eventCounter == pCtx->chanMapUpd.instant))
    {
      lctrMstChanMapUpdateOp(pCtx);
    }
    else if ((pCtx->llcpActiveProc == LCTR_PROC_PHY_UPD) &&
             (pCtx->eventCounter == pCtx->phyUpd.instant))
    {
      lctrMstPhyUpdateOp(pCtx);
    }

    pBle->chan.chanIdx = lctrChSelHdlr[pCtx->usedChSel](pCtx, 0);

    if (SchInsertAtDueTime(pOp, lctrConnResolveConflict))
    {
      break;
    }

    LL_TRACE_WARN2("!!! CE schedule conflict handle=%u, eventCounter=%u", LCTR_GET_CONN_HANDLE(pCtx), pCtx->eventCounter);
  }
}