[svn-commits] tzafrir: linux/trunk r9993 - /linux/trunk/drivers/dahdi/xpp/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Jun 28 13:23:08 CDT 2011


Author: tzafrir
Date: Tue Jun 28 13:23:00 2011
New Revision: 9993

URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=9993
Log:
xpd_echo: XPP Octasic echo canceler module

* xpd_echo (card_echo.c) - a module to handle an Astribank hardware echo
  canceller module.
* All other XPDs are now of type 'telephony_device'. Only a telephony device
  XPD provides a span to register.
* The EC module will typically show up as XPD-40 and will always show up as
  Unregistered in 'dahdi_hardware -v'

Signed-off-by: Oron Peled <oron.peled at xorcom.com>
Signed-off-by: Tzafrir Cohen <tzafrir.cohen at xorcom.com>

Added:
    linux/trunk/drivers/dahdi/xpp/card_echo.c   (with props)
    linux/trunk/drivers/dahdi/xpp/card_echo.h   (with props)
Modified:
    linux/trunk/drivers/dahdi/xpp/Kbuild
    linux/trunk/drivers/dahdi/xpp/card_bri.c
    linux/trunk/drivers/dahdi/xpp/card_fxo.c
    linux/trunk/drivers/dahdi/xpp/card_fxs.c
    linux/trunk/drivers/dahdi/xpp/card_pri.c
    linux/trunk/drivers/dahdi/xpp/xbus-core.c
    linux/trunk/drivers/dahdi/xpp/xbus-core.h
    linux/trunk/drivers/dahdi/xpp/xbus-pcm.c
    linux/trunk/drivers/dahdi/xpp/xbus-pcm.h
    linux/trunk/drivers/dahdi/xpp/xbus-sysfs.c
    linux/trunk/drivers/dahdi/xpp/xpd.h
    linux/trunk/drivers/dahdi/xpp/xpp_dahdi.c
    linux/trunk/drivers/dahdi/xpp/xpp_dahdi.h
    linux/trunk/drivers/dahdi/xpp/xpp_debug
    linux/trunk/drivers/dahdi/xpp/xproto.c
    linux/trunk/drivers/dahdi/xpp/xproto.h

Modified: linux/trunk/drivers/dahdi/xpp/Kbuild
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/Kbuild?view=diff&rev=9993&r1=9992&r2=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/Kbuild (original)
+++ linux/trunk/drivers/dahdi/xpp/Kbuild Tue Jun 28 13:23:00 2011
@@ -13,6 +13,7 @@
 obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_FXO)		+= xpd_fxo.o
 obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_PRI)		+= xpd_pri.o
 obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_BRI)		+= xpd_bri.o
+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_ECHO)		+= xpd_echo.o
 
 # Build only supported modules
 ifneq	(,$(filter y m,$(CONFIG_USB)))
@@ -27,6 +28,7 @@
 xpd_fxo-objs		+= card_fxo.o
 xpd_bri-objs		+= card_bri.o
 xpd_pri-objs		+= card_pri.o
+xpd_echo-objs		+= card_echo.o
 xpp_mmap-objs		+= mmapbus.o mmapdrv.o
 
 ifeq	(y,$(PARPORT_DEBUG))

Modified: linux/trunk/drivers/dahdi/xpp/card_bri.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/card_bri.c?view=diff&rev=9993&r1=9992&r2=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/card_bri.c (original)
+++ linux/trunk/drivers/dahdi/xpp/card_bri.c Tue Jun 28 13:23:00 2011
@@ -863,6 +863,8 @@
 	.hooksig = xpp_hooksig,	/* Only with RBS bits */
 	.ioctl = xpp_ioctl,
 	.maint = xpp_maint,
+	.echocan_create = xpp_echocan_create,
+	.echocan_name = xpp_echocan_name,
 #ifdef	DAHDI_SYNC_TICK
 	.sync_tick = dahdi_sync_tick,
 #endif
@@ -1428,7 +1430,33 @@
 	}
 }
 
-
+int BRI_echocancel_timeslot(xpd_t *xpd, int pos)
+{
+	return xpd->addr.subunit * 4 + pos;
+}
+
+static int BRI_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask)
+{
+	struct BRI_priv_data	*priv;
+	int i;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	XPD_DBG(GENERAL, xpd, "0x%8X\n", ec_mask);
+	if (!ECHOOPS(xpd->xbus)) {
+		XPD_DBG(GENERAL, xpd,
+				"No echo canceller in XBUS: Doing nothing.\n");
+		return -EINVAL;
+	}
+	for (i = 0; i < PHONEDEV(xpd).channels - 1; i++) {
+		int	on = BIT(i) & ec_mask;
+
+		CALL_EC_METHOD(ec_set, xpd->xbus, xpd, i, on);
+	}
+	CALL_EC_METHOD(ec_update, xpd->xbus, xpd->xbus);
+	return 0;
+}
 
 /*---------------- BRI: HOST COMMANDS -------------------------------------*/
 
@@ -1670,6 +1698,8 @@
 	.card_pcm_fromspan	= BRI_card_pcm_fromspan,
 	.card_pcm_tospan	= BRI_card_pcm_tospan,
 	.card_timing_priority	= generic_timing_priority,
+	.echocancel_timeslot	= BRI_echocancel_timeslot,
+	.echocancel_setmask	= BRI_echocancel_setmask,
 	.card_ioctl	= BRI_card_ioctl,
 	.card_open	= BRI_card_open,
 	.card_close	= BRI_card_close,

