[dahdi-commits] dbailey: linux/trunk r5720 - in /linux/trunk: drivers/dahdi/ drivers/dahdi/wc...

SVN commits to the DAHDI project dahdi-commits at lists.digium.com
Mon Jan 19 09:15:33 CST 2009


Author: dbailey
Date: Mon Jan 19 09:15:32 2009
New Revision: 5720

URL: http://svn.digium.com/svn-view/dahdi?view=rev&rev=5720
Log:
Add line reversal MWI to wctdm and wctdm24xxp drivers 
Add global and per channel polarity control to the wctdm24xxp driver 
Add per channel polarity control to the wctdm driver 
 
Reported by: alecdavis
Patches:
      dahdidriver-14104.diff2.txt uploaded by dbailey (license )
Tested by: alecdavis


Modified:
    linux/trunk/drivers/dahdi/wctdm.c
    linux/trunk/drivers/dahdi/wctdm24xxp/base.c
    linux/trunk/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
    linux/trunk/include/dahdi/user.h

Modified: linux/trunk/drivers/dahdi/wctdm.c
URL: http://svn.digium.com/svn-view/dahdi/linux/trunk/drivers/dahdi/wctdm.c?view=diff&rev=5720&r1=5719&r2=5720
==============================================================================
--- linux/trunk/drivers/dahdi/wctdm.c (original)
+++ linux/trunk/drivers/dahdi/wctdm.c Mon Jan 19 09:15:32 2009
@@ -55,6 +55,7 @@
   0x07 : 41mA
 */
 static int loopcurrent = 20;
+#define POLARITY_XOR(card) ((reversepolarity!=0) ^ (wc->mod[(card)].fxs.reversepolarity!=0) ^ (wc->mod[(card)].fxs.vmwi_lrev!=0))
 
 static int reversepolarity = 0;
 
@@ -236,6 +237,12 @@
 			int idletxhookstate;		/* IDLE changing hook state */
 			int lasttxhook;
 			int palarms;
+			int reversepolarity;		/* Reverse Line */
+			int mwisendtype;
+			int vmwimessages;		/* 0=none 1-255=number of 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 */
 			struct calregs calregs;
 		} fxs;
 	} mod[NUM_CARDS];
