[zaptel-commits] tzafrir: branch 1.2 r1457 - in /branches/1.2/xpp: ./ utils/

zaptel-commits at lists.digium.com zaptel-commits at lists.digium.com
Sat Sep 9 08:24:13 MST 2006


Author: tzafrir
Date: Sat Sep  9 10:24:12 2006
New Revision: 1457

URL: http://svn.digium.com/view/zaptel?rev=1457&view=rev
Log:
Latest xpp driver. Backported from trunk (r1455, Xorcom r2157)

Added:
    branches/1.2/xpp/calibrate_slics   (with props)
    branches/1.2/xpp/utils/print_modes.c   (with props)
Modified:
    branches/1.2/xpp/   (props changed)
    branches/1.2/xpp/Makefile
    branches/1.2/xpp/card_fxo.c
    branches/1.2/xpp/card_fxo.h
    branches/1.2/xpp/card_fxs.c
    branches/1.2/xpp/card_fxs.h
    branches/1.2/xpp/init_data_3_19.cmd
    branches/1.2/xpp/init_data_3_20.cmd
    branches/1.2/xpp/init_data_4_19.cmd
    branches/1.2/xpp/init_data_4_20.cmd
    branches/1.2/xpp/initialize_registers
    branches/1.2/xpp/utils/   (props changed)
    branches/1.2/xpp/utils/FPGA_FXS.hex
    branches/1.2/xpp/utils/Makefile
    branches/1.2/xpp/utils/USB_8613.hex   (props changed)
    branches/1.2/xpp/utils/fpga_load.c
    branches/1.2/xpp/utils/genzaptelconf
    branches/1.2/xpp/utils/xpp_fxloader
    branches/1.2/xpp/xbus-core.c
    branches/1.2/xpp/xbus-core.h
    branches/1.2/xpp/xdefs.h
    branches/1.2/xpp/xpd.h
    branches/1.2/xpp/xpp_usb.c
    branches/1.2/xpp/xpp_zap.c
    branches/1.2/xpp/xpp_zap.h
    branches/1.2/xpp/xproto.c
    branches/1.2/xpp/xproto.h

Propchange: branches/1.2/xpp/
------------------------------------------------------------------------------
    svk:merge = f558416c-6c06-0410-9f27-dde2687782d0:/trunk/xpp:1453

Propchange: branches/1.2/xpp/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Sat Sep  9 10:24:12 2006
@@ -3,3 +3,5 @@
 *.o.cmd
 *.ko.cmd
 *.mod.c
+.tmp_versions
+.*.swp

Modified: branches/1.2/xpp/Makefile
URL: http://svn.digium.com/view/zaptel/branches/1.2/xpp/Makefile?rev=1457&r1=1456&r2=1457&view=diff
==============================================================================
--- branches/1.2/xpp/Makefile (original)
+++ branches/1.2/xpp/Makefile Sat Sep  9 10:24:12 2006
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS	= -I$(SUBDIRS) -DDEBUG -DPOLL_DIGITAL_INPUTS -DWITH_ECHO_SUPPRESSION -DWITH_RBS
+EXTRA_CFLAGS	= -I$(SUBDIRS) -DDEBUG -DPOLL_DIGITAL_INPUTS -DWITH_ECHO_SUPPRESSION # -DSOFT_RING
 
 obj-m			= xpp.o xpp_usb.o xpd_fxs.o xpd_fxo.o
 xpp-y			+= xbus-core.o xpp_zap.o xproto.o card_global.o