Added: linux/trunk/drivers/dahdi/xpp/card_echo.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/card_echo.c?view=auto&rev=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/card_echo.c (added)
+++ linux/trunk/drivers/dahdi/xpp/card_echo.c Tue Jun 28 13:23:00 2011
@@ -1,0 +1,387 @@
+/*
+ * Written by Oron Peled <oron at actcom.co.il>
+ * Copyright (C) 2011, Xorcom
+ *
+ * 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.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include "xpd.h"
+#include "xproto.h"
+#include "card_echo.h"
+#include "xpp_dahdi.h"
+#include "dahdi_debug.h"
+#include "xpd.h"
+#include "xbus-core.h"
+
+static const char rcsid[] = "$Id$";
+
+/* must be before dahdi_debug.h: */
+static DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
+
+/*---------------- ECHO Protocol Commands ----------------------------------*/
+
+static bool echo_packet_is_valid(xpacket_t *pack);
+static void echo_packet_dump(const char *msg, xpacket_t *pack);
+
+DEF_RPACKET_DATA(ECHO, SET,
+	byte timeslots[ECHO_TIMESLOTS];
+	);
+
+DEF_RPACKET_DATA(ECHO, SET_REPLY,
+	byte status;
+	byte reserved;
+	);
+
+struct ECHO_priv_data {
+};
+
+static xproto_table_t	PROTO_TABLE(ECHO);
+
+/*---------------- ECHO: Methods -------------------------------------------*/
+
+static xpd_t *ECHO_card_new(xbus_t *xbus, int unit, int subunit,
+		const xproto_table_t *proto_table, byte subtype,
+		int subunits, int subunit_ports, bool to_phone)
+{
+	xpd_t *xpd = NULL;
+	struct ECHO_priv_data *priv;
+	int channels = 0;
+
+	if (subunit_ports != 1) {
+		XBUS_ERR(xbus, "Bad subunit_ports=%d\n", subunit_ports);
+		return NULL;
+	}
+	XBUS_DBG(GENERAL, xbus, "\n");
+	xpd = xpd_alloc(xbus, unit, subunit, subtype, subunits,
+		sizeof(struct ECHO_priv_data), proto_table, channels);
+	if (!xpd)
+		return NULL;
+	xpd->type_name = "ECHO";
+	priv = xpd->priv;
+	return xpd;
+}
+
+static int ECHO_card_init(xbus_t *xbus, xpd_t *xpd)
+{
+	struct ECHO_priv_data *priv;
+	xproto_table_t *proto_table;
+	int ret = 0;
+
+	BUG_ON(!xpd);
+	XPD_DBG(GENERAL, xpd, "\n");
+	xpd->type = XPD_TYPE_ECHO;
+	proto_table = &PROTO_TABLE(ECHO);
+	priv = xpd->priv;
+	XPD_DBG(DEVICES, xpd, "%s\n", xpd->type_name);
+	ret = CALL_EC_METHOD(ec_update, xbus, xbus);
+	return ret;
+}
+
+static int ECHO_card_remove(xbus_t *xbus, xpd_t *xpd)
+{
+	struct ECHO_priv_data *priv;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	XPD_DBG(GENERAL, xpd, "\n");
+	return 0;
+}
+
+static int ECHO_card_tick(xbus_t *xbus, xpd_t *xpd)
+{
+	struct ECHO_priv_data *priv;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	return 0;
+}
+
+static int ECHO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
+{
+	unsigned long flags;
+	struct xpd_addr addr;
+	xpd_t *orig_xpd;
+	byte regnum;
+	byte data_low;
+
+	/* Map UNIT + PORTNUM to XPD */
+	orig_xpd = xpd;
+	addr.unit = orig_xpd->addr.unit;
+	addr.subunit = info->portnum;
+	regnum = REG_FIELD(info, regnum);
+	data_low = REG_FIELD(info, data_low);
+	xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
+	if (!xpd) {
+		static int rate_limit;
+
+		if ((rate_limit++ % 1003) < 5)
+			notify_bad_xpd(__func__, xbus, addr,
+					orig_xpd->xpdname);
+		return -EPROTO;
+	}
+	spin_lock_irqsave(&xpd->lock, flags);
+	/* Update /proc info only if reply related to last reg read request */
+	if (
+			REG_FIELD(&xpd->requested_reply, regnum) ==
+				REG_FIELD(info, regnum) &&
+			REG_FIELD(&xpd->requested_reply, do_subreg) ==
+				REG_FIELD(info, do_subreg) &&
+			REG_FIELD(&xpd->requested_reply, subreg) ==
+				REG_FIELD(info, subreg)) {
+		xpd->last_reply = *info;
+	}
+	spin_unlock_irqrestore(&xpd->lock, flags);
+	return 0;
+}
+
+/*---------------- ECHO: HOST COMMANDS -------------------------------------*/
+
+static /* 0x39 */ HOSTCMD(ECHO, SET)
+{
+	struct xbus_echo_state *es;
+	byte *ts;
+	xframe_t *xframe;
+	xpacket_t *pack;
+	int ret;
+	uint16_t frm_len;
+	int xpd_idx;
+
+	BUG_ON(!xbus);
+	/*
+	 * Find echo canceller XPD address
+	 */
+	es = &xbus->echo_state;
+	xpd_idx = es->xpd_idx;
+	XFRAME_NEW_CMD(xframe, pack, xbus, ECHO, SET, xpd_idx);
+	ts = RPACKET_FIELD(pack, ECHO, SET, timeslots);
+	memcpy(ts, es->timeslots, ECHO_TIMESLOTS);
+	frm_len = XFRAME_LEN(xframe);
+	XBUS_DBG(GENERAL, xbus, "ECHO SET: (len = %d)\n", frm_len);
+	ret = send_cmd_frame(xbus, xframe);
+	return ret;
+}
+
+static int ECHO_ec_set(xpd_t *xpd, int pos, bool on)
+{
+	int ts_number;
+	int ts_mask;
+	byte *ts;
+
+	ts = xpd->xbus->echo_state.timeslots;
+	/*
+	 * ts_number = PCM time slot ("channel number" in the PCM XPP packet)
+	 *
+	 * Bit 0 is for UNIT=0
+	 * PRI: ts_number * 4 + SUBUNIT
+	 * BRI: ts_number
+	 * FXS/FXO(all units): UNIT * 32 + ts_number
+	 *
+	 * Bit 1 is for UNIT=1-3: FXS/FXO
+	 *
+	 */
+	ts_mask = (xpd->addr.unit == 0) ? 0x1 : 0x2;	/* Which bit? */
+	ts_number = CALL_PHONE_METHOD(echocancel_timeslot, xpd, pos);
+	if (ts_number >= ECHO_TIMESLOTS || ts_number < 0) {
+		XPD_ERR(xpd, "Bad ts_number=%d\n", ts_number);
+		return -EINVAL;
+	} else {
+		if (on)
+			ts[ts_number] |= ts_mask;
+		else
+			ts[ts_number] &= ~ts_mask;
+	}
+	LINE_DBG(GENERAL, xpd, pos, "%s = %d -- ts_number=%d ts_mask=0x%X\n",
+		__func__, on, ts_number, ts_mask);
+	return 0;
+}
+
+static int ECHO_ec_get(xpd_t *xpd, int pos)
+{
+	int ts_number;
+	int ts_mask;
+	int is_on;
+	byte *ts;
+
+	ts = xpd->xbus->echo_state.timeslots;
+	ts_mask = (xpd->addr.unit == 0) ? 0x1 : 0x2;	/* Which bit? */
+	ts_number = CALL_PHONE_METHOD(echocancel_timeslot, xpd, pos);
+	if (ts_number >= ECHO_TIMESLOTS || ts_number < 0) {
+		XPD_ERR(xpd, "Bad ts_number=%d\n", ts_number);
+		return -EINVAL;
+	} else {
+		is_on = ts[ts_number] & ts_mask;
+	}
+#if 0
+	LINE_DBG(GENERAL, xpd, pos, "ec_get=%d -- ts_number=%d ts_mask=0x%X\n",
+		is_on, ts_number, ts_mask);
+#endif
+	return is_on;
+}
+
+static void ECHO_ec_dump(xbus_t *xbus)
+{
+	byte *ts;
+	int i;
+
+	ts = xbus->echo_state.timeslots;
+	for (i = 0; i + 15 < ECHO_TIMESLOTS; i += 16) {
+		XBUS_DBG(GENERAL, xbus,
+			"EC-DUMP[%03d]: "
+			"0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X "
+			"0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
+			i,
+			ts[i+0], ts[i+1], ts[i+2], ts[i+3], ts[i+4], ts[i+5],
+				ts[i+6], ts[i+7],
+			ts[i+8], ts[i+9], ts[i+10], ts[i+11], ts[i+12],
+				ts[i+13], ts[i+14], ts[i+15]
+			);
+	}
+}
+
+static int ECHO_ec_update(xbus_t *xbus)
+{
+	XBUS_DBG(GENERAL, xbus, "%s\n", __func__);
+	//ECHO_ec_dump(xbus);
+	return CALL_PROTO(ECHO, SET, xbus, NULL);
+}
+
+/*---------------- ECHO: Astribank Reply Handlers --------------------------*/
+HANDLER_DEF(ECHO, SET_REPLY)
+{
+	byte	status;
+
+	BUG_ON(!xpd);
+	status = RPACKET_FIELD(pack, ECHO, SET_REPLY, status);
+	XPD_DBG(GENERAL, xpd, "status=0x%X\n", status);
+	return 0;
+}
+
+static const struct xops	echo_xops = {
+	.card_new		= ECHO_card_new,
+	.card_init		= ECHO_card_init,
+	.card_remove		= ECHO_card_remove,
+	.card_tick		= ECHO_card_tick,
+	.card_register_reply	= ECHO_card_register_reply,
+};
+
+static const struct echoops	echoops = {
+	.ec_set		= ECHO_ec_set,
+	.ec_get		= ECHO_ec_get,
+	.ec_update	= ECHO_ec_update,
+	.ec_dump	= ECHO_ec_dump,
+};
+
+static xproto_table_t PROTO_TABLE(ECHO) = {
+	.owner = THIS_MODULE,
+	.entries = {
+		/*	Table	Card	Opcode		*/
+		XENTRY(ECHO,	ECHO,	SET_REPLY),
+	},
+	.name = "ECHO",
+	.ports_per_subunit = 1,
+	.type = XPD_TYPE_ECHO,
+	.xops = &echo_xops,
+	.echoops = &echoops,
+	.packet_is_valid = echo_packet_is_valid,
+	.packet_dump = echo_packet_dump,
+};
+
+static bool echo_packet_is_valid(xpacket_t *pack)
+{
+	const xproto_entry_t	*xe = NULL;
+	// DBG(GENERAL, "\n");
+	xe = xproto_card_entry(&PROTO_TABLE(ECHO), XPACKET_OP(pack));
+	return xe != NULL;
+}
+
+static void echo_packet_dump(const char *msg, xpacket_t *pack)
+{
+	DBG(GENERAL, "%s\n", msg);
+}
+
+/*------------------------- sysfs stuff --------------------------------*/
+static int echo_xpd_probe(struct device *dev)
+{
+	xpd_t	*ec_xpd;
+	int	ret = 0;
+
+	ec_xpd = dev_to_xpd(dev);
+	/* Is it our device? */
+	if (ec_xpd->type != XPD_TYPE_ECHO) {
+		XPD_ERR(ec_xpd, "drop suggestion for %s (%d)\n",
+			dev_name(dev), ec_xpd->type);
+		return -EINVAL;
+	}
+	XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
+	return ret;
+}
+
+static int echo_xpd_remove(struct device *dev)
+{
+	xpd_t	*ec_xpd;
+
+	ec_xpd = dev_to_xpd(dev);
+	XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
+	return 0;
+}
+
+static struct xpd_driver	echo_driver = {
+	.type		= XPD_TYPE_ECHO,
+	.driver		= {
+		.name = "echo",
+#ifndef OLD_HOTPLUG_SUPPORT
+		.owner = THIS_MODULE,
+#endif
+		.probe = echo_xpd_probe,
+		.remove = echo_xpd_remove
+	}
+};
+
+static int __init card_echo_startup(void)
+{
+	int ret;
+
+	ret = xpd_driver_register(&echo_driver.driver);
+	if (ret < 0)
+		return ret;
+	INFO("revision %s\n", XPP_VERSION);
+	INFO("FEATURE: WITH Octasic echo canceller\n");
+	xproto_register(&PROTO_TABLE(ECHO));
+	return 0;
+}
+
+static void __exit card_echo_cleanup(void)
+{
+	DBG(GENERAL, "\n");
+	xproto_unregister(&PROTO_TABLE(ECHO));
+	xpd_driver_unregister(&echo_driver.driver);
+}
+
+MODULE_DESCRIPTION("XPP ECHO Card Driver");
+MODULE_AUTHOR("Oron Peled <oron at actcom.co.il>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(XPP_VERSION);
+MODULE_ALIAS_XPD(XPD_TYPE_ECHO);
+
+module_init(card_echo_startup);
+module_exit(card_echo_cleanup);

Propchange: linux/trunk/drivers/dahdi/xpp/card_echo.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: linux/trunk/drivers/dahdi/xpp/card_echo.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: linux/trunk/drivers/dahdi/xpp/card_echo.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: linux/trunk/drivers/dahdi/xpp/card_echo.h
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/card_echo.h?view=auto&rev=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/card_echo.h (added)
+++ linux/trunk/drivers/dahdi/xpp/card_echo.h Tue Jun 28 13:23:00 2011
@@ -1,0 +1,31 @@
+#ifndef	CARD_ECHO_H
+#define	CARD_ECHO_H
+/*
+ * Written by Oron Peled <oron at actcom.co.il>
+ * Copyright (C) 2011, Xorcom
+ *
+ * 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.
+ *
+ */
+#include "xpd.h"
+
+enum echo_opcodes {
+	XPROTO_NAME(ECHO, SET)		= 0x39,
+	XPROTO_NAME(ECHO, SET_REPLY)	= 0x3A,
+};
+
+#endif	/* CARD_ECHO_H */

Propchange: linux/trunk/drivers/dahdi/xpp/card_echo.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: linux/trunk/drivers/dahdi/xpp/card_echo.h
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: linux/trunk/drivers/dahdi/xpp/card_echo.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: linux/trunk/drivers/dahdi/xpp/card_fxo.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/card_fxo.c?view=diff&rev=9993&r1=9992&r2=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/card_fxo.c (original)
+++ linux/trunk/drivers/dahdi/xpp/card_fxo.c Tue Jun 28 13:23:00 2011
@@ -1118,6 +1118,8 @@
 	.card_pcm_fromspan	= generic_card_pcm_fromspan,
 	.card_pcm_tospan	= generic_card_pcm_tospan,
 	.card_timing_priority	= generic_timing_priority,
+	.echocancel_timeslot	= generic_echocancel_timeslot,
+	.echocancel_setmask	= generic_echocancel_setmask,
 	.card_ioctl	= FXO_card_ioctl,
 	.card_open	= FXO_card_open,
 	.card_state	= FXO_card_state,

Modified: linux/trunk/drivers/dahdi/xpp/card_fxs.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/card_fxs.c?view=diff&rev=9993&r1=9992&r2=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/card_fxs.c (original)
+++ linux/trunk/drivers/dahdi/xpp/card_fxs.c Tue Jun 28 13:23:00 2011
@@ -1402,6 +1402,8 @@
 	.card_pcm_fromspan	= generic_card_pcm_fromspan,
 	.card_pcm_tospan	= generic_card_pcm_tospan,
 	.card_timing_priority	= generic_timing_priority,
+	.echocancel_timeslot	= generic_echocancel_timeslot,
+	.echocancel_setmask	= generic_echocancel_setmask,
 	.card_open	= FXS_card_open,
 	.card_close	= FXS_card_close,
 	.card_ioctl	= FXS_card_ioctl,

Modified: linux/trunk/drivers/dahdi/xpp/card_pri.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/card_pri.c?view=diff&rev=9993&r1=9992&r2=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/card_pri.c (original)
+++ linux/trunk/drivers/dahdi/xpp/card_pri.c Tue Jun 28 13:23:00 2011
@@ -1213,6 +1213,8 @@
 	.close = xpp_close,
 	.ioctl = xpp_ioctl,
 	.maint = xpp_maint,
+	.echocan_create = xpp_echocan_create,
+	.echocan_name = xpp_echocan_name,
 #ifdef	DAHDI_SYNC_TICK
 	.sync_tick = dahdi_sync_tick,
 #endif
@@ -1793,7 +1795,38 @@
 	return -ENOENT;
 }
 
