diff --git a/Control/cardreader_interface.c b/Control/cardreader_interface.c index 242b0c59c4e9d3a7a3214e3f2d8edb172d86120c..423063f55489edd0e7c543f67e2d8c8aadd433d8 100644 --- a/Control/cardreader_interface.c +++ b/Control/cardreader_interface.c @@ -32,8 +32,7 @@ * Card -> Host: other ISO7816 status code (-> abort) **/ - -void unlock(void); +void cardreader_process_message(void); uint8_t check_card_status(uint8_t* msg_buffer, uint8_t length, uint8_t expected_body_length); void cardreader_select_auth_applet(void); uint8_t cardreader_select_auth_applet_result(uint8_t* msg_buffer, uint8_t length); @@ -59,11 +58,11 @@ uint8_t cardreader_sys_get_card_status(void); static uint8_t cardreader_power_state = CARDREADER_POWER_STATE_OFF; static volatile uint8_t cardreader_startup_event = 0; -#define AUTH_STATE_NONE 1 -#define AUTH_STATE_CARD_INSERTED 2 -#define AUTH_STATE_SELECTING_AUTH_APPLET 3 -#define AUTH_STATE_AUTH_REQUESTED_SENT 4 -#define AUTH_STATE_AUTH_VERYFIED 5 +#define AUTH_STATE_NONE 1 //System idle +#define AUTH_STATE_CARD_INSERTED 2 //Card has been inserted into th reader, auth will be started. +#define AUTH_STATE_SELECTING_AUTH_APPLET 3 //APDU to select the portal auth application has been sent. +#define AUTH_STATE_AUTH_REQUESTED_SENT 4 //Authorisation challange has been sent. +#define AUTH_STATE_AUTH_VERYFIED 5 //Authorisation key has been verified, new key has been sent. volatile uint8_t auth_state = AUTH_STATE_NONE; volatile uint16_t state_timeout; @@ -145,8 +144,10 @@ void cardreader_process(void){ return; } - if (!transport_data_available()) return; - + if (transport_data_available()) cardreader_process_message(); +} + +void cardreader_process_message(void){ uint8_t msg_buffer[100]; uint16_t ret = transport_receive_message(msg_buffer, 100, 400); @@ -337,11 +338,13 @@ uint8_t cardreader_update_key_result(uint8_t* msg_buffer, uint8_t length){ // cardreader_display_show_result(1); cardreader_display_clear(); - if (toggle_lock_unlock(cardreader_display_write_sz_P)){ +// if ( + toggle_lock_unlock(cardreader_display_write_sz_P); +// ){ // cardreader_display_write_sz_P(PSTR("Auth Successful")); - cardreader_display_move(0,1); - cardreader_display_write_sz_P(PSTR("Remove Card")); - } +// cardreader_display_move(0,1); +// cardreader_display_write_sz_P(PSTR("Remove Card")); +// } keystore_update_salt(); @@ -448,7 +451,6 @@ void cardreader_display_show_result(uint8_t success){ } } - void cardreader_display_set_backlight(uint8_t on){ cardreader_display_message_t msg = {CARDREADER_MSG_TYPE_DISPALY}; msg.command = CARDREADER_DISPLAY_MSG_SET_BACKLIGHT; @@ -457,4 +459,18 @@ void cardreader_display_set_backlight(uint8_t on){ uint8_t success; transport_receive_message(&success, 1, 3000); +} + +void cardreader_display_show_door_retry(void){ + cardreader_display_move(10,0); + cardreader_display_write_sz_P(PSTR("Retry")); +} + +void cardreader_display_show_door_result(uint8_t success){ + cardreader_display_move(0,1); + if (success) { + cardreader_display_write_sz_P(PSTR("OK, remove card ")); + } else { + cardreader_display_write_sz_P(PSTR("Mechanical Fail!")); + } } \ No newline at end of file diff --git a/Control/cardreader_interface.h b/Control/cardreader_interface.h index 8843bdf5d341f2531639f2ee408d220099178243..eaf9e16d21997c517faf0646652bd055584fa641 100644 --- a/Control/cardreader_interface.h +++ b/Control/cardreader_interface.h @@ -23,4 +23,7 @@ void cardreader_process(void); void cardreader_tick(void); uint8_t cardreader_init_card_key(KEY key); -uint8_t cardreader_clear_card_key(void); \ No newline at end of file +uint8_t cardreader_clear_card_key(void); + +void cardreader_display_show_door_retry(void); +void cardreader_display_show_door_result(uint8_t success); \ No newline at end of file diff --git a/Control/door.c b/Control/door.c index a309e06e9af8cbaaf0b104e22a470f3e62cbad3b..664eaf1374de5380f78be3236d102379fe8b2497 100644 --- a/Control/door.c +++ b/Control/door.c @@ -1,5 +1,6 @@ #include "door.h" #include "log.h" +#include "cardreader_interface.h" //for (un)lock messages uint8_t door_read_pin_status(void); uint8_t door_update_status(uint8_t sensor_status); @@ -20,17 +21,21 @@ const char* const status_names[] PROGMEM = {status_unlocked, status_unlocking, status_locking}; -volatile uint8_t door_status; +uint8_t door_status; -volatile uint8_t sensor_candidate_status; -volatile uint8_t sensor_stability; +uint8_t sensor_candidate_status; +uint8_t sensor_stability; #define DOOR_PIN_NEEDED_STABILITY 4 -#define DOOR_COMMAND_PULSE_TIME 35 //350ms -volatile uint8_t door_command_pulse_time = 0; +#define DOOR_COMMAND_PULSE_TIME 45 //450ms +uint8_t door_command_pulse_time = 0; + +#define DOOR_COMMAND_WAIT_TIMEOUT 900 //9s +uint16_t door_command_wait_timeout = 0; + +uint8_t door_command_retry_count = 0; +#define DOOR_COMMAND_MAX_RETRY 1 -#define DOOR_COMMAND_WAIT_TIMEOUT 1000 //10s -volatile uint16_t door_command_wait_timeout = 0; void door_init(void){ DOOR_PORT &= ~(COMMAND_UNLOCK_PIN | COMMAND_LOCK_PIN); //commnd pins off @@ -52,7 +57,9 @@ void door_init(void){ void door_tick(void){ if (door_command_pulse_time != 0) { door_command_pulse_time--; - if (door_command_pulse_time == 0) DOOR_PORT &= (uint8_t)~(COMMAND_LOCK_PIN|COMMAND_UNLOCK_PIN); + if (door_command_pulse_time == 0) { + DOOR_PORT &= (uint8_t)~(COMMAND_LOCK_PIN|COMMAND_UNLOCK_PIN); + } } if ( ((door_status & DOOR_STATUS_UNLOCKING) && !(door_status & DOOR_STATUS_UNLOCKED)) @@ -60,12 +67,30 @@ void door_tick(void){ door_command_wait_timeout--; if (door_command_wait_timeout == 0){ - printf_P(PSTR("Error: Door command timeout\n")); log_append(LOG_EVENT_DOOR_COMMAND_TIMEOUT, 0); - //TODO: Retry (and turn keymatic power on if currently off) + printf_P(PSTR("Error: Door command timeout!")); - door_status &= (uint8_t)~(DOOR_STATUS_UNLOCKING | DOOR_STATUS_LOCKING); //clear activity flags + if (door_command_retry_count < DOOR_COMMAND_MAX_RETRY){ + printf_P(PSTR(" Retry...\n")); + cardreader_display_show_door_retry(); + uint8_t retry = door_command_retry_count; + + //TODO: turn keymatic power on if currently off? + if (door_status & DOOR_STATUS_UNLOCKING) unlock(); + if (door_status & DOOR_STATUS_LOCKING ) lock(); + //lock/unlock resets the counter, restore it. + door_command_retry_count = retry + 1; + + } else { + + log_append(LOG_EVENT_DOOR_COMMAND_RETRY_FAIL, 0); + + printf_P(" Giving Up :((\n"); + cardreader_display_show_door_result(0); + + door_status &= (uint8_t)~(DOOR_STATUS_UNLOCKING | DOOR_STATUS_LOCKING); //clear activity flags + } } } @@ -95,8 +120,15 @@ uint8_t door_read_pin_status(void){ uint8_t door_update_status(uint8_t sensor_status){ uint8_t new_door_status = (sensor_status & DOOR_STATUS_HW_MASK) | (door_status & DOOR_STATUS_SW_MASK); - if (new_door_status & DOOR_STATUS_LOCKED) new_door_status &= (uint8_t)~DOOR_STATUS_LOCKING; - if (new_door_status & DOOR_STATUS_UNLOCKED) new_door_status &= (uint8_t)~DOOR_STATUS_UNLOCKING; + if ((new_door_status & DOOR_STATUS_LOCKED) && (door_status & DOOR_STATUS_LOCKING)){ + new_door_status &= (uint8_t)~DOOR_STATUS_LOCKING; + cardreader_display_show_door_result(1); + } + + if ((new_door_status & DOOR_STATUS_UNLOCKED) && (door_status & DOOR_STATUS_UNLOCKING)){ + new_door_status &= (uint8_t)~DOOR_STATUS_UNLOCKING; + cardreader_display_show_door_result(1); + } if (is_alarm_status(new_door_status)) new_door_status |= DOOR_STATUS_ALARM; @@ -114,7 +146,7 @@ uint8_t is_alarm_status(uint8_t door_status){ //NOTE: This condition is supposed to trigger, if the door is slammed open. // We can't use the LOCKED sensor, because the connection between lock bolt and frame will be interrupted by this. - // This connection is what the sensor actually detects. TODO: Can we improove this? + // This connection is what the sensor actually detects. TODO: Can we improve this? // The UNLOCKED sensor, however will be uneffected, leaving the lock sensors in an // undefined (neither locked nor unlocked) state. We trigger an alarm if this occurs when the door is open. // Unfortunately the UNLOCKED has shown failures in the past, possibly causing a false alarm. @@ -136,6 +168,7 @@ uint8_t door_get_status(void){ void unlock(void){ door_command_pulse_time = DOOR_COMMAND_PULSE_TIME; door_command_wait_timeout = DOOR_COMMAND_WAIT_TIMEOUT; + door_command_retry_count = 0; door_status = (door_status & (uint8_t)~DOOR_STATUS_LOCKING) | DOOR_STATUS_UNLOCKING; DOOR_PORT = (DOOR_PORT & (uint8_t)~COMMAND_LOCK_PIN) | COMMAND_UNLOCK_PIN; @@ -144,6 +177,9 @@ void unlock(void){ void lock(void){ door_command_pulse_time = DOOR_COMMAND_PULSE_TIME; door_command_wait_timeout = DOOR_COMMAND_WAIT_TIMEOUT; + door_command_retry_count = 0; + +// printf_P(PSTR(".")); door_status = (door_status & (uint8_t)~DOOR_STATUS_UNLOCKING) | DOOR_STATUS_LOCKING; DOOR_PORT = (DOOR_PORT & (uint8_t)~COMMAND_UNLOCK_PIN) | COMMAND_LOCK_PIN; @@ -158,34 +194,47 @@ uint8_t toggle_lock_unlock( void (*msg_target)(const char*) ){ } uint8_t unlock_checked( void (*msg_target)(const char*) ){ + uint8_t ok = 0; + const char* msg; + if (door_status & DOOR_STATUS_UNLOCKED){ - msg_target(PSTR("Already unlocked\n")); + msg = PSTR("Already unlocked\n"); } else if (door_status & DOOR_STATUS_LOCKING){ - msg_target(PSTR("Can't unlock while locking\n")); + msg = PSTR("Can't unlock while locking\n"); } else { unlock(); - msg_target(PSTR("Unlocking...\n")); - return 1; + msg = PSTR("Unlocking...\n"); + ok = 1; } - return 0; + + printf_P(msg); + if (msg_target) msg_target(msg); + + return ok; } uint8_t lock_checked( void (*msg_target)(const char*) ){ + uint8_t ok = 0; + const char* msg; if (is_alarm_status(door_status)){ - msg_target(PSTR("Can't lock in alarm state\n")); + msg = PSTR("Can't lock in alarm state\n"); } else if (door_status & DOOR_STATUS_UNLOCKING) { - msg_target(PSTR("Can't lock while unlocking\n")); + msg = PSTR("Can't lock while unlocking\n"); } else if (door_status & DOOR_STATUS_OPEN){ - msg_target(PSTR("Can't lock while door open\n")); + msg = PSTR("Can't lock while door open\n"); } else if (door_status & DOOR_STATUS_LOCKED){ - msg_target(PSTR("Already locked\n")); + msg = PSTR("Already locked\n"); } else { lock(); - msg_target(PSTR("Locking...\n")); - return 1; + msg = PSTR("Locking...\n"); + ok = 1; } - return 0; + + printf_P(msg); + if (msg_target) msg_target(msg); + + return ok; } uint8_t door_clear_alarm(void){ diff --git a/Control/log.c b/Control/log.c index c2ce307ca0595b2253600904f1e760a05025c132..2158ae36a3f34f80c7d637fdd419dd42645924d9 100644 --- a/Control/log.c +++ b/Control/log.c @@ -5,16 +5,17 @@ #include "door.h" #include "power_monitor.h" -const char log_event_startup[] PROGMEM = "== System Started =="; -const char log_event_alarm_raised[] PROGMEM = "Alarm Raised"; -const char log_event_alarm_changed[] PROGMEM = "State change during Alarm"; -const char log_event_alarm_login[] PROGMEM = "Login during Alarm"; -const char log_event_alarm_disabled[] PROGMEM = "Alarm disabled"; -const char log_event_ac_fail[] PROGMEM = "AC Power Fail"; -const char log_event_ac_return[] PROGMEM = "AC Power Restored"; -const char log_event_main_battery_low[] PROGMEM = "Main Battery Low"; -const char log_event_keymatic_battery_low[] PROGMEM = "Keymatic Battery Low"; -const char log_event_door_command_timeout[] PROGMEM = "Door command Timeout"; +const char log_event_startup[] PROGMEM = "== System Started =="; +const char log_event_alarm_raised[] PROGMEM = "Alarm Raised"; +const char log_event_alarm_changed[] PROGMEM = "State change during Alarm"; +const char log_event_alarm_login[] PROGMEM = "Login during Alarm"; +const char log_event_alarm_disabled[] PROGMEM = "Alarm disabled"; +const char log_event_ac_fail[] PROGMEM = "AC Power Fail"; +const char log_event_ac_return[] PROGMEM = "AC Power Restored"; +const char log_event_main_battery_low[] PROGMEM = "Main Battery Low"; +const char log_event_keymatic_battery_low[] PROGMEM = "Keymatic Battery Low"; +const char log_event_door_command_timeout[] PROGMEM = "Door command Timeout"; +const char log_event_door_command_retry_fail[] PROGMEM = "Door command retry failed"; const char* const event_names[] PROGMEM = {log_event_startup, log_event_alarm_raised, @@ -25,7 +26,8 @@ const char* const event_names[] PROGMEM = {log_event_startup, log_event_ac_return, log_event_main_battery_low, log_event_keymatic_battery_low, - log_event_door_command_timeout}; + log_event_door_command_timeout, + log_event_door_command_retry_fail}; uint8_t log_get_first_entry_index(void){ uint8_t l = eeprom_read_byte(LOG_START_POINTER_LOCATION); diff --git a/Control/log.h b/Control/log.h index 111d446ee20b1c978ef4fdb04d17f6019ee3b9a9..67825eb266c7b72df5abe86125eb9f87c58a82d4 100644 --- a/Control/log.h +++ b/Control/log.h @@ -20,16 +20,17 @@ struct log_entry_t{ #define LOG_START_POINTER_LOCATION ((void*)(EEPROM_SIZE-1)) #define LOG_END_POINTER_LOCATION ((void*)(EEPROM_SIZE-2)) -#define LOG_EVENT_STARTUP 0x00 -#define LOG_EVENT_ALARM_RAISED 0x01 -#define LOG_EVENT_ALARM_CHANGED 0x02 -#define LOG_EVENT_ALARM_LOGIN 0x03 -#define LOG_EVENT_ALARM_DISABLED 0x04 -#define LOG_EVENT_AC_FAIL 0x05 -#define LOG_EVENT_AC_RETURN 0x06 -#define LOG_EVENT_MAIN_BATTERY_LOW 0x07 -#define LOG_EVENT_KEYMATIC_BATTERY_LOW 0x08 -#define LOG_EVENT_DOOR_COMMAND_TIMEOUT 0x09 +#define LOG_EVENT_STARTUP 0x00 +#define LOG_EVENT_ALARM_RAISED 0x01 +#define LOG_EVENT_ALARM_CHANGED 0x02 +#define LOG_EVENT_ALARM_LOGIN 0x03 +#define LOG_EVENT_ALARM_DISABLED 0x04 +#define LOG_EVENT_AC_FAIL 0x05 +#define LOG_EVENT_AC_RETURN 0x06 +#define LOG_EVENT_MAIN_BATTERY_LOW 0x07 +#define LOG_EVENT_KEYMATIC_BATTERY_LOW 0x08 +#define LOG_EVENT_DOOR_COMMAND_TIMEOUT 0x09 +#define LOG_EVENT_DOOR_COMMAND_RETRY_FAIL 0x0A #define LOG_EVENT_NONE 0xFF diff --git a/Control/shell/shell.c b/Control/shell/shell.c index 15f840b439455cf3964be5181917156c9330c8cd..158f3540788fabc21e8fc91bec7d7d105b039127 100644 --- a/Control/shell/shell.c +++ b/Control/shell/shell.c @@ -302,14 +302,14 @@ void cmd_lock(readline_parsed_cmd_t* cmd){ if ((cmd->num_args > 0) && (strcmp(cmd->args[0], "-f") == 0)){ lock(); } else { - lock_checked(print_P); + lock_checked(0); } } void cmd_unlock(readline_parsed_cmd_t* cmd){ if ((cmd->num_args > 0) && (strcmp(cmd->args[0], "-f") == 0)){ unlock(); } else { - unlock_checked(print_P); + unlock_checked(0); } }