Added: branches/1.2/xpp/calibrate_slics
URL: http://svn.digium.com/view/zaptel/branches/1.2/xpp/calibrate_slics?rev=1457&view=auto
==============================================================================
--- branches/1.2/xpp/calibrate_slics (added)
+++ branches/1.2/xpp/calibrate_slics Sat Sep  9 10:24:12 2006
@@ -1,0 +1,314 @@
+#!/usr/bin/perl -w
+
+#
+# $Id:$
+#
+
+use strict;
+use Time::HiRes qw (time alarm sleep);
+
+my $SlicsFile = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/$ENV{XPD_NAME}/slics";
+
+my @SlicNums = (0 .. 7);
+
+if ( ! -f $SlicsFile ) {
+	exit 1
+}
+
+sub logger($) {
+	print STDERR "LOG: @_\n";
+	system("logger @_");
+}
+
+sub write_to_slic_file($) {
+	my $write_str = shift;
+	#print STDERR "[Writing string]\n".$write_str."[End String]\n";
+
+	open(SLICS,">$SlicsFile") or 
+		die("Failed writing to slics file $SlicsFile");
+	print SLICS $write_str;
+	close(SLICS);
+	sleep(0.001);
+	
+}
+
+sub read_reg($$$) {
+	my $read_slic = shift;
+	my $read_reg = shift;
+	my $direct = shift;
+	
+	write_to_slic_file(
+		sprintf("%02x 00 00 00 R%s %02X", 
+			1<<$read_slic, $direct, $read_reg));
+	sleep(0.001);
+	open(SLICS,$SlicsFile) or 
+		die("Failed reading from slics file $SlicsFile");
+	my @reply = ();
+	while(<SLICS>){
+		#if (/^[^#]/) {
+		#	print STDERR "answer line: $_";
+		#}
+		if (/^SLIC_REPLY:\s+[DI]\s+reg_num=0x[[:xdigit:]]+,\s+dataH=0x([[:xdigit:]]+)\s+dataL=0x([[:xdigit:]]+)/){
+			@reply = (hex($1), hex($2)); 
+			#print STDERR "got [@reply]\n";
+			last;
+		}
+	}
+	close(SLICS);
+	if ($direct eq 'I') {
+		return @reply;
+	} else {
+		return $reply[1];
+	}
+}
+
+# TODO: rearange arguments
+sub write_reg{#($$$$$) {
+	my $read_slic = shift;
+	my $read_reg = shift;
+	my $direct = shift;
+	my $reg_val_low = shift;
+	my $reg_val_hi = shift;
+	
+	my $str  = sprintf "%02x 00 00 00 W%s %02X %02X", 
+		1<<$read_slic, $direct, $read_reg, $reg_val_low;
+	if ($direct eq 'I') {
+		$str .= sprintf " %02X", $reg_val_hi;
+	}
+	#printf STDERR "Writing: $str\n";
+	write_to_slic_file($str);
+}
+
+# TODO: rearange arguments
+sub write_reg_all_slics{#($$$$) {
+	my $read_reg = shift;
+	my $direct = shift;
+	my $reg_val_low = shift;
+	my $reg_val_hi = shift;
+	
+	my $str  = sprintf "FF FF 00 00 W%s %02X %02X", 
+		$direct, $read_reg, $reg_val_low;
+	if ($direct eq 'I') {
+		$str .= sprintf " %02X", $reg_val_hi;
+	}
+	printf STDERR "Writing: $str\n";
+	write_to_slic_file($str);
+}
+
+sub log_calib_params() {
+	for my $i (100 .. 107) {
+		my $line="Calib Reg $i:  ";
+		for my $slic (@SlicNums) {
+			$line .= " ".read_reg($slic, $i, 'D');
+		}
+		logger($line);
+	}
+}
+
+sub init_indirect_registers() {
+	return write_to_slic_file("#
+FF FF 00 00	WI	00	C2	55
+FF FF 00 00	WI	01	E6	51
+FF FF 00 00	WI	02	85	4B
+FF FF 00 00	WI	03	37	49
+                          
+FF FF 00 00	WI	04	33	33
+FF FF 00 00	WI	05	02	02
+FF FF 00 00	WI	06	02	02
+FF FF 00 00	WI	07	98	01
+                          
+FF FF 00 00	WI	08	98	01
+FF FF 00 00	WI	09	11	06
+FF FF 00 00	WI	0A	02	02
+FF FF 00 00	WI	0B	E5	00
+                          
+FF FF 00 00	WI	0C	1C	0A
+FF FF 00 00	WI	0D	30	7B
+FF FF 00 00	WI	0E	63	00
+FF FF 00 00	WI	0F	00	00
+                          
+FF FF 00 00	WI	10	70	78
+FF FF 00 00	WI	11	7D	00
+FF FF 00 00	WI	12	00	00
+FF FF 00 00	WI	13	00	00
+                          
+FF FF 00 00	WI	14	F0	7E
+FF FF 00 00	WI	15	60	01
+FF FF 00 00	WI	16	00	00
+FF FF 00 00	WI	17	00	20
+                          
+FF FF 00 00	WI	18	00	20
+FF FF 00 00	WI	19	00	00
+FF FF 00 00	WI	1A	00	20
+FF FF 00 00	WI	1B	00	40
+                          
+FF FF 00 00	WI	1C	00	10
+FF FF 00 00	WI	1D	00	36
+FF FF 00 00	WI	1E	00	10
+FF FF 00 00	WI	1F	00	02
+                          
+FF FF 00 00	WI	20	C0	07
+FF FF 00 00	WI	21	00	26
+FF FF 00 00	WI	22	F4	0F
+FF FF 00 00	WI	23	00	80
+
+#FF FF 00 00	WI	24	20	03
+#FF FF 00 00	WI	25	8C	08
+#FF FF 00 00	WI	26	00	01
+#FF FF 00 00	WI	27	10	00
+                          
+FF FF 00 00	WI	24	00	08
+FF FF 00 00	WI	25	00	08
+FF FF 00 00	WI	26	00	08
+FF FF 00 00	WI	27	00	08
+                          
+FF FF 00 00	WI	28	00	0C
+FF FF 00 00	WI	29	00	0C
+FF FF 00 00	WI	2B	00	01
+                          
+FF FF 00 00	WI	63	DA	00
+FF FF 00 00	WI	64	60	6B
+FF FF 00 00	WI	65	74	00
+FF FF 00 00	WI	66	C0	79
+                          
+FF FF 00 00	WI	67	20	11
+FF FF 00 00	WI	68	E0	3B	
+#");
+}
+
+sub init_early_direct_regs() {
+	return write_to_slic_file("#
+FF FF 00 00	WD	08 00
+FF FF 00 00	WD	4A 34
+FF FF 00 00	WD	4B 10
+FF FF 00 00	WD	40 00
+#")
+}
+
+my @FilterParams = ();
+
+sub save_indirect_filter_params() {
+	for my $slic (@SlicNums) {
+		for my $reg (35 .. 39) {
+			$FilterParams[$slic][$reg] = 
+				[read_reg($slic, $reg, 'I')];
+			write_reg($slic, $reg, 'I', 0, 0x80);
+		}
+	}
+	
+}
+
+sub restore_indirect_filter_params() {
+	for my $slic (@SlicNums) {
+		for my $reg (35 .. 39) {
+			write_reg($slic, $reg, 'I', 
+				@{$FilterParams[$slic][$reg]});
+		}
+	}
+}
+
+my $ManualCalibrationSleepTime = 0.04; # 40ms
+
+sub manual_calibrate_loop($$) {
+	my $write_reg = shift;
+	my $read_reg = shift;
+	
+	# counters to count down to (at most) 0
+	my @slic_counters = ();
+	for my $i (0 .. $#SlicNums) {
+		$slic_counters[$i] = 0x1F;
+	}
+	
+	# start calibration:
+	my $calibration_in_progress = 1;
+	write_reg_all_slics($write_reg, 'D', 0x1F);
+	sleep $ManualCalibrationSleepTime;
+	
+	# wait until all slics have finished calibration, or for timeout
+	while ($calibration_in_progress) {
+		$calibration_in_progress = 0; # until proven otherwise
+		print STDERR "ManualCalib:: ";
+		for my $slic(@SlicNums) {
+			my $value = read_reg($slic, $read_reg, 'D');
+			print STDERR " [$slic_counters[$slic]:$value]";
+			if ($value != 0 && $slic_counters[$slic] >= 0) {
+				$calibration_in_progress = 1;
+				$slic_counters[$slic]--;
+				write_reg($slic,$write_reg,'D',$slic_counters[$slic]);
+			}
+		}
+		print STDERR "\n";
+		# TODO: unnecessary sleep in the last round:
+		sleep $ManualCalibrationSleepTime;
+	}
+}
+
+sub manual_calibrate() {
+	manual_calibrate_loop(98, 88);
+	manual_calibrate_loop(99, 89);
+}
+
+sub auto_calibrate($$) {
+	my $calib_96 = shift;
+	my $calib_97 = shift;
+
+	#log_calib_params();
+	# start calibration:
+	write_to_slic_file(
+		sprintf
+			"FF FF 00 00	WD 61 %02X\n".
+			"FF FF 00 00	WD 60 %02X\n".
+			"", $calib_97, $calib_96
+			
+	);
+	# wait until all slics have finished calibration, or for timeout
+	my $end_time=time() + 2;
+	my $timeout=0;
+	CALIB_LOOP: for my $slic (@SlicNums) {
+		logger("checking slic $slic");
+		while(1) {
+			my $reply;
+			if (($reply=read_reg($slic, 96, 'D')) == 0) {
+				# move to next register
+				logger("slic $slic calibrated");
+				last;
+			}
+			print STDERR "reply: $reply\n";
+			my $time=time();
+			if ( $time > $end_time) {
+				$timeout=1;
+				logger("Exiting on timeout: $time is after timeout $end_time .");
+				exit 1;
+				#last CALIB_LOOP;
+			}
+			logger("auto_calibrate not done yet: slic #$slic\n");
+			sleep(0.1);
+		}
+	}
+	#log_calib_params();
+}
+
+###########################################################
+#
+# main
+#
+
+# TODO: for all slics check the following reads to check communication
+#read_reg($slic, 0x08, 'D'): 0x02
+#read_reg($slic, 0x0B, 'D'): 0x33
+#read_reg($slic, 0x40, 'D'): 0x00 (?)
+
+print STDERR "starting\n";
+
+init_indirect_registers();
+print STDERR "after init_indirect_registers\n";
+init_early_direct_regs();
+print STDERR "after init_early_direct_regs\n";
+auto_calibrate(0x47, 0x1E);
+print STDERR "after auto_calibrate\n";
+manual_calibrate();
+print STDERR "after manul_calibrate\n";
+auto_calibrate(0x40, 0x01);
+print STDERR "after auto_calibrate 2\n";
+
+

Propchange: branches/1.2/xpp/calibrate_slics
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: branches/1.2/xpp/calibrate_slics
------------------------------------------------------------------------------
    svn:executable = *

Propchange: branches/1.2/xpp/calibrate_slics
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: branches/1.2/xpp/calibrate_slics
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: branches/1.2/xpp/card_fxo.c
URL: http://svn.digium.com/view/zaptel/branches/1.2/xpp/card_fxo.c?rev=1457&r1=1456&r2=1457&view=diff
==============================================================================
--- branches/1.2/xpp/card_fxo.c (original)
+++ branches/1.2/xpp/card_fxo.c Sat Sep  9 10:24:12 2006
@@ -51,12 +51,14 @@
 #define	NUM_LEDS		1
 #define	DELAY_UNTIL_DIALTONE	3000
 
+#define	BAT_THRESHOLD		3
+#define	BAT_DEBOUNCE		3	/* compensate for battery voltage fluctuation (in poll_battery_interval's) */
+
 /*---------------- FXO Protocol Commands ----------------------------------*/
 
 static /* 0x0F */ DECLARE_CMD(FXO, CHAN_ENABLE, xpp_line_t lines, bool on);
 static /* 0x0F */ DECLARE_CMD(FXO, CHAN_CID, int pos);
 static /* 0x0F */ DECLARE_CMD(FXO, RING, int pos, bool on);
-static /* 0x0F */ DECLARE_CMD(FXO, SETHOOK, int pos, bool offhook);
 static /* 0x0F */ DECLARE_CMD(FXO, RELAY_OUT, byte which, bool on);
 static /* 0x0F */ DECLARE_CMD(FXO, DAA_QUERY, int pos, byte reg_num);
 
@@ -70,20 +72,49 @@
 #define	PROC_DAA_FNAME		"slics"
 #define	PROC_FXO_INFO_FNAME	"fxo_info"
 
+#ifdef SOFT_RING
+#define	POLL_RING_INTERVAL	2
+#define	RING_THRESHOLD		3
+#define	NORING_THRESHOLD	10
+#endif
+#define	DAA_RING_REGISTER	0x05
+
 struct FXO_priv_data {
 	struct proc_dir_entry		*xpd_slic;
 	struct proc_dir_entry		*fxo_info;
+	uint				poll_counter;
 	slic_reply_t			requested_reply;
 	slic_reply_t			last_reply;
 	xpp_line_t			battery;
+	ushort				battery_debounce[CHANNELS_PERXPD];
 	xpp_line_t			ledstate[NUM_LEDS];	/* 0 - OFF, 1 - ON */
+	xpp_line_t			ledcontrol[NUM_LEDS];	/* 0 - OFF, 1 - ON */
 	int				blinking[NUM_LEDS][CHANNELS_PERXPD];
+#ifdef SOFT_RING
+	ushort				ring_thresh[CHANNELS_PERXPD];
+	ushort				noring_thresh[CHANNELS_PERXPD];
+	/* ring_sig is set when Reg5, bit 2 (Ring Detect) is set. 
+	 * While ring_sig=1 we check R5 bit 20H and 40H for ringing. 
+	 * When it drops to 0 that's the end of the ring sequence and 
+	 * we clear the ring detection variables */
+	ushort				ring_sig[CHANNELS_PERXPD];
+#endif
 };
 
 /*---------------- FXO: Static functions ----------------------------------*/
 
 #define	IS_BLINKING(priv,pos,color)	((priv)->blinking[color][pos] != 0)
-#define	DO_BLINK(priv,pos,color,val)	((priv)->blinking[color][pos] = (val))
+#define	MARK_BLINK(priv,pos,color,val)	((priv)->blinking[color][pos] = (val))
+
+void MARK_LED(xpd_t *xpd, lineno_t pos, byte color, bool on)
+{
+	struct FXO_priv_data *priv = xpd->priv;
+
+	if(on)
+		BIT_SET(priv->ledcontrol[color], pos);
+	else
+		BIT_CLR(priv->ledcontrol[color], pos);
+}
 
 /*
  * LED control is done via DAA register 0x20
@@ -130,10 +161,10 @@
 
 static void handle_fxo_leds(xpd_t *xpd)
 {
-	int		i;
-	unsigned long	flags;
+	int			i;
+	unsigned long		flags;
 	const enum fxo_leds	color = LED_GREEN;
-	unsigned int	timer_count;
+	unsigned int		timer_count;
 	struct FXO_priv_data	*priv;
 
 	BUG_ON(!xpd);
@@ -146,7 +177,7 @@
 		if(IS_BLINKING(priv,i,color)) {
 			// led state is toggled
 			if((timer_count % LED_BLINK_PERIOD) == 0) {
-				DBG("%s/%s/%d: led_state=%s\n", xpd->xbus->busname, xpd->xpdname, i,
+				DBG("%s/%s/%d: ledstate=%s\n", xpd->xbus->busname, xpd->xpdname, i,
 						(IS_SET(priv->ledstate[color], i))?"ON":"OFF");
 				if(!IS_SET(priv->ledstate[color], i)) {
 					do_led(xpd, i, color, 1);
@@ -154,35 +185,78 @@
 					do_led(xpd, i, color, 0);
 				}
 			}
+		} else if(IS_SET(priv->ledcontrol[color], i) && !IS_SET(priv->ledstate[color], i)) {
+			do_led(xpd, i, color, 1);
+		} else if(!IS_SET(priv->ledcontrol[color], i) && IS_SET(priv->ledstate[color], i)) {
+			do_led(xpd, i, color, 0);
 		}
 	}
 	spin_unlock_irqrestore(&xpd->lock, flags);
 }
 
-static void do_sethook(xpd_t *xpd, int pos, bool offhook)
+static void mark_ring(xpd_t *xpd, lineno_t pos, bool on)
+{
+	struct FXO_priv_data	*priv;
+
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	if(on && !xpd->ringing[pos]) {
+		DBG("%s/%s/%d: START\n", xpd->xbus->busname, xpd->xpdname, pos);
+		xpd->ringing[pos] = 1;
+		MARK_BLINK(priv, pos, LED_GREEN, LED_BLINK);
+		update_zap_ring(xpd, pos, 1);
+	} else if(!on && xpd->ringing[pos]) {
+		DBG("%s/%s/%d: STOP\n", xpd->xbus->busname, xpd->xpdname, pos);
+		xpd->ringing[pos] = 0;
+		if(IS_BLINKING(priv, pos, LED_GREEN))
+			MARK_BLINK(priv, pos, LED_GREEN, 0);
+		update_zap_ring(xpd, pos, 0);
+	}
+}
+
+static int do_sethook(xpd_t *xpd, int pos, bool to_offhook)
 {
 	unsigned long		flags;
-	struct FXO_priv_data	*priv;
+	xbus_t			*xbus;
+	struct FXO_priv_data	*priv;
+	int			ret = 0;
+	bool			value;
+	xpacket_t		*pack;
+	slic_cmd_t		*sc;
+	int			len;
 
 	BUG_ON(!xpd);
 	BUG_ON(xpd->direction == TO_PHONE);		// We can SETHOOK state only on PSTN
+	xbus = xpd->xbus;
 	priv = xpd->priv;
 	BUG_ON(!priv);
 	if(!IS_SET(priv->battery, pos)) {
-		DBG("%s/%s/%d: WARNING: called while battery is off\n", xpd->xbus->busname, xpd->xpdname, pos);
+		NOTICE("%s/%s/%d: WARNING: called while battery is off\n", xbus->busname, xpd->xpdname, pos);
 	}
 	spin_lock_irqsave(&xpd->lock, flags);
-	xpd->ringing[pos] = 0;				// No more rings
-	CALL_XMETHOD(SETHOOK, xpd->xbus, xpd, pos, offhook);
-	if(offhook) {
-		BIT_SET(xpd->hookstate, pos);
+	mark_ring(xpd, pos, 0);				// No more rings
+	value = (to_offhook) ? 0x09 : 0x08;	/* Bit 3 is for CID */
+	DBG("%s/%s/%d: SETHOOK: value=0x%02X %s\n", xbus->busname, xpd->xpdname, pos, value, (to_offhook)?"OFFHOOK":"ONHOOK");
+	MARK_LED(xpd, pos, LED_GREEN, (to_offhook)?LED_ON:LED_OFF);
+	XPACKET_NEW(pack, xbus, FXO, DAA_WRITE, xpd->id);
+	sc = &RPACKET_FIELD(pack, FXO, DAA_WRITE, slic_cmd);
+	len = slic_cmd_direct_write(sc, BIT(pos), DAA_RING_REGISTER, value);
+	pack->datalen = len;
+	packet_send(xbus, pack);
+#ifdef	SOFT_RING
+	priv->ring_sig[pos] = 0;
+#endif
+	if(to_offhook) {
+		BIT_SET(xpd->offhook, pos);
 	} else {
-		BIT_CLR(xpd->hookstate, pos);
+		BIT_CLR(xpd->offhook, pos);
+		BIT_CLR(xpd->cid_on, pos);
 		xpd->delay_until_dialtone[pos] = 0;
 	}
 	spin_unlock_irqrestore(&xpd->lock, flags);
-	if(offhook)
+	if(to_offhook)
 		wake_up_interruptible(&xpd->txstateq[pos]);
+	return ret;
 }
 
 /*---------------- FXO: Methods -------------------------------------------*/
@@ -282,7 +356,6 @@
 	xbus_t			*xbus;
 	struct FXO_priv_data	*priv;
 	int			i;
-	unsigned long		flags;
 
 	BUG_ON(!xpd);
 	xbus = xpd->xbus;
@@ -300,11 +373,9 @@
 		cur_chan->pvt = xpd;
 		cur_chan->sigcap = FXO_DEFAULT_SIGCAP;
 	}