-
+static int PRI_echocancel_timeslot(xpd_t *xpd, int pos)
+{
+	/*
+	 * Skip ts=0 (used for PRI sync)
+	 */
+	return (1 + pos) * 4 + xpd->addr.subunit;
+}
+
+static int PRI_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask)
+{
+	struct PRI_priv_data *priv;
+	int i;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	XPD_DBG(GENERAL, xpd, "0x%8X\n", ec_mask);
+	if (!ECHOOPS(xpd->xbus)) {
+		XPD_DBG(GENERAL, xpd,
+				"No echo canceller in XBUS: Doing nothing.\n");
+		return -EINVAL;
+	}
+	for (i = 0; i < PHONEDEV(xpd).channels; i++) {
+		int	on = BIT(i) & ec_mask;
+
+		if (i == PRI_DCHAN_IDX(priv))
+			on = 0;
+		CALL_EC_METHOD(ec_set, xpd->xbus, xpd, i, on);
+	}
+	CALL_EC_METHOD(ec_update, xpd->xbus, xpd->xbus);
+	return 0;
+}
 
 /*---------------- PRI: HOST COMMANDS -------------------------------------*/
 
@@ -2111,6 +2144,8 @@
 	.card_pcm_recompute	= PRI_card_pcm_recompute,
 	.card_pcm_fromspan	= PRI_card_pcm_fromspan,
 	.card_pcm_tospan	= PRI_card_pcm_tospan,
