From 8a95fd5481afa321914b4c06bb953efd59256a9b Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 11 May 2018 21:04:03 +0200 Subject: osmo_e1: Add HDLC framing/deframing --- src/e1_test.c | 2 +- src/osmo_e1.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++-------- src/osmo_e1.h | 14 +++++++++++++- 3 files changed, 61 insertions(+), 10 deletions(-) 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 @@ int main(int argc, char **argv) osmo_e1_instance_init(&inst, "e1_test", ¬ify_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 @@ void osmo_e1_ts_reset(struct osmo_e1_instance_ts *e1t) 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 @@ struct osmo_e1_instance_ts *osmo_e1_instance_ts(struct osmo_e1_instance *e1i, ui * \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_ts0(struct osmo_e1_instance *e1i, uint8_t inb) 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 @@ static void e1_rx_tsN(struct osmo_e1_instance_ts *e1t, uint8_t inb) 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 #include #include +#include struct osmo_e1_tx_state { bool remote_alarm; @@ -41,6 +42,11 @@ enum osmo_e1_notify_event { 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 @@ typedef void (*e1_notify_cb)(struct osmo_e1_instance *e1i, enum osmo_e1_notify_e 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 @@ int osmo_e1_instance_init(struct osmo_e1_instance *e1i, const char *name, e1_not 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); -- cgit v1.2.3