-	spin_lock_irqsave(&xpd->lock, flags);
-	do_led(xpd, ALL_LINES, LED_GREEN, LED_OFF);
-	spin_unlock_irqrestore(&xpd->lock, flags);
-	for_each_line(xpd, i) {
-		do_led(xpd, i, LED_GREEN, LED_ON);
+	MARK_LED(xpd, ALL_LINES, LED_GREEN, LED_OFF);
+	for_each_line(xpd, i) {
+		MARK_LED(xpd, i, LED_GREEN, LED_ON);
 		mdelay(50);
 	}
 	return 0;
@@ -323,13 +394,12 @@
 	BUG_ON(!priv);
 	DBG("%s/%s (%d)\n", xbus->busname, xpd->xpdname, on);
 	for_each_line(xpd, i) {
-		do_led(xpd, i, LED_GREEN, LED_OFF);
+		MARK_LED(xpd, i, LED_GREEN, LED_OFF);
 		mdelay(50);
 	}
 	return 0;
 }
 
-#ifdef WITH_RBS
 int FXO_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig)
 {
 	struct FXO_priv_data	*priv;
@@ -355,43 +425,6 @@
 	return 0;
 }
 
-#else
-int FXO_card_sethook(xbus_t *xbus, xpd_t *xpd, int pos, int hookstate)
-{
-	int			ret = 0;
-	struct FXO_priv_data	*priv;
-
-	DBG("%s/%s/%d: %s\n", xbus->busname, xpd->xpdname, pos, hookstate2str(hookstate));
-	switch(hookstate) {
-		/* On-hook, off-hook: The PBX is playing a phone on an FXO line.  */
-		case ZT_ONHOOK:
-			do_sethook(xpd, pos, 0);
-			break;
-		case ZT_START:
-			DBG("%s/%s/%d: fall through ZT_OFFHOOK\n", xbus->busname, xpd->xpdname, pos);
-			xpd->delay_until_dialtone[pos] = DELAY_UNTIL_DIALTONE;
-			// Fall through
-		case ZT_OFFHOOK:
-			do_sethook(xpd, pos, 1);
-			wait_event_interruptible(xpd->txstateq[pos], xpd->delay_until_dialtone[pos] <= 0);
-			break;
-		case ZT_WINK:
-			WARN("No code yet\n");
-			break;
-		case ZT_FLASH:
-			WARN("No code yet\n");
-			break;
-		case ZT_RING:
-			DBG("%s/%s/%d: ZT_RING: %d\n", xbus->busname, xpd->xpdname, pos, xpd->ringing[pos]);
-			break;
-		case ZT_RINGOFF:
-			WARN("No code yet\n");
-			break;
-	}
-	return ret;
-}
-#endif
-
 static void poll_battery(xbus_t *xbus, xpd_t *xpd)
 {
 	int	i;
@@ -401,20 +434,37 @@
 	}
 }
 