+	.echocancel_timeslot	= PRI_echocancel_timeslot,
+	.echocancel_setmask	= PRI_echocancel_setmask,
 	.card_timing_priority	= PRI_timing_priority,
 	.card_ioctl	= PRI_card_ioctl,
 	.card_close	= PRI_card_close,

Modified: linux/trunk/drivers/dahdi/xpp/xbus-core.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/xbus-core.c?view=diff&rev=9993&r1=9992&r2=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/xbus-core.c (original)
+++ linux/trunk/drivers/dahdi/xpp/xbus-core.c Tue Jun 28 13:23:00 2011
@@ -630,6 +630,7 @@
 	int			subunits;
 	int			ret = 0;
 	int			remaining_ports;
+	const struct echoops	*echoops;
 
 	proto_table = xproto_get(type);
 	if(!proto_table) {
@@ -637,6 +638,18 @@
 			"CARD %d: missing protocol table for type %d. Ignored.\n",
 			unit, type);
 		return -EINVAL;
+	}
+	echoops = proto_table->echoops;
+	if (echoops) {
+		XBUS_INFO(xbus, "Detected ECHO Canceler (%d)\n", unit);
+		if (ECHOOPS(xbus)) {
+			XBUS_NOTICE(xbus,
+				"CARD %d: tryies to define echoops (type %d) but we already have one. Ignored.\n",
+				unit, type);
+			return -EINVAL;
+		}
+		xbus->echo_state.echoops = echoops;
+		xbus->echo_state.xpd_idx = XPD_IDX(unit, 0);
 	}
 	remaining_ports = ports;
 	subunits = (ports + proto_table->ports_per_subunit - 1) /
