diff --git a/disk/disk.img b/disk/disk.img index 5896301..ff2c560 100644 Binary files a/disk/disk.img and b/disk/disk.img differ diff --git a/src/defaults.c b/src/defaults.c index 2c8e83b..86c7fad 100644 --- a/src/defaults.c +++ b/src/defaults.c @@ -32,6 +32,8 @@ const config_t default_config = { .only_if_inactive = SCREENSAVER_A_ONLY_IF_INACTIVE, .idle_time_us = (uint64_t)SCREENSAVER_A_IDLE_TIME_SEC * 1000000, .max_time_us = (uint64_t)SCREENSAVER_A_MAX_TIME_SEC * 1000000, + .enable_system_timeout = SCREENSAVER_A_ENABLE_SYSTEM_TIMEOUT, + .max_system_idle_time_us = (uint64_t)SCREENSAVER_A_MAX_SYSTEM_IDLE_TIME_SEC * 1000000 } }, .output[OUTPUT_B] = @@ -52,6 +54,8 @@ const config_t default_config = { .only_if_inactive = SCREENSAVER_B_ONLY_IF_INACTIVE, .idle_time_us = (uint64_t)SCREENSAVER_B_IDLE_TIME_SEC * 1000000, .max_time_us = (uint64_t)SCREENSAVER_B_MAX_TIME_SEC * 1000000, + .enable_system_timeout = SCREENSAVER_B_ENABLE_SYSTEM_TIMEOUT, + .max_system_idle_time_us = (uint64_t)SCREENSAVER_B_MAX_SYSTEM_IDLE_TIME_SEC * 1000000 } }, .enforce_ports = ENFORCE_PORTS, diff --git a/src/handlers.c b/src/handlers.c index 4833449..1313997 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -172,7 +172,7 @@ void handle_keyboard_uart_msg(uart_packet_t *packet, device_t *state) { /* Queue the combined report */ queue_kbd_report(&combined_report, state); - state->last_activity[BOARD_ROLE] = time_us_64(); + state->last_activity[state->active_output] = time_us_64(); } /* Function handles received mouse moves from the other board */ @@ -184,7 +184,7 @@ void handle_mouse_abs_uart_msg(uart_packet_t *packet, device_t *state) { state->pointer_y = mouse_report->y; state->mouse_buttons = mouse_report->buttons; - state->last_activity[BOARD_ROLE] = time_us_64(); + state->last_activity[state->active_output] = time_us_64(); } /* Function handles request to switch output */ diff --git a/src/include/screen.h b/src/include/screen.h index e2a81dc..d2ebbfb 100644 --- a/src/include/screen.h +++ b/src/include/screen.h @@ -35,6 +35,8 @@ typedef struct { uint8_t only_if_inactive; uint64_t idle_time_us; uint64_t max_time_us; + uint8_t enable_system_timeout; + uint64_t max_system_idle_time_us; } screensaver_t; typedef struct { diff --git a/src/include/structs.h b/src/include/structs.h old mode 100644 new mode 100755 diff --git a/src/include/user_config.h b/src/include/user_config.h index e3ce211..bbe488c 100644 --- a/src/include/user_config.h +++ b/src/include/user_config.h @@ -149,6 +149,28 @@ #define SCREENSAVER_A_MAX_TIME_SEC 0 #define SCREENSAVER_B_MAX_TIME_SEC 0 +/**================================================== * + * + * SCREENSAVER_{A|B}_ENABLE_SYSTEM_TIMEOUT: If true, the screensaver will + * stop if there is not activity on any of the outputs exceeding the + * idle time defined below. + * + * */ + +#define SCREENSAVER_A_ENABLE_SYSTEM_TIMEOUT 1 +#define SCREENSAVER_B_ENABLE_SYSTEM_TIMEOUT 1 + +/**================================================== * + * + * SCREENSAVER_{A|B}_MAX_SYSTEM_IDLE_TIME_SEC: Number of seconds that the + * screensaver will run on an output without any activity on any screen + * before being deactivated. 0 for indefinitely. + * + * */ + +#define SCREENSAVER_A_MAX_SYSTEM_IDLE_TIME_SEC 300 +#define SCREENSAVER_B_MAX_SYSTEM_IDLE_TIME_SEC 300 + /**================================================== * * * SCREENSAVER_{A|B}_ONLY_IF_INACTIVE: [0 or 1] 1 means the diff --git a/src/keyboard.c b/src/keyboard.c index 26754f8..22fdf65 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -256,11 +256,11 @@ void send_key(hid_keyboard_report_t *report, device_t *state) { /* Create a combined report from all device states */ hid_keyboard_report_t combined_report; combine_kbd_states(state, &combined_report); + state->last_activity[state->active_output] = time_us_64(); if (CURRENT_BOARD_IS_ACTIVE_OUTPUT) { /* Queue the combined report */ queue_kbd_report(&combined_report, state); - state->last_activity[BOARD_ROLE] = time_us_64(); } else { /* Send the combined report to ensure all keys are included */ queue_packet((uint8_t *)&combined_report, KEYBOARD_REPORT_MSG, KBD_REPORT_LENGTH); @@ -269,19 +269,21 @@ void send_key(hid_keyboard_report_t *report, device_t *state) { /* Decide if consumer control reports go local or to the other board */ void send_consumer_control(uint8_t *raw_report, device_t *state) { + state->last_activity[state->active_output] = time_us_64(); + if (CURRENT_BOARD_IS_ACTIVE_OUTPUT) { queue_cc_packet(raw_report, state); - state->last_activity[BOARD_ROLE] = time_us_64(); } else { queue_packet((uint8_t *)raw_report, CONSUMER_CONTROL_MSG, CONSUMER_CONTROL_LENGTH); } } -/* Decide if consumer control reports go local or to the other board */ +/* Decide if system control reports go local or to the other board */ void send_system_control(uint8_t *raw_report, device_t *state) { + state->last_activity[state->active_output] = time_us_64(); + if (CURRENT_BOARD_IS_ACTIVE_OUTPUT) { queue_system_packet(raw_report, state); - state->last_activity[BOARD_ROLE] = time_us_64(); } else { queue_packet((uint8_t *)raw_report, SYSTEM_CONTROL_MSG, SYSTEM_CONTROL_LENGTH); } diff --git a/src/mouse.c b/src/mouse.c index 776ed72..27572b6 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -123,9 +123,10 @@ enum screen_pos_e update_mouse_position(device_t *state, mouse_values_t *values) /* If we are active output, queue packet to mouse queue, else send them through UART */ void output_mouse_report(mouse_report_t *report, device_t *state) { + state->last_activity[state->active_output] = time_us_64(); + if (CURRENT_BOARD_IS_ACTIVE_OUTPUT) { queue_mouse_report(report, state); - state->last_activity[BOARD_ROLE] = time_us_64(); } else { queue_packet((uint8_t *)report, MOUSE_REPORT_MSG, MOUSE_REPORT_LENGTH); } diff --git a/src/protocol.c b/src/protocol.c index c0e15c1..d3322ff 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -32,7 +32,9 @@ const field_map_t api_field_map[] = { /* Until we increase the payload size from 8 bytes, clamp to avoid exceeding the field size */ { 21, false, UINT64, 7, offsetof(device_t, config.output[0].screensaver.idle_time_us) }, - { 22, false, UINT64, 7, offsetof(device_t, config.output[0].screensaver.max_time_us) }, + { 22, false, UINT8, 1, offsetof(device_t, config.output[0].screensaver.enable_system_timeout) }, + { 23, false, UINT64, 7, offsetof(device_t, config.output[0].screensaver.max_system_idle_time_us) }, + { 24, false, UINT64, 7, offsetof(device_t, config.output[0].screensaver.max_time_us) }, /* Output B */ { 40, false, UINT32, 4, offsetof(device_t, config.output[1].number) }, @@ -47,7 +49,9 @@ const field_map_t api_field_map[] = { { 49, false, UINT8, 1, offsetof(device_t, config.output[1].screensaver.mode) }, { 50, false, UINT8, 1, offsetof(device_t, config.output[1].screensaver.only_if_inactive) }, { 51, false, UINT64, 7, offsetof(device_t, config.output[1].screensaver.idle_time_us) }, - { 52, false, UINT64, 7, offsetof(device_t, config.output[1].screensaver.max_time_us) }, + { 52, false, UINT8, 1, offsetof(device_t, config.output[1].screensaver.enable_system_timeout) }, + { 53, false, UINT64, 7, offsetof(device_t, config.output[1].screensaver.max_system_idle_time_us) }, + { 54, false, UINT64, 7, offsetof(device_t, config.output[1].screensaver.max_time_us) }, /* Common config */ { 70, false, UINT32, 4, offsetof(device_t, config.version) }, diff --git a/src/tasks.c b/src/tasks.c index afb2da1..d8dc82c 100644 --- a/src/tasks.c +++ b/src/tasks.c @@ -108,6 +108,23 @@ void screensaver_task(device_t *state) { if (screensaver->only_if_inactive && CURRENT_BOARD_IS_ACTIVE_OUTPUT) return; + /* + * If a system timeout is enabled, determine the last activity from any output + * and return if the idle time is exceeded + */ + if ( (screensaver->enable_system_timeout == 1) && + (screensaver->max_system_idle_time_us != 0) ) + { + /* Determine the length of time all devices/screens have been inactive */ + uint64_t combined_last_activity = state->last_activity[OUTPUT_A] > state->last_activity[OUTPUT_B] ? + state->last_activity[OUTPUT_A] : state->last_activity[OUTPUT_B]; + uint64_t combined_inactivity_period = time_us_64() - combined_last_activity; + + /* We exceeded the maximum permitted inactivity to play screensaver */ + if ( combined_inactivity_period > screensaver->max_system_idle_time_us ) + return; + } + /* We're active! Now check if it's time to move the cursor yet. */ if (time_us_32() - last_pointer_move < delays[screensaver->mode]) return; diff --git a/src/utils.c b/src/utils.c index 0d96b55..04dba35 100644 --- a/src/utils.c +++ b/src/utils.c @@ -103,6 +103,8 @@ void save_config(device_t *state) { state->config.checksum = checksum; /* Copy the config to buffer and pad the rest with zeros */ + static_assert ( (sizeof(state->page_buffer) > sizeof(config_t)), + "config_t structure has grown beyond a flash page"); memcpy(state->page_buffer, raw_config, sizeof(config_t)); memset(state->page_buffer + sizeof(config_t), 0, FLASH_PAGE_SIZE - sizeof(config_t)); diff --git a/webconfig/config-unpacked.htm b/webconfig/config-unpacked.htm index 0ee7b1f..d001d2c 100644 --- a/webconfig/config-unpacked.htm +++ b/webconfig/config-unpacked.htm @@ -1068,11 +1068,56 @@