Index: include/dahdi/user.h =================================================================== --- include/dahdi/user.h (revision 5825) +++ include/dahdi/user.h (working copy) @@ -970,8 +970,7 @@ * VMWI Specification */ struct dahdi_vmwi_info { - unsigned int messages; /* Number of messages pending */ - unsigned int vmwi_type; + unsigned int vmwi_type; }; #define DAHDI_VMWI_LREV (1 << 0) /* Line Reversal */ @@ -982,7 +981,8 @@ * VoiceMail Waiting Indication (VMWI) -- implemented by low-level driver. * Value: number of waiting messages (hence 0: switch messages off). */ -#define DAHDI_VMWI _IOWR(DAHDI_CODE, 94, struct dahdi_vmwi_info) +#define DAHDI_VMWI _IOWR(DAHDI_CODE, 94, int) +#define DAHDI_VMWI_CONFIG _IOW(DAHDI_CODE, 95, struct dahdi_vmwi_info) /* * Startup or Shutdown a span Index: drivers/dahdi/wctdm.c =================================================================== --- drivers/dahdi/wctdm.c (revision 5825) +++ drivers/dahdi/wctdm.c (working copy) @@ -239,7 +239,8 @@ int palarms; int reversepolarity; /* Reverse Line */ int mwisendtype; - struct dahdi_vmwi_info vmwisetting; + struct dahdi_vmwi_info vmwisetting; + int vmwi_active_messages; int vmwi_lrev:1; /* MWI Line Reversal*/ int vmwi_hvdc:1; /* MWI High Voltage DC Idle line */ int vmwi_hvac:1; /* MWI Neon High Voltage AC Idle line */ @@ -1799,7 +1800,47 @@ return 0; } +static int set_vmwi(struct wctdm * wc, int chan_idx) +{ + if (wc->mod[chan_idx].fxs.vmwi_active_messages){ + wc->mod[chan_idx].fxs.vmwi_lrev = (wc->mod[chan_idx].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_LREV)?1:0; + wc->mod[chan_idx].fxs.vmwi_hvdc = (wc->mod[chan_idx].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_HVDC)?1:0; + wc->mod[chan_idx].fxs.vmwi_hvac = (wc->mod[chan_idx].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_HVAC)?1:0; + } else { + wc->mod[chan_idx].fxs.vmwi_lrev = 0; + wc->mod[chan_idx].fxs.vmwi_hvdc = 0; + wc->mod[chan_idx].fxs.vmwi_hvac = 0; + } + if (debug) { + printk(KERN_DEBUG "Setting VMWI on channel %d, messages=%d, lrev=%d, hvdc=%d, hvac=%d\n", + chan_idx, + wc->mod[chan_idx].fxs.vmwi_active_messages, + wc->mod[chan_idx].fxs.vmwi_lrev, + wc->mod[chan_idx].fxs.vmwi_hvdc, + wc->mod[chan_idx].fxs.vmwi_hvac + ); + } + if (POLARITY_XOR(chan_idx)) { + wc->mod[chan_idx].fxs.idletxhookstate |= 0x4; + /* Do not set while currently ringing or open */ + if (wc->mod[chan_idx].fxs.lasttxhook != 0x04 && + wc->mod[chan_idx ].fxs.lasttxhook != 0x00) { + wc->mod[chan_idx ].fxs.lasttxhook |= 0x4; + wctdm_setreg(wc, chan_idx, 64, wc->mod[chan_idx].fxs.lasttxhook); + } + } else { + wc->mod[chan_idx].fxs.idletxhookstate &= ~0x04; + /* Do not set while currently ringing or open */ + if (wc->mod[chan_idx].fxs.lasttxhook != 0x04 && + wc->mod[chan_idx].fxs.lasttxhook != 0x00) { + wc->mod[chan_idx].fxs.lasttxhook &= ~0x04; + wctdm_setreg(wc, chan_idx, 64, wc->mod[chan_idx].fxs.lasttxhook); + } + } + return 0; +} + static int wctdm_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data) { struct wctdm_stats stats; @@ -1840,49 +1881,23 @@ wc->mod[chan->chanpos - 1].fxs.lasttxhook &= ~0x04; wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook); break; - case DAHDI_VMWI: + case DAHDI_VMWI_CONFIG: if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; if (copy_from_user(&(wc->mod[chan->chanpos - 1].fxs.vmwisetting), (__user void *) data, sizeof(wc->mod[chan->chanpos - 1].fxs.vmwisetting))) return -EFAULT; - - if (wc->mod[chan->chanpos - 1].fxs.vmwisetting.messages){ - wc->mod[chan->chanpos - 1].fxs.vmwi_lrev = (wc->mod[chan->chanpos - 1].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_LREV)?1:0; - wc->mod[chan->chanpos - 1].fxs.vmwi_hvdc = (wc->mod[chan->chanpos - 1].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_HVDC)?1:0; - wc->mod[chan->chanpos - 1].fxs.vmwi_hvac = (wc->mod[chan->chanpos - 1].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_HVAC)?1:0; - } else { - wc->mod[chan->chanpos - 1].fxs.vmwi_lrev = 0; - wc->mod[chan->chanpos - 1].fxs.vmwi_hvdc = 0; - wc->mod[chan->chanpos - 1].fxs.vmwi_hvac = 0; - } - - if (debug) { - printk(KERN_DEBUG "Setting VMWI on channel %d, messages=%d, lrev=%d, hvdc=%d, hvac=%d\n", - chan->chanpos-1, - wc->mod[chan->chanpos - 1].fxs.vmwisetting.messages, - wc->mod[chan->chanpos - 1].fxs.vmwi_lrev, - wc->mod[chan->chanpos - 1].fxs.vmwi_hvdc, - wc->mod[chan->chanpos - 1].fxs.vmwi_hvac - ); - } - if (POLARITY_XOR(chan->chanpos -1)) { - wc->mod[chan->chanpos -1 ].fxs.idletxhookstate |= 0x4; - /* Do not set while currently ringing or open */ - if (wc->mod[chan->chanpos -1 ].fxs.lasttxhook != 0x04 && - wc->mod[chan->chanpos -1 ].fxs.lasttxhook != 0x00) { - wc->mod[chan->chanpos -1 ].fxs.lasttxhook |= 0x4; - wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook); - } - } else { - wc->mod[chan->chanpos -1 ].fxs.idletxhookstate &= ~0x04; - /* Do not set while currently ringing or open */ - if (wc->mod[chan->chanpos -1 ].fxs.lasttxhook != 0x04 && - wc->mod[chan->chanpos -1 ].fxs.lasttxhook != 0x00) { - wc->mod[chan->chanpos -1 ].fxs.lasttxhook &= ~0x04; - wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook); - } - } + set_vmwi(wc, chan->chanpos - 1); break; + case DAHDI_VMWI: + if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) + return -EINVAL; + if (get_user(x, (__user int *) data)) + return -EFAULT; + if (0 > x) + return -EFAULT; + wc->mod[chan->chanpos - 1].fxs.vmwi_active_messages = x; + set_vmwi(wc, chan->chanpos - 1); + break; case WCTDM_GET_STATS: if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { stats.tipvolt = wctdm_getreg(wc, chan->chanpos - 1, 80) * -376; Index: drivers/dahdi/wctdm24xxp/wctdm24xxp.h =================================================================== --- drivers/dahdi/wctdm24xxp/wctdm24xxp.h (revision 5825) +++ drivers/dahdi/wctdm24xxp/wctdm24xxp.h (working copy) @@ -249,7 +249,8 @@ int lasttxhook; /* Bits 0-3 are written to proslic reg 64, Bit 4 indicates if the last write is pending */ int palarms; struct dahdi_vmwi_info vmwisetting; - int linereverse_mwi; + int vmwi_active_messages; + int vmwi_linereverse; int reversepolarity; /* polarity reversal */ struct calregs calregs; } fxs; Index: drivers/dahdi/wctdm24xxp/base.c =================================================================== --- drivers/dahdi/wctdm24xxp/base.c (revision 5825) +++ drivers/dahdi/wctdm24xxp/base.c (working copy) @@ -87,7 +87,7 @@ * polarity reversal for the port, * and the state of the line reversal MWI indicator */ -#define POLARITY_XOR(card) ( (reversepolarity != 0) ^ (wc->mods[(card)].fxs.reversepolarity != 0) ^ (wc->mods[(card)].fxs.linereverse_mwi != 0) ) +#define POLARITY_XOR(card) ( (reversepolarity != 0) ^ (wc->mods[(card)].fxs.reversepolarity != 0) ^ (wc->mods[(card)].fxs.vmwi_linereverse != 0) ) static int reversepolarity = 0; static alpha indirect_regs[] = @@ -1934,6 +1934,46 @@ return 0; } +static int set_vmwi(struct wctdm *wc, int chan_idx) +{ + int x; + /* Presently only supports line reversal MWI */ + if (wc->mods[chan_idx].fxs.vmwi_active_messages && wc->mods[chan_idx].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_LREV){ + wc->mods[chan_idx].fxs.vmwi_linereverse = 1; + } else { + wc->mods[chan_idx].fxs.vmwi_linereverse = 0; + } + /* Set line polarity for new VMWI state */ + if (POLARITY_XOR(chan_idx)) { + wc->mods[chan_idx].fxs.idletxhookstate |= 0x14; + /* Do not set while currently ringing or open */ + if (wc->mods[chan_idx].fxs.lasttxhook != 0x04 && + wc->mods[chan_idx].fxs.lasttxhook != 0x00) { + wc->mods[chan_idx].fxs.lasttxhook |= 0x14; + wc->sethook[chan_idx] = CMD_WR(64, wc->mods[chan_idx].fxs.lasttxhook); + } + } else { + wc->mods[chan_idx].fxs.idletxhookstate &= ~0x04; + /* Do not set while currently ringing or open */ + if (wc->mods[chan_idx].fxs.lasttxhook != 0x04 && + wc->mods[chan_idx].fxs.lasttxhook != 0x00) { + x = wc->mods[chan_idx].fxs.lasttxhook; + x &= ~0x04; + x |= 0x10; + wc->mods[chan_idx].fxs.lasttxhook = x; + wc->sethook[chan_idx] = CMD_WR(64, wc->mods[chan_idx].fxs.lasttxhook); + } + } + if (debug) { + printk(KERN_DEBUG "Setting VMWI on channel %d, messages=%d, lrev=%d\n", + chan_idx, + wc->mods[chan_idx].fxs.vmwi_active_messages, + wc->mods[chan_idx].fxs.vmwi_linereverse + ); + } + return 0; +} + static int wctdm_init_voicedaa(struct wctdm *wc, int card, int fast, int manual, int sane) { unsigned char reg16=0, reg26=0, reg30=0, reg31=0; @@ -2053,7 +2093,7 @@ /* Initialize VMWI settings */ memset(&(wc->mods[card].fxs.vmwisetting), 0, sizeof(wc->mods[card].fxs.vmwisetting)); - wc->mods[card].fxs.linereverse_mwi = 0; + wc->mods[card].fxs.vmwi_linereverse = 0; /* By default, don't send on hook */ if (!reversepolarity != !wc->mods[card].fxs.reversepolarity) { @@ -2444,47 +2484,23 @@ /* wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); */ } break; - case DAHDI_VMWI: + case DAHDI_VMWI_CONFIG: if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; if (copy_from_user(&(wc->mods[chan->chanpos - 1].fxs.vmwisetting), (__user void *) data, sizeof(wc->mods[chan->chanpos - 1].fxs.vmwisetting))) return -EFAULT; - - if (wc->mods[chan->chanpos - 1].fxs.vmwisetting.messages && wc->mods[chan->chanpos - 1].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_LREV){ - wc->mods[chan->chanpos - 1].fxs.linereverse_mwi = 1; - } else { - wc->mods[chan->chanpos - 1].fxs.linereverse_mwi = 0; - } - /* Set line polarity for new VMWI state */ - if (POLARITY_XOR(chan->chanpos -1)) { - wc->mods[chan->chanpos -1 ].fxs.idletxhookstate |= 0x14; - /* Do not set while currently ringing or open */ - if (wc->mods[chan->chanpos -1 ].fxs.lasttxhook != 0x04 && - wc->mods[chan->chanpos -1 ].fxs.lasttxhook != 0x00) { - wc->mods[chan->chanpos -1 ].fxs.lasttxhook |= 0x14; - wc->sethook[chan->chanpos - 1] = CMD_WR(64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); - } - } else { - wc->mods[chan->chanpos -1 ].fxs.idletxhookstate &= ~0x04; - /* Do not set while currently ringing or open */ - if (wc->mods[chan->chanpos -1 ].fxs.lasttxhook != 0x04 && - wc->mods[chan->chanpos -1 ].fxs.lasttxhook != 0x00) { - x = wc->mods[chan->chanpos -1 ].fxs.lasttxhook; - x &= ~0x04; - x |= 0x10; - wc->mods[chan->chanpos -1 ].fxs.lasttxhook = x; - wc->sethook[chan->chanpos - 1] = CMD_WR(64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); - } - } - - if (debug) { - printk(KERN_DEBUG "Setting VMWI on channel %d, messages=%d, lrev=%d\n", - chan->chanpos-1, - wc->mods[chan->chanpos - 1].fxs.vmwisetting.messages, - wc->mods[chan->chanpos - 1].fxs.linereverse_mwi - ); - } + set_vmwi(wc, chan->chanpos - 1); break; + case DAHDI_VMWI: + if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) + return -EINVAL; + if (get_user(x, (__user int *) data)) + return -EFAULT; + if (0 > x) + return -EFAULT; + wc->mods[chan->chanpos - 1].fxs.vmwi_active_messages = x; + set_vmwi(wc, chan->chanpos - 1); + break; case WCTDM_GET_STATS: if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { stats.tipvolt = wctdm_getreg(wc, chan->chanpos - 1, 80) * -376;