libsangoma  1
libsangoma_hwec.c
Go to the documentation of this file.
1 /*******************************************************************************/
33 #include "libsangoma.h"
34 #include "libsangoma-pvt.h"
35 #include "wanpipe_includes.h"
36 
37 #ifdef WP_API_FEATURE_LIBSNG_HWEC
38 
39 #include "wanpipe_events.h"
40 #include "wanec_api.h"
41 #include "wanec_iface_api.h"
42 
43 #if defined (__WINDOWS__)
44 # include "wanpipe_time.h" /* wp_sleep() */
45 # pragma comment( lib, "waneclib" ) /* import functions from waneclib.dll */
46 #endif/* __WINDOWS__) */
47 
48 static int libsng_hwec_verbosity_level = 0x00;
49 
50 /************************************************************/
54 static sangoma_status_t sangoma_hwec_bypass(char *device_name, int enable, unsigned int fe_chan_map)
55 {
57  wanec_api_hwec_t hwec;
58 
59  memset(&hwec, 0, sizeof(wanec_api_hwec_t));
60 
61  hwec.enable = enable;
62  hwec.fe_chan_map = fe_chan_map;
63 
64  /* WAN_EC_API_CMD_HWEC_ENABLE/WAN_EC_API_CMD_HWEC_DISABLE - Controls the "bypass" mode.)*/
65  rc = wanec_api_hwec(device_name, libsng_hwec_verbosity_level, &hwec);
66 
67  return rc;
68 }
69 
70 static int sangoma_hwec_is_numeric_parameter(char *parameter)
71 {
72  int i;
73  static char *WANEC_numeric_params[] = {
74  "WANEC_TailDisplacement",
75  "WANEC_MaxPlayoutBuffers",
76  "WANEC_MaxConfBridges",
77  "WANEC_EchoOperationMode",
78  "WANEC_ComfortNoiseMode",
79  "WANEC_NonLinearityBehaviorA",
80  "WANEC_NonLinearityBehaviorB",
81  "WANEC_DoubleTalkBehavior",
82  "WANEC_RinLevelControlGainDb",
83  "WANEC_SoutLevelControlGainDb",
84  "WANEC_RinAutomaticLevelControlTargetDb",
85  "WANEC_SoutAutomaticLevelControlTargetDb",
86  "WANEC_RinHighLevelCompensationThresholdDb",
87  "WANEC_AnrSnrEnhancementDb",
88  "WANEC_AecTailLength",
89  NULL
90  };
91 
92  i = 0;
93  while(WANEC_numeric_params[i]){
94  if (!wp_strncasecmp(parameter, WANEC_numeric_params[i], strlen(parameter))) {
95  return 1;/* this IS a numeric parameter */
96  }
97  i++;
98  };
99 
100  return 0;/* NOT a numeric parameter */
101 }
102 
103 static sangoma_status_t sangoma_hwec_ioctl(sng_fd_t fd, wan_ec_api_t *ec_api)
104 {
105  wanpipe_api_t tdm_api;
106  sangoma_status_t err;
107 
108  /* it is very important to zero out 'tdm_api' */
109  memset(&tdm_api, 0x00, sizeof(tdm_api));
110 
111  WANPIPE_API_INIT_CHAN((&tdm_api), ec_api->fe_chan);
113 
114  tdm_api.wp_cmd.cmd = WP_API_CMD_EC_IOCTL;
115 
116  tdm_api.wp_cmd.iovec_list.iovec_list[0].iov_base = ec_api;
117  tdm_api.wp_cmd.iovec_list.iovec_list[0].iov_len = sizeof(*ec_api);
118 
119  err = sangoma_cmd_exec(fd, &tdm_api);
120  if (err) {
121  DBG_HWEC("sangoma_cmd_exec() Failed: err %d !\n", err);
122  return err;
123  }
124 
125 #if 0
126  if (WAN_EC_API_RC_OK != ec_api->err) {
127 
128  /* IOCTL ok, but error in cmd - caller must check 'ec_api->err' */
129  switch(ec_api->err){
130  case WAN_EC_API_RC_INVALID_STATE:
131  DBG_HWEC("WP_API_CMD_EC_IOCTL Failed: Invalid State: %s !\n",
132  WAN_EC_STATE_DECODE(ec_api->state));
133  break;
134  case WAN_EC_API_RC_FAILED:
135  case WAN_EC_API_RC_INVALID_CMD:
136  case WAN_EC_API_RC_INVALID_DEV:
137  case WAN_EC_API_RC_BUSY:
138  case WAN_EC_API_RC_INVALID_CHANNELS:
139  case WAN_EC_API_RC_INVALID_PORT:
140  default:
141  DBG_HWEC("WP_API_CMD_EC_IOCTL Failed: %s !\n",
142  WAN_EC_API_RC_DECODE(ec_api->err));
143  break;
144  }
145  }
146 #endif
147 
148  return SANG_STATUS_SUCCESS;
149 }
150 
151 /***************************************************************
152  * Public Functions. (Exported)
153  ***************************************************************/
154 
166 void _LIBSNG_CALL sangoma_hwec_initialize_custom_parameter_structure(wan_custom_param_t *custom_param, char *parameter_name, char *parameter_value)
167 {
168  memset(custom_param, 0x00, sizeof(*custom_param));
169 
170  strncpy( custom_param->name, parameter_name, sizeof(custom_param->name) );
171 
172  if (sangoma_hwec_is_numeric_parameter(parameter_name)) {
173  custom_param->dValue = atoi(parameter_value);
174  } else {
175  strncpy(custom_param->sValue, parameter_value, sizeof(custom_param->sValue));
176  }
177 }
178 
215 sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name, wan_custom_param_t custom_params[], unsigned int number_of_custom_params)
216 {
218  wanec_api_config_t config;
219 
220  memset(&config, 0x00, sizeof(config));
221 
222  if (number_of_custom_params >= 1 && number_of_custom_params <= 4) {
223 
224  wan_custom_param_t *custom_parms_ptr;
225  unsigned int i, custom_params_memory_size;
226 
227  custom_params_memory_size = sizeof(wan_custom_param_t) * number_of_custom_params;
228 
229  /* Do NOT change memory at custom_params[] (it belongs to the caller).
230  * Instead allocate temporary buffer, and use information in custom_params[]
231  * for proper initialization the temproary buffer and
232  * and send if down to API driver. */
233  custom_parms_ptr = malloc(custom_params_memory_size);
234  if (!custom_parms_ptr) {
236  }
237 
238  memset(custom_parms_ptr, 0x00, custom_params_memory_size);
239 
240  for (i = 0; i < number_of_custom_params; i++) {
241 
242  strcpy( custom_parms_ptr[i].name, custom_params[i].name );
243 
244  if (sangoma_hwec_is_numeric_parameter(custom_params[i].name)) {
245  custom_parms_ptr[i].dValue = atoi(custom_params[i].sValue);
246  } else {
247  strcpy(custom_parms_ptr[i].sValue, custom_params[i].sValue);
248  }
249  } /* for() */
250 
251  config.conf.param_no = number_of_custom_params;
252  config.conf.params = custom_parms_ptr;
253 
254  }/* if() */
255 
256  /* Load firmware on EC chip AND apply configuration, if any. */
257  rc = wanec_api_config( device_name, libsng_hwec_verbosity_level, &config );
258 
259  if (config.conf.params) {
260  free(config.conf.params);
261  }
262 
263  return rc;
264 }
265 
266 
284 {
285  sangoma_status_t rc;
286  wanec_api_release_t release;
287 
288  memset(&release, 0, sizeof(wanec_api_release_t));
289 
290  rc = wanec_api_release( device_name, libsng_hwec_verbosity_level, &release );
291 
292  return rc;
293 }
294 
298 sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_operation_mode(char *device_name, int mode, unsigned int fe_chan_map)
299 {
300  sangoma_status_t rc;
301  wanec_api_opmode_t opmode;
302 
303  memset(&opmode, 0, sizeof(wanec_api_opmode_t));
304 
305  opmode.mode = mode;
306  opmode.fe_chan_map = fe_chan_map;
307 
308  /* modes are:
309  WANEC_API_OPMODE_NORMAL,
310  WANEC_API_OPMODE_HT_FREEZE,
311  WANEC_API_OPMODE_HT_RESET,
312  WANEC_API_OPMODE_POWER_DOWN,
313  WANEC_API_OPMODE_NO_ECHO,
314  WANEC_API_OPMODE_SPEECH_RECOGNITION.
315  */
316  rc = wanec_api_opmode(device_name, libsng_hwec_verbosity_level, &opmode);
317 
318  return rc;
319 }
320 
338 sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_power_on(char *device_name, unsigned int fe_chan_map)
339 {
340  return sangoma_hwec_config_operation_mode(device_name, WANEC_API_OPMODE_NORMAL, fe_chan_map);
341 }
342 
361 sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_power_off(char *device_name, unsigned int fe_chan_map)
362 {
363  return sangoma_hwec_config_operation_mode(device_name, WANEC_API_OPMODE_POWER_DOWN, fe_chan_map);
364 }
365 
389 sangoma_status_t _LIBSNG_CALL sangoma_hwec_enable(char *device_name, unsigned int fe_chan_map)
390 {
391  return sangoma_hwec_bypass(device_name, 1 /* enable */, fe_chan_map);
392 }
393 
394 
416 sangoma_status_t _LIBSNG_CALL sangoma_hwec_disable(char *device_name, unsigned int fe_chan_map)
417 {
418  return sangoma_hwec_bypass(device_name, 0 /* disable */, fe_chan_map);;
419 }
420 
464 sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameter(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map)
465 {
466  sangoma_status_t rc;
467  wanec_api_modify_t channelModify;
468  wan_custom_param_t custom_param;
469 
470  memset(&channelModify, 0x00, sizeof(channelModify));
471 
472  sangoma_hwec_initialize_custom_parameter_structure(&custom_param, parameter, parameter_value);
473 
474  channelModify.fe_chan_map = channel_map;
475  channelModify.conf.param_no = 1;
476  channelModify.conf.params = &custom_param;
477 
478  rc = wanec_api_modify( device_name, libsng_hwec_verbosity_level, &channelModify );
479 
480  return rc;
481 }
482 
505 sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_tone_detection(char *device_name, int tone_id, int enable, unsigned int fe_chan_map, unsigned char port_map)
506 {
507  sangoma_status_t rc;
508  wanec_api_tone_t tone;
509 
510  memset(&tone, 0, sizeof(wanec_api_tone_t));
511 
512  tone.id = tone_id;
513  tone.enable = enable;
514  tone.fe_chan_map = fe_chan_map;
515  tone.port_map = port_map;
516  tone.type_map = WAN_EC_TONE_PRESENT | WAN_EC_TONE_STOP;
517 
518  rc = wanec_api_tone( device_name, libsng_hwec_verbosity_level, &tone );
519 
520  return rc;
521 }
522 
541 sangoma_status_t _LIBSNG_CALL sangoma_hwec_print_statistics(char *device_name, int full, unsigned int fe_chan)
542 {
543  sangoma_status_t rc;
544  wanec_api_stats_t stats;
545 
546  memset(&stats, 0, sizeof(wanec_api_stats_t));
547 
548  stats.full = full;
549  stats.fe_chan = fe_chan;
550  stats.reset = 0; /* do not reset */
551 
552  rc = wanec_api_stats( device_name, libsng_hwec_verbosity_level, &stats );
553 
554  return rc;
555 }
556 
574 sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_load(char *device_name, char *filename, char pcmlaw, int *out_buffer_id)
575 {
576  sangoma_status_t rc;
577  wanec_api_bufferload_t bufferload;
578 
579  memset(&bufferload, 0, sizeof(wanec_api_bufferload_t));
580  *out_buffer_id = -1;
581 
582  bufferload.buffer = filename;
583  bufferload.pcmlaw = pcmlaw;
584 
585  rc = wanec_api_buffer_load( device_name, libsng_hwec_verbosity_level, &bufferload );
586  if( rc ) {
587  return rc;
588  }
589 
590  *out_buffer_id = bufferload.buffer_id;
591 
592  return SANG_STATUS_SUCCESS;
593 }
594 
605 sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_mem_buffer_load(char *device_name, unsigned char *buffer, unsigned int in_size, char pcmlaw, int *out_buffer_id)
606 {
607  sangoma_status_t rc;
608  wanec_api_membufferload_t bufferload;
609 
610  memset(&bufferload, 0, sizeof(bufferload));
611  *out_buffer_id = -1;
612 
613  bufferload.buffer = buffer;
614  bufferload.size = in_size;
615  bufferload.pcmlaw = pcmlaw;
616 
617  rc = wanec_api_mem_buffer_load( device_name, libsng_hwec_verbosity_level, &bufferload );
618  if( rc ) {
619  return rc;
620  }
621 
622  *out_buffer_id = bufferload.buffer_id;
623 
624  return SANG_STATUS_SUCCESS;
625 }
626 
638 sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_unload(char *device_name, int in_buffer_id)
639 {
640  sangoma_status_t rc;
641  wanec_api_bufferunload_t bufferunload;
642 
643  memset(&bufferunload, 0, sizeof(wanec_api_bufferunload_t));
644 
645  bufferunload.buffer_id = (unsigned int)in_buffer_id;
646 
647  rc = wanec_api_buffer_unload( device_name, libsng_hwec_verbosity_level, &bufferunload);
648 
649  return rc;
650 }
651 
677 sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_playout(char *device_name, unsigned int fe_chan_map,
678  unsigned char port, int in_buffer_id, int start,
679  int repeat_cnt, int duration)
680 {
681  sangoma_status_t rc;
682  wanec_api_playout_t playout;
683 
684  memset(&playout, 0, sizeof(wanec_api_playout_t));
685 
686  playout.start = start;
687  playout.fe_chan = fe_chan_map;
688  playout.buffer_id = in_buffer_id;
689  playout.port = port;
690  playout.notifyonstop = 1;
691  playout.user_event_id = 0xA5; /* dummy value */
692  playout.repeat_cnt = repeat_cnt;
693  playout.duration = (duration) ? duration : cOCT6100_INVALID_VALUE; /* default is no duration */
694 
695  rc = wanec_api_playout( device_name, libsng_hwec_verbosity_level, &playout);
696 
697  return rc;
698 }
699 
713 {
714  if (verbosity_level >= 0 || verbosity_level <= 3) {
715  libsng_hwec_verbosity_level = verbosity_level;
716  wanec_api_set_lib_verbosity(verbosity_level);
717  return SANG_STATUS_SUCCESS;
718  }
720 }
721 
743 sangoma_status_t _LIBSNG_CALL sangoma_hwec_get_channel_statistics(sng_fd_t fd, unsigned int fe_chan,
744  int *hwec_api_return_code, wanec_chan_stats_t *wanec_chan_stats, int verbose, int reset)
745 {
746  sangoma_status_t err;
747  wan_ec_api_t ec_api;
748 
749  memset(&ec_api, 0x00, sizeof(ec_api));
750 
751  ec_api.cmd = WAN_EC_API_CMD_STATS_FULL;
752 
753  ec_api.verbose = verbose;
754 
755  /* translate channel number into "single bit" bitmap */
756  ec_api.fe_chan_map = (1 << fe_chan);
757 
758  /* user may want to reset (clear) Channel statistics */
759  ec_api.u_chan_stats.reset = reset;
760 
761  err = sangoma_hwec_ioctl(fd, &ec_api);
762  if (err) {
763  /* error in IOCTL */
764  return err;
765  }
766 
767  /* copy stats from driver buffer to user buffer */
768  memcpy(wanec_chan_stats, &ec_api.u_chan_stats, sizeof(*wanec_chan_stats));
769 
770  *hwec_api_return_code = ec_api.err;
771 
772  return SANG_STATUS_SUCCESS;
773 }
774 
794  int *hwec_api_return_code, wanec_chip_stats_t *wanec_chip_stats, int verbose, int reset)
795 {
796 
797  sangoma_status_t err;
798  wan_ec_api_t ec_api;
799 
800  memset(&ec_api, 0x00, sizeof(ec_api));
801 
802  ec_api.cmd = WAN_EC_API_CMD_STATS_FULL;
803 
804  ec_api.verbose = verbose;
805 
806  /* indicate to Driver to get chip stats, not channel stats, by setting fe_chan_map to zero */
807  ec_api.fe_chan_map = 0;
808 
809  /* user may want to reset (clear) Chip statistics */
810  ec_api.u_chip_stats.reset = reset;
811 
812  err = sangoma_hwec_ioctl(fd, &ec_api);
813  if (err) {
814  /* error in IOCTL */
815  return err;
816  }
817 
818  /* copy stats from driver buffer to user buffer */
819  memcpy(wanec_chip_stats, &ec_api.u_chip_stats, sizeof(*wanec_chip_stats));
820 
821  *hwec_api_return_code = ec_api.err;
822 
823  return SANG_STATUS_SUCCESS;
824 
825 }
826 
844  int *hwec_api_return_code, wanec_chip_image_t *wanec_chip_image, int verbose)
845 {
846  sangoma_status_t err;
847  wan_ec_api_t ec_api;
848 
849  memset(&ec_api, 0x00, sizeof(ec_api));
850 
851  ec_api.cmd = WAN_EC_API_CMD_STATS_IMAGE;
852 
853  ec_api.verbose = verbose;
854 
855  /* driver will copy image information into wanec_chip_image->f_ChipImageInfo */
856  ec_api.u_chip_image.f_ChipImageInfo = wanec_chip_image->f_ChipImageInfo;
857 
858  err = sangoma_hwec_ioctl(fd, &ec_api);
859  if (err) {
860  /* error in IOCTL */
861  return err;
862  }
863 
864  *hwec_api_return_code = ec_api.err;
865 
866  return SANG_STATUS_SUCCESS;
867 }
868 
869 
889 sangoma_status_t _LIBSNG_CALL sangoma_hwec_set_hwdtmf_removal(sng_fd_t fd, unsigned int fe_chan,
890  int *hwec_api_return_code, int enable, int verbose)
891 {
892  sangoma_status_t err;
893  wan_ec_api_t ec_api;
894 
895  memset(&ec_api, 0x00, sizeof(ec_api));
896 
897  if (enable) {
898  ec_api.cmd = WAN_EC_API_CMD_HWDTMF_REMOVAL_ENABLE;
899  } else {
900  ec_api.cmd = WAN_EC_API_CMD_HWDTMF_REMOVAL_DISABLE;
901  }
902 
903  ec_api.verbose = verbose;
904 
905  /* translate channel number into "single bit" bitmap */
906  ec_api.fe_chan_map = (1 << fe_chan);
907 
908  err = sangoma_hwec_ioctl(fd, &ec_api);
909  if (err) {
910  /* error in IOCTL */
911  return err;
912  }
913 
914  *hwec_api_return_code = ec_api.err;
915 
916  return SANG_STATUS_SUCCESS;
917 }
918 
919 #endif /* WP_API_FEATURE_LIBSNG_HWEC */
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_power_off(char *device_name, unsigned int fe_chan_map)
Set the channel state in the echo canceller to POWER OFF. This disables echo cancellatio logic inside...
sangoma_status_t _LIBSNG_CALL sangoma_hwec_disable(char *device_name, unsigned int fe_chan_map)
Force AFT FPGA to bypass the echo canceller. This command effectively disables echo cancellation sinc...
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_operation_mode(char *device_name, int mode, unsigned int fe_chan_map)
Modify channel operation mode.
Wanpipe API Library header for Sangoma AFT T1/E1/Analog/BRI/Serial Hardware -.
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_release(char *device_name)
Release resources allocated by sangoma_hwec_config_init(). For single-port cards, such as A101 and A2...
sangoma_status_t _LIBSNG_CALL sangoma_hwec_get_chip_image_info(sng_fd_t fd, int *hwec_api_return_code, wanec_chip_image_t *wanec_chip_image, int verbose)
Get information about Firmware Image of EC chip.
sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_load(char *device_name, char *filename, char pcmlaw, int *out_buffer_id)
Load audio buffer to EC chip. The buffer can be played out using the sangoma_hwec_audio_buffer_playou...
sangoma_status_t _LIBSNG_CALL sangoma_hwec_get_global_chip_statistics(sng_fd_t fd, int *hwec_api_return_code, wanec_chip_stats_t *wanec_chip_stats, int verbose, int reset)
Get Global statistics from EC chip.
sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_playout(char *device_name, unsigned int fe_chan_map, unsigned char port, int in_buffer_id, int start, int repeat_cnt, int duration)
Start playing out an audio buffer previously loaded by sangoma_hwec_audio_buffer_load().
int _LIBSNG_CALL sangoma_cmd_exec(sng_fd_t fd, wanpipe_api_t *tdm_api)
Execute Sangoma API Command.
Definition: libsangoma.c:2004
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameter(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map)
Modify channel configuration parameters.
int sng_fd_t
Windows/Unix file handle abstraction.
sangoma_status_t _LIBSNG_CALL sangoma_hwec_print_statistics(char *device_name, int full, unsigned int fe_chan)
Read and print Chip/Channel statistics from EC chip.
#define SANGOMA_INIT_TDM_API_CMD_RESULT(_name_)
Initialize the &#39;result&#39; in wanpipe_api_t to SANG_STATUS_GENERAL_ERROR.
Definition: libsangoma.h:104
wanpipe_api_cmd_t wp_cmd
int32_t sangoma_status_t
return status from sangoma APIs
Definition: libsangoma.h:338
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_power_on(char *device_name, unsigned int fe_chan_map)
Set the channel state in the echo canceller to NORMAL/POWER ON. This enables echo cancelation logic i...
int start(sangoma_interface *sang_if)
Run the main sangoma interface hanlder code.
Definition: sample.cpp:153
#define _LIBSNG_CALL
Not used in Linux.
Definition: libsangoma.h:185
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name, wan_custom_param_t custom_params[], unsigned int number_of_custom_params)
Load Firmware image onto EC chip and allocated per-port resources in HWEC API. All chip-wide configur...
Wanpipe API Command Structure.
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_verbosity(int verbosity_level)
Set Verbosity level of EC API Driver and Library. The level controls amount of data printed to stdout...
void _LIBSNG_CALL sangoma_hwec_initialize_custom_parameter_structure(wan_custom_param_t *custom_param, char *parameter_name, char *parameter_value)
Initialize Custom Paramter structure.
sangoma_status_t _LIBSNG_CALL sangoma_hwec_enable(char *device_name, unsigned int fe_chan_map)
Redirect audio stream from AFT FPGA to EC chip. This command effectively enables echo cancellation si...
wan_iovec_t iovec_list[WAN_IOVEC_LIST_LEN]
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_tone_detection(char *device_name, int tone_id, int enable, unsigned int fe_chan_map, unsigned char port_map)
Enable/Disable tone detection (such as DTMF) of channels from channel map.