osmo_e1: Add HDLC framing/deframing
diff --git a/src/e1_test.c b/src/e1_test.c
index 5fd416f..c6d0e22 100644
--- a/src/e1_test.c
+++ b/src/e1_test.c
@@ -119,7 +119,7 @@
 	osmo_e1_instance_init(&inst, "e1_test", &notify_cb, true, NULL);
 	for (i = 1; i < 32; i++) {
 		struct osmo_e1_instance_ts *e1t = osmo_e1_instance_ts(&inst, i);
-		osmo_e1_ts_config(e1t, &data_cb, 40, true);
+		osmo_e1_ts_config(e1t, &data_cb, 40, true, OSMO_E1_TS_RAW);
 	}
 
 	printf("\nRx Random...\n");
diff --git a/src/osmo_e1.c b/src/osmo_e1.c
index ecf0cab..a328eb1 100644
--- a/src/osmo_e1.c
+++ b/src/osmo_e1.c
@@ -91,6 +91,10 @@
 	e1t->rx.enabled = false;
 	msgb_free(e1t->rx.msg);
 	e1t->rx.msg = NULL;
+
+	osmo_isdnhdlc_rcv_init(&e1t->rx.hdlc, OSMO_HDLC_F_BITREVERSE);
+	//osmo_isdnhdlc_rcv_init(&e1t->rx.hdlc, 0);
+	osmo_isdnhdlc_out_init(&e1t->tx.hdlc, 0);
 }
 
 /*! stop E1 instance; stops all timeslots and releases any pending rx/tx buffers
@@ -136,13 +140,15 @@
  *  \param[in] e1t Timeslot which we are to configure
  *  \param[in] granularity granularity (buffer size) to use on Rx
  *  \param[in] enable enable (true) or disalble (false) receiving on this TS
+ *  \param[in] mode the mode for this timeslot (raw or hdlc)
  *  \return 0 on success; negative on error */
 int osmo_e1_ts_config(struct osmo_e1_instance_ts *e1t, e1_data_cb cb, unsigned int granularity,
-		      bool enable)
+		      bool enable, enum osmo_e1_ts_mode mode)
 {
 	e1t->rx.data_cb = cb;
 	e1t->rx.enabled = enable;
 	e1t->rx.granularity = granularity;
+	e1t->mode = mode;
 
 	return 0;
 }
@@ -611,6 +617,7 @@
 static void e1_rx_tsN(struct osmo_e1_instance_ts *e1t, uint8_t inb)
 {
 	struct msgb *msg;
+	int count, rc;
 
 	if (!e1t->rx.enabled)
 		return;
@@ -620,14 +627,46 @@
 	msg = e1t->rx.msg;
 	OSMO_ASSERT(msg);
 
-	msgb_put_u8(msg, inb);
-	if (msgb_tailroom(msg) <= 0) {
-		if (!e1t->rx.data_cb)
-			msgb_free(msg);
-		else
-			e1t->rx.data_cb(e1t, msg);
-		e1t->rx.msg = NULL;
+	switch (e1t->mode) {
+	case OSMO_E1_TS_RAW:
+		/* append byte at end of msgb */
+		msgb_put_u8(msg, inb);
+		/* flush msgb, if full */
+		if (msgb_tailroom(msg) <= 0) {
+			goto flush;
+		}
+		break;
+	case OSMO_E1_TS_HDLC_CRC:
+		rc = osmo_isdnhdlc_decode(&e1t->rx.hdlc, &inb, 1, &count,
+					  msgb_data(msg), msgb_tailroom(msg));
+		switch (rc) {
+		case -OSMO_HDLC_FRAMING_ERROR:
+			fprintf(stdout, "Framing Error\n");
+			break;
+		case -OSMO_HDLC_CRC_ERROR:
+			fprintf(stdout, "CRC Error\n");
+			break;
+		case -OSMO_HDLC_LENGTH_ERROR:
+			fprintf(stdout, "Length Error\n");
+			break;
+		case 0:
+			/* no output yet */
+			break;
+		default:
+			msgb_put(msg, rc);
+			goto flush;
+		}
+		break;
 	}
+
+	return;
+flush:
+
+	if (!e1t->rx.data_cb)
+		msgb_free(msg);
+	else
+		e1t->rx.data_cb(e1t, msg);
+	e1t->rx.msg = NULL;
 }
 
 /*! Receive a single E1 frame of 32x8 (=256) bits
diff --git a/src/osmo_e1.h b/src/osmo_e1.h
index f39a308..4f5a18a 100644
--- a/src/osmo_e1.h
+++ b/src/osmo_e1.h
@@ -5,6 +5,7 @@
 #include <osmocom/core/msgb.h>
 #include <osmocom/core/linuxlist.h>
 #include <osmocom/core/fsm.h>
+#include <osmocom/core/isdnhdlc.h>
 
 struct osmo_e1_tx_state {
 	bool remote_alarm;
@@ -41,6 +42,11 @@
 	E1_NTFY_EVT_REMOTE_ALARM,
 };
 
+enum osmo_e1_ts_mode {
+       OSMO_E1_TS_RAW,
+       OSMO_E1_TS_HDLC_CRC,
+};
+
 struct osmo_e1_instance_ts;
 struct osmo_e1_instance;
 typedef void (*e1_data_cb)(struct osmo_e1_instance_ts *ts, struct msgb *msg);
@@ -50,14 +56,20 @@
 struct osmo_e1_instance_ts {
 	/* timeslot number */
 	uint8_t ts_nr;
+	/* mode in which we operate (RAW/HDLC) */
+	enum osmo_e1_ts_mode mode;
 	/* back-pointer to e1 instance */
 	struct osmo_e1_instance *inst;
 	struct {
+		/* optional HDLC encoder state */
+		struct osmo_isdnhdlc_vars hdlc;
 		/* queue of pending to-be-transmitted messages */
 		struct llist_head queue;
 		unsigned long underruns;
 	} tx;
 	struct {
+		/* optional HDLC decoder state */
+		struct osmo_isdnhdlc_vars hdlc;
 		bool enabled;
 		/* how many bytes to buffer before calling call-back */
 		unsigned int granularity;
@@ -101,7 +113,7 @@
 			  bool crc4_enabled, void *priv);
 void osmo_e1_instance_reset(struct osmo_e1_instance *e1i);
 int osmo_e1_ts_config(struct osmo_e1_instance_ts *e1t, e1_data_cb cb, unsigned int granularity,
-		      bool enable);
+		      bool enable, enum osmo_e1_ts_mode mode);
 void osmo_e1_ts_reset(struct osmo_e1_instance_ts *e1t);