From ff4b395956a3741a06284879637dee710d1cb3ff Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Fri, 23 Mar 2012 01:09:30 +0100 Subject: [PATCH] ftmod_misdn: Rework channel de-/activation and activate d-channel early. The former fixes a strange "bug" with hfcsusb, where a b-channel deactivation on a inactive channel (caused by a reset cycle) would cause the port to lock up and stop processing events. NOTE: this still needs to be investigated further, but this workaround will at least prevent it from breaking completely. We'll now keep track of the channel activation state and not send any PH_ACTIVATE_REQ / PH_DEACTIVATE_REQ requests, if the channel already has the desired state. Signed-off-by: Stefan Knoblich --- .../src/ftmod/ftmod_misdn/ftmod_misdn.c | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c b/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c index 947333a14a..326d00a9d9 100644 --- a/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c +++ b/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c @@ -191,6 +191,7 @@ struct misdn_chan_private { int state; int debugfd; int timerfd; + int active; /* hw addr of channel */ struct sockaddr_mISDN addr; @@ -404,12 +405,17 @@ static inline int ts_before(struct timespec *a, struct timespec *b) static ftdm_status_t misdn_activate_channel(ftdm_channel_t *chan, int activate) { + struct misdn_chan_private *priv = ftdm_chan_io_private(chan); char buf[MAX_DATA_MEM] = { 0 }; struct mISDNhead *hh = (struct mISDNhead *) buf; struct timespec abstimeout; int req = 0, resp = 0, ms_left = MISDN_PH_ACTIVATE_TIMEOUT_MS; int retval; + /* NOTE: sending PH_DEACTIVATE_REQ to closed b-channels kills the d-channel (hfcsusb)... */ + if ((activate && priv->active) || (!activate && !priv->active)) + return FTDM_SUCCESS; + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN sending %s request\n", (activate) ? "activation" : "deactivation"); @@ -433,7 +439,7 @@ static ftdm_status_t misdn_activate_channel(ftdm_channel_t *chan, int activate) struct pollfd pfd; pfd.fd = chan->sockfd; - pfd.events = POLLIN /* | POLLPRI */; + pfd.events = POLLIN | POLLPRI; pfd.revents = 0; switch ((retval = poll(&pfd, 1, ms_left))) { @@ -463,15 +469,17 @@ static ftdm_status_t misdn_activate_channel(ftdm_channel_t *chan, int activate) ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_B ? 'B' : 'D'); //#endif switch (hh->prim) { - case PH_ACTIVATE_IND: /* success (or not): save last response, */ - case PH_DEACTIVATE_IND: /* stop looping if it's the one we've been waiting for */ - resp = hh->prim; - if (hh->prim == (activate) ? PH_ACTIVATE_IND : PH_DEACTIVATE_IND) goto out; - break; + case PH_ACTIVATE_IND: case PH_ACTIVATE_CNF: - case PH_DEACTIVATE_CNF: resp = hh->prim; - if (hh->prim == (activate) ? PH_ACTIVATE_CNF : PH_DEACTIVATE_CNF) goto out; + priv->active = 1; + if (activate) goto out; + break; + case PH_DEACTIVATE_CNF: + case PH_DEACTIVATE_IND: + resp = hh->prim; + priv->active = 0; + if (!activate) goto out; break; case PH_ACTIVATE_REQ: /* REQ echo, ignore */ case PH_DEACTIVATE_REQ: @@ -481,6 +489,9 @@ static ftdm_status_t misdn_activate_channel(ftdm_channel_t *chan, int activate) case MPH_INFORMATION_IND: misdn_handle_mph_information_ind(chan, hh, MISDN_MSG_DATA(buf), retval - MISDN_HEADER_LEN); break; + case PH_DATA_IND: /* ignore */ + case PH_DATA_CNF: /* ignore */ + break; default: /* other messages, ignore */ ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN ignoring event '%s (%#x)', id %#x, while waiting for %s confirmation\n", misdn_event2str(hh->prim), hh->prim, hh->id, (activate) ? "activation" : "deactivation"); @@ -500,8 +511,8 @@ out: (activate) ? "activation" : "deactivation"); return FTDM_TIMEOUT; } - if ((req == PH_ACTIVATE_IND && !(resp == PH_ACTIVATE_CNF || resp == PH_ACTIVATE_IND)) || - (req == PH_DEACTIVATE_IND && !(resp == PH_DEACTIVATE_CNF || resp == PH_DEACTIVATE_CNF))) { + if ((req == PH_ACTIVATE_REQ && !(resp == PH_ACTIVATE_CNF || resp == PH_ACTIVATE_IND)) || + (req == PH_DEACTIVATE_REQ && !(resp == PH_DEACTIVATE_CNF || resp == PH_DEACTIVATE_IND))) { ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN received '%s' while waiting for %s\n", misdn_event2str(resp), (activate) ? "activation" : "deactivation"); return FTDM_FAIL; @@ -1436,6 +1447,8 @@ static ftdm_status_t misdn_open_range(ftdm_span_t *span, ftdm_chan_type_t type, ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_INTERVAL); } else { + /* early activate D-Channel */ + misdn_activate_channel(ftdmchan, 1); ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE; } num_configured++;