aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2020-01-12 13:46:34 +0100
committerHarald Welte <laforge@osmocom.org>2020-01-12 15:30:51 +0100
commiteed3916dee01e78fee92e9508aa4026406936102 (patch)
tree901b5c34677e56c72e0eeea49b5a71a2a2e1a71e
parentaccd677414bba9adab4ac2e7979695ebea2dc586 (diff)
e1d: Implement varions non-LAPD timeslot modes
So far, the e1d input driver only contained code for LAPD signaling slots, let's extend it with support for all the other slot types, as well as support for run-time re-configuration. Change-Id: I53369004145681bf9178543fe407dfc75e4ae63a
-rw-r--r--src/input/e1d.c62
1 files changed, 61 insertions, 1 deletions
diff --git a/src/input/e1d.c b/src/input/e1d.c
index c32e330..1e9f3bb 100644
--- a/src/input/e1d.c
+++ b/src/input/e1d.c
@@ -182,6 +182,8 @@ e1d_line_update(struct e1inp_line *line)
* resulting in max. 16 interfaces with 16 lines each */
uint8_t e1d_intf = (line->port_nr >> 4) & 0xF;
uint8_t e1d_line = line->port_nr & 0xF;
+ struct osmo_e1dp_ts_info *ts_info;
+ int num_ts_info;
if (line->driver != &e1d_driver)
return -EINVAL;
@@ -198,6 +200,12 @@ e1d_line_update(struct e1inp_line *line)
LOGPIL(line, DLINP, LOGL_NOTICE, "Line update %d %d=E1D(%d:%d) %d\n", line->num, line->port_nr,
e1d_intf, e1d_line, line->num_ts);
+ ret = osmo_e1dp_client_ts_query(g_e1d, &ts_info, &num_ts_info, e1d_intf, e1d_line, E1DP_INVALID);
+ if (ret < 0) {
+ LOGPIL(line, DLINP, LOGL_ERROR, "Cannot query E1D for timeslot information: %d\n", ret);
+ return -EIO;
+ }
+
for (ts=1; ts<line->num_ts; ts++)
{
unsigned int idx = ts-1;
@@ -212,6 +220,12 @@ e1d_line_update(struct e1inp_line *line)
bfd->priv_nr = ts;
bfd->cb = e1d_fd_cb;
+ if (e1i_ts->type != E1INP_TS_TYPE_NONE && ts >= num_ts_info) {
+ LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "Timeslot configured, but not existant "
+ "on E1D side; skipping\n");
+ continue;
+ }
+
switch (e1i_ts->type) {
case E1INP_TS_TYPE_NONE:
/* close/release LAPD instance, if any */
@@ -225,12 +239,17 @@ e1d_line_update(struct e1inp_line *line)
}
continue;
case E1INP_TS_TYPE_SIGN:
+ if (bfd->fd > 0 && ts_info[ts].cfg.mode != E1DP_TSMODE_HDLCFCS) {
+ close(bfd->fd);
+ bfd->fd = 0;
+ }
if (bfd->fd <= 0) {
bfd->fd = osmo_e1dp_client_ts_open(g_e1d, e1d_intf, e1d_line, ts,
E1DP_TSMODE_HDLCFCS);
}
if (bfd->fd < 0) {
LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "Could not open timeslot %d\n", ts);
+ talloc_free(ts_info);
return -EIO;
}
bfd->when = BSC_FD_READ;
@@ -241,20 +260,61 @@ e1d_line_update(struct e1inp_line *line)
e1i_ts, &lapd_profile_abis);
break;
case E1INP_TS_TYPE_HDLC:
+ /* 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_HDLCFCS) {
+ close(bfd->fd);
+ bfd->fd = 0;
+ }
+ if (bfd->fd <= 0) {
+ bfd->fd = osmo_e1dp_client_ts_open(g_e1d, e1d_intf, e1d_line, ts,
+ E1DP_TSMODE_HDLCFCS);
+ }
+ if (bfd->fd < 0) {
+ LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "Could not open timeslot %d\n", ts);
+ talloc_free(ts_info);
+ return -EIO;
+ }
+ bfd->when = BSC_FD_READ;
break;
case E1INP_TS_TYPE_TRAU:
- break;
case E1INP_TS_TYPE_RAW:
+ /* 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_RAW) {
+ close(bfd->fd);
+ bfd->fd = 0;
+ }
+ if (bfd->fd <= 0) {
+ bfd->fd = osmo_e1dp_client_ts_open(g_e1d, e1d_intf, e1d_line, ts,
+ E1DP_TSMODE_RAW);
+ }
+ if (bfd->fd < 0) {
+ LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "Could not open timeslot %d\n", ts);
+ talloc_free(ts_info);
+ return -EIO;
+ }
+ bfd->when = BSC_FD_READ;
break;
};
ret = osmo_fd_register(bfd);
if (ret < 0) {
LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "could not register FD: %s\n", strerror(ret));
+ talloc_free(ts_info);
return ret;
}
}
+ talloc_free(ts_info);
return 0;
}