@@ -748,6 +761,11 @@
 	}
 	xpd->card_present = 1;
 	if (IS_PHONEDEV(xpd)) {
+		/*
+		 * Set echo canceler channels (off)
+		 * Asterisk will tell us when/if it's needed.
+		 */
+		CALL_PHONE_METHOD(echocancel_setmask, xpd, 0);
 		CALL_PHONE_METHOD(card_state, xpd, 1);	/* Turn on all channels */
 	}
 	if(!xpd_setstate(xpd, XPD_STATE_READY)) {
@@ -758,6 +776,34 @@
 	ret = 0;
 out:
 	return ret;
+}
+
+static int xbus_echocancel(xbus_t *xbus, int on)
+{
+	int unit;
+	int subunit;
+	xpd_t *xpd;
+
+	if (!ECHOOPS(xbus))
+		return 0;
+	for (unit = 0; unit < MAX_UNIT; unit++) {
+		xpd = xpd_byaddr(xbus, unit, 0);
+		if (!xpd || !IS_PHONEDEV(xpd))
+			continue;
+		for (subunit = 0; subunit < MAX_SUBUNIT; subunit++) {
+			int	ret;
+
+			xpd = xpd_byaddr(xbus, unit, subunit);
+			if (!xpd || !IS_PHONEDEV(xpd))
+				continue;
+			ret = echocancel_xpd(xpd, on);
+			if (ret < 0) {
+				XPD_ERR(xpd, "Fail in xbus_echocancel()\n");
+				return ret;
+			}
+		}
+	}
+	return 0;
 }
 
 static int xbus_initialize(xbus_t *xbus)
@@ -807,6 +853,7 @@
 				goto err;
 		}
 	}
+	xbus_echocancel(xbus, 1);
 	do_gettimeofday(&time_end);
 	timediff = usec_diff(&time_end, &time_start);
 	timediff /= 1000*100;
@@ -1154,6 +1201,7 @@
 		return;
 	xbus_request_sync(xbus, SYNC_MODE_NONE);	/* no more ticks */
 	elect_syncer("deactivate");
+	xbus_echocancel(xbus, 0);
 	xbus_request_removal(xbus);
 	XBUS_DBG(DEVICES, xbus, "[%s] Waiting for queues\n", xbus->label);
 	xbus_command_queue_clean(xbus);

Modified: linux/trunk/drivers/dahdi/xpp/xbus-core.h
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/xbus-core.h?view=diff&rev=9993&r1=9992&r2=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/xbus-core.h (original)
+++ linux/trunk/drivers/dahdi/xpp/xbus-core.h Tue Jun 28 13:23:00 2011
@@ -156,6 +156,28 @@
 int	refcount_xbus(xbus_t *xbus);
 
 /*
+ * Echo canceller related data
+ */
+#define	ECHO_TIMESLOTS	128
+
+struct echoops {
+	int	(*ec_set)(xpd_t *xpd, int pos, bool on);
+	int	(*ec_get)(xpd_t *xpd, int pos);
+	int	(*ec_update)(xbus_t *xbus);
+	void	(*ec_dump)(xbus_t *xbus);
+};
+
+struct xbus_echo_state {
+	const struct echoops	*echoops;
+	byte			timeslots[ECHO_TIMESLOTS];
+	int			xpd_idx;
+	struct device_attribute	*da[MAX_XPDS];
+};
+#define	ECHOOPS(xbus)			((xbus)->echo_state.echoops)
+#define	EC_METHOD(name, xbus)		(ECHOOPS(xbus)->name)
+#define	CALL_EC_METHOD(name, xbus, ...)	(EC_METHOD(name, (xbus))(__VA_ARGS__))
+
+/*
  * An xbus is a transport layer for Xorcom Protocol commands
  */
 struct xbus {
@@ -169,6 +191,7 @@
 
 	int			num;
 	struct xpd		*xpds[MAX_XPDS];
+	struct xbus_echo_state	echo_state;
 
 	int			command_tick_counter;
 	int			usec_nosend;		/* Firmware flow control */
@@ -311,6 +334,7 @@
 /* sysfs */
 int	xpd_device_register(xbus_t *xbus, xpd_t *xpd);
 void	xpd_device_unregister(xpd_t *xpd);
+int	echocancel_xpd(xpd_t *xpd, int on);
 
 int	xpp_driver_init(void);
 void	xpp_driver_exit(void);

Modified: linux/trunk/drivers/dahdi/xpp/xbus-pcm.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/xbus-pcm.c?view=diff&rev=9993&r1=9992&r2=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/xbus-pcm.c (original)
+++ linux/trunk/drivers/dahdi/xpp/xbus-pcm.c Tue Jun 28 13:23:00 2011
@@ -935,6 +935,32 @@
 	spin_unlock_irqrestore(&xpd->lock, flags);
 }
 
