提交 810f0d4e authored 作者: Stefan Knoblich's avatar Stefan Knoblich

[ftmod_misdn] Make misdn_handle_mph_information_ind() cope with hfcsusb-style…

[ftmod_misdn] Make misdn_handle_mph_information_ind() cope with hfcsusb-style MPH_INFORMATION_IND messages.

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: 's avatarStefan Knoblich <stkn@openisdn.net>
上级 452c1357
...@@ -622,50 +622,88 @@ static int misdn_handle_ph_control_ind(ftdm_channel_t *chan, const struct mISDNh ...@@ -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) 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); 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"); * mISDN has some inconsistency issues here.
return FTDM_FAIL; *
} * There are only two drivers that emit MPH_INFORMATION_IND messages,
value = *(int *)data; * hfcsusb and hfcmulti. The former sends a set of ph_info and ph_info_ch structures,
alarm_flags = chan->alarm_flags; * 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) { if (data_len < (sizeof(*info) + info->dch.num_bch * sizeof(*bch_info))) {
case L1_SIGNAL_LOS_ON: ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "mISDN MPH_INFORMATION_IND message is too short\n");
alarm_flags |= FTDM_ALARM_RED; return FTDM_FAIL;
break; }
case L1_SIGNAL_LOS_OFF: bch_info = &info->bch[0];
alarm_flags &= ~FTDM_ALARM_RED;
break; 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",
case L1_SIGNAL_AIS_ON: info->dch.state, info->dch.ch.Flags, info->dch.ch.protocol, info->dch.ch.Flags & (1 << 6) ? "yes" : "no");
alarm_flags |= FTDM_ALARM_AIS;
break; /* TODO: try to translate this to a usable set of alarm flags */
case L1_SIGNAL_AIS_OFF:
alarm_flags &= ~FTDM_ALARM_AIS; } else if (data_len == sizeof(int)) {
break; /* alarm info, sent by hfcmulti */
case L1_SIGNAL_RDI_ON: int value = *(int *)data;
alarm_flags |= FTDM_ALARM_YELLOW; int alarm_flags = chan->alarm_flags;
break;
case L1_SIGNAL_RDI_OFF: if (data_len < sizeof(value)) {
alarm_flags &= ~FTDM_ALARM_YELLOW; ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "mISDN MPH_INFORMATION_IND message is too short\n");
break; return FTDM_FAIL;
case L1_SIGNAL_SLIP_RX: }
priv->slip_rx_cnt++;
break; switch (value) {
case L1_SIGNAL_SLIP_TX: case L1_SIGNAL_LOS_ON:
priv->slip_tx_cnt++; alarm_flags |= FTDM_ALARM_RED;
break; break;
default: case L1_SIGNAL_LOS_OFF:
ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN unknown MPH_INFORMATION_IND message: %d\n", alarm_flags &= ~FTDM_ALARM_RED;
value); 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; 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; return FTDM_SUCCESS;
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论