diff --git a/app/src/control_msg.c b/app/src/control_msg.c index 9b0fab67..daa3bde7 100644 --- a/app/src/control_msg.c +++ b/app/src/control_msg.c @@ -278,6 +278,13 @@ sc_control_msg_log(const struct sc_control_msg *msg) { } } +bool +sc_control_msg_is_droppable(const struct sc_control_msg *msg) { + // Cannot drop UHID_CREATE messages, because it would cause all further + // UHID_INPUT messages for this device to be invalid + return msg->type != SC_CONTROL_MSG_TYPE_UHID_CREATE; +} + void sc_control_msg_destroy(struct sc_control_msg *msg) { switch (msg->type) { diff --git a/app/src/control_msg.h b/app/src/control_msg.h index 80714096..63670705 100644 --- a/app/src/control_msg.h +++ b/app/src/control_msg.h @@ -116,6 +116,11 @@ sc_control_msg_serialize(const struct sc_control_msg *msg, uint8_t *buf); void sc_control_msg_log(const struct sc_control_msg *msg); +// Even when the buffer is "full", some messages must absolutely not be dropped +// to avoid inconsistencies. +bool +sc_control_msg_is_droppable(const struct sc_control_msg *msg); + void sc_control_msg_destroy(struct sc_control_msg *msg); diff --git a/app/src/controller.c b/app/src/controller.c index d50e1921..749de0a5 100644 --- a/app/src/controller.c +++ b/app/src/controller.c @@ -4,7 +4,8 @@ #include "util/log.h" -#define SC_CONTROL_MSG_QUEUE_MAX 64 +// Drop droppable events above this limit +#define SC_CONTROL_MSG_QUEUE_LIMIT 60 static void sc_controller_receiver_on_ended(struct sc_receiver *receiver, bool error, @@ -22,7 +23,9 @@ sc_controller_init(struct sc_controller *controller, sc_socket control_socket, void *cbs_userdata) { sc_vecdeque_init(&controller->queue); - bool ok = sc_vecdeque_reserve(&controller->queue, SC_CONTROL_MSG_QUEUE_MAX); + // Add 4 to support 4 non-droppable events without re-allocation + bool ok = sc_vecdeque_reserve(&controller->queue, + SC_CONTROL_MSG_QUEUE_LIMIT + 4); if (!ok) { return false; } @@ -93,20 +96,31 @@ sc_controller_push_msg(struct sc_controller *controller, sc_control_msg_log(msg); } + bool pushed = false; + sc_mutex_lock(&controller->mutex); - bool full = sc_vecdeque_is_full(&controller->queue); - if (!full) { + size_t size = sc_vecdeque_size(&controller->queue); + if (size < SC_CONTROL_MSG_QUEUE_LIMIT) { bool was_empty = sc_vecdeque_is_empty(&controller->queue); sc_vecdeque_push_noresize(&controller->queue, *msg); + pushed = true; if (was_empty) { sc_cond_signal(&controller->msg_cond); } + } else if (!sc_control_msg_is_droppable(msg)) { + bool ok = sc_vecdeque_push(&controller->queue, *msg); + if (ok) { + pushed = true; + } else { + // A non-droppable event must be dropped anyway + LOG_OOM(); + } } - // Otherwise (if the queue is full), the msg is discarded + // Otherwise, the msg is discarded sc_mutex_unlock(&controller->mutex); - return !full; + return pushed; } static bool