dahdi_echocan_oslec.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * DAHDI Telephony Interface to the Open Source Line Echo Canceller (OSLEC)
  3. *
  4. * Written by Tzafrir Cohen <tzafrir.cohen@xorcom.com>
  5. * Copyright (C) 2008 Xorcom, Inc.
  6. *
  7. * All rights reserved.
  8. *
  9. * Based on dahdi_echocan_hpec.c, Copyright (C) 2006-2008 Digium, Inc.
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License version 2 as
  13. * published by the Free Software Foundation.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23. */
  24. #include <linux/kernel.h>
  25. #include <linux/slab.h>
  26. #include <linux/errno.h>
  27. #include <linux/module.h>
  28. #include <linux/init.h>
  29. #include <linux/ctype.h>
  30. #include <linux/moduleparam.h>
  31. /* Fix this if OSLEC is elsewhere */
  32. #include "../staging/echo/oslec.h"
  33. //#include <linux/oslec.h>
  34. #include <dahdi/kernel.h>
  35. static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
  36. struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec);
  37. static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);
  38. static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size);
  39. static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val);
  40. #ifdef CONFIG_DAHDI_ECHOCAN_PROCESS_TX
  41. static void echo_can_hpf_tx(struct dahdi_echocan_state *ec,
  42. short *tx, u32 size);
  43. #endif
  44. static const char *name = "OSLEC";
  45. static const char *ec_name(const struct dahdi_chan *chan) { return name; }
  46. static const struct dahdi_echocan_factory my_factory = {
  47. .get_name = ec_name,
  48. .owner = THIS_MODULE,
  49. .echocan_create = echo_can_create,
  50. };
  51. static const struct dahdi_echocan_ops my_ops = {
  52. .echocan_free = echo_can_free,
  53. .echocan_process = echo_can_process,
  54. .echocan_traintap = echo_can_traintap,
  55. #ifdef CONFIG_DAHDI_ECHOCAN_PROCESS_TX
  56. .echocan_process_tx = echo_can_hpf_tx,
  57. #endif
  58. };
  59. struct ec_pvt {
  60. struct oslec_state *oslec;
  61. struct dahdi_echocan_state dahdi;
  62. };
  63. #define dahdi_to_pvt(a) container_of(a, struct ec_pvt, dahdi)
  64. static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec)
  65. {
  66. struct ec_pvt *pvt = dahdi_to_pvt(ec);
  67. oslec_free(pvt->oslec);
  68. kfree(pvt);
  69. }
  70. static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size)
  71. {
  72. struct ec_pvt *pvt = dahdi_to_pvt(ec);
  73. u32 SampleNum;
  74. for (SampleNum = 0; SampleNum < size; SampleNum++, iref++) {
  75. short iCleanSample;
  76. iCleanSample = oslec_update(pvt->oslec, *iref, *isig);
  77. *isig++ = iCleanSample;
  78. }
  79. }
  80. static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
  81. struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec)
  82. {
  83. struct ec_pvt *pvt;
  84. if (ecp->param_count > 0) {
  85. printk(KERN_WARNING "OSLEC does not support parameters; failing request\n");
  86. return -EINVAL;
  87. }
  88. pvt = kzalloc(sizeof(*pvt), GFP_KERNEL);
  89. if (!pvt)
  90. return -ENOMEM;
  91. pvt->dahdi.ops = &my_ops;
  92. pvt->oslec = oslec_create(ecp->tap_length, ECHO_CAN_USE_ADAPTION | ECHO_CAN_USE_NLP | ECHO_CAN_USE_CLIP | ECHO_CAN_USE_TX_HPF | ECHO_CAN_USE_RX_HPF);
  93. if (!pvt->oslec) {
  94. kfree(pvt);
  95. *ec = NULL;
  96. return -ENOTTY;
  97. } else {
  98. *ec = &pvt->dahdi;
  99. return 0;
  100. }
  101. }
  102. static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val)
  103. {
  104. return 1;
  105. }
  106. #ifdef CONFIG_DAHDI_ECHOCAN_PROCESS_TX
  107. static void echo_can_hpf_tx(struct dahdi_echocan_state *ec, short *tx, u32 size)
  108. {
  109. struct ec_pvt *pvt = dahdi_to_pvt(ec);
  110. u32 SampleNum;
  111. for (SampleNum = 0; SampleNum < size; SampleNum++, tx++) {
  112. short iCleanSample;
  113. iCleanSample = oslec_hpf_tx(pvt->oslec, *tx);
  114. *tx = iCleanSample;
  115. }
  116. }
  117. #endif
  118. static int __init mod_init(void)
  119. {
  120. if (dahdi_register_echocan_factory(&my_factory)) {
  121. module_printk(KERN_ERR, "could not register with DAHDI core\n");
  122. return -EPERM;
  123. }
  124. module_printk(KERN_INFO, "Registered echo canceler '%s'\n",
  125. my_factory.get_name(NULL));
  126. return 0;
  127. }
  128. static void __exit mod_exit(void)
  129. {
  130. dahdi_unregister_echocan_factory(&my_factory);
  131. }
  132. MODULE_DESCRIPTION("DAHDI OSLEC wrapper");
  133. MODULE_AUTHOR("Tzafrir Cohen <tzafrir.cohen@xorcom.com>");
  134. MODULE_LICENSE("GPL");
  135. module_init(mod_init);
  136. module_exit(mod_exit);