/********************************************************************* * @fn gapCentralRole_ProcessOSALMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ static void gapCentralRole_ProcessOSALMsg( osal_event_hdr_t *pMsg ) { switch ( pMsg->event ) { case HCI_GAP_EVENT_EVENT: if ( pMsg->status == HCI_COMMAND_COMPLETE_EVENT_CODE ) { hciEvt_CmdComplete_t *pPkt = (hciEvt_CmdComplete_t *) pMsg; if ( pPkt->cmdOpcode == HCI_READ_RSSI ) { uint16 connHandle = BUILD_UINT16( pPkt->pReturnParam[1], pPkt->pReturnParam[2] ); int8 rssi = (int8) pPkt->pReturnParam[3]; // Report RSSI to app if ( pGapCentralRoleCB && pGapCentralRoleCB->rssiCB ) { pGapCentralRoleCB->rssiCB( connHandle, rssi ); } } } break; case GAP_MSG_EVENT: gapCentralRole_ProcessGAPMsg( (gapEventHdr_t *) pMsg ); break; case GAPCENTRALROLE_RSSI_MSG_EVT: { gapCentralRoleRssi_t *pRssi = ((gapCentralRoleRssiEvent_t *) pMsg)->pRssi; // If link is up and RSSI reads active if (pRssi->connHandle != GAP_CONNHANDLE_ALL && linkDB_Up(pRssi->connHandle)) { // Restart timer osal_CbTimerStart( gapCentralRole_timerCB, (uint8 *) pRssi, pRssi->period, &pRssi->timerId ); // Read RSSI VOID HCI_ReadRssiCmd( pRssi->connHandle ); } } break; default: break; } }
/********************************************************************* * @brief Task Event Processor function. * * Internal function defined in peripheral.h. */ uint16 GAPRole_ProcessEvent( uint8 task_id, uint16 events ) { VOID task_id; // OSAL required parameter that isn't used in this function if ( events & SYS_EVENT_MSG ) { uint8 *pMsg; if ( (pMsg = osal_msg_receive( gapRole_TaskID )) != NULL ) { gapRole_ProcessOSALMsg( (osal_event_hdr_t *)pMsg ); // Release the OSAL message VOID osal_msg_deallocate( pMsg ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } if ( events & GAP_EVENT_SIGN_COUNTER_CHANGED ) { // Sign counter changed, save it to NV VOID osal_snv_write( BLE_NVID_SIGNCOUNTER, sizeof( uint32 ), &gapRole_signCounter ); return ( events ^ GAP_EVENT_SIGN_COUNTER_CHANGED ); } if ( events & START_ADVERTISING_EVT ) { if ( gapRole_AdvEnabled ) { gapAdvertisingParams_t params; // Setup advertisement parameters if ( gapRole_state == GAPROLE_CONNECTED ) { // While in a connection, we can only advertise non-connectable undirected. params.eventType = GAP_ADTYPE_ADV_NONCONN_IND; } else { params.eventType = gapRole_AdvEventType; params.initiatorAddrType = gapRole_AdvDirectType; VOID osal_memcpy( params.initiatorAddr, gapRole_AdvDirectAddr, B_ADDR_LEN ); } params.channelMap = gapRole_AdvChanMap; params.filterPolicy = gapRole_AdvFilterPolicy; if ( GAP_MakeDiscoverable( gapRole_TaskID, ¶ms ) != SUCCESS ) { gapRole_state = GAPROLE_ERROR; if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange ) { pGapRoles_AppCGs->pfnStateChange( gapRole_state ); } } } return ( events ^ START_ADVERTISING_EVT ); } if ( events & RSSI_READ_EVT ) { // Only get RSSI when in a connection if ( (gapRole_state == GAPROLE_CONNECTED) || (gapRole_state == GAPROLE_CONNECTED_ADV) ) { // Ask for RSSI VOID HCI_ReadRssiCmd( gapRole_ConnectionHandle ); // Setup next event if ( gapRole_RSSIReadRate ) { VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate ); } } return ( events ^ RSSI_READ_EVT ); } if ( events & UPDATE_PARAMS_TIMEOUT_EVT ) { // Clear an existing timeout if ( osal_get_timeoutEx( gapRole_TaskID, UPDATE_PARAMS_TIMEOUT_EVT ) ) { VOID osal_stop_timerEx( gapRole_TaskID, UPDATE_PARAMS_TIMEOUT_EVT ); } // The Update Parameters Timeout occurred - Terminate connection VOID GAP_TerminateLinkReq( gapRole_TaskID, gapRole_ConnectionHandle, HCI_DISCONNECT_REMOTE_USER_TERM ); return ( events ^ UPDATE_PARAMS_TIMEOUT_EVT ); } // Discard unknown events return 0; }
/********************************************************************* * @brief Task Event Processor function. * * Internal function defined in peripheral.h. */ uint16 GAPRole_ProcessEvent( uint8 task_id, uint16 events ) { VOID task_id; // OSAL required parameter that isn't used in this function if ( events & SYS_EVENT_MSG ) { uint8 *pMsg; if ( (pMsg = osal_msg_receive( gapRole_TaskID )) != NULL ) { gapRole_ProcessOSALMsg( (osal_event_hdr_t *)pMsg ); // Release the OSAL message VOID osal_msg_deallocate( pMsg ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } if ( events & GAP_EVENT_SIGN_COUNTER_CHANGED ) { // Sign counter changed, save it to NV VOID osal_snv_write( BLE_NVID_SIGNCOUNTER, sizeof( uint32 ), &gapRole_signCounter ); return ( events ^ GAP_EVENT_SIGN_COUNTER_CHANGED ); } if ( events & START_ADVERTISING_EVT ) { if ( gapRole_AdvEnabled ) { gapAdvertisingParams_t params; // Setup advertisement parameters params.eventType = gapRole_AdvEventType; params.initiatorAddrType = gapRole_AdvDirectType; VOID osal_memcpy( params.initiatorAddr, gapRole_AdvDirectAddr, B_ADDR_LEN ); params.channelMap = gapRole_AdvChanMap; params.filterPolicy = gapRole_AdvFilterPolicy; if ( GAP_MakeDiscoverable( gapRole_TaskID, ¶ms ) != SUCCESS ) { gapRole_state = GAPROLE_ERROR; // Notify the application with the new state change if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange ) { pGapRoles_AppCGs->pfnStateChange( gapRole_state ); } } } return ( events ^ START_ADVERTISING_EVT ); } if ( events & RSSI_READ_EVT ) { // Only get RSSI when in a connection if ( gapRole_state == GAPROLE_CONNECTED ) { // Ask for RSSI VOID HCI_ReadRssiCmd( gapRole_ConnectionHandle ); // Setup next event if ( gapRole_RSSIReadRate ) { VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate ); } } return ( events ^ RSSI_READ_EVT ); } if ( events & START_CONN_UPDATE_EVT ) { // Start connection update procedure gapRole_startConnUpdate( GAPROLE_NO_ACTION ); return ( events ^ START_CONN_UPDATE_EVT ); } if ( events & CONN_PARAM_TIMEOUT_EVT ) { // Unsuccessful in updating connection parameters gapRole_HandleParamUpdateNoSuccess(); return ( events ^ CONN_PARAM_TIMEOUT_EVT ); } // Discard unknown events return 0; }
/** * SNP_executeHCIcmd */ uint8_t SNP_executeHCIcmd(snpHciCmdReq_t *pReq, uint16_t dataLen) { bStatus_t stat; uint16_t opcode = pReq->opcode; uint8_t *pData = (uint8_t*)&pReq->pData; uint8_t status = blePending; if(snp_HCIstore.validity) { return SNP_CMD_ALREADY_IN_PROGRESS; } switch (opcode) { case SNP_HCI_OPCODE_EXT_RESET_SYSTEM: { stat = HCI_EXT_ResetSystemCmd(LL_EXT_RESET_SYSTEM_HARD); if(stat == SUCCESS) { status = SNP_SUCCESS; } else { status = bleIncorrectMode; } } break; case SNP_HCI_OPCODE_READ_BDADDR: { stat = HCI_ReadBDADDRCmd(); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_SET_BDADDR: { if(dataLen != B_ADDR_LEN) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_SetBDADDRCmd(pData); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } } break; case SNP_HCI_OPCODE_EXT_SET_TX_POWER: { if(dataLen != sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_SetTxPowerCmd(pData[0]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } } break; case SNP_HCI_OPCODE_EXT_SET_SCA: if(dataLen != sizeof(uint16_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_SetSCACmd((pData[0] &0xFF) + (pData[1] << 8)); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_MODEM_TEST_TX: if(dataLen != 2*sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_ModemTestTxCmd(pData[0], pData[1]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_MODEM_HOP_TEST_TX: stat = HCI_EXT_ModemHopTestTxCmd(); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } break; case SNP_HCI_OPCODE_EXT_MODEM_TEST_RX: if(dataLen != sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_ModemTestRxCmd(pData[0]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_END_MODEM_TEST: stat = HCI_EXT_EndModemTestCmd(); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } break; case SNP_HCI_OPCODE_EXT_ENABLE_PTM: stat = HCI_EXT_EnablePTMCmd(); if(stat == SUCCESS) { status = SNP_SUCCESS; } else { status = stat; } break; case SNP_HCI_OPCODE_EXT_SET_MAX_DTM_TX_POWER: if(dataLen != sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_SetMaxDtmTxPowerCmd(pData[0]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_READ_RSSI: if(dataLen != sizeof(uint16_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_ReadRssiCmd((pData[0] &0xFF) + (pData[1] << 8)); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_LE_RECEIVER_TEST: if(dataLen != sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_LE_ReceiverTestCmd(pData[0]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_LE_TRANSMITTER_TEST: if(dataLen != 3 * sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_LE_TransmitterTestCmd(pData[0], pData[1], pData[2]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_LE_TEST_END: stat = HCI_LE_TestEndCmd(); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } break; case SNP_HCI_OPCODE_EXT_PER: if(dataLen != (sizeof(uint8_t) + sizeof(uint16_t))) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_PacketErrorRateCmd(pData[0] + (pData[1] << 8), pData[2]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_DECRYPT: if(dataLen != (KEYLEN + KEYLEN)) { status = SNP_INVALID_PARAMS; } else { // reverse byte order of key (MSB..LSB required) SNP_ReverseBytes(&pData[0], KEYLEN); // reverse byte order of encText (MSB..LSB required) SNP_ReverseBytes(&pData[KEYLEN], KEYLEN); stat = HCI_EXT_DecryptCmd(&pData[0], &pData[KEYLEN]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_LE_ENCRYPT: if(dataLen != (KEYLEN + KEYLEN)) { status = SNP_INVALID_PARAMS; } else { // reverse byte order of key (MSB..LSB required) SNP_ReverseBytes(&pData[0], KEYLEN); // reverse byte order of encText (MSB..LSB required) SNP_ReverseBytes(&pData[KEYLEN], KEYLEN); stat = HCI_LE_EncryptCmd(&pData[0], &pData[KEYLEN]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_OVERRIDE_SL: if(dataLen != sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_SetSlaveLatencyOverrideCmd(pData[0]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_SET_FAST_TX_RESP_TIME: if(dataLen != sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_SetFastTxResponseTimeCmd(pData[0]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_ONE_PKT_PER_EVT: if(dataLen != sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_OnePktPerEvtCmd(pData[0]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_GET_CONNECTION_INFO: stat = HCI_EXT_GetConnInfoCmd(NULL, NULL, NULL); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } break; default: status = SNP_HCI_CMD_UNKNOWN; break; } return status; }