summaryrefslogtreecommitdiff
path: root/drivers/dahdi/xpp/xbus-sysfs.c
diff options
context:
space:
mode:
authorTzafrir Cohen <tzafrir.cohen@xorcom.com>2011-06-28 18:23:00 +0000
committerTzafrir Cohen <tzafrir.cohen@xorcom.com>2011-06-28 18:23:00 +0000
commit71234e254b574d31d442703e04fdbdcba653010c (patch)
tree0a657a4e9601bc59dfa5fc40880492f69779b8e1 /drivers/dahdi/xpp/xbus-sysfs.c
parent1fa5fa9a723b314f72db9b52114eebf01111c5f0 (diff)
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@xorcom.com> Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9993 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/xpp/xbus-sysfs.c')
-rw-r--r--drivers/dahdi/xpp/xbus-sysfs.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/drivers/dahdi/xpp/xbus-sysfs.c b/drivers/dahdi/xpp/xbus-sysfs.c
index d983f17..daf16fc 100644
--- a/drivers/dahdi/xpp/xbus-sysfs.c
+++ b/drivers/dahdi/xpp/xbus-sysfs.c
@@ -807,6 +807,103 @@ void xpd_device_unregister(xpd_t *xpd)
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)