diff options
author | Stefan Adolfsson <sadolfsson@google.com> | 2018-04-24 14:53:02 +0200 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2018-06-19 20:02:09 +0000 |
commit | 6d53bce60b499d17e1337452bafaed2764d51d74 (patch) | |
tree | b79988e21904106798f311252e322f0ead968fe4 | |
parent | 528d6adda9997b45af62f598d298bf674357c066 (diff) | |
download | chrome-ec-6d53bce60b499d17e1337452bafaed2764d51d74.tar.gz |
npcx: CEC: Add software debouncing
If pulses shorter than the CEC specification allows are detected,
ignore the bus for a while. This avoids CPU stress if there is a
misbehaving device sending short pulses on the CEC bus.
Signed-off-by: Stefan Adolfsson <sadolfsson@chromium.org>
BUG=b:76467407
BRANCH=none
TEST=none
CQ-DEPEND=CL:1030228
Reviewed-on: https://chromium-review.googlesource.com/1030229
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Change-Id: I55819f9437a00799718e235c30f256508465bf4c
Reviewed-on: https://chromium-review.googlesource.com/1055828
Tested-by: Stefan Adolfsson <sadolfsson@chromium.org>
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Commit-Queue: Stefan Adolfsson <sadolfsson@chromium.org>
-rw-r--r-- | chip/npcx/cec.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/chip/npcx/cec.c b/chip/npcx/cec.c index 9b94b281d2..566e9a0ab6 100644 --- a/chip/npcx/cec.c +++ b/chip/npcx/cec.c @@ -90,6 +90,19 @@ #define DATA_LOW(data) DATA_TIME(LOW, data) /* + * Number of short pulses seen before the debounce logic goes into ignoring + * the bus for DEBOUNCE_WAIT_LONG instead of DEBOUNCE_WAIT_SHORT + */ +#define DEBOUNCE_CUTOFF 3 + +/* The limit how short a start-bit can be to trigger debounce logic */ +#define DEBOUNCE_LIMIT APB1_TICKS(200) +/* The time we ignore the bus for the first three debounce cases */ +#define DEBOUNCE_WAIT_SHORT APB1_TICKS(100) +/* The time we ignore the bus after the three initial debounce cases */ +#define DEBOUNCE_WAIT_LONG APB1_TICKS(500) + +/* * The variance in timing we allow outside of the CEC specification for * incoming signals. Our measurements aren't 100% accurate either, so this * gives some robustness. @@ -142,6 +155,7 @@ enum cec_state { CEC_STATE_INITIATOR_ACK_VERIFY, CEC_STATE_FOLLOWER_START_LOW, CEC_STATE_FOLLOWER_START_HIGH, + CEC_STATE_FOLLOWER_DEBOUNCE, CEC_STATE_FOLLOWER_HEADER_INIT_LOW, CEC_STATE_FOLLOWER_HEADER_INIT_HIGH, CEC_STATE_FOLLOWER_HEADER_DEST_LOW, @@ -203,6 +217,8 @@ struct cec_rx { * pulse duration */ int low_time; + /* Number of too short pulses seen in a row */ + int debounce_count; }; /* Transfer buffer and states */ @@ -550,9 +566,18 @@ void enter_state(enum cec_state new_state) timeout = CAP_START_LOW; break; case CEC_STATE_FOLLOWER_START_HIGH: + cec_rx.debounce_count = 0; cap_edge = CAP_EDGE_FALLING; timeout = CAP_START_HIGH; break; + case CEC_STATE_FOLLOWER_DEBOUNCE: + if (cec_rx.debounce_count >= DEBOUNCE_CUTOFF) { + timeout = DEBOUNCE_WAIT_LONG; + } else { + timeout = DEBOUNCE_WAIT_SHORT; + cec_rx.debounce_count++; + } + break; case CEC_STATE_FOLLOWER_HEADER_INIT_LOW: case CEC_STATE_FOLLOWER_HEADER_DEST_LOW: case CEC_STATE_FOLLOWER_EOM_LOW: @@ -723,6 +748,7 @@ static void cec_event_timeout(void) break; case CEC_STATE_FOLLOWER_START_LOW: case CEC_STATE_FOLLOWER_START_HIGH: + case CEC_STATE_FOLLOWER_DEBOUNCE: case CEC_STATE_FOLLOWER_HEADER_INIT_LOW: case CEC_STATE_FOLLOWER_HEADER_INIT_HIGH: case CEC_STATE_FOLLOWER_HEADER_DEST_LOW: @@ -765,6 +791,9 @@ static void cec_event_cap(void) if (VALID_LOW(START_BIT, t)) { cec_rx.low_time = t; enter_state(CEC_STATE_FOLLOWER_START_HIGH); + } else if (t < DEBOUNCE_LIMIT) { + /* Wait a bit if start-pulses are really short */ + enter_state(CEC_STATE_FOLLOWER_DEBOUNCE); } else { enter_state(CEC_STATE_IDLE); } |