aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;
}