Add HDLC timeslot mode
This is useful for protocols that use HDLC framing for signalling on E1
timeslots, but which don't use LAPD inside (our E1INP_TS_TYPE_SIGN).
Examples are particularly a MTP2/MTP3 SS7 stack, like it is used on the
A interfaces or on the core network interfaces of classic
circuit-switched networks.
Change-Id: I2d75801df4d7cbb8dad325f4d6689841f0196fa6
diff --git a/src/input/dahdi.c b/src/input/dahdi.c
index db00f5f..0945daa 100644
--- a/src/input/dahdi.c
+++ b/src/input/dahdi.c
@@ -259,6 +259,51 @@
return 0;
}
+static void handle_hdlc_write(struct osmo_fd *bfd)
+{
+ struct e1inp_line *line = bfd->data;
+ unsigned int ts_nr = bfd->priv_nr;
+ struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
+ struct msgb *msg;
+ int ret;
+
+ /* get the next msg for this timeslot */
+ msg = e1inp_tx_ts(e1i_ts, NULL);
+ if (!msg)
+ return;
+
+ ret = write(bfd->fd, msg->data, msg->len + 2);
+ msgb_free(msg);
+ if (ret == -1)
+ handle_dahdi_exception(e1i_ts);
+ else if (ret < 0)
+ LOGP(DLMI, LOGL_NOTICE, "%s write failed %d\n", __func__, ret);
+}
+
+static int handle_hdlc_read(struct osmo_fd *bfd)
+{
+ struct e1inp_line *line = bfd->data;
+ unsigned int ts_nr = bfd->priv_nr;
+ struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
+ struct msgb *msg = msgb_alloc(TS1_ALLOC_SIZE, "DAHDI HDLC Rx");
+ int ret;
+
+ if (!msg)
+ return -ENOMEM;
+
+ ret = read(bfd->fd, msg->data, TS1_ALLOC_SIZE - 16);
+ if (ret == -1)
+ handle_dahdi_exception(e1i_ts);
+ else if (ret < 0) {
+ perror("read ");
+ }
+ msgb_put(msg, ret - 2);
+ if (ret <= 3) {
+ perror("read ");
+ }
+
+ return e1inp_rx_ts(e1i_ts, msg, 0, 0);
+}
static int invertbits = 1;
@@ -451,6 +496,14 @@
if (what & BSC_FD_WRITE)
rc = handle_ts1_write(bfd);
break;
+ case E1INP_TS_TYPE_HDLC:
+ if (what & BSC_FD_EXCEPT)
+ handle_dahdi_exception(e1i_ts);
+ if (what & BSC_FD_READ)
+ rc = handle_hdlc_read(bfd);
+ if (what & BSC_FD_WRITE)
+ handle_hdlc_write(bfd);
+ break;
case E1INP_TS_TYPE_TRAU:
if (what & BSC_FD_EXCEPT)
handle_dahdi_exception(e1i_ts);
@@ -620,6 +673,20 @@
dahdi_write_msg, bfd, e1inp_dlsap_up,
e1i_ts, &lapd_profile_abis);
break;
+ case E1INP_TS_TYPE_HDLC:
+ if (!bfd->fd)
+ bfd->fd = open(openstr, O_RDWR | O_NONBLOCK);
+ if (bfd->fd == -1) {
+ LOGP(DLINP, LOGL_ERROR,
+ "%s could not open %s %s\n",
+ __func__, openstr, strerror(errno));
+ return -EIO;
+ }
+ bfd->when = BSC_FD_READ | BSC_FD_EXCEPT;
+ ret = dahdi_set_bufinfo(bfd->fd, 1);
+ if (ret < 0)
+ return ret;
+ break;
case E1INP_TS_TYPE_TRAU:
case E1INP_TS_TYPE_RAW:
/* close/release LAPD instance, if any */