diff --git a/Makefile b/Makefile index 5d1fbd2f..cae2b943 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,8 @@ TINYUSB_CDC=1 # Now we're all set to include gossamer's make rules. include $(GOSSAMER_PATH)/make.mk +CFLAGS+=-D_POSIX_C_SOURCE=200112L + define n diff --git a/movement_faces.h b/movement_faces.h index e8fb0fe6..d0580fe4 100644 --- a/movement_faces.h +++ b/movement_faces.h @@ -59,6 +59,7 @@ #include "periodic_table_face.h" #include "squash_face.h" #include "totp_face.h" +#include "totp_lfs_face.h" #include "tally_face.h" #include "probability_face.h" #include "ke_decimal_time_face.h" diff --git a/watch-faces.mk b/watch-faces.mk index 0c78fb47..dbd4ebd3 100644 --- a/watch-faces.mk +++ b/watch-faces.mk @@ -14,7 +14,7 @@ SRCS += \ ./watch-faces/complication/days_since_face.c \ ./watch-faces/complication/breathing_face.c \ ./watch-faces/complication/squash_face.c \ - ./watch-faces/complication/totp_face.c \ + ./watch-faces/complication/totp_lfs_face.c \ ./watch-faces/complication/tally_face.c \ ./watch-faces/complication/wordle_face.c \ ./watch-faces/demo/all_segments_face.c \ diff --git a/legacy/watch_faces/complication/totp_face_lfs.c b/watch-faces/complication/totp_lfs_face.c similarity index 87% rename from legacy/watch_faces/complication/totp_face_lfs.c rename to watch-faces/complication/totp_lfs_face.c index 439aca3f..8be3e28d 100644 --- a/legacy/watch_faces/complication/totp_face_lfs.c +++ b/watch-faces/complication/totp_lfs_face.c @@ -33,7 +33,7 @@ #include "watch_utility.h" #include "filesystem.h" -#include "totp_face_lfs.h" +#include "totp_lfs_face.h" #define MAX_TOTP_RECORDS 30 #define MAX_TOTP_SECRET_SIZE 128 @@ -42,7 +42,7 @@ const char* TOTP_URI_START = "otpauth://totp/"; struct totp_record { - char label[2]; + char label[4]; hmac_alg algorithm; uint8_t period; uint8_t secret_size; @@ -67,19 +67,20 @@ static uint8_t num_totp_records = 0; static void init_totp_record(struct totp_record *totp_record) { totp_record->label[0] = 'A'; totp_record->label[1] = 'A'; + totp_record->label[2] = 'A'; + totp_record->label[3] = 0; totp_record->algorithm = SHA1; totp_record->period = 30; totp_record->secret_size = 0; } -static bool totp_face_lfs_read_param(struct totp_record *totp_record, char *param, char *value) { +static bool totp_lfs_face_read_param(struct totp_record *totp_record, char *param, char *value) { if (!strcmp(param, "issuer")) { - if (value[0] == '\0' || value[1] == '\0') { - printf("TOTP issuer must be >= 2 chars, got '%s'\n", value); + if (value[0] == '\0') { + printf("TOTP issuer must be a non-empty string\n"); return false; } - totp_record->label[0] = value[0]; - totp_record->label[1] = value[1]; + snprintf(totp_record->label, sizeof(totp_record->label), "%-3s", value); } else if (!strcmp(param, "secret")) { totp_record->file_secret_length = strlen(value); if (UNBASE32_LEN(totp_record->file_secret_length) > MAX_TOTP_SECRET_SIZE) { @@ -127,7 +128,7 @@ static bool totp_face_lfs_read_param(struct totp_record *totp_record, char *para return true; } -static void totp_face_lfs_read_file(char *filename) { +static void totp_lfs_face_read_file(char *filename) { // For 'format' of file, see comment at top. const size_t uri_start_len = strlen(TOTP_URI_START); @@ -166,7 +167,7 @@ static void totp_face_lfs_read_file(char *filename) { do { char *param_middle = strchr(param, '='); *param_middle = '\0'; - if (totp_face_lfs_read_param(&totp_records[num_totp_records], param, param_middle + 1)) { + if (totp_lfs_face_read_param(&totp_records[num_totp_records], param, param_middle + 1)) { if (!strcmp(param, "secret")) { totp_records[num_totp_records].file_secret_offset = old_offset + (param_middle + 1 - line); } @@ -189,7 +190,7 @@ static void totp_face_lfs_read_file(char *filename) { } } -void totp_face_lfs_setup(uint8_t watch_face_index, void ** context_ptr) { +void totp_lfs_face_setup(uint8_t watch_face_index, void ** context_ptr) { (void) watch_face_index; if (*context_ptr == NULL) { *context_ptr = malloc(sizeof(totp_lfs_state_t)); @@ -197,12 +198,12 @@ void totp_face_lfs_setup(uint8_t watch_face_index, void ** context_ptr) { #if !(__EMSCRIPTEN__) if (num_totp_records == 0) { - totp_face_lfs_read_file(TOTP_FILE); + totp_lfs_face_read_file(TOTP_FILE); } #endif } -static uint8_t *totp_face_lfs_get_file_secret(struct totp_record *record) { +static uint8_t *totp_lfs_face_get_file_secret(struct totp_record *record) { char buffer[BASE32_LEN(MAX_TOTP_SECRET_SIZE) + 1]; int32_t file_secret_offset = record->file_secret_offset; @@ -231,7 +232,7 @@ static void totp_face_set_record(totp_lfs_state_t *totp_state, int i) { record = &totp_records[i]; TOTP( - totp_face_lfs_get_file_secret(record), + totp_lfs_face_get_file_secret(record), record->secret_size, record->period, record->algorithm @@ -240,7 +241,7 @@ static void totp_face_set_record(totp_lfs_state_t *totp_state, int i) { totp_state->steps = totp_state->timestamp / record->period; } -void totp_face_lfs_activate(void *context) { +void totp_lfs_face_activate(void *context) { memset(context, 0, sizeof(totp_lfs_state_t)); totp_lfs_state_t *totp_state = (totp_lfs_state_t *)context; @@ -248,20 +249,20 @@ void totp_face_lfs_activate(void *context) { if (num_totp_records == 0) { // Doing this here rather than in setup makes things a bit more pleasant in the simulator, since there's no easy way to trigger // setup again after uploading the data. - totp_face_lfs_read_file(TOTP_FILE); + totp_lfs_face_read_file(TOTP_FILE); } #endif - totp_state->timestamp = watch_utility_date_time_to_unix_time(watch_rtc_get_date_time(), movement_get_current_timezone_offset()); + totp_state->timestamp = watch_utility_date_time_to_unix_time(movement_get_utc_date_time(), 0); totp_face_set_record(totp_state, 0); } static void totp_face_display(totp_lfs_state_t *totp_state) { uint8_t index = totp_state->current_index; - char buf[14]; + char buf[7]; if (num_totp_records == 0) { - watch_display_string("No2F Codes", 0); + watch_display_text(WATCH_POSITION_FULL, "No2F Codes"); return; } @@ -272,12 +273,14 @@ static void totp_face_display(totp_lfs_state_t *totp_state) { } uint8_t valid_for = totp_records[index].period - result.rem; - sprintf(buf, "%c%c%2d%06lu", totp_records[index].label[0], totp_records[index].label[1], valid_for, totp_state->current_code); - - watch_display_string(buf, 0); + watch_display_text_with_fallback(WATCH_POSITION_TOP_LEFT, totp_records[index].label, totp_records[index].label); + sprintf(buf, "%2d", valid_for); + watch_display_text_with_fallback(WATCH_POSITION_TOP_RIGHT, buf, buf); + sprintf(buf, "%06lu", totp_state->current_code); + watch_display_text_with_fallback(WATCH_POSITION_BOTTOM, buf, buf); } -bool totp_face_lfs_loop(movement_event_t event, void *context) { +bool totp_lfs_face_loop(movement_event_t event, void *context) { totp_lfs_state_t *totp_state = (totp_lfs_state_t *)context; @@ -315,6 +318,6 @@ bool totp_face_lfs_loop(movement_event_t event, void *context) { return true; } -void totp_face_lfs_resign(void *context) { +void totp_lfs_face_resign(void *context) { (void) context; } diff --git a/legacy/watch_faces/complication/totp_face_lfs.h b/watch-faces/complication/totp_lfs_face.h similarity index 88% rename from legacy/watch_faces/complication/totp_face_lfs.h rename to watch-faces/complication/totp_lfs_face.h index 16276a2e..3e18a6a8 100644 --- a/legacy/watch_faces/complication/totp_face_lfs.h +++ b/watch-faces/complication/totp_lfs_face.h @@ -61,16 +61,16 @@ typedef struct { uint8_t current_index; } totp_lfs_state_t; -void totp_face_lfs_setup(uint8_t watch_face_index, void ** context_ptr); -void totp_face_lfs_activate(void *context); -bool totp_face_lfs_loop(movement_event_t event, void *context); -void totp_face_lfs_resign(void *context); +void totp_lfs_face_setup(uint8_t watch_face_index, void ** context_ptr); +void totp_lfs_face_activate(void *context); +bool totp_lfs_face_loop(movement_event_t event, void *context); +void totp_lfs_face_resign(void *context); -#define totp_face_lfs ((const watch_face_t){ \ - totp_face_lfs_setup, \ - totp_face_lfs_activate, \ - totp_face_lfs_loop, \ - totp_face_lfs_resign, \ +#define totp_lfs_face ((const watch_face_t){ \ + totp_lfs_face_setup, \ + totp_lfs_face_activate, \ + totp_lfs_face_loop, \ + totp_lfs_face_resign, \ NULL, \ })