@@ -1040,24 +1047,21 @@
 			if (wc->mod[x].fxs.lasttxhook == 0x4) {
 				/* RINGing, prepare for OHT */
 				wc->mod[x].fxs.ohttimer = OHT_TIMER << 3;
-				if (reversepolarity)
-					wc->mod[x].fxs.idletxhookstate = 0x6;	/* OHT mode when idle */
-				else
-					wc->mod[x].fxs.idletxhookstate = 0x2; 
+
+				/* logical XOR 3 variables
+				    module parameter 'reversepolarity', global reverse all FXS lines. 
+				    ioctl channel variable fxs 'reversepolarity', Line Reversal Alert Signal if required.
+				    ioctl channel variable fxs 'vmwi_lrev', VMWI pending.
+				 */
+				wc->mod[x].fxs.idletxhookstate = POLARITY_XOR(x) ? 0x6 : 0x2;/* OHT mode when idle */
 			} else {
 				if (wc->mod[x].fxs.ohttimer) {
 					wc->mod[x].fxs.ohttimer-= DAHDI_CHUNKSIZE;
 					if (!wc->mod[x].fxs.ohttimer) {
-						if (reversepolarity)
-							wc->mod[x].fxs.idletxhookstate = 0x5;	/* Switch to active */
-						else
-							wc->mod[x].fxs.idletxhookstate = 0x1;
+						wc->mod[x].fxs.idletxhookstate = POLARITY_XOR(x) ? 0x5 : 0x1; /* Switch to Active : Reverse Forward */
 						if ((wc->mod[x].fxs.lasttxhook == 0x2) || (wc->mod[x].fxs.lasttxhook == 0x6)) {
 							/* Apply the change if appropriate */
-							if (reversepolarity) 
-								wc->mod[x].fxs.lasttxhook = 0x5;
-							else
-								wc->mod[x].fxs.lasttxhook = 0x1;
+							wc->mod[x].fxs.lasttxhook = POLARITY_XOR(x) ? 0x5 : 0x1;
 							wctdm_setreg(wc, x, 64, wc->mod[x].fxs.lasttxhook);
 						}
 					}
@@ -1093,9 +1097,10 @@
 				/* Perform processing */
 				if (wc->modtype[x] == MOD_TYPE_FXS) {
 					wctdm_proslic_check_hook(wc, x);
-					if (!(wc->intcount & 0xf0))
+					if (!(wc->intcount & 0xf0)) {
 						wctdm_proslic_recheck_sanity(wc, x);
-					} else if (wc->modtype[x] == MOD_TYPE_FXO) {
+					}
+				} else if (wc->modtype[x] == MOD_TYPE_FXO) {
 					wctdm_voicedaa_check_hook(wc, x);
 				}
 				break;
@@ -1314,31 +1319,31 @@
 	// Delay 10ms
 	origjiffies=jiffies; 
 	while((jiffies-origjiffies)<1);
-	wctdm_proslic_setreg_indirect(wc, card, 88,0);
-	wctdm_proslic_setreg_indirect(wc,card,89,0);
-	wctdm_proslic_setreg_indirect(wc,card,90,0);
-	wctdm_proslic_setreg_indirect(wc,card,91,0);
-	wctdm_proslic_setreg_indirect(wc,card,92,0);
-	wctdm_proslic_setreg_indirect(wc,card,93,0);
-
-	wctdm_setreg(wc, card, 98,0x10); // This is necessary if the calibration occurs other than at reset time
-	wctdm_setreg(wc, card, 99,0x10);
+	wctdm_proslic_setreg_indirect(wc, card, 88, 0);
+	wctdm_proslic_setreg_indirect(wc, card, 89, 0);
+	wctdm_proslic_setreg_indirect(wc, card, 90, 0);
+	wctdm_proslic_setreg_indirect(wc, card, 91, 0);
+	wctdm_proslic_setreg_indirect(wc, card, 92, 0);
+	wctdm_proslic_setreg_indirect(wc, card, 93, 0);
+
+	wctdm_setreg(wc, card, 98, 0x10); // This is necessary if the calibration occurs other than at reset time
+	wctdm_setreg(wc, card, 99, 0x10);
 
 	for ( i=0x1f; i>0; i--)
 	{
-		wctdm_setreg(wc, card, 98,i);
+		wctdm_setreg(wc, card, 98, i);
 		origjiffies=jiffies; 
 		while((jiffies-origjiffies)<4);
-		if((wctdm_getreg(wc,card,88)) == 0)
+		if((wctdm_getreg(wc, card, 88)) == 0)
 			break;
 	} // for
 
 	for ( i=0x1f; i>0; i--)
 	{
-		wctdm_setreg(wc, card, 99,i);
+		wctdm_setreg(wc, card, 99, i);
 		origjiffies=jiffies; 
 		while((jiffies-origjiffies)<4);
-		if((wctdm_getreg(wc,card,89)) == 0)
+		if((wctdm_getreg(wc, card, 89)) == 0)
 			break;
 	}//for
 
@@ -1350,9 +1355,9 @@
 	wctdm_setreg(wc, card, 64, 0);
 	wctdm_setreg(wc, card, 23, 0x4);  // enable interrupt for the balance Cal
 	wctdm_setreg(wc, card, 97, 0x1); // this is a singular calibration bit for longitudinal calibration
-	wctdm_setreg(wc, card, 96,0x40);
-
-	wctdm_getreg(wc,card,96); /* Read Reg 96 just cause */
+	wctdm_setreg(wc, card, 96, 0x40);
+
+	wctdm_getreg(wc, card, 96); /* Read Reg 96 just cause */
 
 	wctdm_setreg(wc, card, 21, 0xFF);
 	wctdm_setreg(wc, card, 22, 0xFF);
@@ -1462,10 +1467,11 @@
 	wait_just_a_bit(HZ/10);
 
 	/* Enable PCM, ulaw */
-	if (alawoverride)
+	if (alawoverride){
 		wctdm_setreg(wc, card, 33, 0x20);
-	else
+	} else {
 		wctdm_setreg(wc, card, 33, 0x28);
+	}
 
 	/* Set On-hook speed, Ringer impedence, and ringer threshold */
 	reg16 |= (fxo_modes[_opermode].ohs << 6);
@@ -1560,9 +1566,16 @@
 	/* Sanity check the ProSLIC */
 	if (!sane && wctdm_proslic_insane(wc, card))
 		return -2;
+	
+	/* default messages to none and method to FSK */
+	wc->mod[card].fxs.mwisendtype=DAHDI_VMWI_FSK;
+	wc->mod[card].fxs.vmwimessages=0;
+	wc->mod[card].fxs.vmwi_lrev=0;
+	wc->mod[card].fxs.vmwi_hvdc=0;
+	wc->mod[card].fxs.vmwi_hvac=0;
 		
 	/* By default, don't send on hook */
-	if (reversepolarity)
+	if (!reversepolarity != !wc->mod[card].fxs.reversepolarity)
 		wc->mod[card].fxs.idletxhookstate = 5;
 	else
 		wc->mod[card].fxs.idletxhookstate = 1;
@@ -1781,7 +1794,8 @@
 	if(debug)
 			printk(KERN_DEBUG "DEBUG: fxstxgain:%s fxsrxgain:%s\n",((wctdm_getreg(wc, card, 9)/8) == 1)?"3.5":(((wctdm_getreg(wc,card,9)/4) == 1)?"-3.5":"0.0"),((wctdm_getreg(wc, card, 9)/2) == 1)?"3.5":((wctdm_getreg(wc,card,9)%2)?"-3.5":"0.0"));
 
-	wctdm_setreg(wc, card, 64, 0x01);
+	wc->mod[card].fxs.lasttxhook = wc->mod[card].fxs.idletxhookstate;
+	wctdm_setreg(wc, card, 64, wc->mod[card].fxs.lasttxhook);
 	return 0;
 }
 
@@ -1802,17 +1816,11 @@
 		if (get_user(x, (__user int *) data))
 			return -EFAULT;
 		wc->mod[chan->chanpos - 1].fxs.ohttimer = x << 3;
-		if (reversepolarity)
-			wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 0x6;	/* OHT mode when idle */
-		else
-			wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 0x2;
+		wc->mod[chan->chanpos - 1].fxs.idletxhookstate = POLARITY_XOR(chan->chanpos - 1) ? 0x6 : 0x2;	/* OHT mode when idle */
 		if (wc->mod[chan->chanpos - 1].fxs.lasttxhook == 0x1 || wc->mod[chan->chanpos - 1].fxs.lasttxhook == 0x5) {
-				/* Apply the change if appropriate */
-				if (reversepolarity)
-					wc->mod[chan->chanpos - 1].fxs.lasttxhook = 0x6;
-				else
-					wc->mod[chan->chanpos - 1].fxs.lasttxhook = 0x2;
-				wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook);
+			/* Apply the change if appropriate */
+			wc->mod[chan->chanpos - 1].fxs.lasttxhook = POLARITY_XOR(chan->chanpos - 1) ? 0x6 : 0x2;
+			wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook);
 		}
 		break;
 	case DAHDI_SETPOLARITY:
