1 // *********************************************************************************************************** 2 // Custom DPA Handler code example - OTK - Node * 3 // *********************************************************************************************************** 4 // Copyright (c) MICRORISC s.r.o. 5 // 6 // File: $RCSfile: CustomDpaHandler-OTK-Node.c,v $ 7 // Version: $Revision: 1.12 $ 8 // Date: $Date: 2021/08/18 20:43:06 $ 9 // 10 // Revision history: 11 // 2021/08/18 Release for DPA 4.16 12 // 13 // ********************************************************************* 14 15 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/ 16 17 /* 18 This handler allows Node prebonding by NFC Reader "IQD-NFC-01" using OTK (One Time Key) stored at NFC EEPROM of the Node. 19 New OTK is generated upon [1] the restart/reset or when [2] there is an RF NFC activity detected. 20 The Current OTK is stored to the designated IQRF OS buffer to allow SmartConnect prebonding from the NFC Reader device. 21 Default DPA LED indication is unchanged. 22 */ 23 24 // Default IQRF include (modify the path according to your setup) 25 #include "IQRF.h" 26 27 // Default DPA header (modify the path according to your setup) 28 #include "DPA.h" 29 // Default Custom DPA Handler header (modify the path according to your setup) 30 #include "DPAcustomHandler.h" 31 // Libraries 32 #include "lib/NFC.c" 33 34 //############################################################################################ 35 36 // This HWPID 37 #define _HWPID_ 0x888F 38 // I2C SCL frequency [Hz] 39 #define I2Cfrequency 100000 40 // Bonding button timeout [ms] before [N] goes to sleep 41 #define BONDING_BUTTON_TIMEOUT ( 5 * 1000 ) 42 43 // OTK address at NFC EEPROM 44 #define OTK_NFC_EE_ADDRESS 44 45 // OTK Length 46 #define OTK_Length 16 47 48 // Generates new OTK at NFC EEPROM and loads the old one to the IQRF OS place 49 void NewOtk(); 50 // Switches NFC on 51 void NFCon(); 52 // Switches NFC off 53 void NFCoff(); 54 55 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location! 56 //############################################################################################ 57 bit CustomDpaHandler() 58 //############################################################################################ 59 { 60 #pragma updateBank default=UserBank_01 61 62 // Handler presence mark 63 clrwdt(); 64 65 // Detect DPA event to handle 66 switch ( GetDpaEvent() ) 67 { 68 // ------------------------------------------------- 69 case DpaEvent_Interrupt: 70 // Do an extra quick background interrupt work 71 return Carry; 72 73 // ------------------------------------------------- 74 case DpaEvent_Reset: 75 // Do a one time initialization before main loop starts 76 { 77 static bit wasReset; 78 // It this a very first reset event? 79 if ( !wasReset ) 80 { 81 // Reset the flag 82 wasReset = TRUE; 83 // Start I2C 84 _DpaApiI2Cinit( I2CcomputeFrequency( I2Cfrequency ) ); 85 // Switch NFC on 86 NFCon(); 87 // Update IQRF Code and configure NFC EEPROM if needed 88 // Note: To save the code the next call can be omitted supposed it was called at least once, for example during product manufacturing/testing 89 NfcUpdateIQRFcode(); 90 // Or just the plain NFC configuration in case IQRF Code is not required for SmartConnect bonding 91 //NfcConfigure(); 92 // Generate fresh new OTK at NFC EEPROM and make sure the OS buffer does not contain even the last one 93 NewOtk(); 94 NewOtk(); 95 } 96 97 break; 98 } 99 100 // ------------------------------------------------- 101 case DpaEvent_Init: 102 // Do a one time initialization before main loop starts 103 104 // Optional Bonding/Unbonding is over so switch off NFC just in case it was on because of previous bonding 105 _NfcAndI2Coff: 106 NFCoff(); 107 // We do not need I2C any more (in this example) 108 _DpaApiI2Cshutdown(); 109 break; 110 111 // ------------------------------------------------- 112 case DpaEvent_BondingButton: 113 // Called to allow a bonding button customization. This event is called regularly during bonding. 114 115 // Keep the NFC and I2C on during the bonding in order to keep value of IT_STS_Dyn _volatile_ register in the NFC chip 116 _DpaApiI2Cinit( I2CcomputeFrequency( I2Cfrequency ) ); 117 NFCon(); 118 119 // Check, if there was an RF NFC activity detected by checking IT_STS_Dyn.RF_ACTIVITY 120 if ( NfcReadByte( 0x2005 /* IT_STS_Dyn */, I2C_ADDRESS_NFC ) & 0x02 /* b1=RF_ACTIVITY */ ) 121 { 122 // Yes there was an RF activity, hopefully OTK was read from the NFC EEPROM 123 // Generate new OTK in the NFC EEPROM 124 NewOtk(); 125 // Restart the full bonding timeout to keep the device up and ready for the prebonding from the NFC reader 126 goto _RestartBondingTimeout; 127 } 128 129 // We can inspect BondingSleepCountdown value to detect important moments 130 switch ( BondingSleepCountdown ) 131 { 132 // Was the BondingSleepCountdown just initiated? 133 case 0: 134 _RestartBondingTimeout: 135 // Yes, reset the timeout variable to BONDING_BUTTON_TIMEOUT 136 BondingSleepCountdown = BONDING_BUTTON_TIMEOUT / BONDING_SLEEP_COUNTDOWN_UNIT; 137 break; 138 139 // Are we very probably just about one decrement away to go to sleep because of bonding timeout value is close to 0? 140 case 0 + 1: 141 // Yes, switch off NFC and I2C in order to minimize power consumption during the sleep 142 goto _NfcAndI2Coff; 143 } 144 145 break; 146 } 147 148 return FALSE; 149 } 150 #pragma updateBank 1 151 152 //############################################################################################ 153 void NewOtk() 154 //############################################################################################ 155 { 156 // Read current OTK from NFC EEPROM to bufferRF 157 NfcReadBytes( OTK_NFC_EE_ADDRESS, OTK_Length, I2C_ADDRESS_NFC ); 158 // Set OTK to IQRF OS to allow prebonding via SmartConnect from NFC Reader device 159 DpaApiSetOTK(); 160 // Modify OTK bytes randomly 161 bufferRF[0] += Random.high8; 162 bufferRF[1] += Random.low8; 163 bufferRF[2] += TMR1L; 164 // "Encrypt" i.e. generate new OTK@RF using UserKey 165 // !!! Set your own UserKey from a default one in advance 166 decryptBufferRF( OTK_Length / 16 ); 167 // Store new OTK to NFC EE 168 NfcWriteBytes( OTK_NFC_EE_ADDRESS, OTK_Length, I2C_ADDRESS_NFC ); 169 } 170 171 //############################################################################################ 172 void NFCon() 173 //############################################################################################ 174 { 175 // Set the output pin to power NFC 176 TRISC.6 = 0; 177 // NFC is off? 178 if ( !LATC.6 ) 179 { 180 // Set the output high 181 LATC.6 = 1; 182 // Do a short power-up delay 183 waitMS( 1 ); 184 } 185 } 186 187 //############################################################################################ 188 void NFCoff() 189 //############################################################################################ 190 { 191 LATC.6 = 0; 192 } 193 194 //############################################################################################ 195 // Libraries 196 #include "lib/NFC.c" 197 // Default Custom DPA Handler header; 2nd include to implement Code bumper to detect too long code of the Custom DPA Handler (modify the path according to your setup) 198 #include "DPAcustomHandler.h" 199 //############################################################################################