+int generic_echocancel_timeslot(xpd_t *xpd, int pos)
+{
+	return xpd->addr.unit * 32 + pos;
+}
+EXPORT_SYMBOL(generic_echocancel_timeslot);
+
+int generic_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask)
+{
+	int i;
+
+	BUG_ON(!xpd);
+	XPD_DBG(GENERAL, xpd, "0x%8X\n", ec_mask);
+	if (!ECHOOPS(xpd->xbus)) {
+		XPD_DBG(GENERAL, xpd,
+				"No echo canceller in XBUS: Doing nothing.\n");
+		return -EINVAL;
+	}
+	for (i = 0; i < PHONEDEV(xpd).channels; i++) {
+		int on = BIT(i) & ec_mask;
+		CALL_EC_METHOD(ec_set, xpd->xbus, xpd, i, on);
+	}
+	CALL_EC_METHOD(ec_update, xpd->xbus, xpd->xbus);
+	return 0;
+}
+EXPORT_SYMBOL(generic_echocancel_setmask);
+
 static int copy_pcm_tospan(xbus_t *xbus, xframe_t *xframe)
 {
 	byte		*xframe_end;

Modified: linux/trunk/drivers/dahdi/xpp/xbus-pcm.h
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/xbus-pcm.h?view=diff&rev=9993&r1=9992&r2=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/xbus-pcm.h (original)
+++ linux/trunk/drivers/dahdi/xpp/xbus-pcm.h Tue Jun 28 13:23:00 2011
@@ -109,6 +109,8 @@
 void		generic_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack);
 void		generic_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack);
 int		generic_timing_priority(xpd_t *xpd);
+int		generic_echocancel_timeslot(xpd_t *xpd, int pos);
+int		generic_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask);
 void		fill_beep(u_char *buf, int num, int duration);
 const char	*sync_mode_name(enum sync_mode mode);
 void		xbus_set_command_timer(xbus_t *xbus, bool on);

Modified: linux/trunk/drivers/dahdi/xpp/xbus-sysfs.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/xbus-sysfs.c?view=diff&rev=9993&r1=9992&r2=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/xbus-sysfs.c (original)
+++ linux/trunk/drivers/dahdi/xpp/xbus-sysfs.c Tue Jun 28 13:23:00 2011
@@ -807,6 +807,103 @@
 	dev_set_drvdata(dev, NULL);
 }
 