@@ -1824,12 +1832,62 @@
 		if ((wc->mod[chan->chanpos -1 ].fxs.lasttxhook == 0x04) ||
 		    (wc->mod[chan->chanpos -1 ].fxs.lasttxhook == 0x00))
 			return -EINVAL;
-
-		if ((x && !reversepolarity) || (!x && reversepolarity))
+		
+		wc->mod[chan->chanpos - 1].fxs.reversepolarity = x;
+		if ( POLARITY_XOR(chan->chanpos - 1) )
 			wc->mod[chan->chanpos - 1].fxs.lasttxhook |= 0x04;
 		else
 			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:
+		/* value:	bits 15-8 VMWI TYPE */
+		/* 		bits 7-0 VMWI number of messages */
+		if (get_user(x, (__user int *) data))
+			return -EFAULT;
+		if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS)
+			return -EINVAL;
+
+		wc->mod[chan->chanpos - 1].fxs.vmwimessages = (x & 255);
+		wc->mod[chan->chanpos - 1].fxs.mwisendtype = (x & ~255);
+		if (wc->mod[chan->chanpos - 1].fxs.vmwimessages){
+			x = wc->mod[chan->chanpos - 1].fxs.mwisendtype;
+			wc->mod[chan->chanpos - 1].fxs.vmwi_lrev = (x & DAHDI_VMWI_LREV)?1:0;
+			wc->mod[chan->chanpos - 1].fxs.vmwi_hvdc = (x & DAHDI_VMWI_HVDC)?1:0;
+			wc->mod[chan->chanpos - 1].fxs.vmwi_hvac = (x & 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, type=0x%X, messages=%d, lrev=%d, hvdc=%d, hvac=%d\n",
+				chan->chanpos-1,
+				wc->mod[chan->chanpos - 1].fxs.mwisendtype,
+				wc->mod[chan->chanpos - 1].fxs.vmwimessages,
+				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);
+			}
+		}
 		break;
 	case WCTDM_GET_STATS:
 		if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) {
@@ -1942,10 +2000,7 @@
 	wc->usecount--;
 	module_put(THIS_MODULE);
 	if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) {
-		if (reversepolarity)
-			wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 5;
-		else
-			wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 1;
+		wc->mod[chan->chanpos - 1].fxs.idletxhookstate = POLARITY_XOR(chan->chanpos - 1) ? 0x5 : 0x1;
 	}
 	/* If we're dead, release us now */
 	if (!wc->usecount && wc->dead) 