+#ifdef	SOFT_RING
+static void poll_ring(xbus_t *xbus, xpd_t *xpd)
+{
+	int			i;
+	struct FXO_priv_data	*priv;
+
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	for_each_line(xpd, i) {
+		if(priv->ring_sig[i])
+			CALL_PROTO(FXO, DAA_QUERY, xbus, xpd, i, DAA_RING_REGISTER);
+	}
+}
+#endif
 
 static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd)
 {
-	static unsigned		rate_limit = 0;
 	struct FXO_priv_data	*priv;
 
 	BUG_ON(!xpd);
 	priv = xpd->priv;
 	BUG_ON(!priv);
-	rate_limit++;
-	if(poll_battery_interval != 0 && (rate_limit % poll_battery_interval) == 0) {
+	if(poll_battery_interval != 0 && (priv->poll_counter % poll_battery_interval) == 0) {
 		poll_battery(xbus, xpd);
 	}
+#ifdef	SOFT_RING
+	if((priv->poll_counter % POLL_RING_INTERVAL) == 0)
+		poll_ring(xbus, xpd);
+#endif
 	handle_fxo_leds(xpd);
+	priv->poll_counter++;
 	return 0;
 }
 
@@ -433,13 +483,13 @@
 	int 		i,ret;
 
 	BUG_ON(!xpd);
-	DBG("cmd: 0x%x, expecting: 0x%x, pos=%d.\n", cmd, WCTDM_SET_ECHOTUNE, pos);
+	DBG("cmd: 0x%X, expecting: 0x%X, pos=%d.\n", cmd, WCTDM_SET_ECHOTUNE, pos);
 	switch (cmd) {
 		case WCTDM_SET_ECHOTUNE:
 			DBG("-- Setting echo registers: \n");
 			/* first off: check if this span is fxs. If not: -EINVALID */
 			if (copy_from_user(&echoregs.wctdm_struct, 
-				(struct wctdm_echo_coefs*)arg, sizeof(echoregs.wctdm_struct)))
+				(struct wctdm_echo_coefs __user *)arg, sizeof(echoregs.wctdm_struct)))
 				return -EFAULT;
 
 			/* Set the ACIM register */