+static DEVICE_ATTR_READER(echocancel_show, dev, buf)
+{
+	xpd_t *xpd;
+	unsigned long flags;
+	int len = 0;
+	xpp_line_t ec_mask = 0;
+	int i;
+	int ret;
+
+	BUG_ON(!dev);
+	xpd = dev_to_xpd(dev);
+	if (!xpd)
+		return -ENODEV;
+	if (!ECHOOPS(xpd->xbus))
+		return -ENODEV;
+	spin_lock_irqsave(&xpd->lock, flags);
+	for (i = 0; i < PHONEDEV(xpd).channels; i++) {
+		ret = CALL_EC_METHOD(ec_get, xpd->xbus, xpd, i);
+		if (ret < 0) {
+			LINE_ERR(xpd, i, "ec_get failed\n");
+			len = -ENODEV;
+			goto out;
+		}
+		if (ret)
+			ec_mask |= (1 << i);
+	}
+	len += sprintf(buf, "0x%08X\n", ec_mask);
+out:
+	spin_unlock_irqrestore(&xpd->lock, flags);
+	return len;
+}
+
+static DEVICE_ATTR_WRITER(echocancel_store, dev, buf, count)
+{
+	xpd_t *xpd;
+	char *endp;
+	unsigned long mask;
+	int channels;
+	int ret;
+
+	BUG_ON(!dev);
+	xpd = dev_to_xpd(dev);
+	XPD_DBG(GENERAL, xpd, "%s\n", buf);
+	if (!xpd)
+		return -ENODEV;
+	if (!ECHOOPS(xpd->xbus)) {
+		XPD_ERR(xpd, "No echo canceller in this XBUS\n");
+		return -ENODEV;
+	}
+	if (!IS_PHONEDEV(xpd)) {
+		XPD_ERR(xpd, "Not a phone device\n");
+		return -ENODEV;
+	}
+	channels = PHONEDEV(xpd).channels;
+	mask = simple_strtoul(buf, &endp, 0);
+	if (*endp != '\0' && *endp != '\n' && *endp != '\r') {
+		XPD_ERR(xpd, "Too many channels: %d\n", channels);
+		return -EINVAL;
+	}
+	if (mask != 0 && __ffs(mask) > channels) {
+		XPD_ERR(xpd,
+			"Channel mask (0x%lX) larger than available channels (%d)\n",
+			mask, channels);
+		return -EINVAL;
+	}
+	XPD_DBG(GENERAL, xpd, "ECHOCANCEL channels: 0x%lX\n", mask);
+	ret = CALL_PHONE_METHOD(echocancel_setmask, xpd, mask);
+	if (ret < 0) {
+		XPD_ERR(xpd, "echocancel_setmask failed\n");
+		return ret;
+	}
+	return count;
+}
+
+static	DEVICE_ATTR(echocancel, S_IRUGO | S_IWUSR, echocancel_show,
+		echocancel_store);
+
+int echocancel_xpd(xpd_t *xpd, int on)
+{
+	int ret;
+
+	XPD_DBG(GENERAL, xpd, "echocancel_xpd(%s)\n", (on) ? "on" : "off");
+	if (!on) {
+		device_remove_file(xpd->echocancel, &dev_attr_echocancel);
+		return 0;
+	}
+
+	ret = device_create_file(&xpd->xpd_dev, &dev_attr_echocancel);
+	if (ret)
+		XPD_ERR(xpd,
+			"%s: device_create_file(echocancel) failed: %d\n",
+			__func__, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL(echocancel_xpd);
+
 /*--------- Sysfs Device handling ----*/
 
 void xbus_sysfs_transport_remove(xbus_t *xbus)

Modified: linux/trunk/drivers/dahdi/xpp/xpd.h
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/xpd.h?view=diff&rev=9993&r1=9992&r2=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/xpd.h (original)
+++ linux/trunk/drivers/dahdi/xpp/xpd.h Tue Jun 28 13:23:00 2011
@@ -149,6 +149,8 @@
 	struct dahdi_span	span;
 	struct dahdi_chan	*chans[32];
 #define	XPD_CHAN(xpd,chan)	(PHONEDEV(xpd).chans[(chan)])
+	struct dahdi_echocan_state *ec[32];
+
 	int		channels;
 	xpd_direction_t	direction;		/* TO_PHONE, TO_PSTN */
 	xpp_line_t	no_pcm;			/* Temporary: disable PCM (for USB-1) */
@@ -198,6 +200,7 @@
 #define kref_to_xpd(k) container_of(k, struct xpd, kref)
 
 	xbus_t *xbus;			/* The XBUS we are connected to */
+	struct device	*echocancel;
 
 	spinlock_t	lock;
 

Modified: linux/trunk/drivers/dahdi/xpp/xpp_dahdi.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/xpp_dahdi.c?view=diff&rev=9993&r1=9992&r2=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/xpp_dahdi.c (original)
+++ linux/trunk/drivers/dahdi/xpp/xpp_dahdi.c Tue Jun 28 13:23:00 2011
@@ -463,6 +463,8 @@
 		if (phonedev->chans[x]) {
 			KZFREE(phonedev->chans[x]);
 		}
+		if (phonedev->ec[x])
+			KZFREE(phonedev->ec[x]);
 	}
 }
 
@@ -484,6 +486,13 @@
 	for (x = 0; x < phonedev->channels; x++) {
 		if (!(phonedev->chans[x] = KZALLOC(sizeof(*(phonedev->chans[x])), GFP_KERNEL))) {
 			ERR("%s: Unable to allocate channel %d\n", __FUNCTION__, x);
+			goto err;
+		}
+		phonedev->ec[x] = KZALLOC(sizeof(*(phonedev->ec[x])),
+				GFP_KERNEL);
+		if (!phonedev->ec[x]) {
+			ERR("%s: Unable to allocate ec state %d\n", __func__,
+					x);
 			goto err;
 		}
 	}
@@ -887,6 +896,86 @@
 }
 #endif
 
+/*
+ * Hardware Echo Canceller management
+ */
+static void echocan_free(struct dahdi_chan *chan,
+		struct dahdi_echocan_state *ec)
+{
+	xpd_t			*xpd;
+	xbus_t			*xbus;
+	int			pos = chan->chanpos - 1;
+	const struct echoops	*echoops;
+
+	xpd = chan->pvt;
+	xbus = xpd->xbus;
+	echoops = ECHOOPS(xbus);
+	if (!echoops)
+		return;
+	LINE_NOTICE(xpd, pos, "%s: mode=0x%X\n", __func__, ec->status.mode);
+	CALL_EC_METHOD(ec_set, xbus, xpd, pos, 0);
+	CALL_EC_METHOD(ec_update, xbus, xbus);
+}
+
+static const struct dahdi_echocan_features xpp_ec_features = {
+};
+
+static const struct dahdi_echocan_ops xpp_ec_ops = {
+	.echocan_free = echocan_free,
+};
+
+const char *xpp_echocan_name(const struct dahdi_chan *chan)
+{
+	xpd_t	*xpd;
+	xbus_t	*xbus;
+	int	pos;
+
+	if (!chan) {
+		NOTICE("%s(NULL)\n", __func__);
+		return "XPP";
+	}
+	xpd = chan->pvt;
+	xbus = xpd->xbus;
+	pos = chan->chanpos - 1;
+	LINE_DBG(GENERAL, xpd, pos, "%s:\n", __func__);
+	if (!ECHOOPS(xbus))
+		return NULL;
+	return "XPP";
+}
+EXPORT_SYMBOL(xpp_echocan_name);
+
+int xpp_echocan_create(struct dahdi_chan *chan,
+				struct dahdi_echocanparams *ecp,
+				struct dahdi_echocanparam *p,
+				struct dahdi_echocan_state **ec)
+{
+	xpd_t			*xpd;
+	xbus_t			*xbus;
+	int			pos;
+	struct phonedev		*phonedev;
+	const struct echoops	*echoops;
+	int			ret;
+
+	xpd = chan->pvt;
+	xbus = xpd->xbus;
+	pos = chan->chanpos - 1;
+	echoops = ECHOOPS(xbus);
+	if (!echoops)
+		return -ENODEV;
+	phonedev = &PHONEDEV(xpd);
+	*ec = phonedev->ec[pos];
+	(*ec)->ops = &xpp_ec_ops;
+	(*ec)->features = xpp_ec_features;
+	LINE_NOTICE(xpd, pos, "%s: (tap=%d, param_count=%d)\n",
+		__func__,
+		ecp->tap_length, ecp->param_count);
+	ret = CALL_EC_METHOD(ec_set, xbus, xpd, pos, 1);
+	CALL_EC_METHOD(ec_update, xbus, xbus);
+	return ret;
+}
+EXPORT_SYMBOL(xpp_echocan_create);
+
+
 /**
  * Unregister an xpd from dahdi and release related resources
  * @xpd The xpd to be unregistered
@@ -940,6 +1029,8 @@
 	.close = xpp_close,
 	.ioctl = xpp_ioctl,
 	.maint = xpp_maint,
+	.echocan_create = xpp_echocan_create,
+	.echocan_name = xpp_echocan_name,
 };
 
 static const struct dahdi_span_ops xpp_rbs_span_ops = {
@@ -949,6 +1040,8 @@
 	.close = xpp_close,
 	.ioctl = xpp_ioctl,
 	.maint = xpp_maint,
+	.echocan_create = xpp_echocan_create,
+	.echocan_name = xpp_echocan_name,
 };
 
 int dahdi_register_xpd(xpd_t *xpd)

Modified: linux/trunk/drivers/dahdi/xpp/xpp_dahdi.h
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/xpp_dahdi.h?view=diff&rev=9993&r1=9992&r2=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/xpp_dahdi.h (original)
+++ linux/trunk/drivers/dahdi/xpp/xpp_dahdi.h Tue Jun 28 13:23:00 2011
@@ -35,6 +35,11 @@
 void xpd_free(xpd_t *xpd);
 void xpd_remove(xpd_t *xpd);
 void update_xpd_status(xpd_t *xpd, int alarm_flag);
+const char *xpp_echocan_name(const struct dahdi_chan *chan);
+int xpp_echocan_create(struct dahdi_chan *chan,
+				struct dahdi_echocanparams *ecp,
+				struct dahdi_echocanparam *p,
+				struct dahdi_echocan_state **ec);
 void hookstate_changed(xpd_t *xpd, int pos, bool good);
 int xpp_open(struct dahdi_chan *chan);
 int xpp_close(struct dahdi_chan *chan);

Modified: linux/trunk/drivers/dahdi/xpp/xpp_debug
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/xpp_debug?view=diff&rev=9993&r1=9992&r2=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/xpp_debug (original)
+++ linux/trunk/drivers/dahdi/xpp/xpp_debug Tue Jun 28 13:23:00 2011
@@ -3,7 +3,7 @@
 # xpp_debug: Turn on/off debugging flags via /sys/module/*/parameters/debug
 #
 
-modules="xpp xpp_usb xpd_fxs xpd_fxo xpd_bri xpd_pri"
+modules="xpp xpp_usb xpd_fxs xpd_fxo xpd_bri xpd_pri xpd_echo"
 dbg_names="DEFAULT PCM LEDS SYNC SIGNAL PROC REGS DEVICES COMMANDS"
 
 usage() {

Modified: linux/trunk/drivers/dahdi/xpp/xproto.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/xproto.c?view=diff&rev=9993&r1=9992&r2=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/xproto.c (original)
+++ linux/trunk/drivers/dahdi/xpp/xproto.c Tue Jun 28 13:23:00 2011
@@ -455,6 +455,8 @@
 		CHECK_PHONEOP(phoneops, card_pcm_recompute);
 		CHECK_PHONEOP(phoneops, card_pcm_fromspan);
 		CHECK_PHONEOP(phoneops, card_pcm_tospan);
+		CHECK_PHONEOP(phoneops, echocancel_timeslot);
+		CHECK_PHONEOP(phoneops, echocancel_setmask);
 		CHECK_PHONEOP(phoneops, card_dahdi_preregistration);
 		CHECK_PHONEOP(phoneops, card_dahdi_postregistration);
 		/* optional method -- call after testing: */

Modified: linux/trunk/drivers/dahdi/xpp/xproto.h
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/xproto.h?view=diff&rev=9993&r1=9992&r2=9993
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/xproto.h (original)
+++ linux/trunk/drivers/dahdi/xpp/xproto.h Tue Jun 28 13:23:00 2011
@@ -78,6 +78,7 @@
 #define	XPD_TYPE_FXO		2	// TO_PSTN
 #define	XPD_TYPE_BRI		3	// TO_PSTN/TO_PHONE (from hardware)
 #define	XPD_TYPE_PRI		4	// TO_PSTN/TO_PHONE (runtime)
+#define	XPD_TYPE_ECHO		5	// Octasic echo canceller
 #define	XPD_TYPE_NOMODULE	7
 
 typedef	byte	xpd_type_t;
@@ -233,6 +234,8 @@
 	void (*card_pcm_recompute)(xpd_t *xpd, xpp_line_t pcm_mask);
 	void (*card_pcm_fromspan)(xpd_t *xpd, xpacket_t *pack);
 	void (*card_pcm_tospan)(xpd_t *xpd, xpacket_t *pack);
+	int (*echocancel_timeslot)(xpd_t *xpd, int pos);
+	int (*echocancel_setmask)(xpd_t *xpd, xpp_line_t ec_mask);
 	int (*card_timing_priority)(xpd_t *xpd);
 	int (*card_dahdi_preregistration)(xpd_t *xpd, bool on);
 	int (*card_dahdi_postregistration)(xpd_t *xpd, bool on);
@@ -265,6 +268,7 @@
 	xproto_entry_t		entries[256];	/* Indexed by opcode */
 	const struct xops	*xops;		/* Card level operations */
 	const struct phoneops	*phoneops;	/* DAHDI operations */
+	const struct echoops	*echoops;	/* Echo Canceller operations */
 	xpd_type_t	type;
 	byte		ports_per_subunit;
 	const char	*name;




More information about the svn-commits mailing list