@@ -1956,7 +2011,7 @@
 static int wctdm_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig)
 {
 	struct wctdm *wc = chan->pvt;
-	int reg=0;
+
 	if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
 		/* XXX Enable hooksig for FXO XXX */
 		switch(txsig) {
@@ -1976,9 +2031,11 @@
 		switch(txsig) {
 		case DAHDI_TXSIG_ONHOOK:
 			switch(chan->sig) {
-			case DAHDI_SIG_EM:
 			case DAHDI_SIG_FXOKS:
 			case DAHDI_SIG_FXOLS:
+				wc->mod[chan->chanpos-1].fxs.lasttxhook = (wc->mod[chan->chanpos-1].fxs.vmwi_hvac ? 4 : wc->mod[chan->chanpos-1].fxs.idletxhookstate);
+				break;
+			case DAHDI_SIG_EM:
 				wc->mod[chan->chanpos-1].fxs.lasttxhook = wc->mod[chan->chanpos-1].fxs.idletxhookstate;
 				break;
 			case DAHDI_SIG_FXOGS:
@@ -2006,7 +2063,7 @@
 			printk(KERN_NOTICE "wctdm: Can't set tx state to %d\n", txsig);
 		}
 		if (debug)
-			printk(KERN_DEBUG "Setting FXS hook state to %d (%02x)\n", txsig, reg);
+			printk(KERN_DEBUG "Setting FXS hook state to %d (%02x)\n", txsig, wc->mod[chan->chanpos-1].fxs.lasttxhook);
 
 #if 1
 		wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos-1].fxs.lasttxhook);
@@ -2029,8 +2086,9 @@
 	if (alawoverride) {
 		printk(KERN_INFO "ALAW override parameter detected.  Device will be operating in ALAW\n");
 		wc->span.deflaw = DAHDI_LAW_ALAW;
-	} else
+	} else {
 		wc->span.deflaw = DAHDI_LAW_MULAW;
+	}
 	for (x = 0; x < NUM_CARDS; x++) {
 		sprintf(wc->chans[x]->name, "WCTDM/%d/%d", wc->pos, x);
 		wc->chans[x]->sigcap = DAHDI_SIG_FXOKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_SF | DAHDI_SIG_EM | DAHDI_SIG_CLEAR;

Modified: linux/trunk/drivers/dahdi/wctdm24xxp/base.c
URL: http://svn.digium.com/svn-view/dahdi/linux/trunk/drivers/dahdi/wctdm24xxp/base.c?view=diff&rev=5720&r1=5719&r2=5720
==============================================================================
--- linux/trunk/drivers/dahdi/wctdm24xxp/base.c (original)
+++ linux/trunk/drivers/dahdi/wctdm24xxp/base.c Mon Jan 19 09:15:32 2009
@@ -80,6 +80,15 @@
   0x07 : 41mA
 */
 static int loopcurrent = 20;
+
+/* Following define is a logical exclusive OR to determine if the polarity of an fxs line is to be reversed.
+ * 	The items taken into account are:
+ * 	overall polarity reversal for the module,
+ * 	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.vmwilinereverse != 0) )
+static int reversepolarity = 0;
 
 static alpha  indirect_regs[] =
 {
@@ -1035,8 +1044,9 @@
 		wc->mods[card].fxs.palarms++;
 		if (wc->mods[card].fxs.palarms < MAX_ALARMS) {
 			printk(KERN_NOTICE "Power alarm (%02x) on module %d, resetting!\n", res, card + 1);
-			if (wc->mods[card].fxs.lasttxhook == 4)
-				wc->mods[card].fxs.lasttxhook = 0x11;
+			if (wc->mods[card].fxs.lasttxhook == 4) {
+				wc->mods[card].fxs.lasttxhook = POLARITY_XOR(card) ? 0x15 : 0x11;
+			}
 			wc->sethook[card] = CMD_WR(19, res);
 #if 0
 			wc->sethook[card] = CMD_WR(64, wc->mods[card].fxs.lasttxhook);
@@ -1064,8 +1074,9 @@
 		wc->mods[card].fxs.palarms++;
 		if (wc->mods[card].fxs.palarms < MAX_ALARMS) {
 			printk(KERN_NOTICE "Power alarm on module %d, resetting!\n", card + 1);
-			if (wc->mods[card].fxs.lasttxhook == 4)
-				wc->mods[card].fxs.lasttxhook = 0x11;
+			if (wc->mods[card].fxs.lasttxhook == 4) {
+				wc->mods[card].fxs.lasttxhook = POLARITY_XOR(card) ? 0x15 : 0x11;;
+			}
 			wc->mods[card].fxs.lasttxhook |= 0x10;
 			wc->sethook[card] = CMD_WR(64, wc->mods[card].fxs.lasttxhook);
 
@@ -1543,16 +1554,21 @@
 				if (wc->mods[x].fxs.lasttxhook == 0x4) {
 					/* RINGing, prepare for OHT */
 					wc->mods[x].fxs.ohttimer = OHT_TIMER << 3;
-					wc->mods[x].fxs.idletxhookstate = 0x2;	/* OHT mode when idle */
+					wc->mods[x].fxs.idletxhookstate = POLARITY_XOR(x) ? 0x6 : 0x2; /* OHT mode when idle */
 				} else {
 					if (wc->mods[x].fxs.ohttimer) {
 						wc->mods[x].fxs.ohttimer-= DAHDI_CHUNKSIZE;
 						if (!wc->mods[x].fxs.ohttimer) {
-							wc->mods[x].fxs.idletxhookstate = 0x1;	/* Switch to active */
-							if (wc->mods[x].fxs.lasttxhook == 0x2) {
+							wc->mods[x].fxs.idletxhookstate = POLARITY_XOR(x) ? 0x5 : 0x1; 	/* Switch to active */ 
+							if (wc->mods[x].fxs.lasttxhook == 0x2) {	
 								/* Apply the change if appropriate */
 								wc->mods[x].fxs.lasttxhook = 0x11;
-								wc->sethook[x] = CMD_WR(64, wc->mods[x].fxs.lasttxhook);
+								wc->sethook[x] = CMD_WR(64, wc->mods[x].fxs.lasttxhook);	/* Data enqueued here */  
+								/* wctdm_setreg_intr(wc, x, 64, wc->mods[x].fxs.lasttxhook); */
+							} else if (wc->mods[x].fxs.lasttxhook == 0x6) {	
+								/* Apply the change if appropriate */
+								wc->mods[x].fxs.lasttxhook = 0x15;
+								wc->sethook[x] = CMD_WR(64, wc->mods[x].fxs.lasttxhook);	/* Data enqueued here */  
 								/* wctdm_setreg_intr(wc, x, 64, wc->mods[x].fxs.lasttxhook); */
 							}
 						}
@@ -1942,10 +1958,11 @@
 	wait_just_a_bit(HZ/10);
 
 	/* Enable PCM, ulaw */
-	if (alawoverride)
+	if (alawoverride) {
 		wctdm_setreg(wc, card, 33, 0x20);
-	else
+	} else {
 		wctdm_setreg(wc, card, 33, 0x28);
+	}
 
 	/* Set On-hook speed, Ringer impedence, and ringer threshold */
 	reg16 |= (fxo_modes[_opermode].ohs << 6);
@@ -2034,8 +2051,17 @@
 	if (!sane && wctdm_proslic_insane(wc, card))
 		return -2;
 
+	/* Initialize VMWI settings */
+	wc->mods[card].fxs.mwisendtype  = 0;	
+	wc->mods[card].fxs.vmwimessages = 0;
+	wc->mods[card].fxs.vmwilinereverse    = 0;
+
 	/* By default, don't send on hook */
-	wc->mods[card].fxs.idletxhookstate = 1;
+	if (!reversepolarity != !wc->mods[card].fxs.reversepolarity) {
+		wc->mods[card].fxs.idletxhookstate = 5;
+	} else {
+		wc->mods[card].fxs.idletxhookstate = 1;
+	}
 	wc->mods[card].fxs.lasttxhook = 0x10;
 
 	if (sane) {
@@ -2253,8 +2279,8 @@
 	if (debug)
 		printk(KERN_DEBUG "DEBUG: fxstxgain:%s fxsrxgain:%s\n",((wctdm_getreg(wc, card, 9)/8) == 1)?"3.5":(((wctdm_getreg(wc,card,9)/4) == 1)?"-3.5":"0.0"),((wctdm_getreg(wc, card, 9)/2) == 1)?"3.5":((wctdm_getreg(wc,card,9)%2)?"-3.5":"0.0"));
 
-	wc->mods[card].fxs.lasttxhook = 0x11;
-	wctdm_setreg(wc, card, 64, 0x01);
+	wc->mods[card].fxs.lasttxhook = wc->mods[card].fxs.idletxhookstate;
+	wctdm_setreg(wc, card, 64, wc->mods[card].fxs.lasttxhook);
 	return 0;
 }
 
@@ -2412,11 +2438,58 @@
 			return -EFAULT;
 		wc->mods[chan->chanpos - 1].fxs.ohttimer = x << 3;
 		wc->mods[chan->chanpos - 1].fxs.idletxhookstate = 0x2;	/* OHT mode when idle */
-		if (wc->mods[chan->chanpos - 1].fxs.lasttxhook == 0x1) {
+		if (wc->mods[chan->chanpos - 1].fxs.lasttxhook == 0x1 || wc->mods[chan->chanpos - 1].fxs.lasttxhook == 0x5) {
 			/* Apply the change if appropriate */
-			wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x12;
+			wc->mods[chan->chanpos - 1].fxs.lasttxhook = POLARITY_XOR(chan->chanpos -1) ? 0x16 : 0x12;
 			wc->sethook[chan->chanpos - 1] = CMD_WR(64, wc->mods[chan->chanpos - 1].fxs.lasttxhook);
 			/* wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); */
+		}
+		break;
+	case DAHDI_VMWI:
+		/* value:	bits 15-8 VMWI TYPE */
+		/* 		bits 7-0 VMWI number of messages */
+		if (get_user(x, (__user int *) data))
+			return -EFAULT;
+		if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS)
+			return -EINVAL;
+
+		wc->mods[chan->chanpos - 1].fxs.vmwimessages = (x & 255);
+		wc->mods[chan->chanpos - 1].fxs.mwisendtype = (x & ~255);
+		if (wc->mods[chan->chanpos - 1].fxs.vmwimessages){
+			x = wc->mods[chan->chanpos - 1].fxs.mwisendtype;
+			wc->mods[chan->chanpos - 1].fxs.vmwilinereverse= (x & DAHDI_VMWI_LREV)?1:0;
+		} else {
+			wc->mods[chan->chanpos - 1].fxs.vmwilinereverse= 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, type=0x%X, messages=%d, lrev=%d\n",
+				chan->chanpos-1,
+				wc->mods[chan->chanpos - 1].fxs.mwisendtype,
+				wc->mods[chan->chanpos - 1].fxs.vmwimessages,
+				wc->mods[chan->chanpos - 1].fxs.vmwilinereverse
+			);
 		}
 		break;
 	case WCTDM_GET_STATS:
@@ -2529,6 +2602,32 @@
 		}
 		return 0;
 #endif
+	case DAHDI_SETPOLARITY:
+		if (get_user(x, (__user int *) data))
+			return -EFAULT;
+		if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS)
+			return -EINVAL;
+		/* Can't change polarity while ringing or when open */
+		if ((wc->mods[chan->chanpos -1 ].fxs.lasttxhook == 0x04) ||
+						(wc->mods[chan->chanpos -1 ].fxs.lasttxhook == 0x00))
+			return -EINVAL;
+		if (x) {
+			wc->mods[chan->chanpos -1 ].fxs.reversepolarity = 1;
+		} else {
+			wc->mods[chan->chanpos -1 ].fxs.reversepolarity = 0;
+		}
+		if (POLARITY_XOR(chan->chanpos -1)) {
+			wc->mods[chan->chanpos -1 ].fxs.idletxhookstate |= 0x14;
+			wc->mods[chan->chanpos -1 ].fxs.lasttxhook |= 0x14;
+		} else {
+			wc->mods[chan->chanpos -1 ].fxs.idletxhookstate &= ~0x04;
+			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);
+		break;
 	case DAHDI_RADIO_GETPARAM:
 		if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_QRV) 
 			return -ENOTTY;
