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