@@ -474,7 +524,6 @@
 
 static /* 0x0F */ HOSTCMD(FXO, CHAN_ENABLE, xpp_line_t lines, bool on)
 {
-	unsigned long		flags;
 	int	ret = 0;
 	int	i;
 
@@ -486,15 +535,11 @@
 	DBG("Channel Activation: 0x%4X %s\n", lines, (on) ? "on" : "off");
 	if(on) {
 		for_each_line(xpd, i) {
-			spin_lock_irqsave(&xpd->lock, flags);
-			do_led(xpd, i, LED_GREEN, LED_ON);
-			spin_unlock_irqrestore(&xpd->lock, flags);
+			MARK_LED(xpd, i, LED_GREEN, LED_ON);
 			mdelay(20);
 		}
 		for_each_line(xpd, i) {
-			spin_lock_irqsave(&xpd->lock, flags);
-			do_led(xpd, i, LED_GREEN, LED_OFF);
-			spin_unlock_irqrestore(&xpd->lock, flags);
+			MARK_LED(xpd, i, LED_GREEN, LED_OFF);
 			mdelay(20);
 		}
 	}
@@ -539,31 +584,6 @@
 	return ret;
 }
 
-static /* 0x0F */ HOSTCMD(FXO, SETHOOK, int pos, bool offhook)
-{
-	int		ret = 0;
-	xpacket_t	*pack;
-	slic_cmd_t	*sc;
-	int		len;
-	unsigned long	flags;
-	bool		value;
-
-	BUG_ON(!xbus);
-	BUG_ON(!xpd);
-	value = (offhook) ? 0x09 : 0x08;
-	// value |= BIT(3);	/* Bit 3 is for CID */
-	DBG("%s/%s/%d: SETHOOK: value=0x%02X %s\n", xbus->busname, xpd->xpdname, pos, value, (offhook)?"OFFHOOK":"ONHOOK");
-	spin_lock_irqsave(&xpd->lock, flags);
-	XPACKET_NEW(pack, xbus, FXO, DAA_WRITE, xpd->id);
-	sc = &RPACKET_FIELD(pack, FXO, DAA_WRITE, slic_cmd);
-	len = slic_cmd_direct_write(sc, BIT(pos), 0x05, value);
-	pack->datalen = len;
-	packet_send(xbus, pack);
-	do_led(xpd, pos, LED_GREEN, (offhook)?LED_ON:LED_OFF);
-	spin_unlock_irqrestore(&xpd->lock, flags);
-	return ret;
-}
-
 static /* 0x0F */ HOSTCMD(FXO, RELAY_OUT, byte which, bool on)
 {
 	return -ENOSYS;
@@ -597,19 +617,39 @@
 	xpp_line_t	sig_toggles = RPACKET_FIELD(pack, FXO, SIG_CHANGED, sig_toggles);
 	unsigned long	flags;
 	int		i;
+	struct FXO_priv_data	*priv;
 
 	if(!xpd) {
 		NOTICE("%s: received %s for non-existing xpd: %d\n",
 				__FUNCTION__, cmd->name, XPD_NUM(pack->content.addr));
 		return -EPROTO;
 	}
+	priv = xpd->priv;
+	BUG_ON(!priv);
 	DBG("%s/%s: (PSTN) sig_toggles=0x%04X sig_status=0x%04X\n", xpd->xbus->busname, xpd->xpdname, sig_toggles, sig_status);
 	spin_lock_irqsave(&xpd->lock, flags);
 	for_each_line(xpd, i) {
-		if(IS_SET(sig_status, i)) {
-			xpd->ringing[i] = 1;
-		} else {
-			xpd->ringing[i] = 0;
+		if(IS_SET(sig_toggles, i)) {
+			if(!IS_SET(priv->battery, i)) {
+				DBG("%s/%s/%d: battery is off. ignore false alarm.\n",
+					xbus->busname, xpd->xpdname, i);
+				continue;
+			}
+			if(IS_SET(sig_status, i)) {
+#ifdef	SOFT_RING
+				priv->ring_sig[i]=1;		/* trigger register polling */
+				/* reset ring check counters */
+				priv->ring_thresh[i] = 0;
+				priv->noring_thresh[i] = 0;
+#else
+				mark_ring(xpd, i, 1);
+#endif
+			} else {
+#ifdef	SOFT_RING
+				priv->ring_sig[i] = 0;
+#endif
+				mark_ring(xpd, i, 0);
+			}
 		}
 	}
 	spin_unlock_irqrestore(&xpd->lock, flags);
@@ -632,25 +672,58 @@
 	priv = xpd->priv;
 	BUG_ON(!priv);
 	if(!info->indirect && info->reg_num == DAA_VBAT_REGISTER) {
-		xpp_line_t	last_batt_on = priv->battery;
-		xpp_line_t	changed_lines;
+		byte		bat = abs((signed char)info->data_low);
 		int		i;
 
-		if(abs(info->data_low) < BAT_THRESHOLD) {
-			priv->battery &= ~lines;
-			// DBG("%s/%s: BATTERY OFF (%04X) = %d\n", xpd->xbus->busname, xpd->xpdname, lines, info->data_low);
-		} else {
-			priv->battery |= lines;
-			// DBG("%s/%s: BATTERY ON (%04X) = %d\n", xpd->xbus->busname, xpd->xpdname, lines, info->data_low);
-		}
-		changed_lines = last_batt_on ^ priv->battery;
 		for_each_line(xpd, i) {
-			if(IS_SET(changed_lines, i)) {
-				update_line_status(xpd, i, IS_SET(priv->battery, i));
+			if(!IS_SET(lines, i))
+				continue;
+			if(bat < BAT_THRESHOLD) {
+				/*
+				 * Check for battery voltage fluctuations
+				 */
+				if(IS_SET(priv->battery, i) && priv->battery_debounce[i]++ > BAT_DEBOUNCE) {
+					DBG("%s/%s: BATTERY OFF (%04X) voltage=%d\n", xpd->xbus->busname, xpd->xpdname, lines, bat);
+					BIT_CLR(priv->battery, i);
+					update_line_status(xpd, i, 0);
+				}
+			} else {
+				priv->battery_debounce[i] = 0;
+				if(!IS_SET(priv->battery, i)) {
+					DBG("%s/%s: BATTERY ON (%04X) voltage=%d\n", xpd->xbus->busname, xpd->xpdname, lines, bat);
+					BIT_SET(priv->battery, i);
+				}
 			}
 		}
 	}
+#ifdef	SOFT_RING
+	if(!info->indirect && info->reg_num == DAA_RING_REGISTER) {
+		bool		ringit = (info->data_low & (0x20 | 0x40)) ? 1 : 0;	/* Ring positive | Ring negative */
+		int		i;
+
+		for_each_line(xpd, i) {
+			if(!IS_SET(lines, i))
+				continue;
+			if (!priv->ring_sig[i])
+				continue;
+			if(ringit) {
+				if(priv->ring_thresh[i] > RING_THRESHOLD) {
+					mark_ring(xpd, i, 1);
+					priv->noring_thresh[i] = 0;
+				} else
+					priv->ring_thresh[i]++;
+			} else {
+				if(priv->noring_thresh[i] > NORING_THRESHOLD) {
+					mark_ring(xpd, i, 0);
+					priv->ring_thresh[i] = 0;
+				} else
+					priv->noring_thresh[i]++;
+			}
+		}
+	}
+#endif
 #if 0
+	if (info->reg_num != 29) 
 	DBG("DAA_REPLY: xpd #%d %s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
 			xpd->id, (info->indirect)?"I":"D",
 			info->reg_num, info->data_low, info->data_high);
@@ -681,16 +754,11 @@
 		.card_remove	= FXO_card_remove,
 		.card_zaptel_preregistration	= FXO_card_zaptel_preregistration,
 		.card_zaptel_postregistration	= FXO_card_zaptel_postregistration,
-#ifdef WITH_RBS
 		.card_hooksig	= FXO_card_hooksig,
-#else
-		.card_sethook	= FXO_card_sethook,
-#endif
 		.card_tick	= FXO_card_tick,
 		.card_ioctl	= FXO_card_ioctl,
 
 		.RING		= XPROTO_CALLER(FXO, RING),
-		.SETHOOK	= XPROTO_CALLER(FXO, SETHOOK),
 		.RELAY_OUT	= XPROTO_CALLER(FXO, RELAY_OUT),
 		.CHAN_ENABLE	= XPROTO_CALLER(FXO, CHAN_ENABLE),
 		.CHAN_CID	= XPROTO_CALLER(FXO, CHAN_CID),
@@ -734,21 +802,47 @@
 	len += sprintf(page + len, "\t%-17s: ", "Channel");
 	for_each_line(xpd, i) {
 		if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
-			len += sprintf(page + len, "%d ", i % 10);
+			len += sprintf(page + len, "%2d ", i % 10);
 	}
 	len += sprintf(page + len, "\n\t%-17s: ", "ledstate");
 	for_each_line(xpd, i) {
 		if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
-			len += sprintf(page + len, "%d ", IS_SET(priv->ledstate[LED_GREEN], i));
+			len += sprintf(page + len, "%2d ", IS_SET(priv->ledstate[LED_GREEN], i));
+	}
+	len += sprintf(page + len, "\n\t%-17s: ", "ledcontrol");
+	for_each_line(xpd, i) {
+		if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
+			len += sprintf(page + len, "%2d ", IS_SET(priv->ledcontrol[LED_GREEN], i));
 	}
 	len += sprintf(page + len, "\n\t%-17s: ", "blinking");
 	for_each_line(xpd, i) {
 		if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
-			len += sprintf(page + len, "%d ", IS_BLINKING(priv,i,LED_GREEN));
-	}
+			len += sprintf(page + len, "%2d ", IS_BLINKING(priv,i,LED_GREEN));
+	}
+#ifdef	SOFT_RING
+	len += sprintf(page + len, "\n\t%-17s: ", "ring_thresh");
+	for_each_line(xpd, i) {
+		if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
+			len += sprintf(page + len, "%2d ", priv->ring_thresh[i]);
+	}
+	len += sprintf(page + len, "\n\t%-17s: ", "noring_thresh");
+	for_each_line(xpd, i) {
+		if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
+			len += sprintf(page + len, "%2d ", priv->noring_thresh[i]);
+	}
+	len += sprintf(page + len, "\n\t%-17s: ", "ring_sig");
+	for_each_line(xpd, i) {
+		if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
+			len += sprintf(page + len, "%d ", priv->ring_sig[i]);
+	}
+#endif
 	len += sprintf(page + len, "\n\t%-17s: ", "battery");
 	for_each_line(xpd, i) {
-		len += sprintf(page + len, "%d ", IS_SET(priv->battery, i));
+		len += sprintf(page + len, "%2d ", IS_SET(priv->battery, i));
+	}
+	len += sprintf(page + len, "\n\t%-17s: ", "battery_debounce");
+	for_each_line(xpd, i) {
+		len += sprintf(page + len, "%2d ", priv->battery_debounce[i]);
 	}
 	len += sprintf(page + len, "\n");
 	spin_unlock_irqrestore(&xpd->lock, flags);
@@ -896,8 +990,7 @@
 static int proc_xpd_slic_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
 {
 	xpd_t		*xpd = data;
-	const int	LINE_LEN = 500;
-	char		buf[LINE_LEN];
+	char		buf[MAX_PROC_WRITE];
 	char		*p;
 	int		i;
 	int		ret;
@@ -905,7 +998,7 @@
 	if(!xpd)
 		return -ENODEV;
 	for(i = 0; i < count; /* noop */) {
-		for(p = buf; p < buf + LINE_LEN; p++) {	/* read a line */
+		for(p = buf; p < buf + MAX_PROC_WRITE; p++) {	/* read a line */
 			if(i >= count)
 				break;
 			if(get_user(*p, buffer + i))
@@ -914,7 +1007,7 @@
 			if(*p == '\n' || *p == '\r')	/* whatever */
 				break;
 		}
-		if(p >= buf + LINE_LEN)
+		if(p >= buf + MAX_PROC_WRITE)
 			return -E2BIG;
 		*p = '\0';
 		ret = process_slic_cmdline(xpd, buf);
@@ -929,6 +1022,11 @@
 int __init card_fxo_startup(void)
 {
 	INFO("%s revision %s\n", THIS_MODULE->name, ZAPTEL_VERSION);
+#ifdef	SOFT_RING
+	INFO("FEATURE: %s with SOFT_RING\n", THIS_MODULE->name);
+#else
+	INFO("FEATURE: %s without SOFT_RING\n", THIS_MODULE->name);
+#endif
 	xproto_register(&PROTO_TABLE(FXO));
 	return 0;
 }

Modified: branches/1.2/xpp/card_fxo.h
URL: http://svn.digium.com/view/zaptel/branches/1.2/xpp/card_fxo.h?rev=1457&r1=1456&r2=1457&view=diff
==============================================================================
--- branches/1.2/xpp/card_fxo.h (original)
+++ branches/1.2/xpp/card_fxo.h Sat Sep  9 10:24:12 2006
@@ -32,7 +32,6 @@
 	XPROTO_NAME(FXO, CHAN_ENABLE)		= 0x0F,	/* Write to DAA */
 	XPROTO_NAME(FXO, CHAN_CID)		= 0x0F,	/* Write to DAA */
 	XPROTO_NAME(FXO, RING)			= 0x0F,	/* Write to DAA */
-	XPROTO_NAME(FXO, SETHOOK)		= 0x0F,	/* Write to DAA */
 	XPROTO_NAME(FXO, LED)			= 0x0F,	/* Write to DAA */
 	XPROTO_NAME(FXO, RELAY_OUT)		= 0x0F,	/* Write to DAA */
 	XPROTO_NAME(FXO, DAA_INIT)		= 0x0F,	/* Write to DAA */
@@ -56,6 +55,5 @@
 	);
 
 #define	DAA_VBAT_REGISTER	29
-#define	BAT_THRESHOLD		3
 
 #endif	/* CARD_FXO_H */

Modified: branches/1.2/xpp/card_fxs.c
URL: http://svn.digium.com/view/zaptel/branches/1.2/xpp/card_fxs.c?rev=1457&r1=1456&r2=1457&view=diff
==============================================================================
--- branches/1.2/xpp/card_fxs.c (original)
+++ branches/1.2/xpp/card_fxs.c Sat Sep  9 10:24:12 2006
@@ -77,7 +77,6 @@
 static /* 0x0F */ DECLARE_CMD(FXS, CHAN_ENABLE, xpp_line_t lines, bool on);
 static /* 0x0F */ DECLARE_CMD(FXS, CHAN_CID, int pos);
 static /* 0x0F */ DECLARE_CMD(FXS, RING, int pos, bool on);
-static /* 0x0F */ DECLARE_CMD(FXS, SETHOOK, int pos, bool offhook);
 static /* 0x0F */ DECLARE_CMD(FXS, RELAY_OUT, byte which, bool on);
 static /* 0x0F */ DECLARE_CMD(FXS, SLIC_QUERY, int pos, byte reg_num);
 
@@ -326,17 +325,8 @@
 	/*
 	 * Setup ring timers
 	 */
-#ifdef	WITH_RBS
 	/* Software controled ringing (for CID) */
 	ret = SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x22, 0x00);	/* Ringing Oscilator Control */
-#else
-	/* Hardware controled ringing (no CID) */
-	ret += SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x30, 0x80);	/* Active timer low byte */
-	ret += SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x31, 0x3E);	/* Active timer high byte */
-	ret += SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x32, 0x80);	/* Inactive timer low byte */
-	ret += SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x33, 0x3E);	/* Inactive timer high byte */
-	ret += SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x22, 0x18);	/* Ringing Oscilator Control */
-#endif
 	if(ret < 0)
 		goto err;
 	DBG("%s/%s: done\n", xbus->busname, xpd->xpdname);
@@ -418,7 +408,6 @@
 	return 0;
 }
 
-#ifdef WITH_RBS
 int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig)
 {
 	int		ret = 0;
@@ -490,74 +479,6 @@
 	return ret;
 }
 
-#else
-int FXS_card_sethook(xbus_t *xbus, xpd_t *xpd, int pos, int hookstate)
-{
-	int	ret = 0;
-
-	DBG("%s/%s/%d: %s\n", xbus->busname, xpd->xpdname, pos, hookstate2str(hookstate));
-	switch(hookstate) {
-		/* On-hook, off-hook: The PBX is playing a phone on an FXO line. 
-		 * Can be ignored for an FXS line
-		 */
-		case ZT_ONHOOK:
-			if(IS_SET(xpd->digital_inputs, pos)) {
-				NOTICE("%s: Trying to ONHOOK a digital input channel %d. Ignoring\n", __FUNCTION__, pos);
-				ret = -EINVAL;
-				break;
-			}
-			if(IS_SET(xpd->digital_outputs, pos)) {
-				DBG("%s/%s/%d: digital output OFF\n", xbus->busname, xpd->xpdname, pos);
-				ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 0);
-				break;
-			}
-			xpd->ringing[pos] = 0;
-			DBG("%s/%s/%d: stop ringing\n", xbus->busname, xpd->xpdname, pos);
-#if 1	// FIXME: Not needed -- verify
-			ret = CALL_XMETHOD(RING, xbus, xpd, pos, 0);			// RING off
-#endif
-			if(ret) {
-				DBG("ZT_ONHOOK(stop ring) Failed: ret=0x%02X\n", ret);
-				break;
-			}
-			break;
-		case ZT_START:
-			DBG("%s/%s/%d: fall through ZT_OFFHOOK\n", xbus->busname, xpd->xpdname, pos);
-			// Fall through
-		case ZT_OFFHOOK:
-			DBG("%s/%s/%d: ZT_OFFHOOK (ignoring for PHONES)\n", xbus->busname, xpd->xpdname, pos);
-			break;
-		case ZT_WINK:
-			WARN("No code yet\n");
-			break;
-		case ZT_FLASH:
-			WARN("No code yet\n");
-			break;
-		case ZT_RING:
-			DBG("%s/%s/%d: ZT_RING: %d\n", xbus->busname, xpd->xpdname, pos, xpd->ringing[pos]);
-			if(IS_SET(xpd->digital_inputs, pos)) {
-				NOTICE("%s: Trying to RING a digital input channel %d. Ignoring\n", __FUNCTION__, pos);
-				return -EINVAL;
-			}
-			if(IS_SET(xpd->digital_outputs, pos)) {
-				DBG("%s/%s/%d: digital output ON\n", xbus->busname, xpd->xpdname, pos);
-				ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 1);
-				return ret;
-			}
-			xpd->ringing[pos] = 1;
-			ret = CALL_XMETHOD(RING, xbus, xpd, pos, 1);		// RING on
-			if(ret) {
-				DBG("ZT_RING Failed: ret=0x%02X\n", ret);
-			}
-			break;
-		case ZT_RINGOFF:
-			WARN("No code yet\n");
-			break;
-	}
-	return ret;
-}
-#endif
-
 /*
  * INPUT polling is done via SLIC register 0x06 (same as LEDS):
  *         7     6     5     4     3     2     1     0
@@ -698,12 +619,6 @@
 	return ret;
 }
 
-static /* 0x0F */ HOSTCMD(FXS, SETHOOK, int pos, bool offhook)
-{
-	BUG();	// Should never be called
-	return 0;
-}
-
 static /* 0x0F */ HOSTCMD(FXS, RELAY_OUT, byte which, bool on)
 {
 	int		ret = 0;
@@ -775,21 +690,17 @@
 		if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i))
 			continue;
 		if(IS_SET(sig_toggles, i)) {
-			struct zt_chan *chan = &xpd->span.chans[i];
-
 			xpd->ringing[i] = 0;		// No more ringing...
 			do_chan_power(xpd->xbus, xpd, BIT(i), 0);	// When not ringing, VBAT is always Low
 			MARK_BLINK(priv,i,LED_GREEN,0);
 			if(IS_SET(sig_status, i)) {
-				DBG("OFFHOOK: channo=%d\n", chan->channo);
+				DBG("%s/%s/%d: OFFHOOK\n", xbus->busname, xpd->xpdname, i);
 				MARK_LED(priv,i,LED_GREEN,LED_ON);
-				BIT_SET(xpd->hookstate, i);
-				zt_hooksig(chan, ZT_RXSIG_OFFHOOK);
+				update_line_status(xpd, i, 1);
 			} else {
-				DBG("ONHOOK channo=%d\n", chan->channo);
+				DBG("%s/%s/%d: ONHOOK\n", xbus->busname, xpd->xpdname, i);
 				MARK_LED(priv,i,LED_GREEN,LED_OFF);
-				BIT_CLR(xpd->hookstate, i);
-				zt_hooksig(chan, ZT_RXSIG_ONHOOK);
+				update_line_status(xpd, i, 0);
 			}
 		}
 	}
@@ -824,27 +735,22 @@
 		for(i = 0; i < ARRAY_SIZE(input_channels); i++) {
 			int		channo = input_channels[i];
 			int		newchanno;
-			struct zt_chan	*chan;
 
 			if(IS_SET(lines, channo)) {
 				newchanno = LINES_REGULAR + LINES_DIGI_OUT + i;
 				BIT_CLR(lines, channo);
 				BIT_SET(lines, newchanno);
-				chan = &xpd->span.chans[newchanno];
 				xpd->ringing[newchanno] = 0;			// Stop ringing. No leds for digital inputs.
-				if(offhook && !IS_SET(xpd->hookstate, newchanno)) {		// OFFHOOK
-					DBG("OFFHOOK: channo=%d\n", chan->channo);
-					BIT_SET(xpd->hookstate, newchanno);
-					zt_hooksig(chan, ZT_RXSIG_OFFHOOK);
-				} else if(!offhook && IS_SET(xpd->hookstate, newchanno)) {	// ONHOOK
-					DBG("ONHOOK channo=%d\n", chan->channo);
-					BIT_CLR(xpd->hookstate, newchanno);
-					zt_hooksig(chan, ZT_RXSIG_ONHOOK);
+				if(offhook && !IS_SET(xpd->offhook, newchanno)) {		// OFFHOOK
+					DBG("%s/%s/%d: OFFHOOK\n", xbus->busname, xpd->xpdname, newchanno);
+					update_line_status(xpd, newchanno, 1);
+				} else if(!offhook && IS_SET(xpd->offhook, newchanno)) {	// ONHOOK
+					DBG("%s/%s/%d: ONHOOK\n", xbus->busname, xpd->xpdname, newchanno);
+					update_line_status(xpd, newchanno, 0);
 				}
 			}
 		}
 	}
