Skip to content
Snippets Groups Projects
Commit f47434c4 authored by da1l6's avatar da1l6
Browse files

PortalControl: Implement (un)lock retry, if the door sensor state does not change.

parent f9f7a7a3
No related branches found
No related tags found
No related merge requests found
...@@ -32,8 +32,7 @@ ...@@ -32,8 +32,7 @@
* Card -> Host: other ISO7816 status code (-> abort) * Card -> Host: other ISO7816 status code (-> abort)
**/ **/
void cardreader_process_message(void);
void unlock(void);
uint8_t check_card_status(uint8_t* msg_buffer, uint8_t length, uint8_t expected_body_length); uint8_t check_card_status(uint8_t* msg_buffer, uint8_t length, uint8_t expected_body_length);
void cardreader_select_auth_applet(void); void cardreader_select_auth_applet(void);
uint8_t cardreader_select_auth_applet_result(uint8_t* msg_buffer, uint8_t length); 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); ...@@ -59,11 +58,11 @@ uint8_t cardreader_sys_get_card_status(void);
static uint8_t cardreader_power_state = CARDREADER_POWER_STATE_OFF; static uint8_t cardreader_power_state = CARDREADER_POWER_STATE_OFF;
static volatile uint8_t cardreader_startup_event = 0; static volatile uint8_t cardreader_startup_event = 0;
#define AUTH_STATE_NONE 1 #define AUTH_STATE_NONE 1 //System idle
#define AUTH_STATE_CARD_INSERTED 2 #define AUTH_STATE_CARD_INSERTED 2 //Card has been inserted into th reader, auth will be started.
#define AUTH_STATE_SELECTING_AUTH_APPLET 3 #define AUTH_STATE_SELECTING_AUTH_APPLET 3 //APDU to select the portal auth application has been sent.
#define AUTH_STATE_AUTH_REQUESTED_SENT 4 #define AUTH_STATE_AUTH_REQUESTED_SENT 4 //Authorisation challange has been sent.
#define AUTH_STATE_AUTH_VERYFIED 5 #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 uint8_t auth_state = AUTH_STATE_NONE;
volatile uint16_t state_timeout; volatile uint16_t state_timeout;
...@@ -145,8 +144,10 @@ void cardreader_process(void){ ...@@ -145,8 +144,10 @@ void cardreader_process(void){
return; return;
} }
if (!transport_data_available()) return; if (transport_data_available()) cardreader_process_message();
}
void cardreader_process_message(void){
uint8_t msg_buffer[100]; uint8_t msg_buffer[100];
uint16_t ret = transport_receive_message(msg_buffer, 100, 400); 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){ ...@@ -337,11 +338,13 @@ uint8_t cardreader_update_key_result(uint8_t* msg_buffer, uint8_t length){
// cardreader_display_show_result(1); // cardreader_display_show_result(1);
cardreader_display_clear(); 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_write_sz_P(PSTR("Auth Successful"));
cardreader_display_move(0,1); // cardreader_display_move(0,1);
cardreader_display_write_sz_P(PSTR("Remove Card")); // cardreader_display_write_sz_P(PSTR("Remove Card"));
} // }
keystore_update_salt(); keystore_update_salt();
...@@ -448,7 +451,6 @@ void cardreader_display_show_result(uint8_t success){ ...@@ -448,7 +451,6 @@ void cardreader_display_show_result(uint8_t success){
} }
} }
void cardreader_display_set_backlight(uint8_t on){ void cardreader_display_set_backlight(uint8_t on){
cardreader_display_message_t msg = {CARDREADER_MSG_TYPE_DISPALY}; cardreader_display_message_t msg = {CARDREADER_MSG_TYPE_DISPALY};
msg.command = CARDREADER_DISPLAY_MSG_SET_BACKLIGHT; msg.command = CARDREADER_DISPLAY_MSG_SET_BACKLIGHT;
...@@ -457,4 +459,18 @@ void cardreader_display_set_backlight(uint8_t on){ ...@@ -457,4 +459,18 @@ void cardreader_display_set_backlight(uint8_t on){
uint8_t success; uint8_t success;
transport_receive_message(&success, 1, 3000); 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
...@@ -23,4 +23,7 @@ void cardreader_process(void); ...@@ -23,4 +23,7 @@ void cardreader_process(void);
void cardreader_tick(void); void cardreader_tick(void);
uint8_t cardreader_init_card_key(KEY key); uint8_t cardreader_init_card_key(KEY key);
uint8_t cardreader_clear_card_key(void); uint8_t cardreader_clear_card_key(void);
\ No newline at end of file
void cardreader_display_show_door_retry(void);
void cardreader_display_show_door_result(uint8_t success);
\ No newline at end of file
#include "door.h" #include "door.h"
#include "log.h" #include "log.h"
#include "cardreader_interface.h" //for (un)lock messages
uint8_t door_read_pin_status(void); uint8_t door_read_pin_status(void);
uint8_t door_update_status(uint8_t sensor_status); uint8_t door_update_status(uint8_t sensor_status);
...@@ -20,17 +21,21 @@ const char* const status_names[] PROGMEM = {status_unlocked, ...@@ -20,17 +21,21 @@ const char* const status_names[] PROGMEM = {status_unlocked,
status_unlocking, status_unlocking,
status_locking}; status_locking};
volatile uint8_t door_status; uint8_t door_status;
volatile uint8_t sensor_candidate_status; uint8_t sensor_candidate_status;
volatile uint8_t sensor_stability; uint8_t sensor_stability;
#define DOOR_PIN_NEEDED_STABILITY 4 #define DOOR_PIN_NEEDED_STABILITY 4
#define DOOR_COMMAND_PULSE_TIME 35 //350ms #define DOOR_COMMAND_PULSE_TIME 45 //450ms
volatile uint8_t door_command_pulse_time = 0; 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){ void door_init(void){
DOOR_PORT &= ~(COMMAND_UNLOCK_PIN | COMMAND_LOCK_PIN); //commnd pins off DOOR_PORT &= ~(COMMAND_UNLOCK_PIN | COMMAND_LOCK_PIN); //commnd pins off
...@@ -52,7 +57,9 @@ void door_init(void){ ...@@ -52,7 +57,9 @@ void door_init(void){
void door_tick(void){ void door_tick(void){
if (door_command_pulse_time != 0) { if (door_command_pulse_time != 0) {
door_command_pulse_time--; 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)) if ( ((door_status & DOOR_STATUS_UNLOCKING) && !(door_status & DOOR_STATUS_UNLOCKED))
...@@ -60,12 +67,30 @@ void door_tick(void){ ...@@ -60,12 +67,30 @@ void door_tick(void){
door_command_wait_timeout--; door_command_wait_timeout--;
if (door_command_wait_timeout == 0){ if (door_command_wait_timeout == 0){
printf_P(PSTR("Error: Door command timeout\n"));
log_append(LOG_EVENT_DOOR_COMMAND_TIMEOUT, 0); 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){ ...@@ -95,8 +120,15 @@ uint8_t door_read_pin_status(void){
uint8_t door_update_status(uint8_t sensor_status){ 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); 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_LOCKED) && (door_status & DOOR_STATUS_LOCKING)){
if (new_door_status & DOOR_STATUS_UNLOCKED) new_door_status &= (uint8_t)~DOOR_STATUS_UNLOCKING; 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; 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){ ...@@ -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. //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. // 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 // 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. // 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. // Unfortunately the UNLOCKED has shown failures in the past, possibly causing a false alarm.
...@@ -136,6 +168,7 @@ uint8_t door_get_status(void){ ...@@ -136,6 +168,7 @@ uint8_t door_get_status(void){
void unlock(void){ void unlock(void){
door_command_pulse_time = DOOR_COMMAND_PULSE_TIME; door_command_pulse_time = DOOR_COMMAND_PULSE_TIME;
door_command_wait_timeout = DOOR_COMMAND_WAIT_TIMEOUT; 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_status = (door_status & (uint8_t)~DOOR_STATUS_LOCKING) | DOOR_STATUS_UNLOCKING;
DOOR_PORT = (DOOR_PORT & (uint8_t)~COMMAND_LOCK_PIN) | COMMAND_UNLOCK_PIN; DOOR_PORT = (DOOR_PORT & (uint8_t)~COMMAND_LOCK_PIN) | COMMAND_UNLOCK_PIN;
...@@ -144,6 +177,9 @@ void unlock(void){ ...@@ -144,6 +177,9 @@ void unlock(void){
void lock(void){ void lock(void){
door_command_pulse_time = DOOR_COMMAND_PULSE_TIME; door_command_pulse_time = DOOR_COMMAND_PULSE_TIME;
door_command_wait_timeout = DOOR_COMMAND_WAIT_TIMEOUT; 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_status = (door_status & (uint8_t)~DOOR_STATUS_UNLOCKING) | DOOR_STATUS_LOCKING;
DOOR_PORT = (DOOR_PORT & (uint8_t)~COMMAND_UNLOCK_PIN) | COMMAND_LOCK_PIN; 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*) ){ ...@@ -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 unlock_checked( void (*msg_target)(const char*) ){
uint8_t ok = 0;
const char* msg;
if (door_status & DOOR_STATUS_UNLOCKED){ if (door_status & DOOR_STATUS_UNLOCKED){
msg_target(PSTR("Already unlocked\n")); msg = PSTR("Already unlocked\n");
} else if (door_status & DOOR_STATUS_LOCKING){ } 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 { } else {
unlock(); unlock();
msg_target(PSTR("Unlocking...\n")); msg = PSTR("Unlocking...\n");
return 1; 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 lock_checked( void (*msg_target)(const char*) ){
uint8_t ok = 0;
const char* msg;
if (is_alarm_status(door_status)){ 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) { } 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){ } 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){ } else if (door_status & DOOR_STATUS_LOCKED){
msg_target(PSTR("Already locked\n")); msg = PSTR("Already locked\n");
} else { } else {
lock(); lock();
msg_target(PSTR("Locking...\n")); msg = PSTR("Locking...\n");
return 1; ok = 1;
} }
return 0;
printf_P(msg);
if (msg_target) msg_target(msg);
return ok;
} }
uint8_t door_clear_alarm(void){ uint8_t door_clear_alarm(void){
......
...@@ -5,16 +5,17 @@ ...@@ -5,16 +5,17 @@
#include "door.h" #include "door.h"
#include "power_monitor.h" #include "power_monitor.h"
const char log_event_startup[] PROGMEM = "== System Started =="; const char log_event_startup[] PROGMEM = "== System Started ==";
const char log_event_alarm_raised[] PROGMEM = "Alarm Raised"; 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_changed[] PROGMEM = "State change during Alarm";
const char log_event_alarm_login[] PROGMEM = "Login 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_alarm_disabled[] PROGMEM = "Alarm disabled";
const char log_event_ac_fail[] PROGMEM = "AC Power Fail"; const char log_event_ac_fail[] PROGMEM = "AC Power Fail";
const char log_event_ac_return[] PROGMEM = "AC Power Restored"; 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_main_battery_low[] PROGMEM = "Main Battery Low";
const char log_event_keymatic_battery_low[] PROGMEM = "Keymatic 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_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, const char* const event_names[] PROGMEM = {log_event_startup,
log_event_alarm_raised, log_event_alarm_raised,
...@@ -25,7 +26,8 @@ const char* const event_names[] PROGMEM = {log_event_startup, ...@@ -25,7 +26,8 @@ const char* const event_names[] PROGMEM = {log_event_startup,
log_event_ac_return, log_event_ac_return,
log_event_main_battery_low, log_event_main_battery_low,
log_event_keymatic_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 log_get_first_entry_index(void){
uint8_t l = eeprom_read_byte(LOG_START_POINTER_LOCATION); uint8_t l = eeprom_read_byte(LOG_START_POINTER_LOCATION);
......
...@@ -20,16 +20,17 @@ struct log_entry_t{ ...@@ -20,16 +20,17 @@ struct log_entry_t{
#define LOG_START_POINTER_LOCATION ((void*)(EEPROM_SIZE-1)) #define LOG_START_POINTER_LOCATION ((void*)(EEPROM_SIZE-1))
#define LOG_END_POINTER_LOCATION ((void*)(EEPROM_SIZE-2)) #define LOG_END_POINTER_LOCATION ((void*)(EEPROM_SIZE-2))
#define LOG_EVENT_STARTUP 0x00 #define LOG_EVENT_STARTUP 0x00
#define LOG_EVENT_ALARM_RAISED 0x01 #define LOG_EVENT_ALARM_RAISED 0x01
#define LOG_EVENT_ALARM_CHANGED 0x02 #define LOG_EVENT_ALARM_CHANGED 0x02
#define LOG_EVENT_ALARM_LOGIN 0x03 #define LOG_EVENT_ALARM_LOGIN 0x03
#define LOG_EVENT_ALARM_DISABLED 0x04 #define LOG_EVENT_ALARM_DISABLED 0x04
#define LOG_EVENT_AC_FAIL 0x05 #define LOG_EVENT_AC_FAIL 0x05
#define LOG_EVENT_AC_RETURN 0x06 #define LOG_EVENT_AC_RETURN 0x06
#define LOG_EVENT_MAIN_BATTERY_LOW 0x07 #define LOG_EVENT_MAIN_BATTERY_LOW 0x07
#define LOG_EVENT_KEYMATIC_BATTERY_LOW 0x08 #define LOG_EVENT_KEYMATIC_BATTERY_LOW 0x08
#define LOG_EVENT_DOOR_COMMAND_TIMEOUT 0x09 #define LOG_EVENT_DOOR_COMMAND_TIMEOUT 0x09
#define LOG_EVENT_DOOR_COMMAND_RETRY_FAIL 0x0A
#define LOG_EVENT_NONE 0xFF #define LOG_EVENT_NONE 0xFF
......
...@@ -302,14 +302,14 @@ void cmd_lock(readline_parsed_cmd_t* cmd){ ...@@ -302,14 +302,14 @@ void cmd_lock(readline_parsed_cmd_t* cmd){
if ((cmd->num_args > 0) && (strcmp(cmd->args[0], "-f") == 0)){ if ((cmd->num_args > 0) && (strcmp(cmd->args[0], "-f") == 0)){
lock(); lock();
} else { } else {
lock_checked(print_P); lock_checked(0);
} }
} }
void cmd_unlock(readline_parsed_cmd_t* cmd){ void cmd_unlock(readline_parsed_cmd_t* cmd){
if ((cmd->num_args > 0) && (strcmp(cmd->args[0], "-f") == 0)){ if ((cmd->num_args > 0) && (strcmp(cmd->args[0], "-f") == 0)){
unlock(); unlock();
} else { } else {
unlock_checked(print_P); unlock_checked(0);
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment