jolly has uploaded this change for review.
Reworked mi_e1_line_update() and some of its sub routines
Now it closes file descriptor and frees lapd resources, if time slot
type changes or if it is released. Local states are reset.
printf and fprintf are replaced by logging functions.
Change-Id: Iab0776fce6921661b39e9e53376cf01a80bcd42c
---
M src/input/misdn.c
1 file changed, 79 insertions(+), 42 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-abis refs/changes/96/31296/1
diff --git a/src/input/misdn.c b/src/input/misdn.c
index e0eed19..eaea646 100644
--- a/src/input/misdn.c
+++ b/src/input/misdn.c
@@ -71,6 +71,7 @@
struct misdn_line {
int use_userspace_lapd;
int unconfirmed_ts[NUM_E1_TS];
+ enum e1inp_ts_type type_ts[NUM_E1_TS];
int dummy_dchannel;
int los, ais, rai;
};
@@ -725,7 +726,6 @@
struct e1inp_ts *e1i_ts = &line->ts[idx];
struct osmo_fd *bfd = &e1i_ts->driver.misdn.fd;
- fprintf(stdout, "activate bchan\n");
if (act)
hh.prim = PH_ACTIVATE_REQ;
else
@@ -764,18 +764,26 @@
struct misdn_line *mline = line->driver_data;
int ts, ret;
- mline->dummy_dchannel = -1;
- if (mline->use_userspace_lapd) {
+ /* check if sign type is used */
+ for (ts = 1; ts < line->num_ts; ts++) {
+ unsigned int idx = ts - 1;
+ struct e1inp_ts *e1i_ts = &line->ts[idx];
+ if (e1i_ts->type == E1INP_TS_TYPE_SIGN)
+ break;
+ }
+ if (ts < line->num_ts && mline->use_userspace_lapd) {
+ unsigned int idx = ts - 1;
+ struct e1inp_ts *e1i_ts = &line->ts[idx];
/* Open dummy d-channel in order to use b-channels.
* Also it is required to define the mode.
*/
- if (mline->dummy_dchannel < 0) {
+ if (mline->dummy_dchannel <= 0) {
struct sockaddr_mISDN addr;
mline->dummy_dchannel = socket(PF_ISDN, SOCK_DGRAM,
ISDN_P_NT_E1);
if (mline->dummy_dchannel < 0) {
- fprintf(stderr, "%s could not open socket %s\n",
+ LOGPITS(e1i_ts, DLMI, LOGL_ERROR, "%s could not open socket %s\n",
__func__, strerror(errno));
return mline->dummy_dchannel;
}
@@ -788,56 +796,90 @@
ret = bind(mline->dummy_dchannel,
(struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
- fprintf(stderr, "could not bind l2 socket %s\n",
- strerror(errno));
+ LOGPITS(e1i_ts, DLMI, LOGL_ERROR, "could not bind l2 socket %s\n", strerror(errno));
return -EIO;
}
}
+ } else {
+ /* close dummy d-channel */
+ if (mline->dummy_dchannel > 0) {
+ close(mline->dummy_dchannel);
+ mline->dummy_dchannel = -1;
+ }
}
+ LOGPIL(line, DLINP, LOGL_NOTICE, "Line update %d %d %d\n", line->num, line->port_nr, line->num_ts);
+
/* TS0 is CRC4, don't need any fd for it */
- for (ts = 1; ts < NUM_E1_TS; ts++) {
- unsigned int idx = ts-1;
+ for (ts = 1; ts < line->num_ts; ts++) {
+ unsigned int idx = ts - 1;
struct e1inp_ts *e1i_ts = &line->ts[idx];
struct osmo_fd *bfd = &e1i_ts->driver.misdn.fd;
struct sockaddr_mISDN addr;
+ /* no change in type */
+ if (mline->type_ts[idx] == e1i_ts->type)
+ continue;
+
+ LOGPIL(line, DLINP, LOGL_INFO, "Time slot %d changes from type %s to type %s\n", ts,
+ e1inp_tstype_name(mline->type_ts[idx]), e1inp_tstype_name(e1i_ts->type));
+
+ /* unregister FD if it was already registered */
+ if (bfd->list.next && bfd->list.next != LLIST_POISON1)
+ osmo_fd_unregister(bfd);
+
+ /* close/release LAPD instance, if any */
+ if (e1i_ts->lapd) {
+ lapd_instance_free(e1i_ts->lapd);
+ e1i_ts->lapd = NULL;
+ }
+
+ /* close old file descriptor */
+ if (bfd->fd) {
+ close(bfd->fd);
+ bfd->fd = 0;
+ }
+
+ /* clear 'unconfirmed' state */
+ mline->unconfirmed_ts[idx] = 0;
+
+ /* set new type */
+ mline->type_ts[idx] = e1i_ts->type;
+
switch (e1i_ts->type) {
case E1INP_TS_TYPE_NONE:
+ /* keep closed */
continue;
- break;
case E1INP_TS_TYPE_HDLC:
+ /* open hdlc socket */
/* TS 16 is the D-channel, so we use D-channel proto */
bfd->fd = socket(PF_ISDN, SOCK_DGRAM,
(ts == 16) ? ISDN_P_NT_E1 : ISDN_P_B_HDLC);
- bfd->when = OSMO_FD_READ;
break;
case E1INP_TS_TYPE_SIGN:
+ /* open and allocate user space lapd, if required */
if (mline->use_userspace_lapd)
bfd->fd = socket(PF_ISDN, SOCK_DGRAM,
ISDN_P_B_HDLC);
else
bfd->fd = socket(PF_ISDN, SOCK_DGRAM,
ISDN_P_LAPD_NT);
- bfd->when = OSMO_FD_READ;
break;
case E1INP_TS_TYPE_TRAU:
case E1INP_TS_TYPE_I460:
case E1INP_TS_TYPE_RAW:
+ /* open raw socket */
bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
- /* We never include the mISDN B-Channel FD into the
- * writeset, since it doesn't support poll() based
- * write flow control */
- bfd->when = OSMO_FD_READ;
break;
}
+ /* failed to open? */
if (bfd->fd < 0) {
- fprintf(stderr, "%s could not open socket %s\n",
- __func__, strerror(errno));
+ LOGPITS(e1i_ts, DLMI, LOGL_ERROR, "could not open socket: %s\n", strerror(errno));
return bfd->fd;
}
+ /* configure mISDN socket, also add user space lapd, if enabled */
memset(&addr, 0, sizeof(addr));
addr.family = AF_ISDN;
addr.dev = line->port_nr;
@@ -869,37 +911,33 @@
break;
}
+ /* bind mISDN socket */
ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
- fprintf(stderr, "could not bind l2 socket %s\n",
+ LOGPITS(e1i_ts, DLMI, LOGL_ERROR, "could not bind l2 socket %s\n",
strerror(errno));
return -EIO;
}
+ /* release L2 in case of kernel space lapd, activate b-channel in other cases */
if (e1i_ts->type == E1INP_TS_TYPE_SIGN) {
if (!mline->use_userspace_lapd) {
ret = ioctl(bfd->fd, IMCLEAR_L2, &release_l2);
if (ret < 0) {
- fprintf(stderr, "could not send IOCTL IMCLEAN_L2 %s\n", strerror(errno));
+ LOGPITS(e1i_ts, DLMI, LOGL_ERROR, "could not send IOCTL IMCLEAN_L2 %s\n",
+ strerror(errno));
return -EIO;
}
} else
activate_bchan(line, ts, 1);
- }
-
- /* FIXME: only activate B-Channels once we start to
- * use them to conserve CPU power */
- if (e1i_ts->type == E1INP_TS_TYPE_HDLC
- || e1i_ts->type == E1INP_TS_TYPE_RAW
- || e1i_ts->type == E1INP_TS_TYPE_TRAU)
+ } else
activate_bchan(line, ts, 1);
- osmo_fd_setup(bfd, bfd->fd, bfd->when, misdn_fd_cb, line, ts);
-
+ /* register file descriptor with read set enabled */
+ osmo_fd_setup(bfd, bfd->fd, OSMO_FD_READ, misdn_fd_cb, line, ts);
ret = osmo_fd_register(bfd);
if (ret < 0) {
- fprintf(stderr, "could not register FD: %s\n",
- strerror(-ret));
+ LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "could not register FD: %s\n", strerror(ret));
return ret;
}
}
@@ -931,29 +969,28 @@
close(sk);
return -ENODEV;
}
- //LOGPIL(line, DLMI, LOGL_DEBUG, "%d device%s found\n", cnt, (cnt==1)?"":"s");
- printf("%d device%s found\n", cnt, (cnt==1)?"":"s");
+ LOGPIL(line, DLMI, LOGL_INFO, "%d device%s found\n", cnt, (cnt == 1) ? "" : "s");
#if 1
memset(&devinfo, 0, sizeof(devinfo));
devinfo.id = line->port_nr;
ret = ioctl(sk, IMGETDEVINFO, &devinfo);
if (ret < 0) {
- fprintf(stdout, "error getting info for device %d: %s\n",
- line->port_nr, strerror(errno));
+ LOGPIL(line, DLMI, LOGL_ERROR, "error getting info for device %d: %s\n",
+ line->port_nr, strerror(errno));
close(sk);
return -ENODEV;
}
- fprintf(stdout, " id: %d\n", devinfo.id);
- fprintf(stdout, " Dprotocols: %08x\n", devinfo.Dprotocols);
- fprintf(stdout, " Bprotocols: %08x\n", devinfo.Bprotocols);
- fprintf(stdout, " protocol: %d\n", devinfo.protocol);
- fprintf(stdout, " nrbchan: %d\n", devinfo.nrbchan);
- fprintf(stdout, " name: %s\n", devinfo.name);
+ LOGPIL(line, DLMI, LOGL_INFO, " id: %d\n", devinfo.id);
+ LOGPIL(line, DLMI, LOGL_INFO, " Dprotocols: %08x\n", devinfo.Dprotocols);
+ LOGPIL(line, DLMI, LOGL_INFO, " Bprotocols: %08x\n", devinfo.Bprotocols);
+ LOGPIL(line, DLMI, LOGL_INFO, " protocol: %d\n", devinfo.protocol);
+ LOGPIL(line, DLMI, LOGL_INFO, " nrbchan: %d\n", devinfo.nrbchan);
+ LOGPIL(line, DLMI, LOGL_INFO, " name: %s\n", devinfo.name);
#endif
close(sk);
if (!(devinfo.Dprotocols & (1 << ISDN_P_NT_E1))) {
- fprintf(stderr, "error: card is not of type E1 (NT-mode)\n");
+ LOGPIL(line, DLMI, LOGL_ERROR, "error, card is not of type E1 (NT-mode)\n");
return -EINVAL;
}
To view, visit change 31296. To unsubscribe, or for help writing mail filters, visit settings.