/** * @fn SAP_close * * @brief Tears down the port with the network processor * * @param None. * * @return uint8_t - SNP_SUCCESS if able to close */ uint8_t SAP_close(void) { asyncCBNode_t *aNode = asyncCBListRoot; asyncCBNode_t *aTempNode = NULL; eventCBNode_t *eNode = eventCBListRoot; eventCBNode_t *eTempNode = NULL; serviceNode_t *sNode = serviceListRoot; serviceNode_t *sTempNode = NULL; // Clean up call back and service lists while(aNode != NULL) { aTempNode = (asyncCBNode_t *)aNode->next; SNP_free(aNode); aNode = aTempNode; } asyncCBListRoot = NULL; while(eNode != NULL) { eTempNode = (eventCBNode_t *)eNode->next; SNP_free(eNode); eNode = eTempNode; } eventCBListRoot = NULL; while(sNode != NULL) { sTempNode = (serviceNode_t *)sNode->next; SNP_free(sNode); sNode = sTempNode; } serviceListRoot = NULL; SNP_close(); return NPITask_close(); }
/** * @fn SAP_reset * * @brief Reset the network processor. * * @param None. * * @return None. */ uint8_t SAP_reset(void) { snpHciCmdReq_t lReq; uint8_t status; // Initialize Request Struct lReq.opcode = SNP_HCI_OPCODE_EXT_RESET_SYSTEM; lReq.pData = (uint8_t *)SNP_malloc(sizeof(uint8_t)); lReq.pData[0] = 0x01; // Default to Soft Reset status = SNP_sendHCICommand(&lReq, sizeof(uint8_t)); // Free Allocated Mem in Request Struct SNP_free(lReq.pData); return status; }
/* * Iterate through list of asynchronous callbacks and */ void handleAsyncCB(uint8_t cmd1, snp_msg_t *pMsg, uint16_t msgLen) { asyncCBNode_t *iter = asyncCBListRoot; serviceNode_t *curr = serviceListRoot; switch(SNP_GET_OPCODE_HDR_CMD1(cmd1)) { case SNP_GATT_GRP: // GATT Request, determine which service call back to invoke based upon // the handle of the request. switch (cmd1) { case SNP_CHAR_READ_IND: { snpCharReadCnf_t lCnf; uint16_t size = 0; snpCharReadInd_t *rI = (snpCharReadInd_t *)pMsg; // Initialize Confirmation Struct lCnf.connHandle = rI->connHandle; lCnf.attrHandle = rI->attrHandle; lCnf.offset = rI->offset; lCnf.pData = (uint8_t *)SNP_malloc(rI->maxSize); lCnf.status = SNP_FAILURE; // Searching for service that contains handle while (curr != NULL) { if (rI->attrHandle >= curr->minHandle && rI->attrHandle <= curr->maxHandle) { // Found correct service. If call back is registered invoke, // else return error status if (curr->charReadCB) { lCnf.status = curr->charReadCB(curr->context, rI->connHandle, rI->attrHandle, rI->offset, rI->maxSize, &size, lCnf.pData); } break; } curr = (serviceNode_t *)curr->next; } SNP_readCharCnf(&lCnf,size); SNP_free(lCnf.pData); } break; case SNP_CHAR_WRITE_IND: { snpCharWriteCnf_t lCnf; snpCharWriteInd_t *wI = (snpCharWriteInd_t *)pMsg; // msgLen is the amount of payload bytes. Adjust it to only be // the amount of bytes to be written to the characteristic msgLen = msgLen - sizeof(pMsg->charWriteInd) + sizeof(pMsg->charWriteInd.pData); // Initialize Confirmation Struct lCnf.status = SNP_FAILURE; lCnf.connHandle = wI->connHandle; // Searching for service that contains handle while (curr != NULL) { if (wI->attrHandle >= curr->minHandle && wI->attrHandle <= curr->maxHandle) { // Found correct service. If call back is registered invoke, // else return error status if (curr->charWriteCB) { lCnf.status = curr->charWriteCB(curr->context, wI->connHandle, wI->attrHandle, msgLen, wI->pData); } break; } curr = (serviceNode_t *)curr->next; } // Respond to write request SNP_writeCharCnf(&lCnf); } break; case SNP_CCCD_UPDATED_IND: { snpCharCfgUpdatedRsp_t lRsp; snpCharCfgUpdatedInd_t *cu = (snpCharCfgUpdatedInd_t *)pMsg; // Initialize Response Struct lRsp.status = SNP_FAILURE; lRsp.connHandle = cu->connHandle; while (curr != NULL) { if (cu->cccdHandle >= curr->minHandle && cu->cccdHandle <= curr->maxHandle) { if (curr->cccdIndCB) { // Found correct service. If call back is registered invoke, // else return error status lRsp.status = curr->cccdIndCB(curr->context, cu->connHandle, cu->cccdHandle, cu->rspNeeded, cu->value); } break; } curr = (serviceNode_t *)curr->next; } // Respond to CCCD Indication SNP_charConfigUpdatedRsp(&lRsp); } break; default: break; } break; default: // Not GATT request, pass on to all registered call backs while(iter != NULL) { // Send to callback. iter->asyncCB(cmd1, pMsg); // Next callback. iter = (asyncCBNode_t *)iter->next; } break; } }
// ----------------------------------------------------------------------------- //! \brief Call back function provided to NPI Task. All incoming NPI //! received by NPI Task with the subsystem ID of this subsystem //! will be sent to this call back through the NPI routing system //! //! *** This function MUST free pNPIMsg //! //! \param[in] pNPIMsg Pointer to a "framed" NPI message //! //! \return void // ----------------------------------------------------------------------------- void NPISS_BLE_SNP_msgFromSNP(_npiFrame_t *pNPIMsg) { uint16_t msgLen = pNPIMsg->dataLen; switch(SNP_GET_OPCODE_HDR_CMD1(pNPIMsg->cmd1)) { /* Device group */ case SNP_DEVICE_GRP: { switch( pNPIMsg->cmd1 ) { #ifndef SNP_LOCAL // NP is powered up indication. case SNP_POWER_UP_IND: // Device has restarted. if (SNP_asyncCB) { SNP_asyncCB(pNPIMsg->cmd1, NULL, msgLen); } break; // Mask Events response. case SNP_MASK_EVENT_RSP: if ( npiRetMsg.pMsg ) { npiRetMsg.len = msgLen; // Explicitly copy response npiRetMsg.pMsg->maskEventCnf.maskedEvent = BUILD_UINT16(pNPIMsg->pData[0],pNPIMsg->pData[1]); } break; case SNP_GET_REVISION_RSP: if ( npiRetMsg.pMsg ) { npiRetMsg.len = msgLen; // Explicitly copy response npiRetMsg.pMsg->revisionRsp.status = pNPIMsg->pData[0]; npiRetMsg.pMsg->revisionRsp.snpVer = BUILD_UINT16(pNPIMsg->pData[1],pNPIMsg->pData[2]); memcpy(npiRetMsg.pMsg->revisionRsp.stackBuildVer, &pNPIMsg->pData[3], sizeof(npiRetMsg.pMsg->revisionRsp.stackBuildVer)); } break; case SNP_GET_RAND_RSP: if ( npiRetMsg.pMsg ) { npiRetMsg.len = msgLen; // Explicitly copy response npiRetMsg.pMsg->randRsp.rand = BUILD_UINT32(pNPIMsg->pData[0], pNPIMsg->pData[1], pNPIMsg->pData[2], pNPIMsg->pData[3]); } break; // HCI command response case SNP_HCI_CMD_RSP: { snpHciCmdRsp_t hciRsp; // Initialize Response Struct hciRsp.status = pNPIMsg->pData[0]; hciRsp.opcode = BUILD_UINT16(pNPIMsg->pData[1],pNPIMsg->pData[2]); hciRsp.pData = (uint8_t *)&pNPIMsg->pData[3]; if (SNP_asyncCB) { SNP_asyncCB(pNPIMsg->cmd1, (snp_msg_t *)&hciRsp, msgLen); } } break; #endif //SNP_LOCAL case SNP_EVENT_IND: { snpEvt_t pEvt; // Copy non-Pointer members of Event Struct pEvt.event = BUILD_UINT16(pNPIMsg->pData[0],pNPIMsg->pData[1]); // Send event back up to NP. switch(pEvt.event) { case SNP_CONN_EST_EVT: { snpConnEstEvt_t connEstEvt; // Initialize Event connEstEvt.connHandle = BUILD_UINT16(pNPIMsg->pData[2],pNPIMsg->pData[3]); connEstEvt.connInterval = BUILD_UINT16(pNPIMsg->pData[4],pNPIMsg->pData[5]); connEstEvt.slaveLatency = BUILD_UINT16(pNPIMsg->pData[6],pNPIMsg->pData[7]); connEstEvt.supervisionTimeout = BUILD_UINT16(pNPIMsg->pData[8],pNPIMsg->pData[9]); connEstEvt.addressType = pNPIMsg->pData[10]; memcpy(connEstEvt.pAddr, &pNPIMsg->pData[11], sizeof(connEstEvt.pAddr)); pEvt.pEvtParams = (snpEventParam_t *)&connEstEvt; } break; case SNP_CONN_TERM_EVT: { snpConnTermEvt_t connTermEvt; // Initialize Event connTermEvt.connHandle = BUILD_UINT16(pNPIMsg->pData[2],pNPIMsg->pData[3]); connTermEvt.reason = pNPIMsg->pData[4]; pEvt.pEvtParams = (snpEventParam_t *)&connTermEvt; } break; case SNP_CONN_PARAM_UPDATED_EVT: { snpUpdateConnParamEvt_t event; // Initialize Event event.connHandle = BUILD_UINT16(pNPIMsg->pData[2],pNPIMsg->pData[3]); event.connInterval = BUILD_UINT16(pNPIMsg->pData[4],pNPIMsg->pData[5]); event.slaveLatency = BUILD_UINT16(pNPIMsg->pData[6],pNPIMsg->pData[7]); event.supervisionTimeout = BUILD_UINT16(pNPIMsg->pData[8],pNPIMsg->pData[9]); pEvt.pEvtParams = (snpEventParam_t *)&event; } break; case SNP_ADV_STARTED_EVT: case SNP_ADV_ENDED_EVT: { snpAdvStatusEvt_t event; // Initialize Event event.status = pNPIMsg->pData[2]; pEvt.pEvtParams = (snpEventParam_t *)&event; } break; case SNP_ATT_MTU_EVT: { snpATTMTUSizeEvt_t event; // Initialize Event event.connHandle = BUILD_UINT16(pNPIMsg->pData[2],pNPIMsg->pData[3]); event.attMtuSize = BUILD_UINT16(pNPIMsg->pData[4],pNPIMsg->pData[5]); pEvt.pEvtParams = (snpEventParam_t *)&event; } break; case SNP_SECURITY_EVT: { snpSecurityEvt_t event; // Initialize Event event.state = pNPIMsg->pData[2]; event.status = pNPIMsg->pData[3]; pEvt.pEvtParams = (snpEventParam_t *)&event; } break; case SNP_AUTHENTICATION_EVT: { snpAuthenticationEvt_t event; // Initialize Event event.display = pNPIMsg->pData[2]; event.input = pNPIMsg->pData[3]; event.numCmp = BUILD_UINT32(pNPIMsg->pData[4], pNPIMsg->pData[5], pNPIMsg->pData[6], pNPIMsg->pData[7]); pEvt.pEvtParams = (snpEventParam_t *)&event; } break; } // Send to NP layer. if ( SNP_eventCB ) { SNP_eventCB(&pEvt); } } break; case SNP_GET_STATUS_RSP: if ( npiRetMsg.pMsg ) { npiRetMsg.len = msgLen; // Explicitly copy response npiRetMsg.pMsg->getStatusRsp.gapRoleStatus = pNPIMsg->pData[0]; npiRetMsg.pMsg->getStatusRsp.advStatus = pNPIMsg->pData[1]; npiRetMsg.pMsg->getStatusRsp.ATTstatus = pNPIMsg->pData[2]; npiRetMsg.pMsg->getStatusRsp.ATTmethod = pNPIMsg->pData[3]; } break; #ifndef SNP_LOCAL case SNP_TEST_RSP: { snpTestCmdRsp_t rsp; // Initialize Response Struct rsp.memAlo = BUILD_UINT16(pNPIMsg->pData[0],pNPIMsg->pData[1]); rsp.memMax = BUILD_UINT16(pNPIMsg->pData[2],pNPIMsg->pData[3]); rsp.memSize = BUILD_UINT16(pNPIMsg->pData[4],pNPIMsg->pData[5]); if (SNP_asyncCB) { SNP_asyncCB(pNPIMsg->cmd1, (snp_msg_t *)&rsp, msgLen); } } break; #endif //SNP_LOCAL default: // Unknown command break; } } break; /* GAP group */ case SNP_GAP_GRP: { switch(pNPIMsg->cmd1) { #ifndef SNP_LOCAL // GAP Role initialized. case SNP_INIT_DEVICE_CNF: // RFU break; // Advertisement data confirmation case SNP_SET_ADV_DATA_CNF: { snpSetAdvDataCnf_t cnf; cnf.status = pNPIMsg->pData[0]; if (SNP_asyncCB) { SNP_asyncCB(pNPIMsg->cmd1, (snp_msg_t *)&cnf, msgLen); } } case SNP_UPDATE_CONN_PARAM_CNF: { snpUpdateConnParamCnf_t cnf; cnf.status = pNPIMsg->pData[0]; cnf.connHandle = BUILD_UINT16(pNPIMsg->pData[1], pNPIMsg->pData[2]); if (SNP_asyncCB) { SNP_asyncCB(pNPIMsg->cmd1, (snp_msg_t *)&cnf, msgLen); } } break; #endif //SNP_LOCAL // Set GAP parameter response. case SNP_SET_GAP_PARAM_RSP: if ( npiRetMsg.pMsg ) { npiRetMsg.len = msgLen; // Explicitly copy response npiRetMsg.pMsg->setGapParamRsp.status = pNPIMsg->pData[0]; } break; // Get GAP parameter response. case SNP_GET_GAP_PARAM_RSP: if ( npiRetMsg.pMsg ) { npiRetMsg.len = msgLen; // Explicitly copy response npiRetMsg.pMsg->getGapParamRsp.status = pNPIMsg->pData[0]; npiRetMsg.pMsg->getGapParamRsp.paramId = BUILD_UINT16(pNPIMsg->pData[1],pNPIMsg->pData[2]); npiRetMsg.pMsg->getGapParamRsp.status = BUILD_UINT16(pNPIMsg->pData[3],pNPIMsg->pData[4]); } break; #ifdef SNP_LOCAL case SNP_SET_SECURITY_PARAM_RSP: if ( npiRetMsg.pMsg ) { npiRetMsg.len = msgLen; // Explicitly copy response npiRetMsg.pMsg->setSecParamRsp.status = pNPIMsg->pData[0]; } break; case SNP_SEND_AUTHENTICATION_DATA_RSP: if ( npiRetMsg.pMsg ) { npiRetMsg.len = msgLen; // Explicitly copy response npiRetMsg.pMsg->setAuthDataRsp.status = pNPIMsg->pData[0]; } break; case SNP_SET_WHITE_LIST_POLICY_RSP: if ( npiRetMsg.pMsg ) { npiRetMsg.len = msgLen; //Explicitly copy reponse npiRetMsg.pMsg->setWhiteListRsp.status = pNPIMsg->pData[0]; } break; #endif //!SNP_LOCAL default: // Unknown command break; } } break; /* GATT group */ case SNP_GATT_GRP: { switch(pNPIMsg->cmd1) { #ifndef SNP_LOCAL case SNP_ADD_SERVICE_RSP: if ( npiRetMsg.pMsg ) { npiRetMsg.len = msgLen; // Explicitly copy response npiRetMsg.pMsg->addServiceRsp.status = pNPIMsg->pData[0]; } break; case SNP_ADD_CHAR_VAL_DECL_RSP: if ( npiRetMsg.pMsg ) { npiRetMsg.len = msgLen; // Explicitly copy response npiRetMsg.pMsg->addCharValueDecRsp.status = pNPIMsg->pData[0]; npiRetMsg.pMsg->addCharValueDecRsp.attrHandle = BUILD_UINT16(pNPIMsg->pData[1],pNPIMsg->pData[2]); } break; case SNP_ADD_CHAR_DESC_DECL_RSP: if ( npiRetMsg.pMsg ) { uint8_t i = 0; npiRetMsg.len = msgLen; // Explicitly copy response npiRetMsg.pMsg->addCharDescDeclRsp.status = pNPIMsg->pData[0]; npiRetMsg.pMsg->addCharDescDeclRsp.header = pNPIMsg->pData[1]; // Remaining Msg contents are uint16 handles while(i < (msgLen - 2)) { npiRetMsg.pMsg->addCharDescDeclRsp.handles[(i/2)] = BUILD_UINT16(pNPIMsg->pData[2 + i],pNPIMsg->pData[3 + i]); i += 2; } } break; case SNP_REGISTER_SERVICE_RSP: if ( npiRetMsg.pMsg ) { npiRetMsg.len = msgLen; // Explicitly copy response npiRetMsg.pMsg->addCharValueDecRsp.status = pNPIMsg->pData[0]; npiRetMsg.pMsg->addCharValueDecRsp.attrHandle = BUILD_UINT16(pNPIMsg->pData[1],pNPIMsg->pData[2]); } break; case SNP_SET_GATT_PARAM_RSP: if ( npiRetMsg.pMsg ) { npiRetMsg.len = msgLen; // Explicitly copy response npiRetMsg.pMsg->setGattParamRsp.status = pNPIMsg->pData[0]; } break; // Get GATT parameter of predefined NP service response. case SNP_GET_GATT_PARAM_RSP: if ( npiRetMsg.pMsg ) { npiRetMsg.len = msgLen; // Explicitly copy response npiRetMsg.pMsg->getGattParamRsp.serviceID = pNPIMsg->pData[0]; npiRetMsg.pMsg->getGattParamRsp.paramID = pNPIMsg->pData[1]; npiRetMsg.pMsg->getGattParamRsp.pData = (uint8_t *)&pNPIMsg->pData[2]; } break; // Get attribute value from NP response. case SNP_GET_ATTR_VALUE_RSP: //RFU break; // Set attribute value on NP response. case SNP_SET_ATTR_VALUE_RSP: //RFU break; #endif //!SNP_LOCAL case SNP_CHAR_READ_IND: if (SNP_asyncCB) { snpCharReadInd_t readInd; readInd.connHandle = BUILD_UINT16(pNPIMsg->pData[0], pNPIMsg->pData[1]); readInd.attrHandle = BUILD_UINT16(pNPIMsg->pData[2], pNPIMsg->pData[3]); readInd.offset = BUILD_UINT16(pNPIMsg->pData[4], pNPIMsg->pData[5]); readInd.maxSize = BUILD_UINT16(pNPIMsg->pData[6], pNPIMsg->pData[7]); SNP_asyncCB(pNPIMsg->cmd1, (snp_msg_t *)&readInd, msgLen); } break; // Characteristic write indication. case SNP_CHAR_WRITE_IND: { snpCharWriteInd_t writeInd; writeInd.connHandle = BUILD_UINT16(pNPIMsg->pData[0], pNPIMsg->pData[1]); writeInd.attrHandle = BUILD_UINT16(pNPIMsg->pData[2], pNPIMsg->pData[3]); writeInd.rspNeeded = pNPIMsg->pData[4]; writeInd.offset = BUILD_UINT16(pNPIMsg->pData[5], pNPIMsg->pData[6]); writeInd.pData = (uint8_t *)&pNPIMsg->pData[7]; if (SNP_asyncCB) { SNP_asyncCB(pNPIMsg->cmd1, (snp_msg_t *)&writeInd, msgLen); } } break; case SNP_SEND_NOTIF_IND_CNF: if (SNP_asyncCB) { snpNotifIndCnf_t notifCnf; notifCnf.status = pNPIMsg->pData[0]; notifCnf.connHandle = BUILD_UINT16(pNPIMsg->pData[1], pNPIMsg->pData[2]); SNP_asyncCB(pNPIMsg->cmd1, (snp_msg_t *)¬ifCnf, msgLen); } break; case SNP_CCCD_UPDATED_IND: if (SNP_asyncCB) { snpCharCfgUpdatedInd_t cccdInd; cccdInd.connHandle = BUILD_UINT16(pNPIMsg->pData[0], pNPIMsg->pData[1]); cccdInd.cccdHandle = BUILD_UINT16(pNPIMsg->pData[2], pNPIMsg->pData[3]); cccdInd.rspNeeded = pNPIMsg->pData[4]; cccdInd.value = BUILD_UINT16(pNPIMsg->pData[5], pNPIMsg->pData[6]); SNP_asyncCB(pNPIMsg->cmd1, (snp_msg_t *)&cccdInd, msgLen); } break; default: // Unknown command break; } } break; default: // Unknown. break; } #ifndef SNP_LOCAL if (pNPIMsg->cmd0 == SNP_NPI_SYNC_RSP_TYPE) { // This is a synchronous response, signal the application who requested this. SNP_responseReceived(); } #endif //SNP_LOCAL // Ok to deallocate SNP_free(pNPIMsg); }