@@ -2713,8 +2812,9 @@
 	wc->usecount--;
 	module_put(THIS_MODULE);
 	for (x=0;x<wc->cards;x++) {
-		if (wc->modtype[x] == MOD_TYPE_FXS)
-			wc->mods[x].fxs.idletxhookstate = 1;
+		if (wc->modtype[x] == MOD_TYPE_FXS) {
+			wc->mods[x].fxs.idletxhookstate = POLARITY_XOR(x) ? 5 : 1;
+		}
 		if (wc->modtype[x] == MOD_TYPE_QRV)
 		{
 			int qrvcard = x & 0xfc;
@@ -2788,14 +2888,22 @@
 					wc->mods[chan->chanpos - 1].fxs.idletxhookstate;
 				break;
 			case DAHDI_SIG_FXOGS:
-				wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x13;
+				if (POLARITY_XOR(chan->chanpos -1)) {
+					wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x17;
+				} else {
+					wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x13;
+				}
 				break;
 			}
 			break;
 		case DAHDI_TXSIG_OFFHOOK:
 			switch(chan->sig) {
 			case DAHDI_SIG_EM:
-				wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x15;
+				if (POLARITY_XOR(chan->chanpos -1)) {
+					wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x11;
+				} else {
+					wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x15;
+				}
 				break;
 			default:
 				wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x10 |
@@ -2934,8 +3042,9 @@
 	if (alawoverride) {
 		printk(KERN_INFO "ALAW override parameter detected.  Device will be operating in ALAW\n");
 		wc->span.deflaw = DAHDI_LAW_ALAW;
-	} else
+	} else {
 		wc->span.deflaw = DAHDI_LAW_MULAW;
+	}
 	for (x=0;x<wc->cards;x++) {
 		sprintf(wc->chans[x]->name, "WCTDM/%d/%d", wc->pos, x);
 		wc->chans[x]->sigcap = DAHDI_SIG_FXOKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_SF | DAHDI_SIG_EM | DAHDI_SIG_CLEAR;
@@ -4093,6 +4202,7 @@
 module_param(debug, int, 0600);
 module_param(fxovoltage, int, 0600);
 module_param(loopcurrent, int, 0600);
+module_param(reversepolarity, int, 0600);
 module_param(robust, int, 0600);
 module_param(opermode, charp, 0600);
 module_param(lowpower, int, 0600);

Modified: linux/trunk/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
URL: http://svn.digium.com/svn-view/dahdi/linux/trunk/drivers/dahdi/wctdm24xxp/wctdm24xxp.h?view=diff&rev=5720&r1=5719&r2=5720
==============================================================================
--- linux/trunk/drivers/dahdi/wctdm24xxp/wctdm24xxp.h (original)
+++ linux/trunk/drivers/dahdi/wctdm24xxp/wctdm24xxp.h Mon Jan 19 09:15:32 2009
@@ -245,9 +245,13 @@
 			int lastrxhook;
 			int debounce;
 			int ohttimer;
-			int idletxhookstate;		/* IDLE changing hook state */
-			int lasttxhook;
+			int idletxhookstate;	/* IDLE changing hook state */
+			int lasttxhook;		/* Bits 0-3 are written to proslic reg 64, Bit 4 indicates if the last write is pending */
 			int palarms;
+			int mwisendtype;
+			int vmwimessages;	/* 0=none 1-255=number of messages */
+			int vmwilinereverse;	/* MWI Line Reversal*/
+			int reversepolarity;	/* polarity reversal */
 			struct calregs calregs;
 		} fxs;
 	} mods[NUM_CARDS];

