/********************************************************************* * @fn osal_nv_delete * * @brief Delete item from NV. This function will fail if the length * parameter does not match the length of the item in NV. * * @param id - Valid NV item Id. * @param len - Length of item to delete. * * @return SUCCESS if item was deleted, * NV_ITEM_UNINIT if item did not exist in NV, * NV_BAD_ITEM_LEN if length parameter not correct, * NV_OPER_FAILED if attempted deletion failed. */ uint8 osal_nv_delete( uint16 id, uint16 len ) { uint16 length; uint16 offset; offset = findItem( id ); if ( offset == OSAL_NV_ITEM_NULL ) { // NV item does not exist return NV_ITEM_UNINIT; } length = osal_nv_item_len( id ); if ( length != len ) { // NV item has different length return NV_BAD_ITEM_LEN; } // Set item header ID to zero to 'delete' the item setItem( findPg, offset, eNvZero ); // Verify that item has been removed offset = findItem( id ); if ( offset != OSAL_NV_ITEM_NULL ) { // Still there return NV_OPER_FAILED; } else { // Yes, it's gone return SUCCESS; } }
/*************************************************************************************************** * @fn MT_SapiReadCfg * * @brief Process SAPI Read Config Commands * * @param pBuf - pointer to received buffer * * @return none ***************************************************************************************************/ void MT_SapiReadCfg(uint8 *pBuf) { uint8 len, retStatus; uint8 cfgId, cmdId; uint8 *pRetBuf; /* Parse header */ cmdId = pBuf[MT_RPC_POS_CMD1]; cfgId = pBuf[MT_RPC_POS_DAT0]; /* Length of item in NV memory */ len = (uint8)osal_nv_item_len(cfgId); pRetBuf = osal_mem_alloc(len+3); if (pRetBuf != NULL) { if (len && ((cfgId != ZCD_NV_NIB) && (cfgId != ZCD_NV_DEVICE_LIST) && (cfgId != ZCD_NV_ADDRMGR) && (cfgId != ZCD_NV_NWKKEY))) { if ((zb_ReadConfiguration(cfgId, len, pRetBuf+3)) == ZSUCCESS) { retStatus = ZSuccess; } else { retStatus = ZFailure; } } else { retStatus = ZInvalidParameter; } if (retStatus != ZSuccess) { /* Don't return garbage with error */ len = 0; } /* Status */ pRetBuf[0] = retStatus; /* Config ID */ pRetBuf[1] = cfgId; /* NV item length */ pRetBuf[2] = len; /* Build and send back the response */ MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_SAPI), cmdId, len+3, pRetBuf ); osal_mem_free(pRetBuf); } }
void deviceManagerInit(void){ ZDO_DeviceAnnce_t * iter, *end; end = table +TABLE_SIZE; for(iter = table; iter != end; iter++){ iter->nwkAddr=INVALID; } osal_nv_item_init(NV_ID, sizeof(ZDO_DeviceAnnce_t)*TABLE_SIZE, table); uint16 size = osal_nv_item_len(NV_ID); if (size > TABLE_SIZE*sizeof(ZDO_DeviceAnnce_t)){ size = TABLE_SIZE*sizeof(ZDO_DeviceAnnce_t); } osal_nv_read(NV_ID, 0, size, table); }
/****************************************************************************** * @fn zb_ReadConfiguration * * @brief The zb_ReadConfiguration function is used to get a * Configuration Protperty from Nonvolatile memory. * * @param configId - The identifier for the configuration property * len - The size of the pValue buffer in bytes * pValue - A buffer to hold the configuration property * * @return none */ uint8 zb_ReadConfiguration( uint8 configId, uint8 len, void *pValue ) { uint8 size; size = (uint8)osal_nv_item_len( configId ); if ( size > len ) { return ZFailure; } else { return( osal_nv_read(configId, 0, size, pValue) ); } }
uint8 cb_ReadConfiguration( uint8 configId, uint8 len, void *pValue ) // it's just check the configId if existed,wont create one,unlikely osal_nv_item_init { uint8 size; size = (uint8)osal_nv_item_len( configId ); if ( size > len ) { return ZFailure; } else { return( osal_nv_read(configId, 0, size, pValue) ); } }
/*************************************************************************************************** * @fn MT_UtilSetPreCfgKey * * @brief Set Pre Cfg Key * * @param pBuf - pointer to the data * * @return void ***************************************************************************************************/ void MT_UtilSetPreCfgKey(uint8 *pBuf) { uint8 retValue = ZFailure; uint8 cmdId; /* parse header */ cmdId = pBuf[MT_RPC_POS_CMD1]; pBuf += MT_RPC_FRAME_HDR_SZ; retValue = osal_nv_write( ZCD_NV_PRECFGKEY, 0, osal_nv_item_len( ZCD_NV_PRECFGKEY ), pBuf); /* Build and send back the response */ MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_UTIL), cmdId, 1, &retValue ); }
/*************************************************************************************************** * @fn MT_UtilSetChannels * * @brief Set Channels * * @param pBuf - pointer to the data * * @return void ***************************************************************************************************/ void MT_UtilSetChannels(uint8 *pBuf) { uint32 tmp32; uint8 retValue = ZFailure; uint8 cmdId; /* parse header */ cmdId = pBuf[MT_RPC_POS_CMD1]; pBuf += MT_RPC_FRAME_HDR_SZ; tmp32 = BUILD_UINT32(pBuf[0], pBuf[1], pBuf[2], pBuf[3]); retValue = osal_nv_write(ZCD_NV_CHANLIST, 0, osal_nv_item_len( ZCD_NV_CHANLIST ), &tmp32); /* Build and send back the response */ MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_UTIL), cmdId, 1, &retValue); }
/*************************************************************************************************** * @fn MT_UtilSetPanID * * @brief Set PanID message * * @param pBuf - pointer to the data * * @return void ***************************************************************************************************/ void MT_UtilSetPanID(uint8 *pBuf) { uint16 temp16; uint8 retValue = ZFailure; uint8 cmdId; /* parse header */ cmdId = pBuf[MT_RPC_POS_CMD1]; pBuf += MT_RPC_FRAME_HDR_SZ; temp16 = BUILD_UINT16(pBuf[0], pBuf[1]); pBuf += sizeof(uint16); retValue = osal_nv_write(ZCD_NV_PANID, 0, osal_nv_item_len( ZCD_NV_PANID ), &temp16); /* Build and send back the response */ MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_UTIL), cmdId, 1, &retValue); }
/*************************************************************************************************** * @fn MT_SysOsalNVLength * * @brief Attempt to get the length to an NV item * * @param uint8 pData - pointer to the data * * @return None ***************************************************************************************************/ void MT_SysOsalNVLength(uint8 *pBuf) { uint16 nvId; uint16 nvLen; uint8 rsp[2]; /* Skip over RPC header */ pBuf += MT_RPC_FRAME_HDR_SZ; /* Get the ID */ nvId = BUILD_UINT16(pBuf[0], pBuf[1]); /* Attempt to get NV item length */ nvLen = osal_nv_item_len( nvId ); rsp[0] = LO_UINT16( nvLen ); rsp[1] = HI_UINT16( nvLen ); /* Build and send back the response */ MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_SYS), MT_SYS_OSAL_NV_LENGTH, 2, rsp); }
/*************************************************************************************************** * @fn MT_SysOsalNVRead * * @brief Read a NV value * * @param uint8 pBuf - pointer to the data * * @return None ***************************************************************************************************/ void MT_SysOsalNVRead(uint8 *pBuf) { uint16 nvId; uint8 nvItemLen=0, nvItemOffset=0; uint8 *pRetBuf=NULL; uint8 respLen; /* Skip over RPC header */ pBuf += MT_RPC_FRAME_HDR_SZ; /* Get the ID */ nvId = BUILD_UINT16(pBuf[0], pBuf[1]); /* Get the offset */ nvItemOffset = pBuf[2]; #if !MT_SYS_OSAL_NV_READ_CERTIFICATE_DATA if ((ZCD_NV_IMPLICIT_CERTIFICATE == nvId) || (ZCD_NV_CA_PUBLIC_KEY == nvId) || (ZCD_NV_DEVICE_PRIVATE_KEY == nvId)) { uint8 tmp[2] = { INVALIDPARAMETER, 0 }; MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_SYS), MT_SYS_OSAL_NV_READ, 2, tmp); return; } #endif #if !MT_SYS_KEY_MANAGEMENT if ( (nvId == ZCD_NV_NWK_ACTIVE_KEY_INFO) || (nvId == ZCD_NV_NWK_ALTERN_KEY_INFO) || ((nvId >= ZCD_NV_TCLK_TABLE_START) && (nvId <= ZCD_NV_TCLK_TABLE_END)) || ((nvId >= ZCD_NV_APS_LINK_KEY_DATA_START) && (nvId <= ZCD_NV_APS_LINK_KEY_DATA_END)) || ((nvId >= ZCD_NV_MASTER_KEY_DATA_START) && (nvId <= ZCD_NV_MASTER_KEY_DATA_END)) || (nvId == ZCD_NV_PRECFGKEY) ) { uint8 tmp1[2] = { INVALIDPARAMETER, 0 }; MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_SYS), MT_SYS_OSAL_NV_READ, 2, tmp1); return; } #endif //!MT_SYS_KEY_MANAGEMENT nvItemLen = osal_nv_item_len(nvId); /* Return only 250 bytes max */ if (nvItemLen > MT_NV_ITEM_MAX_LENGTH) { nvItemLen = MT_NV_ITEM_MAX_LENGTH; } if ((nvItemLen > 0) && ((nvItemLen - nvItemOffset) > 0)) { respLen = nvItemLen - nvItemOffset + 2; } else { respLen = 2; } pRetBuf = osal_mem_alloc(respLen); if (pRetBuf != NULL) { osal_memset(pRetBuf, 0, respLen); /* Default to ZFailure */ pRetBuf[0] = ZFailure; if (respLen > 2) { if (((osal_nv_read( nvId, (uint16)nvItemOffset, (uint16)nvItemLen, &pRetBuf[2])) == ZSUCCESS) && (respLen > 2)) { pRetBuf[0] = ZSuccess; } pRetBuf[1] = nvItemLen - nvItemOffset; } else { pRetBuf[1] = 0; } /* Build and send back the response */ MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_SYS), MT_SYS_OSAL_NV_READ, respLen, pRetBuf ); osal_mem_free(pRetBuf); } }
/********************************************************************* * @fn BindUpgradeTableInNV * * @brief Verifies if the existing table in NV has different size * than the table defined by parameters in the current code. * If different, creates a backup table, deletes the existing * table and creates the new table with the new size. After * this process is done ZCD_NV_BINDING_TABLE NV item contains * only valid records retrieved from the original table, up to * the maximum number of records defined by gNWK_MAX_BINDING_ENTRIES * * @param none * * @return ZSuccess - the Update process was sucessful. * ZFailure - otherwise. */ static uint8 BindUpgradeTableInNV( void ) { uint8 status = ZSuccess; nvBindingHdr_t hdr; uint16 dupLen; uint16 bindLen; uint16 newLen; bool duplicateReady = FALSE; // Size of the Binding table based on current paramenters in the code newLen = sizeof(nvBindingHdr_t) + NV_BIND_ITEM_SIZE; // Size of the Binding table NV item, this is the whole size of the item, // it could inculde invalid records also bindLen = osal_nv_item_len( ZCD_NV_BINDING_TABLE ); // Get the number of valid records from the Binding table osal_nv_read( ZCD_NV_BINDING_TABLE, 0, sizeof(nvBindingHdr_t), &hdr ); // Identify if there is a duplicate NV item, if it is there, that means an // Upgrade process did not finish properly last time // The length function will return 0 if the Backup NV ID does not exist. dupLen = osal_nv_item_len( ZCD_NV_DUPLICATE_BINDING_TABLE ); // A duplicate of the original Binding item will be done if: // 1) A duplicate NV item DOES NOT exist AND the size of the original Binding // item in NV is different (larger/smaller) than the the length calculated // from the parameters in the code. If they are the same there is no need // to do the Upgrade process. // 2) A duplicate NV item exists (probably because the previous upgrade // process was interrupted) and [the original Binding NV items exists AND // has valid recods (it is important to make sure that valid records exist // in the binding table because it is possible that the item was created // but the data was not copied in the previous upgrade process). if ( ( ( dupLen == 0 ) && ( bindLen != newLen ) ) || ( ( dupLen > 0 ) && ( bindLen > 0 ) && ( hdr.numRecs > 0 ) ) ) { // Create a copy from original NV item into a duplicate NV item if ( ( status = nwkCreateDuplicateNV( ZCD_NV_BINDING_TABLE, ZCD_NV_DUPLICATE_BINDING_TABLE ) ) == ZSuccess ) { // Delete the original NV item once the duplicate is ready if ( osal_nv_delete( ZCD_NV_BINDING_TABLE, bindLen ) != ZSuccess ) { status = ZFailure; } else { duplicateReady = TRUE; } } } else if ( ( ( dupLen > 0 ) && ( bindLen == 0 ) ) || ( ( dupLen > 0 ) && ( bindLen > 0 ) && ( hdr.numRecs == 0 ) ) ) { // If for some reason a duplicate NV item was left in the system from a // previous upgrade process and: // 1) The original Binding NV item DOES NOT exist OR // 2) The original Binding NV item exist, but has no valid records. // it is necessary to rely in the data in the Duplicate item to create // the Binding table bindLen = dupLen; duplicateReady = TRUE; } if ( duplicateReady == TRUE ) { // Creates the New Binding table, Copy data from backup and Delete backup NV ID status = BindCopyBackupToNewNV( bindLen, newLen ); } return ( status ); }
/********************************************************************* * @fn BindCopyBackupToNewNV * * @brief Creates the New NV item, copies the backup data into * the New NV ID, and Deletes the duplicate NV item. * * @param dupLen - NV item length of the old Binding table. * @param newLen - NV item length of the new Binding table to be created. * * @return ZSuccess - All the actions were successful. * ZFailure - Any of the actions failed. */ static uint8 BindCopyBackupToNewNV( uint16 dupLen, uint16 newLen ) { uint8 status = ZSuccess; uint16 bindLen; bindLen = osal_nv_item_len( ZCD_NV_BINDING_TABLE ); if ( ( bindLen > 0 ) && ( bindLen != newLen ) ) { // The existing item does not match the New length osal_nv_delete( ZCD_NV_BINDING_TABLE, bindLen ); } // Create Binding Table NV item with the NEW legth if ( osal_nv_item_init( ZCD_NV_BINDING_TABLE, newLen, NULL ) != NV_OPER_FAILED ) { nvBindingHdr_t hdrBackup; // Copy ONLY the valid records from the duplicate NV table into the new table // at the end of this process the table content will be compacted if ( osal_nv_read( ZCD_NV_DUPLICATE_BINDING_TABLE, 0, sizeof(nvBindingHdr_t), &hdrBackup ) == ZSuccess ) { bindTableIndex_t i; uint16 validBackupRecs = 0; BindingEntry_t backupRec; // Read in the device list. This loop will stop when: // The total number of valid records has been reached either because: // The new table is full of valid records OR // The old table has less valid records than the size of the table for ( i = 0; ( validBackupRecs < gNWK_MAX_BINDING_ENTRIES ) && ( validBackupRecs < hdrBackup.numRecs ); i++ ) { if ( osal_nv_read( ZCD_NV_DUPLICATE_BINDING_TABLE, (uint16)(sizeof(nvBindingHdr_t) + (i * NV_BIND_REC_SIZE)), NV_BIND_REC_SIZE, &backupRec ) == ZSuccess ) { if ( backupRec.srcEP != NV_BIND_EMPTY ) { // Save the valid record into the NEW NV table. if ( osal_nv_write( ZCD_NV_BINDING_TABLE, (uint16)((sizeof(nvBindingHdr_t)) + (validBackupRecs * NV_BIND_REC_SIZE)), NV_BIND_REC_SIZE, &backupRec ) != ZSuccess ) { status = ZFailure; break; // Terminate the loop as soon as a problem with NV is detected } validBackupRecs++; } } else { status = ZFailure; break; // Terminate the loop as soon as a problem with NV is detected } } // Only save the header and delete the duplicate element if the previous // process was successful if ( status == ZSuccess ) { // Save off the header if ( osal_nv_write( ZCD_NV_BINDING_TABLE, 0, sizeof(nvBindingHdr_t), &validBackupRecs ) == ZSuccess ) { // Delete the duplicate NV Item, once the data has been stored in the NEW table if ( osal_nv_delete( ZCD_NV_DUPLICATE_BINDING_TABLE, dupLen ) != ZSuccess ) { status = ZFailure; } } else { status = ZFailure; } } } else { status = ZFailure; } } else { status = ZFailure; } return ( status ); }
void GenericApp_Init( uint8 task_id ) { uint16 size; GenericApp_TaskID = task_id; GenericApp_NwkState = DEV_INIT; GenericApp_TransID = 0; uint8 networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE; devStartModes_t devStartMode = MODE_RESUME; //GenericApp_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent; //(afAddrMode_t)Addr16Bit; GenericApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; GenericApp_DstAddr.endPoint = GENERICAPP_ENDPOINT; GenericApp_DstAddr.addr.shortAddr = 0xFFFF; // Fill out the endpoint description. GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT; GenericApp_epDesc.task_id = &GenericApp_TaskID; GenericApp_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc; GenericApp_epDesc.latencyReq = noLatencyReqs; // Register the endpoint description with the AF afRegister( &GenericApp_epDesc ); // Register for all key events - This app will handle all key events RegisterForKeys( GenericApp_TaskID ); // Update the display #if defined ( LCD_SUPPORTED ) HalLcdWriteString( "GenericApp", HAL_LCD_LINE_1 ); #endif #if !defined( ZDO_COORDINATOR ) ZDO_RegisterForZDOMsg( GenericApp_TaskID, End_Device_Bind_rsp ); ZDO_RegisterForZDOMsg( GenericApp_TaskID, Match_Desc_rsp ); #endif #if defined ( BUILD_ALL_DEVICES ) size = osal_nv_item_len( ZCD_NV_LOGICAL_TYPE ); if( size <= sizeof(zgDeviceLogicalType) && size != 0 ) { cb_ReadConfiguration( ZCD_NV_LOGICAL_TYPE, sizeof(zgDeviceLogicalType), &zgDeviceLogicalType); } #endif #if defined ( HOLD_AUTO_START ) if(start_flag == 1) { ZDOInitDevice(0); } #endif serial_init(); init_cc2530(); HalLedSet( HAL_LED_2, HAL_LED_MODE_ON ); }