jolly has uploaded this change for review. (
https://gerrit.osmocom.org/c/libosmo-abis/+/41140?usp=email )
Change subject: Add CAS channel support
......................................................................
Add CAS channel support
CAS is currently supported by e1d driver only.
Change-Id: I81cc89e01bb4207dc899ab28f24a131f24b61c9c
---
M include/osmocom/abis/e1_input.h
M src/e1_input.c
M src/input/dahdi.c
M src/input/e1d.c
M src/input/misdn.c
5 files changed, 154 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-abis refs/changes/40/41140/1
diff --git a/include/osmocom/abis/e1_input.h b/include/osmocom/abis/e1_input.h
index 66985ea..ccf6926 100644
--- a/include/osmocom/abis/e1_input.h
+++ b/include/osmocom/abis/e1_input.h
@@ -77,6 +77,7 @@
E1INP_TS_TYPE_RAW,
E1INP_TS_TYPE_HDLC,
E1INP_TS_TYPE_I460,
+ E1INP_TS_TYPE_CAS,
};
const char *e1inp_tstype_name(enum e1inp_ts_type tp);
extern const struct value_string e1inp_ts_type_names[];
@@ -120,6 +121,12 @@
struct llist_head tx_queue;
} hdlc;
struct {
+ /* call-back for every received frame */
+ void (*recv_cb)(struct e1inp_ts *ts, struct msgb *msg);
+ /* pending to-be-transmitted msgb */
+ struct msgb *tx_msg;
+ } cas;
+ struct {
struct osmo_i460_timeslot i460_ts;
} i460;
};
@@ -335,6 +342,11 @@
void (*hdlc_recv_cb)(struct e1inp_ts *ts,
struct msgb *msg));
+/* configure and initialize one timeslot dedicated to CAS frames */
+int e1inp_ts_config_cas(struct e1inp_ts *ts, struct e1inp_line *line,
+ void (*cas_recv_cb)(struct e1inp_ts *ts,
+ struct msgb *msg));
+
/* configure and initialize one timeslot dedicated to nothing */
int e1inp_ts_config_none(struct e1inp_ts *ts, struct e1inp_line *line);
@@ -410,5 +422,6 @@
int e1inp_ts_send_raw(struct e1inp_ts *ts, struct msgb *msg);
int e1inp_ts_send_hdlc(struct e1inp_ts *ts, struct msgb *msg);
+int e1inp_ts_send_cas(struct e1inp_ts *ts, struct msgb *msg);
#endif /* _E1_INPUT_H */
diff --git a/src/e1_input.c b/src/e1_input.c
index 066a572..656d657 100644
--- a/src/e1_input.c
+++ b/src/e1_input.c
@@ -283,6 +283,7 @@
{ E1INP_TS_TYPE_RAW, "RAW" },
{ E1INP_TS_TYPE_HDLC, "HDLC" },
{ E1INP_TS_TYPE_I460, "I460" },
+ { E1INP_TS_TYPE_CAS, "CAS" },
{ 0, NULL }
};
@@ -361,6 +362,23 @@
return 0;
}
+int e1inp_ts_send_cas(struct e1inp_ts *ts, struct msgb *msg)
+{
+ struct e1inp_driver *driver;
+
+ OSMO_ASSERT(ts->type == E1INP_TS_TYPE_CAS);
+
+ /* notify the driver we have something to write */
+ driver = ts->line->driver;
+ driver->want_write(ts);
+
+ /* update CAS message */
+ msgb_free(ts->cas.tx_msg);
+ ts->cas.tx_msg = msg;
+
+ return 0;
+}
+
/* Depending on its typ a timeslot may hold resources which must be cleaned up
* or reset before the type of the timeslot type may be changed. */
static int cleanup_e1inp_ts(struct e1inp_ts *e1i_ts)
@@ -390,6 +408,10 @@
case E1INP_TS_TYPE_HDLC:
msgb_queue_free(&e1i_ts->hdlc.tx_queue);
return 0;
+ case E1INP_TS_TYPE_CAS:
+ msgb_free(e1i_ts->cas.tx_msg);
+ e1i_ts->cas.tx_msg = NULL;
+ return 0;
case E1INP_TS_TYPE_I460:
/* The caller is responsible for removing all I.460 subchannels
* first. */
@@ -504,6 +526,23 @@
return 0;
}
+int e1inp_ts_config_cas(struct e1inp_ts *ts, struct e1inp_line *line,
+ void (*cas_recv_cb)(struct e1inp_ts *ts,
+ struct msgb *msg))
+{
+ if (ts->type == E1INP_TS_TYPE_CAS && ts->line && line)
+ return 0;
+
+ cleanup_e1inp_ts(ts);
+
+ ts->type = E1INP_TS_TYPE_CAS;
+ ts->line = line;
+ ts->cas.recv_cb = cas_recv_cb;
+ ts->cas.tx_msg = NULL;
+
+ return 0;
+}
+
int e1inp_ts_config_none(struct e1inp_ts *ts, struct e1inp_line *line)
{
if (ts->type == E1INP_TS_TYPE_NONE && ts->line && line)
@@ -879,6 +918,9 @@
case E1INP_TS_TYPE_HDLC:
ts->hdlc.recv_cb(ts, msg);
break;
+ case E1INP_TS_TYPE_CAS:
+ ts->cas.recv_cb(ts, msg);
+ break;
case E1INP_TS_TYPE_I460:
osmo_i460_demux_in(&ts->i460.i460_ts, msg->l2h, msgb_l2len(msg));
msgb_free(msg);
@@ -1013,6 +1055,10 @@
/* Get msgb from tx_queue */
msg = msgb_dequeue(&e1i_ts->hdlc.tx_queue);
break;
+ case E1INP_TS_TYPE_CAS:
+ /* Get msgb from tx_msg, but don't remove it. */
+ msg = e1i_ts->cas.tx_msg;
+ break;
case E1INP_TS_TYPE_I460:
msg = msgb_alloc(TSX_ALLOC_SIZE, "I460_TX");
if (!msg)
diff --git a/src/input/dahdi.c b/src/input/dahdi.c
index b9a3fcf..1e6df31 100644
--- a/src/input/dahdi.c
+++ b/src/input/dahdi.c
@@ -718,6 +718,9 @@
* write flow control */
bfd->when = OSMO_FD_READ | OSMO_FD_EXCEPT;// | OSMO_FD_WRITE;
break;
+ case E1INP_TS_TYPE_CAS:
+ LOGPITS(e1i_ts, DLMI, LOGL_ERROR, "CAS not supported by dahdi driver.\n");
+ return -ENOTSUP;
}
if (bfd->fd < 0)
diff --git a/src/input/e1d.c b/src/input/e1d.c
index dd4e9fe..9d48bbb 100644
--- a/src/input/e1d.c
+++ b/src/input/e1d.c
@@ -542,6 +542,35 @@
return ret;
}
+/* write to a CAS channel TS */
+static int handle_ts_cas_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;
+
+ /* Disable write, as there can be only one CAS message. */
+ osmo_fd_write_disable(bfd);
+
+ /* Get the msg, but don't free it. When the application is restarted,
+ * it will be sent again, so the application gets the latest CAS message. */
+ msg = e1inp_tx_ts(e1i_ts, NULL);
+ if (!msg)
+ return 0;
+
+ LOGPITS(e1i_ts, DLMIB, LOGL_DEBUG, "CAS CHAN TX: %s\n",
osmo_hexdump(msg->data, msg->len));
+
+ ret = write(bfd->fd, msg->data, msg->len);
+ if (ret < msg->len) {
+ LOGPITS(e1i_ts, DLINP, LOGL_NOTICE, "write returns %d instead of %d\n", ret,
msg->len);
+ osmo_fsm_inst_dispatch(g_e1d_fsm_inst, EV_CONN_LOST, line);
+ }
+
+ return ret;
+}
+
#define TSX_ALLOC_SIZE 4096
/* read from a hdlc channel TS */
@@ -573,6 +602,35 @@
return ret;
}
+/* read from a CAS channel TS */
+static int handle_ts_cas_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(TSX_ALLOC_SIZE, "E1D CAS TS");
+ int ret;
+
+ if (!msg)
+ return -ENOMEM;
+
+ ret = read(bfd->fd, msg->data, TSX_ALLOC_SIZE);
+ if (ret <= 0) {
+ LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "%s read error: %d %s\n", __func__, ret,
strerror(errno));
+ msgb_free(msg);
+ osmo_fsm_inst_dispatch(g_e1d_fsm_inst, EV_CONN_LOST, line);
+ return ret;
+ }
+
+ msgb_put(msg, ret);
+
+ msg->l2h = msg->data;
+ LOGPITS(e1i_ts, DLMIB, LOGL_DEBUG, "CAS CHAN RX: %s\n",
msgb_hexdump_l2(msg));
+ ret = e1inp_rx_ts(e1i_ts, msg, 0, 0);
+
+ return ret;
+}
+
static void e1d_write_msg(struct msgb *msg, void *cbdata)
{
struct osmo_fd *bfd = cbdata;
@@ -631,6 +689,12 @@
if (what & OSMO_FD_WRITE)
ret = handle_ts_hdlc_write(bfd);
break;
+ case E1INP_TS_TYPE_CAS:
+ if (what & OSMO_FD_READ)
+ ret = handle_ts_cas_read(bfd);
+ if (what & OSMO_FD_WRITE)
+ ret = handle_ts_cas_write(bfd);
+ break;
default:
LOGPITS(e1i_ts, DLINP, LOGL_NOTICE, "unknown/unsupported E1 TS type %u\n",
e1i_ts->type);
break;
@@ -777,6 +841,30 @@
}
bfd->when = OSMO_FD_READ;
break;
+ case E1INP_TS_TYPE_CAS:
+ /* close/release LAPD instance, if any */
+ if (e1i_ts->lapd) {
+ lapd_instance_free(e1i_ts->lapd);
+ e1i_ts->lapd = NULL;
+ }
+ /* close, if old timeslot mode doesn't match new config */
+ if (bfd->fd >= 0 && ts_info[ts].cfg.mode != E1DP_TSMODE_CAS) {
+ close(bfd->fd);
+ bfd->fd = -1;
+ }
+ if (bfd->fd < 0) {
+ bfd->fd = osmo_e1dp_client_ts_open(g_e1d, e1d_intf, e1d_line, ts,
+ E1DP_TSMODE_CAS, D_BCHAN_TX_GRAN);
+ }
+ if (bfd->fd < 0) {
+ LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "Could not open timeslot %d\n", ts);
+ talloc_free(ts_info);
+ osmo_fsm_inst_dispatch(g_e1d_fsm_inst, EV_CONN_LOST, NULL);
+ return -EIO;
+ }
+ /* Also trigger one write, so latest CAS frame will be sent, if any. */
+ bfd->when = OSMO_FD_READ | OSMO_FD_WRITE;
+ break;
case E1INP_TS_TYPE_TRAU:
case E1INP_TS_TYPE_I460:
case E1INP_TS_TYPE_RAW:
diff --git a/src/input/misdn.c b/src/input/misdn.c
index 8f04567..3172ee4 100644
--- a/src/input/misdn.c
+++ b/src/input/misdn.c
@@ -866,6 +866,9 @@
/* open raw socket */
bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
break;
+ case E1INP_TS_TYPE_CAS:
+ LOGPITS(e1i_ts, DLMI, LOGL_ERROR, "CAS not supported by mISDN\n");
+ return -ENOTSUP;
}
/* failed to open? */
@@ -901,6 +904,7 @@
/* TS 16 is D-channel, so we use channel 0 */
addr.channel = (ts == 16) ? 0 : ts;
break;
+ case E1INP_TS_TYPE_CAS:
default:
LOGPITS(e1i_ts, DLMI, LOGL_ERROR, "unsupported E1 TS type: %u\n",
e1i_ts->type);
break;
--
To view, visit
https://gerrit.osmocom.org/c/libosmo-abis/+/41140?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: libosmo-abis
Gerrit-Branch: master
Gerrit-Change-Id: I81cc89e01bb4207dc899ab28f24a131f24b61c9c
Gerrit-Change-Number: 41140
Gerrit-PatchSet: 1
Gerrit-Owner: jolly <andreas(a)eversberg.eu>