From eda45b4df2f8f9adf2ab79f7b8e2b2180cdf7a63 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Beat=20K=C3=BCng?= <beat-kueng@gmx.net>
Date: Fri, 14 Dec 2018 12:11:16 +0100
Subject: [PATCH] sbus: add time-based hardening (only for IO and NuttX)

Since SBUS does not have CRC, we can use timing information to improve
parsing reliability and reject unexpected bytes.
---
 src/lib/rc/sbus.cpp | 55 ++++++++++++++++++++++++++++-----------------
 1 file changed, 34 insertions(+), 21 deletions(-)

diff --git a/src/lib/rc/sbus.cpp b/src/lib/rc/sbus.cpp
index 7b70044c91..a765460e94 100644
--- a/src/lib/rc/sbus.cpp
+++ b/src/lib/rc/sbus.cpp
@@ -52,6 +52,8 @@
 #include "common_rc.h"
 #include <drivers/drv_hrt.h>
 
+using namespace time_literals;
+
 #define SBUS_DEBUG_LEVEL 	0 /* Set debug output level */
 
 #if defined(__PX4_POSIX_OCPOC)
@@ -280,8 +282,21 @@ bool
 sbus_input(int sbus_fd, uint16_t *values, uint16_t *num_values, bool *sbus_failsafe, bool *sbus_frame_drop,
 	   uint16_t max_channels)
 {
-	int		ret = 1;
-	hrt_abstime	now;
+	/*
+	 * Fetch bytes, but no more than we would need to complete
+	 * a complete frame.
+	 */
+	uint8_t buf[SBUS_FRAME_SIZE * 2];
+
+	int ret = read(sbus_fd, &buf[0], SBUS_FRAME_SIZE);
+
+	/* if the read failed for any reason, just give up here */
+	if (ret < 1) {
+		return false;
+	}
+
+	const hrt_abstime now = hrt_absolute_time();
+#ifdef __PX4_NUTTX /* limit time-based hardening to RTOS's where we have reliable timing */
 
 	/*
 	 * The S.BUS protocol doesn't provide reliable framing,
@@ -298,32 +313,30 @@ sbus_input(int sbus_fd, uint16_t *values, uint16_t *num_values, bool *sbus_fails
 	 * provides a degree of protection. Of course, it would be better
 	 * if we didn't drop bytes...
 	 */
-	now = hrt_absolute_time();
-
-	/*
-	 * Fetch bytes, but no more than we would need to complete
-	 * a complete frame.
-	 */
-	uint8_t buf[SBUS_FRAME_SIZE * 2];
-	bool sbus_decoded = false;
-
-	ret = read(sbus_fd, &buf[0], SBUS_FRAME_SIZE);
+	if (now - last_rx_time > 3_ms) {
+		if (partial_frame_count > 0) {
+			partial_frame_count = 0;
+			sbus_decode_state = SBUS2_DECODE_STATE_DESYNC;
+#if defined(SBUS_DEBUG_LEVEL) && SBUS_DEBUG_LEVEL > 0
+			printf("SBUS: RESET (TIME LIM)\n");
+#endif
+		}
+	}
 
-	/* if the read failed for any reason, just give up here */
-	if (ret < 1) {
+	if (partial_frame_count == 0 && buf[0] != SBUS_START_SYMBOL) {
+		/* don't bother going through the buffer if we don't get the
+		 * expected start symbol as a first byte */
+		sbus_decode_state = SBUS2_DECODE_STATE_DESYNC;
 		return false;
 	}
 
+#endif /* __PX4_NUTTX */
+
 	/*
 	 * Try to decode something with what we got
 	 */
-	if (sbus_parse(now, &buf[0], ret, values, num_values, sbus_failsafe,
-		       sbus_frame_drop, &sbus_frame_drops, max_channels)) {
-
-		sbus_decoded = true;
-	}
-
-	return sbus_decoded;
+	return sbus_parse(now, &buf[0], ret, values, num_values, sbus_failsafe,
+			  sbus_frame_drop, &sbus_frame_drops, max_channels);
 }
 
 bool
-- 
GitLab