soft_uart: implement parity checking for the receiver

Change-Id: I28be2ca19d423447a718fb518566d52ae1967ec7
Related: OS#4396
diff --git a/src/core/soft_uart.c b/src/core/soft_uart.c
index c7c8020..d8ce9d9 100644
--- a/src/core/soft_uart.c
+++ b/src/core/soft_uart.c
@@ -43,7 +43,7 @@
 		uint8_t bit_count;
 		uint8_t shift_reg;
 		struct msgb *msg;
-		ubit_t parity_bit;
+		ubit_t parity_bit; /* 0 (even) / 1 (odd) */
 		unsigned int flags;
 		unsigned int status;
 		struct osmo_timer_list timer;
@@ -117,13 +117,16 @@
 			suart->rx.flags = 0x00;
 			suart->rx.shift_reg = 0;
 			suart->rx.bit_count = 0;
+			suart->rx.parity_bit = 0;
 		}
 		break;
 	case SUART_FLOW_ST_DATA:
 		suart->rx.bit_count++;
 		suart->rx.shift_reg >>= 1;
-		if (bit != 0)
+		if (bit != 0) {
+			suart->rx.parity_bit = !suart->rx.parity_bit; /* flip */
 			suart->rx.shift_reg |= 0x80;
+		}
 		if (suart->rx.bit_count >= suart->cfg.num_data_bits) {
 			/* we have accumulated enough data bits */
 			if (suart->cfg.parity_mode != OSMO_SUART_PARITY_NONE)
@@ -133,7 +136,22 @@
 		}
 		break;
 	case SUART_FLOW_ST_PARITY:
-		/* TODO: actually verify parity */
+		switch (suart->cfg.parity_mode) {
+		case OSMO_SUART_PARITY_EVEN:
+			/* number of 1-bits (in both data and parity) shall be even */
+			if (suart->rx.parity_bit != bit)
+				suart->rx.flags |= OSMO_SUART_F_PARITY_ERROR;
+			break;
+		case OSMO_SUART_PARITY_ODD:
+			/* number of 1-bits (in both data and parity) shall be odd */
+			if (suart->rx.parity_bit == bit)
+				suart->rx.flags |= OSMO_SUART_F_PARITY_ERROR;
+			break;
+		case OSMO_SUART_PARITY_NONE: /* shall not happen */
+		default:
+			OSMO_ASSERT(0);
+		}
+
 		suart->rx.flow_state = SUART_FLOW_ST_STOP;
 		break;
 	case SUART_FLOW_ST_STOP: