[aadk-commits] dbailey: uClinux/trunk r460 - in /uClinux/trunk/uClinux-dist/user/busybox: ./...

aadk-commits at lists.digium.com aadk-commits at lists.digium.com
Thu May 31 15:08:44 MST 2007


Author: dbailey
Date: Thu May 31 17:08:43 2007
New Revision: 460

URL: http://svn.digium.com/view/aadk?view=rev&rev=460
Log:
Add fxotune to busybox so that it can run efficiently on the appliance

Added:
    uClinux/trunk/uClinux-dist/user/busybox/include/fxotune.h   (with props)
    uClinux/trunk/uClinux-dist/user/busybox/include/wctdm.h   (with props)
    uClinux/trunk/uClinux-dist/user/busybox/miscutils/fxotune.c   (with props)
Modified:
    uClinux/trunk/uClinux-dist/user/busybox/.config.mkconfig
    uClinux/trunk/uClinux-dist/user/busybox/config-s800i
    uClinux/trunk/uClinux-dist/user/busybox/defconfig
    uClinux/trunk/uClinux-dist/user/busybox/include/applets.h
    uClinux/trunk/uClinux-dist/user/busybox/include/usage.h
    uClinux/trunk/uClinux-dist/user/busybox/miscutils/Config.in
    uClinux/trunk/uClinux-dist/user/busybox/miscutils/Makefile.in
    uClinux/trunk/uClinux-dist/user/busybox/miscutils/ztmonitor.c

Modified: uClinux/trunk/uClinux-dist/user/busybox/.config.mkconfig
URL: http://svn.digium.com/view/aadk/uClinux/trunk/uClinux-dist/user/busybox/.config.mkconfig?view=diff&rev=460&r1=459&r2=460
==============================================================================
--- uClinux/trunk/uClinux-dist/user/busybox/.config.mkconfig (original)
+++ uClinux/trunk/uClinux-dist/user/busybox/.config.mkconfig Thu May 31 17:08:43 2007
@@ -320,6 +320,8 @@
 # CONFIG_WATCHDOG is not set
 CONFIG_ZAPSCAN=y
 CONFIG_ZTCFG=y
+CONFIG_ZTMONITOR=y
+CONFIG_FXOTUNE=y
 
 #
 # Linux Module Utilities

Modified: uClinux/trunk/uClinux-dist/user/busybox/config-s800i
URL: http://svn.digium.com/view/aadk/uClinux/trunk/uClinux-dist/user/busybox/config-s800i?view=diff&rev=460&r1=459&r2=460
==============================================================================
--- uClinux/trunk/uClinux-dist/user/busybox/config-s800i (original)
+++ uClinux/trunk/uClinux-dist/user/busybox/config-s800i Thu May 31 17:08:43 2007
@@ -284,6 +284,7 @@
 CONFIG_MAKEIPLIST=y
 CONFIG_ZTCFG=y
 CONFIG_ZTMONITOR=y
+CONFIG_FXOTUNE=y
 CONFIG_NVRAM_EDIT=y
 
 #

Modified: uClinux/trunk/uClinux-dist/user/busybox/defconfig
URL: http://svn.digium.com/view/aadk/uClinux/trunk/uClinux-dist/user/busybox/defconfig?view=diff&rev=460&r1=459&r2=460
==============================================================================
--- uClinux/trunk/uClinux-dist/user/busybox/defconfig (original)
+++ uClinux/trunk/uClinux-dist/user/busybox/defconfig Thu May 31 17:08:43 2007
@@ -320,6 +320,8 @@
 # CONFIG_WATCHDOG is not set
 # CONFIG_ZAPSCAN is not set
 # CONFIG_ZTCFG is not set
+# CONFIG_ZTMONITOR is not set
+# CONFIG_FXOTUNE is not set
 
 #
 # Linux Module Utilities

Modified: uClinux/trunk/uClinux-dist/user/busybox/include/applets.h
URL: http://svn.digium.com/view/aadk/uClinux/trunk/uClinux-dist/user/busybox/include/applets.h?view=diff&rev=460&r1=459&r2=460
==============================================================================
--- uClinux/trunk/uClinux-dist/user/busybox/include/applets.h (original)
+++ uClinux/trunk/uClinux-dist/user/busybox/include/applets.h Thu May 31 17:08:43 2007
@@ -223,6 +223,9 @@
 #ifdef CONFIG_FTPPUT
 	APPLET(ftpput, ftpgetput_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER)
 #endif
+#ifdef CONFIG_FXOTUNE
+	APPLET(fxotune, fxotune_main, _BB_DIR_SBIN, _BB_SUID_NEVER)
+#endif
 #ifdef CONFIG_GETOPT
 	APPLET(getopt, getopt_main, _BB_DIR_BIN, _BB_SUID_NEVER)
 #endif

Added: uClinux/trunk/uClinux-dist/user/busybox/include/fxotune.h
URL: http://svn.digium.com/view/aadk/uClinux/trunk/uClinux-dist/user/busybox/include/fxotune.h?view=auto&rev=460
==============================================================================
--- uClinux/trunk/uClinux-dist/user/busybox/include/fxotune.h (added)
+++ uClinux/trunk/uClinux-dist/user/busybox/include/fxotune.h Thu May 31 17:08:43 2007
@@ -1,0 +1,103 @@
+/*
+ * This file and contents thereof are distributed under the terms of the
+ * GNU Public License version 2.  For terms and conditions of this license
+ * see http://www.gnu.org
+ *
+ * fxotune.h -- data structures and associated definitions for fxotune.c
+ *
+ * By Matthew Fredrickson <creslin at digium.com>
+ *
+ * Echo coefficients and acim register values taken from AN84 from Silicon
+ * Laboratories app note AN84 for setting echo cancellation coefficients
+ *
+ * (C) 2005 Digium, Inc.
+ */
+
+#include <wctdm.h>
+
+struct wctdm_echo_coefs echo_trys [] =
+{
+	/* 600 ohm echo settings */
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{ 10, 0, 6, 1, 254, 2, 255, 0, 0},
+	{ 3, 255, 255, 0, 1, 0, 0, 0, 0},
+	{ 3, 1, 253, 253, 2, 255, 0, 0, 0},
+	{ 9, 254, 251, 255, 2, 0, 1, 0, 0},
+	{ 5, 3, 251, 250, 2, 254, 0, 0, 255},
+	{ 8, 253, 2, 244, 255, 10, 244, 3, 253},
+	{ 10, 249, 244, 8, 12, 245, 252, 0, 1},
+	
+	/* 900 ohm echo settings */
+	{ 1, 0, 0, 0, 0, 0, 0, 0, 0},
+	{ 10, 252, 255, 1, 255, 0, 0, 0, 0},
+	{ 7, 255, 251, 251, 2, 255, 255, 1, 255},
+	{ 3, 1, 251, 250, 1, 254, 255, 0, 255},
+	{ 5, 252, 250, 0, 0, 255, 1, 0, 0},
+	{ 5, 3, 251, 250, 1, 253, 0, 0, 255},
+	{ 8, 253, 2, 244, 255, 10, 244, 3, 253},
+	{ 10, 249, 244, 8, 12, 245, 252, 0, 1},
+
+	/* 270 ohm + (750 ohm || 150 nF) (CTR21) */
+	{ 2, 0, 0, 0, 0, 0, 0, 0, 0},
+	{ 7, 0, 0, 255, 254, 0, 0, 0, 0},
+	{ 9, 0, 253, 254, 2, 255, 0, 0, 0},
+	{ 5, 1, 249, 254, 4, 253, 1, 0, 0},
+	{ 5, 252, 250, 1, 1, 254, 0, 255, 0},
+	{ 5, 3, 251, 250, 2, 253, 255, 255, 255},
+	{ 8, 253, 2, 244, 255, 10, 244, 3, 253},
+	{ 10, 249, 244, 8, 12, 245, 252, 0, 1},
+
+	/* 220 ohm + (820 ohm || 120 nF) (Australia/NewZealand) and 220 ohm + (820 ohm
+	 * || 115nF) (Slovakia/SAfrica/Germany/Austria/Bulgaria)
+	 */
+	{ 3, 0, 0, 0, 0, 0, 0, 0, 0},
+	{ 7, 0, 255, 254, 255, 0, 255, 0, 0},
+	{ 9, 0, 253, 253, 1, 255, 0, 0, 0},
+	{ 5, 1, 249, 254, 3, 253, 1, 0, 0},
+	{ 5, 252, 250, 1, 1, 254, 0, 255, 0},
+	{ 5, 3, 251, 251, 2, 253, 255, 255, 255},
+	{ 8, 253, 2, 244, 255, 10, 244, 3, 253},
+	{ 10, 249, 244, 8, 12, 245, 252, 0, 1},
+	
+	/* 370 ohm + (620ohm || 310nF) (New Zealand #2/India) CO Termination */
+	{ 4, 0, 0, 0, 0, 0, 0, 0, 0},
+	{ 9, 255, 1, 4, 0, 0, 1, 255, 0},
+	{ 9, 0, 253, 0, 3, 254, 0, 0, 255},
+	{ 9, 2, 250, 253, 5, 253, 1, 0 ,255},
+	{ 5, 252, 250, 1, 2, 255, 0 ,255, 0},
+	{ 5, 3, 251, 250, 3, 254, 255, 255, 255},
+	{ 8, 253, 2, 244, 255, 10, 244, 3, 253},
+	{ 10, 249, 244, 8, 12, 245, 252, 0, 1},
+	
+	/* 320 ohm + (1050ohm || 230 nF) (England) CO Termination */
+	{ 5, 0, 0, 0, 0, 0, 0, 0, 0},
+	{ 9, 0 ,255, 1, 255, 255, 0, 255, 0},
+	{ 5, 255, 252, 0, 2, 254, 0, 255, 255},
+	{ 9, 2, 250, 253, 4, 252, 0, 255, 255},
+	{ 5, 252, 250, 1, 1, 254, 0 ,255, 255},
+	{ 5, 3, 251, 250, 2, 253, 255, 255, 254},
+	{ 3, 1, 1, 242, 2, 9, 245, 3, 253},
+	{ 10, 249, 244, 8, 12, 245, 252, 0, 1},
+
+	/* 370 ohm + (820 ohm || 110 nF) CO Termination */
+	{ 6, 0, 0, 0, 0, 0, 0, 0, 0},
+	{ 6, 1, 254, 253, 0, 255, 0, 0, 0},
+	{ 9, 0, 251, 252, 2, 255, 0, 0, 0},
+	{ 5, 1, 248, 252, 4, 253, 1, 0, 0},
+	{ 5, 252, 250, 0, 0, 254, 0 , 255, 0},
+	{ 5, 3, 251, 250, 2, 253, 255, 255, 254},
+	{ 3, 1, 1, 242, 2, 9, 245, 3, 253},
+	{ 10, 249, 244, 8, 12, 245, 252, 0, 1},
+
+	/* 275 ohm + (780 ohm || 115 nF) CO Termination */
+	{ 7, 0, 0, 0, 0, 0, 0, 0, 0},
+	{ 7, 255, 255, 255, 255, 0, 0, 0, 0},
+	{ 9, 0, 253, 254, 2, 255, 0, 0, 0},
+	{ 5, 1, 249, 254, 4, 253, 1, 0, 0},
+	{ 5, 252, 250, 1, 1, 254, 0, 255, 0},
+	{ 5, 3, 251, 250, 2, 253, 255, 255, 255},
+	{ 8, 253, 2, 244, 255, 10, 244, 3, 253},
+	{ 10, 249, 244, 8, 12, 245, 252, 0, 1},
+	
+};
+

Propchange: uClinux/trunk/uClinux-dist/user/busybox/include/fxotune.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: uClinux/trunk/uClinux-dist/user/busybox/include/fxotune.h
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: uClinux/trunk/uClinux-dist/user/busybox/include/fxotune.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: uClinux/trunk/uClinux-dist/user/busybox/include/usage.h
URL: http://svn.digium.com/view/aadk/uClinux/trunk/uClinux-dist/user/busybox/include/usage.h?view=diff&rev=460&r1=459&r2=460
==============================================================================
--- uClinux/trunk/uClinux-dist/user/busybox/include/usage.h (original)
+++ uClinux/trunk/uClinux-dist/user/busybox/include/usage.h Thu May 31 17:08:43 2007
@@ -73,7 +73,7 @@
 
 #define nvram_full_usage \
 	"[dump|store] [FILENAME]\n" \
-	"  Dump NVRAM config into a specified file or load\n"
+	"  Dump NVRAM config into a specified file or load\n" \
 	"  contents of specified file into NVRAM\n"
 
 #define ztcfg_trivial_usage \
@@ -85,8 +85,11 @@
 #define ztmonitor_trivial_usage \
 	"<channel num> [OPTIONS]..."
 
+#define fxotune_trivial_usage \
+	"[OPTIONS]..."
+
 #define ztcfg_full_usage \
-	"[OPTIONS]...\n"
+	"[OPTIONS]...\n" \
 	"   Configure zaptel interfaces.   Valid options are:\n" \
 	"  -c <filename>     -- Use <filename> instead of /etc/zaptel.conf\n" \
 	"  -d [level]        -- Generate debugging output. (Default level is 1.)\n" \
@@ -106,6 +109,29 @@
 	"  -v[v]             -- verbose output \n" \
 	"  -f  FILE          -- output data to the specified file. \n" 
 
+#define fxotune_full_usage \
+	"(-s | -i [<options>] | -d [<options>]) \n" \
+	"	-s : set previously calibrated echo settings\n" \
+	"	-i : calibrate echo settings\n" \
+	"		options : [<dialstring>] [-t <calibtype>]\n" \
+	"		[-b <startdev>][-e <stopdev>]\n" \
+	"		[-n <dialstring>][-l <delaytosilence>][-m <silencegoodfor>]\n" \
+	" 	-d : dump input and output waveforms to ./fxotune_dump.vals\n" \
+	"Options: \n" \
+	"	-v : debug output (-vv, -vvv also)\n" \
+	"	-t <calibtype> : type of calibration\n" \
+	"		                   (default 2, old method 1)\n" \
+	"	-b <startdev> : \n" \
+	"	-e <stopdev>  :  defines a range of devices to test\n" \
+	"		                   (default: 1-252)\n" \
+	"	-n <dialstring> : string to dial to clear the line\n" \
+	"		                   (default 5)\n" \
+	"	-l <delaytosilence> : seconds to wait for line to clear (default 0)\n" \
+	"	-m <silencegoodfor> : seconds before line will no longer be clear\n" \
+	"		                   (default 18)\n" \
+	"	-w <waveform> : -1 for multitone waveform, or frequency of\n" \
+	"		                   single tone (default -1)\n"
+
 #define makeiplist_trivial_usage \
 	"START COUNT"
 
@@ -113,9 +139,9 @@
 	"START COUNT...\n" \
 	"Creates /etc/configs/dhcpd.iplist starting from START address\n" \
 	"and creating COUNT entries.\n"
-
 #define awk_trivial_usage \
 	"[OPTION]... [program-text] [FILE ...]"
+
 #define awk_full_usage \
 	"Options:\n" \
 	"\t-v var=val\t\tassign value 'val' to variable 'var'\n" \

Added: uClinux/trunk/uClinux-dist/user/busybox/include/wctdm.h
URL: http://svn.digium.com/view/aadk/uClinux/trunk/uClinux-dist/user/busybox/include/wctdm.h?view=auto&rev=460
==============================================================================
--- uClinux/trunk/uClinux-dist/user/busybox/include/wctdm.h (added)
+++ uClinux/trunk/uClinux-dist/user/busybox/include/wctdm.h Thu May 31 17:08:43 2007
@@ -1,0 +1,69 @@
+/*
+ * Wilcard S100P FXS Interface Driver for Zapata Telephony interface
+ *
+ * Written by Mark Spencer <markster at linux-support.net>
+ *
+ * Copyright (C) 2001, Linux Support Services, Inc.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ */
+
+#ifndef _WCTDM_H
+#define _WCTDM_H
+
+#include <linux/ioctl.h>
+
+#define NUM_REGS	  109
+#define NUM_INDIRECT_REGS 105
+
+struct wctdm_stats {
+	int tipvolt;	/* TIP voltage (mV) */
+	int ringvolt;	/* RING voltage (mV) */
+	int batvolt;	/* VBAT voltage (mV) */
+};
+
+struct wctdm_regs {
+	unsigned char direct[NUM_REGS];
+	unsigned short indirect[NUM_INDIRECT_REGS];
+};
+
+struct wctdm_regop {
+	int indirect;
+	unsigned char reg;
+	unsigned short val;
+};
+
+struct wctdm_echo_coefs {
+	unsigned char acim;
+	unsigned char coef1;
+	unsigned char coef2;
+	unsigned char coef3;
+	unsigned char coef4;
+	unsigned char coef5;
+	unsigned char coef6;
+	unsigned char coef7;
+	unsigned char coef8;
+};
+
+#define WCTDM_GET_STATS	_IOR (ZT_CODE, 60, struct wctdm_stats)
+#define WCTDM_GET_REGS	_IOR (ZT_CODE, 61, struct wctdm_regs)
+#define WCTDM_SET_REG	_IOW (ZT_CODE, 62, struct wctdm_regop)
+#define WCTDM_SET_ECHOTUNE _IOW (ZT_CODE, 63, struct wctdm_echo_coefs)
+
+
+#endif /* _WCTDM_H */

Propchange: uClinux/trunk/uClinux-dist/user/busybox/include/wctdm.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: uClinux/trunk/uClinux-dist/user/busybox/include/wctdm.h
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: uClinux/trunk/uClinux-dist/user/busybox/include/wctdm.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: uClinux/trunk/uClinux-dist/user/busybox/miscutils/Config.in
URL: http://svn.digium.com/view/aadk/uClinux/trunk/uClinux-dist/user/busybox/miscutils/Config.in?view=diff&rev=460&r1=459&r2=460
==============================================================================
--- uClinux/trunk/uClinux-dist/user/busybox/miscutils/Config.in (original)
+++ uClinux/trunk/uClinux-dist/user/busybox/miscutils/Config.in Thu May 31 17:08:43 2007
@@ -225,6 +225,14 @@
 	  The ztmonitor utility is used with Digium zaptel hardware to capture 
 	  zaptel channel activity You'll want this on an S800i or similar.
 
+config CONFIG_FXOTUNE
+	bool "fxotune"
+	default y
+	help
+	  The fxotune utility helps match impedance on zaptel FXO lines.  
+	  The utility both determines coefficient values as well as restore 
+	  settings from a configuration file. 
+
 config CONFIG_NVRAM
 	bool "nvram"
 	default y

Modified: uClinux/trunk/uClinux-dist/user/busybox/miscutils/Makefile.in
URL: http://svn.digium.com/view/aadk/uClinux/trunk/uClinux-dist/user/busybox/miscutils/Makefile.in?view=diff&rev=460&r1=459&r2=460
==============================================================================
--- uClinux/trunk/uClinux-dist/user/busybox/miscutils/Makefile.in (original)
+++ uClinux/trunk/uClinux-dist/user/busybox/miscutils/Makefile.in Thu May 31 17:08:43 2007
@@ -40,6 +40,7 @@
 MISCUTILS-$(CONFIG_ZTCFG)		+= ztcfg.o
 MISCUTILS-$(CONFIG_ZTMONITOR)		+= ztmonitor.o
 MISCUTILS-$(CONFIG_ZAPSCAN)		+= zapscan.o
+MISCUTILS-$(CONFIG_FXOTUNE)		+= fxotune.o
 MISCUTILS-$(CONFIG_NVRAM)		+= nvram.o
 MISCUTILS-$(CONFIG_MAKEIPLIST)		+= makeiplist.o
 
@@ -49,6 +50,7 @@
 needlibm-$(CONFIG_DC) := y
 needlibm-$(CONFIG_ZTCFG) := y
 needlibm-$(CONFIG_ZTMONITOR) := y
+needlibm-$(CONFIG_FXOTUNE) := y
 
 ifeq ($(needlibm-y),y)
   LIBRARIES += -lm

Added: uClinux/trunk/uClinux-dist/user/busybox/miscutils/fxotune.c
URL: http://svn.digium.com/view/aadk/uClinux/trunk/uClinux-dist/user/busybox/miscutils/fxotune.c?view=auto&rev=460
==============================================================================
--- uClinux/trunk/uClinux-dist/user/busybox/miscutils/fxotune.c (added)
+++ uClinux/trunk/uClinux-dist/user/busybox/miscutils/fxotune.c Thu May 31 17:08:43 2007
@@ -1,0 +1,998 @@
+/* 
+ * This file and contents thereof are licensed under the terms and
+ * conditions of the GNU Public License version 2.  For more information
+ * (including terms and conditions) see http://www.gnu.org/
+ *
+ * fxotune.c -- A utility for tuning the various settings on the fxo
+ * 		modules for the TDM400 cards.
+ *
+ * by Matthew Fredrickson <creslin at digium.com>
+ * 
+ * (C) 2004-2005 Digium, Inc.
+ */
+
+#include "busybox.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <math.h>
+#include <sys/time.h>
+
+#ifdef STANDALONE_ZAPATA
+#include "zaptel.h"
+#else
+#include <zaptel/zaptel.h>
+#endif
+#include "wctdm.h"
+#include "fxotune.h"
+
+#define TEST_DURATION 2000			/* 4000 samples (or 500 ms) of test */
+#define BUFFER_LENGTH (2 * TEST_DURATION)             /* 4000 sample buffers */
+#define SKIP_SAMPLES 800                      /* skip first 100 ms of test when computing echo powers - gives the system time to acquire data */
+
+static const float loudness = 16384.0;
+
+static char *zappath = "/dev/zap";
+static char *configfile = "/etc/fxotune.conf";
+
+static char *usage =
+"Usage: fxotune [-v[vv] (-s | -i <options> | -d <options>)\n"
+"\n"
+"	-s : set previously calibrated echo settings\n"
+"	-i : calibrate echo settings\n"
+"		options : [<dialstring>] [-t <calibtype>]\n"
+"		[-b <startdev>][-e <stopdev>]\n"
+"		[-n <dialstring>][-l <delaytosilence>][-m <silencegoodfor>]\n"
+" 	-d : dump input and output waveforms to ./fxotune_dump.vals\n"
+"		options : [-b <device>][-w <waveform>]\n"
+"		   [-n <dialstring>][-l <delaytosilence>][-m <silencegoodfor>]\n"
+"	-v : more output (-vv, -vvv also)\n"
+"\n"
+"		<calibtype>      - type of calibration\n"
+"		                   (default 2, old method 1)\n"
+"		<startdev>\n"
+"		<stopdev>        - defines a range of devices to test\n"
+"		                   (default: 1-252)\n"
+"		<dialstring>     - string to dial to clear the line\n"
+"		                   (default 5)\n"
+"		<delaytosilence> - seconds to wait for line to clear (default 0)\n"
+"		<silencegoodfor> - seconds before line will no longer be clear\n"
+"		                   (default 18)\n"
+"		<device>         - the device to perform waveform dump on\n"
+"		                   (default 1)\n"
+"		<waveform>       - -1 for multitone waveform, or frequency of\n"
+"		                   single tone (default -1)\n";
+
+
+#define OUT_OF_BOUNDS(x) ((x) < 0 || (x) > 255)
+
+struct silence_info{
+	char *dialstr;
+	/** fd of device we are working with */
+	int device; 
+	/** seconds we should wait after dialing the dialstring before we know for sure we'll have silence */
+	int initial_delay;
+	/** seconds after which a reset should occur */
+	int reset_after;
+	/** time of last reset */
+	struct timeval last_reset; 
+};
+
+static short outbuf[TEST_DURATION];
+static int debug = 0;
+
+static FILE *debugoutfile = NULL;
+
+/**
+ * Makes sure that the line is clear.
+ * Right now, we do this by relying on the user to specify how long after dialing the
+ * dialstring we can rely on the line being silent (before the telco complains about
+ * the user not hitting the next digit).
+ * 
+ * A more robust way to do this would be to actually measure the sound levels on the line,
+ * but that's a lot more complicated, and this should work.
+ * 
+ * @return 0 if succesful (no errors), 1 if unsuccesful
+ */
+static int ensure_silence(struct silence_info *info)
+{
+	struct timeval tv;
+	long int elapsedms;
+	
+	gettimeofday(&tv, NULL);
+	
+	if (info->last_reset.tv_sec == 0) {
+		/* this is the first request, we will force it to run */
+		elapsedms = -1;
+	} else {
+		/* this is not the first request, we will compute elapsed time */
+		elapsedms = ((tv.tv_sec - info->last_reset.tv_sec) * 1000L + (tv.tv_usec - info->last_reset.tv_usec) / 1000L);
+	}
+	if (debug > 4) {
+		fprintf(stdout, "Reset line request received - elapsed ms = %li / reset after = %ld\n", elapsedms, info->reset_after * 1000L);
+	}
+
+	if (elapsedms > 0 && elapsedms < info->reset_after * 1000L)
+		return 0;
+	
+	if (debug > 1){
+		fprintf(stdout, "Resetting line\n");
+	}
+	
+	/* do a line reset */
+	/* prepare line for silence */
+	/* Do line hookstate reset */
+	int x = ZT_ONHOOK;
+
+	if (ioctl(info->device, ZT_HOOK, &x)) {
+		fprintf(stderr, "Unable to hang up fd %d\n", info->device);
+		return -1;
+	}
+
+	sleep(2);
+	x = ZT_OFFHOOK;
+	if (ioctl(info->device, ZT_HOOK, &x)) {
+		fprintf(stderr, "Cannot bring fd %d off hook\n", info->device);
+		return -1;
+	}
+	sleep(2); /* Added to ensure that dial can actually takes place */
+
+	struct zt_dialoperation dop;
+	memset(&dop, 0, sizeof(dop));
+	dop.op = ZT_DIAL_OP_REPLACE;
+	dop.dialstr[0] = 'T';
+	strncpy(dop.dialstr + 1, info->dialstr, sizeof(dop.dialstr) - 1);
+
+	if (ioctl(info->device, ZT_DIAL, &dop)) {
+		fprintf(stderr, "Unable to dial!\n");
+		return -1;
+	}
+	sleep(1); 
+	sleep(info->initial_delay);  
+	
+	
+	gettimeofday(&info->last_reset, NULL);
+	
+	
+	return 0;
+}
+
+/**
+ * Generates a tone of specified frequency.
+ * 
+ * @param hz the frequency of the tone to be generated
+ * @param index the current sample
+ * 		to begenerated.  For a normal waveform you need to increment
+ * 		this every time you execute the function.
+ *
+ * @return 16bit slinear sample for the specified index
+ */
+static short inline gentone(int hz, int idx)
+{
+	return loudness * sin((idx * 2.0 * M_PI * hz)/8000);
+}
+
+/**
+ * Generates a waveform of several frequencies.
+ * 
+ * @param index the current sample
+ * 		to begenerated.  For a normal waveform you need to increment
+ * 		this every time you execute the function.
+ *
+ * @return 16bit slinear sample for the specified index
+ */
+static short inline genwaveform(int idx)
+{
+	int freqs[] = {300, 600, 900, 1004, 1300, 1600}; /* chose 1004 Hz to include the milliwatt test tone frequency - but there was no particular reson to do so */
+	int freqcount = 6;
+	int i = 0;
+	float response = (float)0;
+	for (i = 0; i < freqcount; i++){
+		response += sin((idx * 2.0 * M_PI * freqs[i])/8000);
+	}
+	
+
+	return loudness * response / freqcount;
+}
+
+
+/**
+ *  Calculates the RMS of the waveform buffer of samples in 16bit slinear format.
+ *  prebuf the buffer of either shorts or floats
+ *  bufsize the number of elements in the prebuf buffer (not the number of bytes!)
+ *  short_format 1 if prebuf points to an array of shorts, 0 if it points to an array of floats
+ *  
+ *  Formula for RMS (http://en.wikipedia.org/wiki/Root_mean_square): 
+ *  
+ *  Xrms = sqrt(1/N Sum(x1^2, x2^2, ..., xn^2))
+ *  
+ *  Note:  this isn't really a power calculation - but it gives a good measure of the level of the response
+ *  
+ *  @param prebuf the buffer containing the values to compute
+ *  @param bufsize the size of the buffer
+ *  @param short_format 1 if prebuf contains short values, 0 if it contains float values
+ */
+static float power_of(void *prebuf, int bufsize, int short_format)
+{
+	float sum_of_squares = 0;
+	int numsamples = 0;
+	float finalanswer = 0;
+	short *sbuf = (short*)prebuf;
+	float *fbuf = (float*)prebuf;
+	int i = 0;
+
+	if (short_format) {
+		/* idiot proof checks */
+		if (bufsize <= 0)
+			return -1;
+
+		numsamples = bufsize; /* Got rid of divide by 2 - the bufsize parameter should give the number of samples (that's what it does for the float computation, and it should do it here as well) */
+
+		for (i = 0; i < numsamples; i++) {
+			sum_of_squares += ((float)sbuf[i] * (float)sbuf[i]);
+		}
+	} else {
+		/* Version for float inputs */
+		for (i = 0; i < bufsize; i++) {
+			sum_of_squares += (fbuf[i] * fbuf[i]);
+		}
+	}
+
+	finalanswer = sum_of_squares/(float)bufsize; /* need to divide by the number of elements in the sample for RMS calc */
+
+	if (finalanswer < 0) {
+		printf("Error: Final answer negative number %f\n", finalanswer);
+		return -3;
+	}
+
+	return sqrtf(finalanswer);
+}
+
+/**
+ *  dumps input and output buffer contents for the echo test - used to see exactly what's going on
+ */
+static int maptone(int whichzap, int freq, char *dialstr, int delayuntilsilence)
+{
+	int i = 0;
+	int res = 0, x = 0;
+	struct zt_bufferinfo bi;
+	short inbuf[TEST_DURATION]; /* changed from BUFFER_LENGTH - this buffer is for short values, so it should be allocated using the length of the test */
+	FILE *outfile = NULL;
+
+	outfile = fopen("fxotune_dump.vals", "w");
+	if (!outfile) {
+		fprintf(stdout, "Cannot create fxotune_dump.vals\n");
+		return -1;
+	}
+
+	x = 1;
+	if (ioctl(whichzap, ZT_SETLINEAR, &x)) {
+		fprintf(stderr, "Unable to set channel to signed linear mode.\n");
+		return -1;
+	}
+
+	memset(&bi, 0, sizeof(bi));
+	if (ioctl(whichzap, ZT_GET_BUFINFO, &bi)) {
+		fprintf(stderr, "Unable to get buffer information!\n");
+		return -1;
+	}
+	bi.numbufs = 2;
+	bi.bufsize = TEST_DURATION; /* KD - changed from BUFFER_LENGTH; */
+	bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
+	bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
+	if (ioctl(whichzap, ZT_SET_BUFINFO, &bi)) {
+		fprintf(stderr, "Unable to set buffer information!\n");
+		return -1;
+	}
+
+	/* Fill the output buffers */
+	int leadin = 50;
+	int trailout = 100;
+	for (i = 0; i < leadin; i++)
+		outbuf[i] = 0;
+	for (; i < TEST_DURATION - trailout; i++){
+		outbuf[i] = freq > 0 ? gentone(freq, i) : genwaveform(i); /* if frequency is negative, use a multi-part waveform instead of a single frequency */
+	}
+	for (; i < TEST_DURATION; i++)
+		outbuf[i] = 0;
+
+	/* Make sure the line is clear */
+	struct silence_info sinfo;
+	memset(&sinfo, 0, sizeof(sinfo));
+	sinfo.device = whichzap;
+	sinfo.dialstr = dialstr;
+	sinfo.initial_delay = delayuntilsilence;
+	sinfo.reset_after = 4; /* doesn't matter - we are only running one test */
+	
+	if (ensure_silence(&sinfo)){
+		fprintf(stderr, "Unable to get a clear outside line\n");
+		return -1;
+	}
+
+	/* Flush buffers */
+	x = ZT_FLUSH_READ | ZT_FLUSH_WRITE | ZT_FLUSH_EVENT;
+	if (ioctl(whichzap, ZT_FLUSH, &x)) {
+		fprintf(stderr, "Unable to flush I/O: %s\n", strerror(errno));
+		return -1;
+	}
+
+	/* send data out on line */
+	res = write(whichzap, outbuf, BUFFER_LENGTH); /* we are sending a TEST_DURATION length array of shorts (which are 2 bytes each) */
+	if (res != BUFFER_LENGTH) { 
+		fprintf(stderr, "Could not write all data to line\n");
+		return -1;
+	}
+
+	/* read return response */
+	res = read(whichzap, inbuf, BUFFER_LENGTH);
+	if (res != BUFFER_LENGTH) {
+		fprintf(stderr, "Could not fill input buffer\n");
+		return -1;
+	}
+
+	/* write content of output buffer to debug file */
+	float power_result = power_of(inbuf, TEST_DURATION, 1); 
+	float power_waveform = power_of(outbuf, TEST_DURATION, 1); 
+	float echo = power_result/power_waveform;
+	
+	fprintf(outfile, "Buffers, freq=%d, outpower=%0.0f, echo=%0.4f\n", freq, power_result, echo);
+	fprintf(outfile, "Sample, Input (received from the line), Output (sent to the line)\n");
+	for (i = 0; i < TEST_DURATION; i++){
+		fprintf(outfile, "%d, %d, %d\n", 
+			i,
+			inbuf[i],
+			outbuf[i]
+		);
+	}
+
+	fclose(outfile);
+	
+	fprintf(stdout, "echo ratio = %0.4f (%0.1f / %0.1f)\n", echo, power_result, power_waveform);
+	
+	return 0;
+}
+
+
+
+/**
+ * Perform calibration type 2 on the specified device
+ * 
+ * Determine optimum echo coefficients for the specified device
+ * 
+ * New tuning strategy.  If we have a number that we can dial that will result in silence from the
+ * switch, the tune will be *much* faster (we don't have to keep hanging up and dialing a digit, etc...)
+ * The downside is that the user needs to actually find a 'no tone' phone number at their CO's switch - but for
+ * really fixing echo problems, this is what it takes.
+ *
+ * Also, for the purposes of optimizing settings, if we pick a single frequency and test with that,
+ * we can try a whole bunch of impedence/echo coefficients.  This should give better results than trying
+ * a bunch of frequencies, and we can always do a a frequency sweep to pick between the best 3 or 4
+ * impedence/coefficients configurations.
+ *   
+ * Note:  It may be possible to take this even further and do some pertubation analysis on the echo coefficients
+ * 		 themselves (maybe use the 64 entry sweep to find some settings that are close to working well, then
+ * 		 deviate the coefficients a bit to see if we can improve things).  A better way to do this would be to
+ * 		 use the optimization strategy from silabs.  For reference, here is an application note that describes
+ * 		 the echo coefficients (and acim values):
+ * 		 
+ * 		 http://www.silabs.com/public/documents/tpub_doc/anote/Wireline/Silicon_DAA/en/an84.pdf
+ * 		 
+ */
+static int acim_tune2(int whichzap, int freq, char *dialstr, int delayuntilsilence, int silencegoodfor, struct wctdm_echo_coefs *coefs_out)
+{
+	int i = 0;
+	int res = 0, x = 0;
+	int lowesttry = -1;
+	float lowesttryresult = 999999999999.0;
+	float lowestecho = 999999999999.0;;
+	struct zt_bufferinfo bi;
+
+	short inbuf[TEST_DURATION];
+
+	if (debug && !debugoutfile) {
+		if (!(debugoutfile = fopen("fxotune.vals", "w"))) {
+			fprintf(stdout, "Cannot create fxotune.vals\n");
+			return -1;
+		}
+	}
+
+	/* Set echo settings */
+	if (ioctl(whichzap, WCTDM_SET_ECHOTUNE, &echo_trys[0])) {
+		fprintf(stderr, "Unable to set impedance on fd %d\n", whichzap);
+		return -1;
+	}
+
+	x = 1;
+	if (ioctl(whichzap, ZT_SETLINEAR, &x)) {
+		fprintf(stderr, "Unable to set channel to signed linear mode.\n");
+		return -1;
+	}
+
+	memset(&bi, 0, sizeof(bi));
+	if (ioctl(whichzap, ZT_GET_BUFINFO, &bi)) {
+		fprintf(stderr, "Unable to get buffer information!\n");
+		return -1;
+	}
+	bi.numbufs = 2;
+	bi.bufsize = BUFFER_LENGTH;
+	bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
+	bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
+	if (ioctl(whichzap, ZT_SET_BUFINFO, &bi)) {
+		fprintf(stderr, "Unable to set buffer information!\n");
+		return -1;
+	}
+	x = ZT_OFFHOOK;
+	if (ioctl(whichzap, ZT_HOOK, &x)) {
+		fprintf(stderr, "Cannot bring fd %d off hook", whichzap);
+		return -1;
+	}
+
+
+	/* Set up silence settings */
+	struct silence_info sinfo;
+	memset(&sinfo, 0, sizeof(sinfo));
+	sinfo.device = whichzap;
+	sinfo.dialstr = dialstr;
+	sinfo.initial_delay = delayuntilsilence;
+	sinfo.reset_after = silencegoodfor;
+
+	/* Fill the output buffers */
+	for (i = 0; i < TEST_DURATION; i++)
+		outbuf[i] = freq > 0 ? gentone(freq, i) : genwaveform(i); /* if freq is negative, use a multi-frequency waveform */
+	
+	/* compute power of input (so we can later compute echo levels relative to input) */
+	float waveform_power = power_of(outbuf+SKIP_SAMPLES, TEST_DURATION-SKIP_SAMPLES, 1);
+	
+
+	/* sweep through the various coefficient settings and see how our responses look */
+
+	int echo_trys_size = 64;
+	int trys = 0;
+	for (trys = 0; trys < echo_trys_size; trys++){
+		
+		/* ensure silence on the line */
+		if (ensure_silence(&sinfo)){
+			fprintf(stderr, "Unable to get a clear outside line\n");
+			return -1;
+		}
+		
+		if (ioctl(whichzap, WCTDM_SET_ECHOTUNE, &echo_trys[trys])) {
+			fprintf(stderr, "Unable to set echo coefficients on fd %d\n", whichzap);
+			return -1;
+		}
+
+		/* Flush buffers */
+		x = ZT_FLUSH_READ | ZT_FLUSH_WRITE | ZT_FLUSH_EVENT;
+		if (ioctl(whichzap, ZT_FLUSH, &x)) {
+			fprintf(stderr, "Unable to flush I/O: %s\n", strerror(errno));
+			return -1;
+		}
+
+		/* send data out on line */
+		res = write(whichzap, outbuf, BUFFER_LENGTH);
+		if (res != BUFFER_LENGTH) {
+			fprintf(stderr, "Could not write all data to line\n");
+			return -1;
+		}
+
+		/* read return response */
+		res = read(whichzap, inbuf, BUFFER_LENGTH);
+		if (res != BUFFER_LENGTH) {
+			fprintf(stderr, "Could not fill input buffer - got %d bytes, expected %d bytes\n", res, BUFFER_LENGTH);
+			return -1;
+		}
+
+		/* calculate RMS of response */
+		
+		float freq_result = power_of(inbuf+SKIP_SAMPLES, TEST_DURATION-SKIP_SAMPLES, 1);
+		float echo = freq_result/waveform_power;
+		
+		if (freq_result < lowesttryresult){
+			lowesttry = trys;
+			lowesttryresult = freq_result;
+			lowestecho = echo;
+		}
+		if (debug) {
+			char result[256];
+			snprintf(result, sizeof(result), "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%f,%f", 
+						echo_trys[trys].acim, 
+						echo_trys[trys].coef1, 
+						echo_trys[trys].coef2, 
+						echo_trys[trys].coef3, 
+						echo_trys[trys].coef4, 
+						echo_trys[trys].coef5, 
+						echo_trys[trys].coef6, 
+						echo_trys[trys].coef7, 
+						echo_trys[trys].coef8, 
+						freq, 
+						freq_result,
+						echo
+					);
+			
+			fprintf(debugoutfile, "%s\n", result);
+			if (debug > 1)
+				fprintf(stdout, "%s\n", result);
+		}
+	}
+
+	if (debug > 0)
+		fprintf(stdout, "Config with lowest response = %d, power = %0.0f, echo = %0.4f\n", lowesttry, lowesttryresult, lowestecho);
+
+	memcpy(coefs_out, &echo_trys[lowesttry], sizeof(struct wctdm_echo_coefs));
+
+	return 0;
+}
+
+/**
+ *  Perform calibration type 1 on the specified device.  Only tunes the line impedance.  Look for best response range 
+ */
+static int acim_tune(int whichzap, char *dialstr, int delayuntilsilence, int silencegoodfor, struct wctdm_echo_coefs *coefs_out)
+{
+	int i = 0, freq = 0, acim = 0;
+	int res = 0, x = 0;
+	struct zt_bufferinfo bi;
+	struct wctdm_echo_coefs coefs;
+	short inbuf[TEST_DURATION]; /* changed from BUFFER_LENGTH - this buffer is for short values, so it should be allocated using the length of the test */
+	int lowest = 0;
+	FILE *outfile = NULL;
+	float acim_results[16];
+
+
+	if (debug) {
+		outfile = fopen("fxotune.vals", "w");
+		if (!outfile) {
+			fprintf(stdout, "Cannot create fxotune.vals\n");
+			return -1;
+		}
+	}
+
+	/* Set up silence settings */
+	struct silence_info sinfo;
+	memset(&sinfo, 0, sizeof(sinfo));
+	sinfo.device = whichzap;
+	sinfo.dialstr = dialstr;
+	sinfo.initial_delay = delayuntilsilence;
+	sinfo.reset_after = silencegoodfor;
+	
+	/* Set echo settings */
+	memset(&coefs, 0, sizeof(coefs));
+	if (ioctl(whichzap, WCTDM_SET_ECHOTUNE, &coefs)) {
+		fprintf(stdout, "Skipping non-TDM / non-FXO\n");
+		return -1;
+	}
+
+	x = 1;
+	if (ioctl(whichzap, ZT_SETLINEAR, &x)) {
+		fprintf(stderr, "Unable to set channel to signed linear mode.\n");
+		return -1;
+	}
+
+	memset(&bi, 0, sizeof(bi));
+	if (ioctl(whichzap, ZT_GET_BUFINFO, &bi)) {
+		fprintf(stderr, "Unable to get buffer information!\n");
+		return -1;
+	}
+	bi.numbufs = 2;
+	bi.bufsize = BUFFER_LENGTH;
+	bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
+	bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
+	if (ioctl(whichzap, ZT_SET_BUFINFO, &bi)) {
+		fprintf(stderr, "Unable to set buffer information!\n");
+		return -1;
+	}
+
+	for (acim = 0; acim < 16; acim++) {
+		float freq_results[15];
+
+		coefs.acim = acim;
+		if (ioctl(whichzap, WCTDM_SET_ECHOTUNE, &coefs)) {
+			fprintf(stderr, "Unable to set impedance on fd %d\n", whichzap);
+			return -1;
+		}
+
+		for (freq = 200; freq <=3000; freq+=200) {
+			/* Fill the output buffers */
+			for (i = 0; i < TEST_DURATION; i++)
+				outbuf[i] = gentone(freq, i);
+
+			/* Make sure line is ready for next test iteration */
+			if (ensure_silence(&sinfo)){
+				fprintf(stderr, "Unable to get a clear line\n");
+				return -1;
+			}
+			
+
+			/* Flush buffers */
+			x = ZT_FLUSH_READ | ZT_FLUSH_WRITE | ZT_FLUSH_EVENT;
+			if (ioctl(whichzap, ZT_FLUSH, &x)) {
+				fprintf(stderr, "Unable to flush I/O: %s\n", strerror(errno));
+				return -1;
+			}
+	
+			/* send data out on line */
+			res = write(whichzap, outbuf, BUFFER_LENGTH);
+			if (res != BUFFER_LENGTH) {
+				fprintf(stderr, "Could not write all data to line\n");
+				return -1;
+			}
+
+			/* read return response */
+			res = read(whichzap, inbuf, BUFFER_LENGTH);
+			if (res != BUFFER_LENGTH) {
+				fprintf(stderr, "Could not fill input buffer\n");
+				return -1;
+			}
+
+			/* calculate power of response */
+			
+			freq_results[(freq/200)-1] = power_of(inbuf+SKIP_SAMPLES, TEST_DURATION-SKIP_SAMPLES, 1); /* changed from inbuf+SKIP_BYTES, BUFFER_LENGTH-SKIP_BYTES, 1 */
+			if (debug) fprintf(outfile, "%d,%d,%f\n", acim, freq, freq_results[(freq/200)-1]);
+		}
+		acim_results[acim] = power_of(freq_results, 15, 0);
+	}
+
+	if (debug) {
+		for (i = 0; i < 16; i++)
+			fprintf(outfile, "acim_results[%d] = %f\n", i, acim_results[i]);
+	}
+	/* Find out what the "best" impedance is for the line */
+	lowest = 0;
+	for (i = 0; i < 16; i++) {
+		if (acim_results[i] < acim_results[lowest]) {
+			lowest = i;
+		}
+	}
+
+	coefs_out->acim = lowest;
+	coefs_out->coef1 = 0;
+	coefs_out->coef2 = 0;
+	coefs_out->coef3 = 0;
+	coefs_out->coef4 = 0;
+	coefs_out->coef5 = 0;
+	coefs_out->coef6 = 0;
+	coefs_out->coef7 = 0;
+	coefs_out->coef8 = 0;
+	
+	return 0;
+}
+
+/**
+ * Reads echo register settings from the configuration file and pushes them into
+ * the appropriate devices
+ * 
+ * @param configfilename the path of the file that the calibration results should be written to
+ * 
+ * @return 0 if successful, !0 otherwise
+ */	
+static int do_set(char *configfilename)
+{
+	FILE *fp = NULL;
+	int res = 0;
+	int fd = 0;
+		
+	fp = fopen(configfile, "r");
+	
+    if (!fp) {
+            fprintf(stdout, "Cannot open %s!\n",configfile);
+            return -1;
+    }
+
+	
+	while (res != EOF) {
+		struct wctdm_echo_coefs mycoefs;
+		char completezappath[56] = "";
+		int myzap,myacim,mycoef1,mycoef2,mycoef3,mycoef4,mycoef5,mycoef6,mycoef7,mycoef8;
+
+
+		res = fscanf(fp, "%d=%d,%d,%d,%d,%d,%d,%d,%d,%d",&myzap,&myacim,&mycoef1,
+				&mycoef2,&mycoef3,&mycoef4,&mycoef5,&mycoef6,&mycoef7,
+				&mycoef8);
+
+		if (res == EOF) {
+			break;
+		}
+
+		/* Check to be sure conversion is done correctly */
+		if (OUT_OF_BOUNDS(myacim) || OUT_OF_BOUNDS(mycoef1)||
+			OUT_OF_BOUNDS(mycoef2)|| OUT_OF_BOUNDS(mycoef3)||
+			OUT_OF_BOUNDS(mycoef4)|| OUT_OF_BOUNDS(mycoef5)||
+			OUT_OF_BOUNDS(mycoef6)|| OUT_OF_BOUNDS(mycoef7)|| OUT_OF_BOUNDS(mycoef8)) {
+
+			fprintf(stdout, "Bounds check error on inputs from %s:%d\n", configfile, myzap);
+			return -1;
+		}
+
+		mycoefs.acim = myacim;
+		mycoefs.coef1 = mycoef1;
+		mycoefs.coef2 = mycoef2;
+		mycoefs.coef3 = mycoef3;
+		mycoefs.coef4 = mycoef4;
+		mycoefs.coef5 = mycoef5;
+		mycoefs.coef6 = mycoef6;
+		mycoefs.coef7 = mycoef7;
+		mycoefs.coef8 = mycoef8;
+	
+		snprintf(completezappath, sizeof(completezappath), "%s/%d", zappath, myzap);
+		fd = open(completezappath, O_RDWR);
+
+		if (fd < 0) {
+			fprintf(stdout, "open error on %s: %s\n", completezappath, strerror(errno));
+			return -1;
+		}
+
+		if (ioctl(fd, WCTDM_SET_ECHOTUNE, &mycoefs)) {
+			fprintf(stdout, "%s: %s\n", completezappath, strerror(errno));
+			return -1;
+		}
+
+		close(fd);
+	}
+
+	fclose(fp);
+
+	fprintf(stdout, "fxotune: successfully set echo coeffecients on FXO modules\n");
+	return 0;	
+}
+
+/**
+ * Output waveform information from a single test
+ * 
+ * Clears the line, then sends a single waveform (multi-tone, or single tone), and listens
+ * for the response on the line.  Output is written to fxotune_dump.vals
+ * 
+ * @param startdev the device to test
+ * @param dialstr the string that should be dialed to clear the dialtone from the line
+ * @param delayuntilsilence the number of seconds to wait after dialing dialstr before starting the test
+ * @param silencegoodfor the number of seconds that the test can run before having to reset the line again
+ * 			(this is basically the amount of time it takes before the 'if you'd like to make a call...' message
+ * 			kicks in after you dial dialstr.  This test is so short that the value is pretty much ignored.
+ * @param waveformtype the type of waveform to use - -1 = multi-tone waveform, otherwise the specified value
+ * 			is used as the frequency of a single tone.  A value of 0 will output silence.
+ */
+static int do_dump(int startdev, char* dialstr, int delayuntilsilence, int silencegoodfor, int waveformtype)
+{
+	int res = 0;
+	int fd;
+	char zapdev[80] = "";
+	
+	int zapmodule = startdev;
+	snprintf(zapdev, sizeof(zapdev), "%s/%d", zappath, zapmodule);
+

[... 261 lines stripped ...]


More information about the aadk-commits mailing list