summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Adolfsson <sadolfsson@google.com>2018-04-24 14:53:02 +0200
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2018-06-19 20:02:09 +0000
commit6d53bce60b499d17e1337452bafaed2764d51d74 (patch)
treeb79988e21904106798f311252e322f0ead968fe4
parent528d6adda9997b45af62f598d298bf674357c066 (diff)
downloadchrome-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.c29
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);
}