diff options
Diffstat (limited to 'common/mkbp_fifo.c')
-rw-r--r-- | common/mkbp_fifo.c | 241 |
1 files changed, 0 insertions, 241 deletions
diff --git a/common/mkbp_fifo.c b/common/mkbp_fifo.c deleted file mode 100644 index 428d6412fc..0000000000 --- a/common/mkbp_fifo.c +++ /dev/null @@ -1,241 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Matrix KeyBoard Protocol FIFO buffer implementation - */ - -#include "atomic.h" -#include "common.h" -#include "keyboard_config.h" -#include "mkbp_event.h" -#include "mkbp_fifo.h" -#include "system.h" -#include "task.h" -#include "util.h" - -/* Console output macros */ -#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args) - -/* - * Common FIFO depth. This needs to be big enough not to overflow if a - * series of keys is pressed in rapid succession and the kernel is too busy - * to read them out right away. - * - * RAM usage is (depth * #cols); A 16-entry FIFO will consume 16x13=208 bytes, - * which is non-trivial but not horrible. - */ - -static uint32_t fifo_start; /* first entry */ -static uint32_t fifo_end; /* last entry */ -static uint32_t fifo_entries; /* number of existing entries */ -static uint8_t fifo_max_depth = FIFO_DEPTH; -static struct ec_response_get_next_event fifo[FIFO_DEPTH]; - -/* - * Mutex for critical sections of mkbp_fifo_add(), which is called - * from various tasks. - */ -K_MUTEX_DEFINE(fifo_add_mutex); -/* - * Mutex for critical sections of fifo_remove(), which is called from the - * hostcmd task and from keyboard_clear_buffer(). - */ -K_MUTEX_DEFINE(fifo_remove_mutex); - -static int get_data_size(enum ec_mkbp_event e) -{ - switch (e) { - case EC_MKBP_EVENT_KEY_MATRIX: - return KEYBOARD_COLS_MAX; - -#ifdef CONFIG_HOST_EVENT64 - case EC_MKBP_EVENT_HOST_EVENT64: - return sizeof(uint64_t); -#endif - - case EC_MKBP_EVENT_HOST_EVENT: - case EC_MKBP_EVENT_BUTTON: - case EC_MKBP_EVENT_SWITCH: - case EC_MKBP_EVENT_SYSRQ: - return sizeof(uint32_t); - default: - /* For unknown types, say it's 0. */ - return 0; - } -} - -/** - * Pop MKBP event data from FIFO - * - * @return EC_SUCCESS if entry popped, EC_ERROR_UNKNOWN if FIFO is empty - */ -static int fifo_remove(uint8_t *buffp) -{ - int size; - - mutex_lock(&fifo_remove_mutex); - if (!fifo_entries) { - /* no entry remaining in FIFO : return last known state */ - int last = (fifo_start + FIFO_DEPTH - 1) % FIFO_DEPTH; - - size = get_data_size(fifo[last].event_type); - - memcpy(buffp, &fifo[last].data, size); - mutex_unlock(&fifo_remove_mutex); - - /* - * Bail out without changing any FIFO indices and let the - * caller know something strange happened. The buffer will - * will contain the last known state of the keyboard. - */ - return EC_ERROR_UNKNOWN; - } - - /* Return just the event data. */ - if (buffp) { - size = get_data_size(fifo[fifo_start].event_type); - /* skip over event_type. */ - memcpy(buffp, &fifo[fifo_start].data, size); - } - - fifo_start = (fifo_start + 1) % FIFO_DEPTH; - atomic_sub(&fifo_entries, 1); - mutex_unlock(&fifo_remove_mutex); - - return EC_SUCCESS; -} - -/*****************************************************************************/ -/* Interface */ - -void mkbp_fifo_depth_update(uint8_t new_max_depth) -{ - fifo_max_depth = new_max_depth; -} - - -void mkbp_fifo_clear_keyboard(void) -{ - int i, new_fifo_entries = 0; - - CPRINTS("clear keyboard MKBP fifo"); - - /* - * Order of these locks is important to prevent deadlock since - * mkbp_fifo_add() may call fifo_remove(). - */ - mutex_lock(&fifo_add_mutex); - mutex_lock(&fifo_remove_mutex); - - /* Reset the end position */ - fifo_end = fifo_start; - - for (i = 0; i < fifo_entries; i++) { - int cur = (fifo_start + i) % FIFO_DEPTH; - - /* Drop keyboard events */ - if (fifo[cur].event_type == EC_MKBP_EVENT_KEY_MATRIX) - continue; - - /* And move other events to the front */ - memmove(&fifo[fifo_end], &fifo[cur], sizeof(fifo[cur])); - fifo_end = (fifo_end + 1) % FIFO_DEPTH; - ++new_fifo_entries; - } - fifo_entries = new_fifo_entries; - - mutex_unlock(&fifo_remove_mutex); - mutex_unlock(&fifo_add_mutex); -} - -void mkbp_clear_fifo(void) -{ - int i; - - CPRINTS("clear MKBP fifo"); - - /* - * Order of these locks is important to prevent deadlock since - * mkbp_fifo_add() may call fifo_remove(). - */ - mutex_lock(&fifo_add_mutex); - mutex_lock(&fifo_remove_mutex); - - fifo_start = 0; - fifo_end = 0; - /* This assignment is safe since both mutexes are held. */ - fifo_entries = 0; - for (i = 0; i < FIFO_DEPTH; i++) - memset(&fifo[i], 0, sizeof(struct ec_response_get_next_event)); - - mutex_unlock(&fifo_remove_mutex); - mutex_unlock(&fifo_add_mutex); -} - -test_mockable int mkbp_fifo_add(uint8_t event_type, const uint8_t *buffp) -{ - uint8_t size; - - mutex_lock(&fifo_add_mutex); - if (fifo_entries >= fifo_max_depth) { - mutex_unlock(&fifo_add_mutex); - CPRINTS("MKBP common FIFO depth %d reached", - fifo_max_depth); - - return EC_ERROR_OVERFLOW; - } - - size = get_data_size(event_type); - fifo[fifo_end].event_type = event_type; - memcpy(&fifo[fifo_end].data, buffp, size); - fifo_end = (fifo_end + 1) % FIFO_DEPTH; - atomic_add(&fifo_entries, 1); - - /* - * If our event didn't generate an interrupt then the host is still - * asleep. In this case, we don't want to queue our event, except if - * another event just woke the host (and wake is already in progress). - */ - if (!mkbp_send_event(event_type) && fifo_entries == 1) - fifo_remove(NULL); - - mutex_unlock(&fifo_add_mutex); - return EC_SUCCESS; -} - -int mkbp_fifo_get_next_event(uint8_t *out, enum ec_mkbp_event evt) -{ - uint8_t t = fifo[fifo_start].event_type; - uint8_t size; - - if (!fifo_entries) - return -1; - - /* - * We need to peek at the next event to check that we were called with - * the correct event. - */ - if (t != (uint8_t)evt) { - /* - * We were called with the wrong event. The next element in the - * FIFO's event type doesn't match with what we were called - * with. Return an error that we're busy. The caller will need - * to call us with the correct event first. - */ - return -EC_ERROR_BUSY; - } - - fifo_remove(out); - - /* Keep sending events if FIFO is not empty */ - if (fifo_entries) - mkbp_send_event(fifo[fifo_start].event_type); - - /* Return the correct size of the data. */ - size = get_data_size(t); - if (size) - return size; - else - return -EC_ERROR_UNKNOWN; -} |