-
 	/* Update /proc info only if reply relate to the last slic read request */
 	if(priv->requested_reply.indirect == info->indirect &&
 			priv->requested_reply.reg_num == info->reg_num) {
@@ -869,15 +775,10 @@
 		.card_remove	= FXS_card_remove,
 		.card_zaptel_preregistration	= FXS_card_zaptel_preregistration,
 		.card_zaptel_postregistration	= FXS_card_zaptel_postregistration,
-#ifdef WITH_RBS
 		.card_hooksig	= FXS_card_hooksig,
-#else
-		.card_sethook	= FXS_card_sethook,
-#endif
 		.card_tick	= FXS_card_tick,
 
 		.RING		= XPROTO_CALLER(FXS, RING),
-		.SETHOOK	= XPROTO_CALLER(FXS, SETHOOK),
 		.RELAY_OUT	= XPROTO_CALLER(FXS, RELAY_OUT),
 		.CHAN_ENABLE	= XPROTO_CALLER(FXS, CHAN_ENABLE),
 		.CHAN_CID	= XPROTO_CALLER(FXS, CHAN_CID),
@@ -1088,8 +989,7 @@
 static int proc_xpd_slic_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
 {
 	xpd_t		*xpd = data;
-	const int	LINE_LEN = 500;
-	char		buf[LINE_LEN];
+	char		buf[MAX_PROC_WRITE];
 	char		*p;
 	int		i;
 	int		ret;
@@ -1097,7 +997,7 @@
 	if(!xpd)
 		return -ENODEV;
 	for(i = 0; i < count; /* noop */) {
-		for(p = buf; p < buf + LINE_LEN; p++) {	/* read a line */
+		for(p = buf; p < buf + MAX_PROC_WRITE; p++) {	/* read a line */
 			if(i >= count)
 				break;
 			if(get_user(*p, buffer + i))
@@ -1106,7 +1006,7 @@
 			if(*p == '\n' || *p == '\r')	/* whatever */
 				break;
 		}
-		if(p >= buf + LINE_LEN)
+		if(p >= buf + MAX_PROC_WRITE)
 			return -E2BIG;
 		*p = '\0';
 		ret = process_slic_cmdline(xpd, buf);

Modified: branches/1.2/xpp/card_fxs.h
URL: http://svn.digium.com/view/zaptel/branches/1.2/xpp/card_fxs.h?rev=1457&r1=1456&r2=1457&view=diff
==============================================================================
--- branches/1.2/xpp/card_fxs.h (original)
+++ branches/1.2/xpp/card_fxs.h Sat Sep  9 10:24:12 2006
@@ -33,7 +33,6 @@
 	XPROTO_NAME(FXS, CHAN_POWER)		= 0x0F,	/* Write to SLIC */
 	XPROTO_NAME(FXS, CHAN_CID)		= 0x0F,	/* Write to SLIC */
 	XPROTO_NAME(FXS, RING)			= 0x0F,	/* Write to SLIC */
-	XPROTO_NAME(FXS, SETHOOK)		= 0x0F,	/* Write to SLIC */
 	XPROTO_NAME(FXS, LED)			= 0x0F,	/* Write to SLIC */
 	XPROTO_NAME(FXS, RELAY_OUT)		= 0x0F,	/* Write to SLIC */
 	XPROTO_NAME(FXS, SLIC_INIT)		= 0x0F,	/* Write to SLIC */

Modified: branches/1.2/xpp/init_data_3_19.cmd
URL: http://svn.digium.com/view/zaptel/branches/1.2/xpp/init_data_3_19.cmd?rev=1457&r1=1456&r2=1457&view=diff
==============================================================================
--- branches/1.2/xpp/init_data_3_19.cmd (original)
+++ branches/1.2/xpp/init_data_3_19.cmd Sat Sep  9 10:24:12 2006
@@ -17,14 +17,15 @@
 ;
 ; SLICS		CMD	Reg	High	Low
 
-; ----------------------------------==== 8-channel FXS unit initialization ===-----------------------------------------
+; -------------------------------------- 8-channel FXS unit initialization
 ; INTERNAL PS
-; Change SLICs states to "Open state"s  (Off,all transfers tristated to avoid data collision), Voltage sense
+; Change SLICs states to "Open state"s  (Off,all transfers tristated to avoid
+; data collision), Voltage sense
 
 FF 00 00 00	WD	40	00
 FF 00 00 00	WD	6C	01
 
-; ------------------------------------- Initialization of indirect registers ------------------------------------------
+; ------------------------------------- Initialization of indirect registers
 

[... 3089 lines stripped ...]


More information about the zaptel-commits mailing list