]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
[ftmod_misdn] Make misdn_handle_mph_information_ind() cope with hfcsusb-style MPH_INF...
authorStefan Knoblich <stkn@openisdn.net>
Tue, 7 Feb 2012 17:25:29 +0000 (18:25 +0100)
committerStefan Knoblich <stkn@openisdn.net>
Tue, 7 Feb 2012 17:39:11 +0000 (18:39 +0100)
Only two mISDN hardware drivers emit MPH_INFORMATION_IND messages and both use a different payload:

- hfcsusb (HFC-based USB dongle) sends a set of ph_info + ph_info_ch structures
  which contain the complete state information of the port
  (including internal hw-specific state and flags).

- hfcmulti which sends a single integer, a single L1_SIGNAL_* event.

We now try to guess the type of message from the payload length.

The hfcmulti signals are converted to FreeTDM alarm flags; the hfcsusb
state/flags are defined in kernel internal hw-specific headers and are ignored ATM (todo).

Signed-off-by: Stefan Knoblich <stkn@openisdn.net>
libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c

index 643e6daeb8c853ef5d423698dccc16acbcddb85b..306f884c052e257c1d14d1dc4e800478467c6c6d 100644 (file)
@@ -622,50 +622,88 @@ static int misdn_handle_ph_control_ind(ftdm_channel_t *chan, const struct mISDNh
 static int misdn_handle_mph_information_ind(ftdm_channel_t *chan, const struct mISDNhead *hh, const void *data, const int data_len)
 {
        struct misdn_chan_private *priv = ftdm_chan_io_private(chan);
-       int alarm_flags, value;
 
-       if (data_len < sizeof(value)) {
-               ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "mISDN MPH_INFORMATION_IND message is too short\n");
-               return FTDM_FAIL;
-       }
-       value = *(int *)data;
-       alarm_flags = chan->alarm_flags;
+       /*
+        * mISDN has some inconsistency issues here.
+        *
+        * There are only two drivers that emit MPH_INFORMATION_IND messages,
+        * hfcsusb and hfcmulti. The former sends a set of ph_info and ph_info_ch structures,
+        * while the latter just sends an int containing the current L1_SIGNAL_* event id.
+        *
+        * The flags and state information in the ph_info and ph_info_ch structures
+        * are defined in kernel internal hw-specific headers (mISDNhw.h).
+        *
+        * Use the payload size to guess the type of message.
+        */
+       if (data_len >= sizeof(struct ph_info)) {
+               /* complete port status, hfcsusb sends this */
+               struct ph_info *info = (struct ph_info *)data;
+               struct ph_info_ch *bch_info = NULL;
 
-       switch (value) {
-       case L1_SIGNAL_LOS_ON:
-               alarm_flags |= FTDM_ALARM_RED;
-               break;
-       case L1_SIGNAL_LOS_OFF:
-               alarm_flags &= ~FTDM_ALARM_RED;
-               break;
-       case L1_SIGNAL_AIS_ON:
-               alarm_flags |= FTDM_ALARM_AIS;
-               break;
-       case L1_SIGNAL_AIS_OFF:
-               alarm_flags &= ~FTDM_ALARM_AIS;
-               break;
-       case L1_SIGNAL_RDI_ON:
-               alarm_flags |= FTDM_ALARM_YELLOW;
-               break;
-       case L1_SIGNAL_RDI_OFF:
-               alarm_flags &= ~FTDM_ALARM_YELLOW;
-               break;
-       case L1_SIGNAL_SLIP_RX:
-               priv->slip_rx_cnt++;
-               break;
-       case L1_SIGNAL_SLIP_TX:
-               priv->slip_tx_cnt++;
-               break;
-       default:
-               ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN unknown MPH_INFORMATION_IND message: %d\n",
-                       value);
+               if (data_len < (sizeof(*info) + info->dch.num_bch * sizeof(*bch_info))) {
+                       ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "mISDN MPH_INFORMATION_IND message is too short\n");
+                       return FTDM_FAIL;
+               }
+               bch_info = &info->bch[0];
+
+               ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN port state:\n\tD-Chan state:\t%hu\n\tD-Chan flags:\t%#x\n\tD-Chan proto:\t%hu\n\tD-Chan active:\t%s\n",
+                       info->dch.state, info->dch.ch.Flags, info->dch.ch.protocol, info->dch.ch.Flags & (1 << 6) ? "yes" : "no");
+
+               /* TODO: try to translate this to a usable set of alarm flags */
+
+       } else if (data_len == sizeof(int)) {
+               /* alarm info, sent by hfcmulti */
+               int value = *(int *)data;
+               int alarm_flags = chan->alarm_flags;
+
+               if (data_len < sizeof(value)) {
+                       ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "mISDN MPH_INFORMATION_IND message is too short\n");
+                       return FTDM_FAIL;
+               }
+
+               switch (value) {
+               case L1_SIGNAL_LOS_ON:
+                       alarm_flags |= FTDM_ALARM_RED;
+                       break;
+               case L1_SIGNAL_LOS_OFF:
+                       alarm_flags &= ~FTDM_ALARM_RED;
+                       break;
+               case L1_SIGNAL_AIS_ON:
+                       alarm_flags |= FTDM_ALARM_AIS;
+                       break;
+               case L1_SIGNAL_AIS_OFF:
+                       alarm_flags &= ~FTDM_ALARM_AIS;
+                       break;
+               case L1_SIGNAL_RDI_ON:
+                       alarm_flags |= FTDM_ALARM_YELLOW;
+                       break;
+               case L1_SIGNAL_RDI_OFF:
+                       alarm_flags &= ~FTDM_ALARM_YELLOW;
+                       break;
+               case L1_SIGNAL_SLIP_RX:
+                       priv->slip_rx_cnt++;
+                       break;
+               case L1_SIGNAL_SLIP_TX:
+                       priv->slip_tx_cnt++;
+                       break;
+               default:
+                       ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN unknown MPH_INFORMATION_IND signal: %#04x\n",
+                               value);
+                       return FTDM_FAIL;
+               }
+
+               /* check whether alarm status has changed, update channel flags if it has */
+               if ((value = (alarm_flags ^ chan->alarm_flags))) {
+                       ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN alarm flags have changed %#x -> %#x\n",
+                               chan->alarm_flags, alarm_flags);
+                       chan->alarm_flags ^= value;
+               }
+       } else {
+               ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN sent MPH_INFORMATION_IND message with unknown size %d\n",
+                       data_len);
                return FTDM_FAIL;
        }
-       if ((value = (alarm_flags ^ chan->alarm_flags))) {
-               ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN alarm flags have changed %#x -> %#x\n",
-                       chan->alarm_flags, alarm_flags);
-               chan->alarm_flags ^= value;
-       }
+
        return FTDM_SUCCESS;
 }