00001
00048 #include "common.h"
00049 #include "config.h"
00050 #include "aes.h"
00051 #include "cmac.h"
00052 #include "memory.h"
00053 #include "comms.h"
00054 #include "timer.h"
00055 #include "crc.h"
00056 #include "radio.h"
00057
00058
00060 static volatile bool learnModeRequest = false;
00061
00062
00063
00065 #pragma vector = LEARN_MODE_PCINT_VECT
00066 __interrupt void learnModeSwitchHandler(void)
00067 {
00068
00069 if( (LEARN_MODE_INPUT_REG & (1<<LEARN_MODE_INPUT_BIT)) == 0 ) {
00070 learnModeRequest = true;
00071 }
00072 }
00073
00074
00075
00077 #pragma vector = WDT_vect
00078 __interrupt void watchdogInterrupt(void)
00079 {
00080
00081 }
00082
00083
00084
00086 void initCommand( void )
00087 {
00088 DDRC |= (1<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3) | (1<<PC4);
00089 PORTC |= (0<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3) | (1<<PC4);
00090 }
00091
00092
00093
00095 void executeCommand( byte commandCode )
00096 {
00097 byte oldValue = PORTC;
00098 byte LEDMask = (1<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3) | (1<<PC4);
00099 byte oldLEDs = oldValue & LEDMask;
00100
00101 oldValue &= ~LEDMask;
00102
00103 if( commandCode == (1<<1) ) {
00104 PORTC = oldValue |
00105 ( ((oldLEDs << 1) | (oldLEDs >> 4)) & LEDMask );
00106 } else if( commandCode == (1<<2) ) {
00107 PORTC = oldValue |
00108 ( ((oldLEDs >> 1) | (oldLEDs << 4)) & LEDMask );
00109 }
00110 }
00111
00112
00113
00115 void setupLearnModeIO(void)
00116 {
00117 PCICR |= (1<<LEARN_MODE_PCINT_ENABLE_BIT);
00118 LEARN_MODE_PCINT_MASK_REG |= (1<<LEARN_MODE_PCINT_MASK_BIT);
00119 LEARN_MODE_INPUT_DDR &= ~(1<<LEARN_MODE_INPUT_BIT);
00120 LEARN_MODE_INPUT_PULLUP_REG |= (1<<LEARN_MODE_INPUT_BIT);
00121
00122 LEARN_MODE_OUTPUT_DDR |= (1<<LEARN_MODE_OUTPUT_BIT);
00123 LEARN_MODE_OUTPUT_HIGH();
00124 }
00125
00126
00127
00129 void learnMode(void)
00130 {
00131 LEARN_MODE_OUTPUT_LOW();
00132
00133 startLongTimeout();
00134
00135 #ifndef DONT_ERASE_TRANSMITTERS
00136 bool transmittersErasedYet = false;
00137 while( !longTimeout && (transmittersErasedYet == false || transmitterCount < MAX_TRANSMITTERS) ) {
00138 #else
00139 while( !longTimeout && transmitterCount < MAX_TRANSMITTERS) {
00140 #endif
00141
00142 __watchdog_reset();
00143 WDTCSR |= (1<<WDIE);
00144
00145 enableReception( sizeof( LearnMessage ) );
00146 while( !messageComplete() && !receiverTimedOut() && !longTimeout ) {
00147
00148 if( !(WDTCSR & (1<<WDIE)) ) {
00149 __watchdog_reset();
00150 WDTCSR |= (1<<WDIE);
00151 }
00152 __sleep();
00153 }
00154
00155 if( messageComplete() ) {
00156 initCRC();
00157 byte i;
00158 for( i = 0; i < sizeof( LearnMessage ); ++i ) {
00159 calcCRC( ( (byte *) &receiveBuffer.learnMessage )[ i ] );
00160 }
00161 if( (CRCReg[0] == 0) && (CRCReg[1] == 0) ) {
00162 LEARN_MODE_OUTPUT_HIGH();
00163 copyBytesFromEEPROM( tempKeyStorage, sharedKey, KEY_SIZE );
00164 prepareInvCipher( scheduleBuffer, tempKeyStorage );
00165 invCipher( receiveBuffer.learnMessage.secretKey,
00166 scheduleBuffer );
00167 #if KEY_SIZE == 24 || KEY_SIZE == 32
00168 prepareInvCipher( scheduleBuffer, tempKeyStorage );
00169 invCipher( receiveBuffer.learnMessage.secretKey + BLOCK_SIZE,
00170 scheduleBuffer );
00171 #endif
00172 #ifndef DONT_ERASE_TRANSMITTERS
00173 if( transmittersErasedYet == false ) {
00174 eraseTransmitters();
00175 transmittersErasedYet = true;
00176 }
00177 #endif
00178
00179 transmitters[ transmitterCount ].serialNo =
00180 receiveBuffer.learnMessage.serialNo;
00181 transmitters[ transmitterCount ].lastCounterValue =
00182 receiveBuffer.learnMessage.lastCounterValue;
00183 copyBytesToEEPROM( transmitters[ transmitterCount ].secretKey,
00184 receiveBuffer.learnMessage.secretKey, KEY_SIZE );
00185 ++transmitterCount;
00186 LEARN_MODE_OUTPUT_LOW();
00187
00188 startLongTimeout();
00189 }
00190 }
00191 }
00192
00193 stopTimer();
00194 LEARN_MODE_OUTPUT_HIGH();
00195 }
00196
00197
00198
00199
00200
00202 void errorLoop( byte blinkCount )
00203 {
00204
00205 __watchdog_reset();
00206 WDTCSR = (1<<WDCE) | (1<<WDE);
00207 WDTCSR = (1<<WDCE) | (1<<WDE) | (1<<WDP3) | (1<<WDP0);
00208 WDTCSR |= (1<<WDIF) | (1<<WDIE);
00209
00210
00211 SMCR = (0<<SM2) | (1<<SM1) | (0<<SM0) | (1<<SE);;
00212
00213
00214 __enable_interrupt();
00215 LEARN_MODE_OUTPUT_DDR |= (1<<LEARN_MODE_OUTPUT_BIT);
00216 for(;;) {
00217 __sleep();
00218 __watchdog_reset();
00219 WDTCSR |= (1<<WDIE);
00220 byte blinks;
00221 for( blinks = 0; blinks < blinkCount; ++blinks ) {
00222 LEARN_MODE_OUTPUT_LOW();
00223 __delay_cycles( (CPU_F/1000)*50 );
00224 LEARN_MODE_OUTPUT_HIGH();
00225 __delay_cycles( (CPU_F/1000)*50 );
00226 }
00227 }
00228 }
00229
00230
00231
00233 void handleResetFlags( void )
00234 {
00235 static __no_init byte __eeprom watchdogResetCount;
00236
00237
00238 byte resetFlags = MCUSR;
00239 MCUSR = 0x00;
00240
00241
00242 if( resetFlags & (1<<PORF) ) {
00243
00244 watchdogResetCount = 0;
00245 }
00246 if( resetFlags & (1<<WDRF) ) {
00247 if( watchdogResetCount >= MAX_WATCHDOG_RESETS ) {
00248 errorLoop( 1 );
00249 } else {
00250 ++watchdogResetCount;
00251 }
00252 }
00253
00254 }
00255
00256
00257
00259 void setupPeripherals( void )
00260 {
00261
00262 __watchdog_reset();
00263 WDTCSR = (1<<WDCE) | (1<<WDE);
00264 WDTCSR = (1<<WDCE) | (1<<WDE) | (1<<WDP3) | (1<<WDP0);
00265 WDTCSR |= (1<<WDIF) | (1<<WDIE);
00266
00267
00268 ACSR = (1<<ACD);
00269
00270
00271
00272
00273
00274 SMCR = (0<<SM2) | (0<<SM1) | (0<<SM0) | (1<<SE);
00275 }
00276
00277
00278
00279 void main( void )
00280 {
00281 handleResetFlags();
00282 __delay_cycles( 8000000 );
00283 if( !initReceiver() ) {
00284 errorLoop( 3 );
00285 }
00286 setupPeripherals();
00287 setupLearnModeIO();
00288 initCommand();
00289 __enable_interrupt();
00290
00291 for(;;) {
00292
00293 stopTimer();
00294 enableReception( sizeof( CommandMessage ) );
00295
00296
00297 __watchdog_reset();
00298 WDTCSR |= (1<<WDIE);
00299
00300
00301 while( messageBytesReceived() < SERIAL_NO_BYTES &&
00302 !receiverTimedOut() &&
00303 !learnModeRequest) {
00304
00305
00306
00307 if( !(WDTCSR & (1<<WDIE)) ) {
00308 __watchdog_reset();
00309 WDTCSR |= (1<<WDIE);
00310 rx_WriteOFF( false );
00311 }
00312 __sleep();
00313 }
00314
00315
00316 if( learnModeRequest ) {
00317 learnMode();
00318 learnModeRequest = false;
00319 continue;
00320 }
00321
00322 if( receiverTimedOut() ) {
00323 continue;
00324 }
00325
00326
00327 byte transmitterIdx = 0;
00328 TransmitterInfo __eeprom * transmitter = transmitters;
00329 bool found = false;
00330 while( transmitterIdx < transmitterCount && !found) {
00331 if( receiveBuffer.commandMessage.serialNo ==
00332 transmitter->serialNo ) {
00333 found = true;
00334 } else {
00335 ++transmitterIdx;
00336 ++transmitter;
00337 }
00338 }
00339
00340
00341 if( !found ) {
00342 while( !messageComplete() && !receiverTimedOut() ) {
00343 __sleep();
00344 }
00345
00346 continue;
00347 }
00348
00349
00350 copyBytesFromEEPROM( tempKeyStorage,
00351 transmitter->secretKey,
00352 KEY_SIZE );
00353
00354
00355 calcCMACSubkey( CMACSubkey, scheduleBuffer,
00356 tempKeyStorage );
00357
00358
00359 while( messageBytesReceived() <
00360 SERIAL_NO_BYTES + SEQ_COUNTER_BYTES &&
00361 !receiverTimedOut() ) {
00362 __sleep();
00363 }
00364
00365 if( receiverTimedOut() ) {
00366 continue;
00367 }
00368
00369
00370 if( receiveBuffer.commandMessage.counterValue -
00371 (transmitter->lastCounterValue + 1) >=
00372 WINDOW_SIZE ) {
00373 while( !messageComplete() && !receiverTimedOut() ) {
00374 __sleep();
00375 }
00376
00377 continue;
00378 }
00379
00380
00381 while( messageBytesReceived() <
00382 SERIAL_NO_BYTES + SEQ_COUNTER_BYTES +
00383 COMMAND_CODE_BYTES &&
00384 !receiverTimedOut() ) {
00385 __sleep();
00386 }
00387
00388 if( receiverTimedOut() ) {
00389 continue;
00390 }
00391
00392
00393 calcCMAC( (const byte *) &receiveBuffer.commandMessage.serialNo,
00394 CMACSubkey,
00395 scheduleBuffer,
00396 tempKeyStorage,
00397 cryptoBlock );
00398
00399
00400 while( !messageComplete() && !receiverTimedOut() ) {
00401 __sleep();
00402 }
00403
00404 if( receiverTimedOut() ) {
00405 continue;
00406 }
00407
00408
00409 byte MACIdx = 0;
00410 bool stillMatches = true;
00411 byte * generatedMAC = cryptoBlock;
00412 byte * receivedMAC = receiveBuffer.commandMessage.MAC;
00413 while( MACIdx < MAC_BYTES && stillMatches ) {
00414 if( *generatedMAC++ != *receivedMAC++ ) {
00415 stillMatches = false;
00416 }
00417 ++MACIdx;
00418 }
00419
00420
00421 if( stillMatches ) {
00422 executeCommand( receiveBuffer.commandMessage.
00423 commandCode );
00424 transmitter->lastCounterValue =
00425 receiveBuffer.commandMessage.counterValue;
00426 }
00427 }
00428 }