static void wsfSecHciCback(hciEvt_t *pEvent) { wsfSecQueueBuf_t *pBuf; wsfHandlerId_t handlerId; /* handle random number event */ if (pEvent->hdr.event == HCI_LE_RAND_CMD_CMPL_CBACK_EVT) { /* move up data by eight bytes */ memcpy(&wsfSecCb.rand[HCI_RAND_LEN], wsfSecCb.rand, HCI_RAND_LEN); /* copy new data to random data buffer */ memcpy(wsfSecCb.rand, pEvent->leRandCmdCmpl.randNum, HCI_RAND_LEN); } /* handle encryption event */ else if (pEvent->hdr.event == HCI_LE_ENCRYPT_CMD_CMPL_CBACK_EVT) { /* dequeue parameter buffer */ if ((pBuf = WsfMsgDeq(&wsfSecCb.aesQueue, &handlerId)) != NULL) { /* set encrypted data pointer and copy */ pBuf->aes.pCiphertext = pBuf->ciphertext; Calc128Cpy(pBuf->aes.pCiphertext, pEvent->leEncryptCmdCmpl.data); /* send message */ WsfMsgSend(handlerId, pBuf); } else { WSF_TRACE_WARN0("WSF sec queue empty!"); } } }
void LlScanEnable(uint8_t enable, uint8_t filterDup) { lctrScanEnableMsg_t *pMsg; LL_TRACE_INFO2("### LlApi ### LlScanEnable: enable=%u, filterDup=%u", enable, filterDup); if ((LL_API_PARAM_CHECK == 1) && !LmgrIsLegacyCommandAllowed()) { LmgrSendScanEnableCnf(LL_ERROR_CODE_CMD_DISALLOWED); return; } if ((LL_API_PARAM_CHECK == 1) && !LmgrIsAddressTypeAvailable(lmgrMstScanCb.scanParam.ownAddrType)) { LL_TRACE_WARN1("Address type invalid or not available, ownAddrType=%u", lmgrMstScanCb.scanParam.ownAddrType); LmgrSendScanEnableCnf(LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS); return; } if ((pMsg = WsfMsgAlloc(sizeof(*pMsg))) != NULL) { pMsg->hdr.dispId = LCTR_DISP_SCAN; pMsg->hdr.event = enable ? LCTR_SCAN_MSG_DISCOVER_ENABLE : LCTR_SCAN_MSG_DISCOVER_DISABLE; pMsg->filtDup = filterDup; WsfMsgSend(lmgrPersistCb.handlerId, pMsg); } }
uint8_t LlLtkReqReply(uint16_t handle, const uint8_t *pKey) { lctrLtkReply_t *pMsg; LL_TRACE_INFO1("### LlApi ### LlLtkReqReply, handle=%u", handle); if ((LL_API_PARAM_CHECK == 1) && ((handle >= pLctrRtCfg->maxConn) || !LctrIsConnHandleEnabled(handle))) { return LL_ERROR_CODE_UNKNOWN_CONN_ID; } if ((LL_API_PARAM_CHECK == 1) && ((LctrGetRole(handle) != LL_ROLE_SLAVE) || !LctrIsWaitingForReply(handle, LCTR_HOST_REPLY_LTK_REQ))) { return LL_ERROR_CODE_CMD_DISALLOWED; } if ((pMsg = (lctrLtkReply_t *)WsfMsgAlloc(sizeof(*pMsg))) != NULL) { pMsg->hdr.handle = handle; pMsg->hdr.dispId = LCTR_DISP_CONN; pMsg->hdr.event = LCTR_CONN_MSG_API_LTK_REPLY; memcpy(pMsg->key, pKey, sizeof(pMsg->key)); WsfMsgSend(lmgrPersistCb.handlerId, pMsg); } return LL_SUCCESS; }
static void DmCback(dmEvt_t *pDmEvt) { dmEvt_t *pMsg; if ((pMsg = (dmEvt_t*)WsfMsgAlloc(sizeof(dmEvt_t))) != NULL) { memcpy(pMsg, pDmEvt, sizeof(dmEvt_t)); WsfMsgSend(maximHandlerId, pMsg); } }
uint8_t LlSetScanParam(const LlScanParam_t *pParam) { const uint16_t rangeMin = 0x0004; /* 2.5 ms */ const uint16_t rangeMax = 0x4000; /* 10,240.0 ms */ const uint8_t scanTypeMax = LL_SCAN_ACTIVE; const uint8_t scanFiltPolicyMax = ((lmgrCb.features & LL_FEAT_EXT_SCAN_FILT_POLICY) != 0) ? LL_SCAN_FILTER_WL_OR_RES_INIT : LL_SCAN_FILTER_WL_BIT; const uint8_t ownAddrTypeMax = ((lmgrCb.features & LL_FEAT_PRIVACY) != 0) ? LL_ADDR_RANDOM_IDENTITY : LL_ADDR_RANDOM; LL_TRACE_INFO1("### LlApi ### LlSetScanParam, scanType=%u", pParam->scanType); if ((LL_API_PARAM_CHECK == 1) && !LmgrIsLegacyCommandAllowed()) { return LL_ERROR_CODE_CMD_DISALLOWED; } if (lmgrCb.numScanEnabled || lmgrCb.numInitEnabled) { return LL_ERROR_CODE_CMD_DISALLOWED; } if ((LL_API_PARAM_CHECK == 1) && ((rangeMax < pParam->scanInterval) || (pParam->scanInterval < pParam->scanWindow) || (pParam->scanWindow < rangeMin) || (pParam->scanType > scanTypeMax) || (pParam->ownAddrType > ownAddrTypeMax) || (pParam->scanFiltPolicy > scanFiltPolicyMax))) { return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; } lctrScanParamMsg_t *pMsg; if ((pMsg = WsfMsgAlloc(sizeof(*pMsg))) != NULL) { pMsg->hdr.dispId = LCTR_DISP_SCAN; pMsg->hdr.event = LCTR_SCAN_MSG_PARAM_UPD; pMsg->param.scanInterval = pParam->scanInterval; pMsg->param.scanWindow = pParam->scanWindow; pMsg->param.scanType = pParam->scanType; pMsg->param.ownAddrType = pParam->ownAddrType; pMsg->param.scanFiltPolicy = pParam->scanFiltPolicy; WsfMsgSend(lmgrPersistCb.handlerId, pMsg); } return LL_SUCCESS; }
void LlAdvEnable(uint8_t enable) { lctrMsgHdr_t *pMsg; LL_TRACE_INFO1("### LlApi ### LlAdvEnable: enable=%u", enable); if ((LL_API_PARAM_CHECK == 1) && !LmgrIsLegacyCommandAllowed()) { LmgrSendAdvEnableCnf(LL_ERROR_CODE_CMD_DISALLOWED); return; } /* Disallow connectable advertising when no connections remain. */ switch (lmgrSlvAdvCb.advParam.advType) { case LL_ADV_CONN_UNDIRECT: case LL_ADV_CONN_DIRECT_HIGH_DUTY: case LL_ADV_CONN_DIRECT_LOW_DUTY: if (lmgrCb.numConnEnabled == pLctrRtCfg->maxConn) { LmgrSendAdvEnableCnf(LL_ERROR_CODE_CMD_DISALLOWED); return; } break; default: break; } if ((LL_API_PARAM_CHECK == 1) && !LmgrIsAddressTypeAvailable(lmgrSlvAdvCb.advParam.ownAddrType)) { LL_TRACE_WARN1("Address type invalid or not available, ownAddrType=%u", lmgrSlvAdvCb.advParam.ownAddrType); LmgrSendAdvEnableCnf(LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS); return; } if ((pMsg = WsfMsgAlloc(sizeof(*pMsg))) != NULL) { pMsg->dispId = LCTR_DISP_ADV; pMsg->event = enable ? LCTR_ADV_MSG_START : LCTR_ADV_MSG_STOP; WsfMsgSend(lmgrPersistCb.handlerId, pMsg); } }
void attcSendMsg(dmConnId_t connId, uint16_t handle, uint8_t msgId, attcPktParam_t *pPkt, bool_t continuing) { attcCcb_t *pCcb; uint16_t mtu; bool_t transTimedOut; WsfTaskLock(); /* get CCB and verify connection still in use */ if ((pCcb = attcCcbByConnId(connId)) != NULL) { /* get MTU size */ mtu = pCcb->pMainCcb->mtu; transTimedOut = pCcb->pMainCcb->transTimedOut; } /* else connection not in use */ else { /* MTU size unknown */ mtu = 0; transTimedOut = FALSE; } WsfTaskUnlock(); /* if MTU size known for connection */ if (mtu > 0) { /* if no transaction's timed out */ if (!transTimedOut) { uint16_t dataLen = 0; /* if packet is not null then find out its length */ if (pPkt != NULL) { /* if not prepare write request */ if (msgId != ATTC_MSG_API_PREP_WRITE) { dataLen = pPkt->len; } /* else prepare write request */ else { /* if not continuing */ if (!continuing) { /* single prepare write request */ dataLen = ATT_PREP_WRITE_REQ_LEN + pPkt->w.len; } /* else will be sent as multiple prepare write requests */ } } /* if packet length is less than or equal to negotiated MTU */ if (dataLen <= mtu) { attcApiMsg_t *pMsg; /* allocate message buffer */ if ((pMsg = WsfMsgAlloc(sizeof(attcApiMsg_t))) != NULL) { /* set parameters */ pMsg->hdr.param = connId; pMsg->hdr.status = continuing; pMsg->hdr.event = msgId; pMsg->pPkt = pPkt; pMsg->handle = handle; /* send message */ WsfMsgSend(attCb.handlerId, pMsg); return; } } /* else packet length exceeds MTU size */ else { /* call callback with failure status */ attcExecCallback(connId, msgId, handle, ATT_ERR_MTU_EXCEEDED); } } else /* transaction's timed out */ { /* call callback with failure status */ attcExecCallback(connId, msgId, handle, ATT_ERR_TIMEOUT); } } /* alloc failed, transaction's timed out or packet length exceeded MTU size; free packet buffer */ if (pPkt != NULL) { WsfMsgFree(pPkt); } }
uint8_t LlSetAdvParam(uint16_t advIntervalMin, uint16_t advIntervalMax, uint8_t advType, uint8_t ownAddrType, uint8_t peerAddrType, const uint8_t *pPeerAddr, uint8_t advChanMap, uint8_t advFiltPolicy) { const uint16_t rangeMin = 0x0020; /* 20 ms */ const uint16_t rangeMax = 0x4000; /* 10,240 ms */ const uint8_t advTypeMax = LL_ADV_CONN_DIRECT_LOW_DUTY; const uint8_t peerAddrTypeMax = LL_ADDR_RANDOM; const uint8_t advFiltPolicyMax = LL_ADV_FILTER_WL_ONLY; const uint8_t ownAddrTypeMax = ((lmgrCb.features & LL_FEAT_PRIVACY) != 0) ? LL_ADDR_RANDOM_IDENTITY : LL_ADDR_RANDOM; LL_TRACE_INFO1("### LlApi ### LlSetAdvParam, advType=%u", advType); if ((LL_API_PARAM_CHECK == 1) && !LmgrIsLegacyCommandAllowed()) { return LL_ERROR_CODE_CMD_DISALLOWED; } if (lmgrCb.advEnabled) { return LL_ERROR_CODE_CMD_DISALLOWED; } if ((LL_API_PARAM_CHECK == 1) && /* For high-duty cycle directed advertising, advertising intervals are ignored. */ (((advType != LL_ADV_CONN_DIRECT_HIGH_DUTY) && ((advIntervalMin < rangeMin) || (advIntervalMax < advIntervalMin) || (rangeMax < advIntervalMax))) || (advType > advTypeMax) || (ownAddrType > ownAddrTypeMax) || /* If directed advertising or advertiser is private, peer address should be valid. */ (((advType == LL_ADV_CONN_DIRECT_HIGH_DUTY) || (advType == LL_ADV_CONN_DIRECT_LOW_DUTY) || ((ownAddrType & LL_ADDR_IDENTITY_BIT) != 0)) && (!pPeerAddr || (peerAddrType > peerAddrTypeMax))) || (advChanMap & ~LL_ADV_CHAN_ALL) || (advChanMap == 0) || /* If directed advertising, filter policy is ignored. */ ((advType != LL_ADV_CONN_DIRECT_HIGH_DUTY) && (advType != LL_ADV_CONN_DIRECT_LOW_DUTY) && (advFiltPolicy > advFiltPolicyMax)))) { return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS; } lctrAdvParamMsg_t *pMsg; if ((pMsg = WsfMsgAlloc(sizeof(*pMsg))) != NULL) { pMsg->hdr.dispId = LCTR_DISP_ADV; pMsg->hdr.event = LCTR_ADV_MSG_PARAM_UPD; pMsg->param.advInterMin = BB_BLE_TO_BB_TICKS(advIntervalMin); pMsg->param.advInterMax = BB_BLE_TO_BB_TICKS(advIntervalMax); pMsg->param.advType = advType; pMsg->param.ownAddrType = ownAddrType; pMsg->param.peerAddrType = peerAddrType; pMsg->param.advChanMap = advChanMap; pMsg->param.advFiltPolicy = advFiltPolicy; BSTREAM_TO_BDA64(pMsg->param.peerAddr, pPeerAddr); WsfMsgSend(lmgrPersistCb.handlerId, pMsg); } return LL_SUCCESS; }
bool_t smpSendKey(smpCcb_t *pCcb, uint8_t keyDist) { uint8_t *pPkt; uint8_t *p; wsfMsgHdr_t *pHdr; if (smpCb.lescSupported && pCcb->pScCcb->lescEnabled && pCcb->lastSentKey == 0) { dmSecKeyIndEvt_t keyInd; /* pass LTK to app via DM */ if (DmConnRole(pCcb->connId) == DM_ROLE_MASTER) { keyInd.type = DM_KEY_PEER_LTK; } else { keyInd.type = DM_KEY_LOCAL_LTK; } keyInd.hdr.event = DM_SEC_KEY_IND; keyInd.hdr.param = pCcb->connId; keyInd.secLevel = smpGetScSecLevel(pCcb); keyInd.keyData.ltk.ediv = 0; memset(keyInd.keyData.ltk.rand, 0, SMP_RAND8_LEN); Calc128Cpy(keyInd.keyData.ltk.key, pCcb->pScCcb->pLtk->ltk_t); DmSmpCbackExec((dmEvt_t *)&keyInd); pCcb->lastSentKey = SMP_CMD_MASTER_ID; } /* check if we're done sending keys */ if ((keyDist == 0) || (keyDist == SMP_KEY_DIST_ENC && pCcb->lastSentKey == SMP_CMD_MASTER_ID) || (keyDist <= (SMP_KEY_DIST_ENC | SMP_KEY_DIST_ID) && pCcb->lastSentKey == SMP_CMD_ID_ADDR_INFO) || (pCcb->lastSentKey == SMP_CMD_SIGN_INFO)) { return TRUE; } /* if flow disabled return */ if (pCcb->flowDisabled) { return FALSE; } /* allocate packet buffer for largest packet size */ if ((pPkt = smpMsgAlloc(SMP_ENC_INFO_LEN + L2C_PAYLOAD_START)) != NULL) { p = pPkt + L2C_PAYLOAD_START; /* determine next key to send */ if (pCcb->lastSentKey == 0 && (keyDist & SMP_KEY_DIST_ENC)) { /* generate LTK, EDIV, and RAND */ smpGenerateLtk(pCcb); /* send first part of LTK */ UINT8_TO_BSTREAM(p, SMP_CMD_ENC_INFO); Calc128Cpy(p, pCcb->pScr->keyInd.keyData.ltk.key); } else if (pCcb->lastSentKey == SMP_CMD_ENC_INFO) { /* send second part of LTK */ UINT8_TO_BSTREAM(p, SMP_CMD_MASTER_ID); UINT16_TO_BSTREAM(p, pCcb->pScr->keyInd.keyData.ltk.ediv); memcpy(p, pCcb->pScr->keyInd.keyData.ltk.rand, SMP_RAND8_LEN); } else if ((keyDist & SMP_KEY_DIST_ID) && (pCcb->lastSentKey == 0 || pCcb->lastSentKey == SMP_CMD_MASTER_ID)) { /* send first part of IRK */ UINT8_TO_BSTREAM(p, SMP_CMD_ID_INFO); Calc128Cpy(p, DmSecGetLocalIrk()); } else if (pCcb->lastSentKey == SMP_CMD_ID_INFO) { /* send second part of IRK */ UINT8_TO_BSTREAM(p, SMP_CMD_ID_ADDR_INFO); UINT8_TO_BSTREAM(p, DM_ADDR_PUBLIC); BDA_TO_BSTREAM(p, HciGetBdAddr()); } else if ((keyDist & SMP_KEY_DIST_SIGN) && (pCcb->lastSentKey == 0 || pCcb->lastSentKey == SMP_CMD_ID_ADDR_INFO || pCcb->lastSentKey == SMP_CMD_MASTER_ID)) { /* send SRK */ UINT8_TO_BSTREAM(p, SMP_CMD_SIGN_INFO); Calc128Cpy(p, DmSecGetLocalCsrk()); } else { /* should never get here */ WsfMsgFree(pPkt); SMP_TRACE_WARN2("smpSendKey unexpected state keyDist:%d lastSentKey:%d", keyDist, pCcb->lastSentKey); return TRUE; } /* set last sent key to command code */ pCcb->lastSentKey = pPkt[L2C_PAYLOAD_START]; /* send command packet */ smpSendPkt(pCcb, pPkt); /* if flow not disabled set up to send next key */ if (!pCcb->flowDisabled) { if ((pHdr = WsfMsgAlloc(sizeof(wsfMsgHdr_t))) != NULL) { pHdr->event = SMP_MSG_INT_SEND_NEXT_KEY; pHdr->param = pCcb->connId; WsfMsgSend(smpCb.handlerId, pHdr); } } } return FALSE; }
void SmpDmMsgSend(smpDmMsg_t *pMsg) { WsfMsgSend(smpCb.handlerId, pMsg); }
void LlExtAdvEnable(uint8_t enable, uint8_t numAdvSets, LlExtAdvEnableParam_t enaParam[]) { LL_TRACE_INFO2("### LlApi ### LlExtAdvEnable: enable=%u, numAdvSets=%u", enable, numAdvSets); /* Non-overlapping enable requests. */ WSF_ASSERT(lmgrCb.extAdvEnaDelayCnt == 0); lmgrCb.advSetEnaStatus = LL_SUCCESS; if ((LL_API_PARAM_CHECK == 1) && !LmgrIsExtCommandAllowed()) { lmgrCb.extAdvEnaDelayCnt = 1; LmgrSendExtAdvEnableCnf(0, LL_ERROR_CODE_CMD_DISALLOWED); return; } if ((LL_API_PARAM_CHECK == 1) && (((numAdvSets > LL_MAX_ADV_SETS)) || ((numAdvSets == 0) && enable))) { lmgrCb.extAdvEnaDelayCnt = 1; LmgrSendExtAdvEnableCnf(0, LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS); return; } for (unsigned int i = 0; i < numAdvSets; i++) { uint8_t status; if (((status = LctrIsExtAdvEnableReady(enaParam[i].handle)) != LL_SUCCESS) || ((status = LctrIsExtAdvEnableParamValid(enable, &enaParam[i])) != LL_SUCCESS)) { lmgrCb.extAdvEnaDelayCnt = 1; LmgrSendExtAdvEnableCnf(enaParam[i].handle, status); return; } } if (numAdvSets > 0) { for (unsigned int i = 0; i < numAdvSets; i++) { LctrExtAdvEnableMsg_t *pMsg; if ((pMsg = WsfMsgAlloc(sizeof(*pMsg))) != NULL) { pMsg->hdr.handle = enaParam[i].handle; pMsg->hdr.dispId = LCTR_DISP_EXT_ADV; pMsg->hdr.event = enable ? LCTR_EXT_ADV_MSG_START : LCTR_EXT_ADV_MSG_STOP; pMsg->durMs = enaParam[i].duration * 10; pMsg->maxEvents = enaParam[i].numEvents; /* Delay enable confirm event until all advertising sets respond. */ lmgrCb.extAdvEnaDelayCnt++; WsfMsgSend(lmgrPersistCb.handlerId, pMsg); } } } else /* (numAdvSets == 0) */ { /* N.B. Parameter check guarantees enable is FALSE. */ uint8_t numHandles; uint8_t handles[LL_MAX_ADV_SETS] = { 0 }; numHandles = LctrGetAdvHandles(handles); for (unsigned int i = 0; i < numHandles; i++) { LctrExtAdvEnableMsg_t *pMsg; if ((pMsg = WsfMsgAlloc(sizeof(*pMsg))) != NULL) { pMsg->hdr.handle = handles[i]; pMsg->hdr.dispId = LCTR_DISP_EXT_ADV; pMsg->hdr.event = LCTR_EXT_ADV_MSG_STOP; pMsg->durMs = 0; pMsg->maxEvents = 0; /* Delay enable confirm event until all advertising sets respond. */ lmgrCb.extAdvEnaDelayCnt++; WsfMsgSend(lmgrPersistCb.handlerId, pMsg); } } } }