Modified: linux/trunk/include/dahdi/user.h
URL: http://svn.digium.com/svn-view/dahdi/linux/trunk/include/dahdi/user.h?view=diff&rev=5720&r1=5719&r2=5720
==============================================================================
--- linux/trunk/include/dahdi/user.h (original)
+++ linux/trunk/include/dahdi/user.h Mon Jan 19 09:15:32 2009
@@ -967,10 +967,16 @@
 #define DAHDI_TC_GETINFO		_IOWR(DAHDI_TC_CODE, 2, struct dahdi_transcoder_info)
 
 /*
- * VoiceMail Waiting Indication (WMWI) -- implemented by low-level driver.
+ * 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, int)
+
+#define DAHDI_VMWI_FSK	(1 << 8)	/* default FSK, no Ring Pulse Alert Signal*/
+#define DAHDI_VMWI_RPAS	(1 << 9)	/* Ring Pulse Alert Signal then FSK */
+#define DAHDI_VMWI_LREV	(1 << 10)	/* Line Reversal */
+#define DAHDI_VMWI_HVDC	(1 << 11)	/* HV 90VDC */
+#define DAHDI_VMWI_HVAC	(1 << 12)	/* HV 90VAC Neon lamp */
 
 /* 
  * Startup or Shutdown a span




More information about the dahdi-commits mailing list