root/src/ftmod/ftmod_pika/ftmod_pika.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. FTDM_ENUM_NAMES
  2. pika_board_type_string
  3. FIO_CONFIGURE_FUNCTION
  4. media_out_callback
  5. pika_open_range
  6. FIO_CONFIGURE_SPAN_FUNCTION
  7. FIO_OPEN_FUNCTION
  8. FIO_CLOSE_FUNCTION
  9. FIO_WAIT_FUNCTION
  10. FIO_READ_FUNCTION
  11. FIO_WRITE_FUNCTION
  12. FIO_COMMAND_FUNCTION
  13. FIO_SPAN_POLL_EVENT_FUNCTION
  14. FIO_SPAN_NEXT_EVENT_FUNCTION
  15. FIO_SPAN_DESTROY_FUNCTION
  16. FIO_CHANNEL_DESTROY_FUNCTION
  17. FIO_GET_ALARMS_FUNCTION
  18. FIO_IO_LOAD_FUNCTION
  19. FIO_IO_UNLOAD_FUNCTION

   1 /*
   2  * Copyright (c) 2007, Anthony Minessale II
   3  * All rights reserved.
   4  * 
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 
   9  * * Redistributions of source code must retain the above copyright
  10  * notice, this list of conditions and the following disclaimer.
  11  * 
  12  * * Redistributions in binary form must reproduce the above copyright
  13  * notice, this list of conditions and the following disclaimer in the
  14  * documentation and/or other materials provided with the distribution.
  15  * 
  16  * * Neither the name of the original author; nor the names of any contributors
  17  * may be used to endorse or promote products derived from this software
  18  * without specific prior written permission.
  19  * 
  20  * 
  21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
  25  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  28  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  29  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  30  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32  */
  33 
  34 
  35 #include "freetdm.h"
  36 #include "ftdm_pika.h"
  37 
  38 
  39 #define MAX_NUMBER_OF_TRUNKS 64
  40 #define PIKA_BLOCK_SIZE 160
  41 #define PIKA_BLOCK_LEN 20
  42 #define PIKA_NUM_BUFFERS 8
  43 #define TRY_OR_DIE(__code, __status, __label) if ((status = __code ) != __status) goto __label
  44 #define pk_atof(__a) (PK_FLOAT) atof(__a)
  45 
  46 PK_VOID PK_CALLBACK media_out_callback(PKH_TPikaEvent *event);
  47 
  48 FTDM_ENUM_NAMES(PIKA_SPAN_NAMES, PIKA_SPAN_STRINGS)
  49 PIKA_STR2ENUM(pika_str2span, pika_span2str, PIKA_TSpanFraming, PIKA_SPAN_NAMES, PIKA_SPAN_INVALID)
  50 
  51 FTDM_ENUM_NAMES(PIKA_SPAN_ENCODING_NAMES, PIKA_SPAN_ENCODING_STRINGS)
  52 PIKA_STR2ENUM(pika_str2span_encoding, pika_span_encoding2str, PIKA_TSpanEncoding, PIKA_SPAN_ENCODING_NAMES, PIKA_SPAN_ENCODING_INVALID)
  53 
  54 FTDM_ENUM_NAMES(PIKA_LL_NAMES, PIKA_LL_STRINGS)
  55 PIKA_STR2ENUM(pika_str2loop_length, pika_loop_length2str, PIKA_TSpanLoopLength, PIKA_LL_NAMES, PIKA_SPAN_LOOP_INVALID)
  56 
  57 FTDM_ENUM_NAMES(PIKA_LBO_NAMES, PIKA_LBO_STRINGS)
  58 PIKA_STR2ENUM(pika_str2lbo, pika_lbo2str, PIKA_TSpanBuildOut, PIKA_LBO_NAMES, PIKA_SPAN_LBO_INVALID)
  59 
  60 FTDM_ENUM_NAMES(PIKA_SPAN_COMPAND_MODE_NAMES, PIKA_SPAN_COMPAND_MODE_STRINGS)
  61 PIKA_STR2ENUM(pika_str2compand_mode, pika_compand_mode2str, PIKA_TSpanCompandMode, PIKA_SPAN_COMPAND_MODE_NAMES, PIKA_SPAN_COMPAND_MODE_INVALID)
  62 
  63 
  64 typedef enum {
  65         PK_FLAG_READY = (1 << 0),
  66         PK_FLAG_LOCKED = (1 << 1)
  67 } pk_flag_t;
  68 
  69 struct general_config {
  70         uint32_t region;
  71 };
  72 typedef struct general_config general_config_t;
  73 
  74 struct pika_channel_profile {
  75         char name[80];
  76         PKH_TRecordConfig record_config;
  77         PKH_TPlayConfig play_config;
  78         int ec_enabled;
  79         PKH_TECConfig ec_config;
  80         PKH_TSpanConfig span_config;
  81         general_config_t general_config;
  82         int cust_span;
  83 };
  84 typedef struct pika_channel_profile pika_channel_profile_t;
  85 
  86 static struct {
  87         PKH_TSystemDeviceList board_list;
  88         TPikaHandle open_boards[MAX_NUMBER_OF_TRUNKS];
  89         TPikaHandle system_handle;
  90         PKH_TSystemConfig system_config;
  91         PKH_TRecordConfig record_config;
  92         PKH_TPlayConfig play_config;
  93         PKH_TECConfig ec_config;
  94         PKH_TSpanConfig t1_span_config;
  95         PKH_TSpanConfig e1_span_config;
  96         ftdm_hash_t *profile_hash;
  97         general_config_t general_config;
  98 } globals;
  99 
 100 
 101 struct pika_span_data {
 102         TPikaHandle event_queue;
 103         PKH_TPikaEvent last_oob_event;
 104         uint32_t boardno;
 105         PKH_TSpanConfig span_config;
 106         TPikaHandle handle;
 107         uint32_t flags;
 108 };
 109 typedef struct pika_span_data pika_span_data_t;
 110 
 111 struct pika_chan_data {
 112         TPikaHandle handle;
 113         TPikaHandle media_in;
 114         TPikaHandle media_out;
 115         TPikaHandle media_in_queue;
 116         TPikaHandle media_out_queue;
 117         PKH_TPikaEvent last_media_event;
 118         PKH_TPikaEvent last_oob_event;
 119         PKH_TRecordConfig record_config;
 120         PKH_TPlayConfig play_config;
 121         int ec_enabled;
 122         PKH_TECConfig ec_config;
 123         PKH_THDLCConfig hdlc_config;
 124         ftdm_buffer_t *digit_buffer;
 125         ftdm_mutex_t *digit_mutex;
 126         ftdm_size_t dtmf_len;
 127         uint32_t flags;
 128         uint32_t hdlc_bytes;
 129 };
 130 typedef struct pika_chan_data pika_chan_data_t;
 131 
 132 static const char *pika_board_type_string(PK_UINT type)
 133 {
 134         if (type == PKH_BOARD_TYPE_DIGITAL_GATEWAY) {
 135                 return "digital_gateway";
 136         }
 137 
 138         if (type == PKH_BOARD_TYPE_ANALOG_GATEWAY) {
 139                 return "analog_gateway";
 140         }
 141 
 142         return "unknown";
 143 }
 144 
 145 /**
 146  * \brief Process configuration variable for a pika profile
 147  * \param category Pika profile name
 148  * \param var Variable name
 149  * \param val Variable value
 150  * \param lineno Line number from configuration file (unused)
 151  * \return Success
 152  */
 153 static FIO_CONFIGURE_FUNCTION(pika_configure)
 154 {
 155         pika_channel_profile_t *profile = NULL;
 156         int ok = 1;
 157 
 158         if (!(profile = (pika_channel_profile_t *) hashtable_search(globals.profile_hash, (char *)category))) {
 159                 profile = ftdm_malloc(sizeof(*profile));
 160                 memset(profile, 0, sizeof(*profile));
 161                 ftdm_set_string(profile->name, category);
 162                 profile->ec_config = globals.ec_config;
 163                 profile->record_config = globals.record_config;
 164                 profile->play_config = globals.play_config;
 165                 hashtable_insert(globals.profile_hash, (void *)profile->name, profile, HASHTABLE_FLAG_NONE);
 166                 ftdm_log(FTDM_LOG_INFO, "creating profile [%s]\n", category);
 167         }
 168 
 169         if (!strcasecmp(var, "rx-gain")) {
 170                 profile->record_config.gain = pk_atof(val);
 171         } else if (!strcasecmp(var, "rx-agc-enabled")) {
 172                 profile->record_config.AGC.enabled = ftdm_true(val);
 173         } else if (!strcasecmp(var, "rx-agc-targetPower")) {
 174                 profile->record_config.AGC.targetPower = pk_atof(val);
 175         } else if (!strcasecmp(var, "rx-agc-minGain")) {
 176                 profile->record_config.AGC.minGain = pk_atof(val);
 177         } else if (!strcasecmp(var, "rx-agc-maxGain")) {
 178                 profile->record_config.AGC.maxGain = pk_atof(val);
 179         } else if (!strcasecmp(var, "rx-agc-attackRate")) {
 180                 profile->record_config.AGC.attackRate = atoi(val);
 181         } else if (!strcasecmp(var, "rx-agc-decayRate")) {
 182                 profile->record_config.AGC.decayRate = atoi(val);
 183         } else if (!strcasecmp(var, "rx-agc-speechThreshold")) {
 184                 profile->record_config.AGC.speechThreshold = pk_atof(val);
 185         } else if (!strcasecmp(var, "rx-vad-enabled")) {
 186                 profile->record_config.VAD.enabled = ftdm_true(val);
 187         } else if (!strcasecmp(var, "rx-vad-activationThreshold")) {
 188                 profile->record_config.VAD.activationThreshold = pk_atof(val);
 189         } else if (!strcasecmp(var, "rx-vad-activationDebounceTime")) {
 190                 profile->record_config.VAD.activationDebounceTime = atoi(val);
 191         } else if (!strcasecmp(var, "rx-vad-deactivationThreshold")) {
 192                 profile->record_config.VAD.deactivationThreshold = pk_atof(val);
 193         } else if (!strcasecmp(var, "rx-vad-deactivationDebounceTime")) {
 194                 profile->record_config.VAD.deactivationDebounceTime = atoi(val);
 195         } else if (!strcasecmp(var, "rx-vad-preSpeechBufferSize")) {
 196                 profile->record_config.VAD.preSpeechBufferSize = atoi(val);
 197         } else if (!strcasecmp(var, "tx-gain")) {
 198                 profile->play_config.gain = pk_atof(val);
 199         } else if (!strcasecmp(var, "tx-agc-enabled")) {
 200                 profile->play_config.AGC.enabled = ftdm_true(val);
 201         } else if (!strcasecmp(var, "tx-agc-targetPower")) {
 202                 profile->play_config.AGC.targetPower = pk_atof(val);
 203         } else if (!strcasecmp(var, "tx-agc-minGain")) {
 204                 profile->play_config.AGC.minGain = pk_atof(val);
 205         } else if (!strcasecmp(var, "tx-agc-maxGain")) {
 206                 profile->play_config.AGC.maxGain = pk_atof(val);
 207         } else if (!strcasecmp(var, "tx-agc-attackRate")) {
 208                 profile->play_config.AGC.attackRate = atoi(val);
 209         } else if (!strcasecmp(var, "tx-agc-decayRate")) {
 210                 profile->play_config.AGC.decayRate = atoi(val);
 211         } else if (!strcasecmp(var, "tx-agc-speechThreshold")) {
 212                 profile->play_config.AGC.speechThreshold = pk_atof(val);
 213         } else if (!strcasecmp(var, "ec-enabled")) {
 214                 profile->ec_enabled = ftdm_true(val);
 215         } else if (!strcasecmp(var, "ec-doubleTalkerThreshold")) {
 216                 profile->ec_config.doubleTalkerThreshold = pk_atof(val);
 217         } else if (!strcasecmp(var, "ec-speechPresentThreshold")) {
 218                 profile->ec_config.speechPresentThreshold = pk_atof(val);
 219         } else if (!strcasecmp(var, "ec-echoSuppressionThreshold")) {
 220                 profile->ec_config.echoSuppressionThreshold = pk_atof(val);
 221         } else if (!strcasecmp(var, "ec-echoSuppressionEnabled")) {
 222                 profile->ec_config.echoSuppressionEnabled = ftdm_true(val);
 223         } else if (!strcasecmp(var, "ec-comfortNoiseEnabled")) {
 224                 profile->ec_config.comfortNoiseEnabled = ftdm_true(val);
 225         } else if (!strcasecmp(var, "ec-adaptationModeEnabled")) {
 226                 profile->ec_config.adaptationModeEnabled = ftdm_true(val);
 227         } else if (!strcasecmp(var, "framing")) {
 228                 profile->span_config.framing = pika_str2span(val);
 229                 profile->cust_span++;
 230         } else if (!strcasecmp(var, "encoding")) {
 231                 profile->span_config.encoding = pika_str2span_encoding(val);
 232                 profile->cust_span++;
 233         } else if (!strcasecmp(var, "loopLength")) {
 234                 profile->span_config.loopLength = pika_str2loop_length(val);
 235                 profile->cust_span++;
 236         } else if (!strcasecmp(var, "buildOut")) {
 237                 profile->span_config.buildOut = pika_str2lbo(val);
 238                 profile->cust_span++;
 239         } else if (!strcasecmp(var, "compandMode")) {
 240                 profile->span_config.compandMode = pika_str2compand_mode(val);
 241                 profile->cust_span++;
 242         } else if (!strcasecmp(var, "region")) {
 243                 if (!strcasecmp(val, "eu")) {
 244                         profile->general_config.region = PKH_TRUNK_EU;
 245                 } else {
 246                         profile->general_config.region = PKH_TRUNK_NA;
 247                 }
 248         } else {
 249                 ok = 0;
 250         }
 251 
 252         if (ok) {
 253                 ftdm_log(FTDM_LOG_INFO, "setting param [%s]=[%s] for profile [%s]\n", var, val, category);
 254         } else {
 255                 ftdm_log(FTDM_LOG_ERROR, "unknown param [%s]\n", var);
 256         }
 257 
 258         return FTDM_SUCCESS;
 259 }
 260 
 261 /**
 262  * \brief Pika event handler
 263  * \param event Pika event
 264  */
 265 PK_VOID PK_CALLBACK media_out_callback(PKH_TPikaEvent *event)
 266 {
 267         PK_STATUS pk_status;
 268         ftdm_channel_t *ftdmchan = event->userData;
 269         pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data;
 270 
 271         //PK_CHAR event_text[PKH_EVENT_MAX_NAME_LENGTH];
 272         //PKH_EVENT_GetText(event->id, event_text, sizeof(event_text));
 273         //ftdm_log(FTDM_LOG_DEBUG, "Event: %s\n", event_text);
 274         
 275         switch (event->id) {
 276         case PKH_EVENT_PLAY_IDLE:
 277                 {
 278                         while (ftdm_buffer_inuse(chan_data->digit_buffer)) {
 279                                 char dtmf[128] = "";
 280                                 ftdm_mutex_lock(chan_data->digit_mutex);
 281                                 chan_data->dtmf_len = ftdm_buffer_read(chan_data->digit_buffer, dtmf, sizeof(dtmf));
 282                                 pk_status = PKH_TG_PlayDTMF(chan_data->media_out, dtmf);
 283                                 ftdm_mutex_unlock(chan_data->digit_mutex);
 284                         }
 285                 }
 286                 break;
 287         case PKH_EVENT_TG_TONE_PLAYED:
 288                 {
 289 
 290                         if (!event->p1) {
 291                                 ftdm_mutex_lock(chan_data->digit_mutex);
 292                                 PKH_PLAY_Start(chan_data->media_out);
 293                                 chan_data->dtmf_len = 0;
 294                                 ftdm_mutex_unlock(chan_data->digit_mutex);
 295                         }
 296 
 297                                 
 298                 }
 299                 break;
 300         default:
 301                 break;
 302         }
 303 
 304 }
 305 
 306 /**
 307  * \brief Initialises a range of pika channels
 308  * \param span FreeTDM span
 309  * \param boardno Pika board number
 310  * \param spanno Pika span number
 311  * \param start Initial pika channel number
 312  * \param end Final pika channel number
 313  * \param type FreeTDM channel type
 314  * \param name FreeTDM span name
 315  * \param number FreeTDM span number
 316  * \param profile Pika channel profile
 317  * \return number of spans configured
 318  */
 319 static unsigned pika_open_range(ftdm_span_t *span, unsigned boardno, unsigned spanno, unsigned start, unsigned end, 
 320                                                                 ftdm_chan_type_t type, char *name, char *number, pika_channel_profile_t *profile)
 321 {
 322         unsigned configured = 0, x;
 323         PK_STATUS status;
 324         PK_CHAR error_text[PKH_ERROR_MAX_NAME_LENGTH];
 325         pika_span_data_t *span_data;
 326 
 327         if (boardno >= globals.board_list.numberOfBoards) {
 328                 ftdm_log(FTDM_LOG_ERROR, "Board %u is not present!\n", boardno);
 329                 return 0;
 330         }
 331 
 332         if (!globals.open_boards[boardno]) {
 333                 status = PKH_BOARD_Open(globals.board_list.board[boardno].id,
 334                                                                 NULL,
 335                                                                 &globals.open_boards[boardno]);
 336                 if(status != PK_SUCCESS) {
 337                         ftdm_log(FTDM_LOG_ERROR, "Error: PKH_BOARD_Open %d failed(%s)!\n",  boardno,
 338                                         PKH_ERROR_GetText(status, error_text, sizeof(error_text)));
 339                         return 0;
 340                 }
 341 
 342                 ftdm_log(FTDM_LOG_DEBUG, "Open board %u\n",  boardno);
 343 
 344                 //PKH_BOARD_SetDebugTrace(globals.open_boards[boardno], 1, 0);
 345                 
 346         }
 347 
 348         if (span->io_data) {
 349                 span_data = span->io_data;
 350         } else {
 351                 span_data = ftdm_malloc(sizeof(*span_data));
 352                 assert(span_data != NULL);
 353                 memset(span_data, 0, sizeof(*span_data));
 354                 span_data->boardno = boardno;
 355                 
 356                 status = PKH_QUEUE_Create(PKH_QUEUE_TYPE_NORMAL, &span_data->event_queue);
 357                 
 358                 if (status != PK_SUCCESS) {
 359                         ftdm_log(FTDM_LOG_ERROR, "Error: PKH_QUEUE_Create failed(%s)!\n",
 360                                         PKH_ERROR_GetText(status, error_text, sizeof(error_text)));
 361                         ftdm_safe_free(span_data);
 362                         return 0;
 363                 }
 364 
 365                 //PKH_QUEUE_Attach(span_data->event_queue, globals.open_boards[boardno], NULL);
 366 
 367                 span->io_data = span_data;
 368         }
 369 
 370         if (type == FTDM_CHAN_TYPE_FXS || type == FTDM_CHAN_TYPE_FXO) {
 371                 start--;
 372                 end--;
 373         }
 374 
 375         for(x = start; x < end; x++) {
 376                 ftdm_channel_t *chan;
 377                 pika_chan_data_t *chan_data = NULL;
 378 
 379                 chan_data = ftdm_malloc(sizeof *chan_data);
 380                 assert(chan_data);
 381                 memset(chan_data, 0, sizeof(*chan_data));
 382                 ftdm_span_add_channel(span, 0, type, &chan);
 383                 chan->io_data = chan_data;
 384 
 385                 if ((type == FTDM_CHAN_TYPE_B || type == FTDM_CHAN_TYPE_DQ921) && !span_data->handle) {
 386                         PKH_TBoardConfig boardConfig;
 387                         
 388                         TRY_OR_DIE(PKH_BOARD_GetConfig(globals.open_boards[boardno], &boardConfig), PK_SUCCESS, error);
 389                         if ((profile && profile->general_config.region == PKH_TRUNK_EU) || ftdm_test_flag(span_data, PK_FLAG_LOCKED)) {
 390                                 if (span->trunk_type == FTDM_TRUNK_T1) {
 391                                         ftdm_log(FTDM_LOG_WARNING, "Changing trunk type to E1 based on previous config.\n");
 392                                 }
 393                                 span->trunk_type = FTDM_TRUNK_E1;
 394                         }
 395 
 396                         if (span->trunk_type == FTDM_TRUNK_T1) {
 397                                 if (ftdm_test_flag(span_data, PK_FLAG_LOCKED)) {
 398                                         ftdm_log(FTDM_LOG_WARNING, "Already locked into E1 mode!\n");
 399                                 }
 400                         } else if (span->trunk_type == FTDM_TRUNK_E1) {
 401                                 boardConfig.specific.DigitalGateway.interfaceType = PKH_BOARD_INTERFACE_TYPE_E1;
 402                                 if ((status = PKH_BOARD_SetConfig(globals.open_boards[boardno], &boardConfig)) != PK_SUCCESS) {
 403                                         ftdm_log(FTDM_LOG_ERROR, "Error: [%s]\n",
 404                                                         PKH_ERROR_GetText(status, error_text, sizeof(error_text)));
 405                                 }
 406                                 ftdm_set_flag(span_data, PK_FLAG_LOCKED);
 407                         }
 408                         
 409                         TRY_OR_DIE(PKH_SPAN_Open(globals.open_boards[boardno], spanno, NULL, &span_data->handle), PK_SUCCESS, error);
 410                         TRY_OR_DIE(PKH_SPAN_GetConfig(span_data->handle, &span_data->span_config), PK_SUCCESS, error);
 411                         TRY_OR_DIE(PKH_QUEUE_Attach(span_data->event_queue, span_data->handle, (PK_VOID*) span), PK_SUCCESS, error);
 412                 }
 413 
 414                 if (type == FTDM_CHAN_TYPE_FXO) {
 415                         PKH_TTrunkConfig trunkConfig;
 416                         
 417                         TRY_OR_DIE(PKH_TRUNK_Open(globals.open_boards[boardno], x, &chan_data->handle), PK_SUCCESS, error);
 418                         TRY_OR_DIE(PKH_TRUNK_Seize(chan_data->handle), PK_SUCCESS, error);
 419 
 420                         if (profile && profile->general_config.region == PKH_TRUNK_EU) {
 421                                 TRY_OR_DIE(PKH_TRUNK_GetConfig(chan_data->handle, &trunkConfig), PK_SUCCESS, error);
 422                                 trunkConfig.internationalControl = PKH_PHONE_INTERNATIONAL_CONTROL_EU;
 423                                 trunkConfig.audioFormat = PKH_AUDIO_ALAW;
 424                                 trunkConfig.compandMode = PKH_PHONE_AUDIO_ALAW;
 425                                 chan->native_codec = chan->effective_codec = FTDM_CODEC_ALAW;
 426                                 TRY_OR_DIE(PKH_TRUNK_SetConfig(chan_data->handle, &trunkConfig), PK_SUCCESS, error);
 427                         } else {
 428                                 chan->native_codec = chan->effective_codec = FTDM_CODEC_ULAW;
 429                         }
 430 
 431                         
 432                         TRY_OR_DIE(PKH_QUEUE_Attach(span_data->event_queue, chan_data->handle, (PK_VOID*) chan), PK_SUCCESS, error);
 433                         TRY_OR_DIE(PKH_TRUNK_GetMediaStreams(chan_data->handle, &chan_data->media_in, &chan_data->media_out), PK_SUCCESS, error);
 434                         TRY_OR_DIE(PKH_QUEUE_Create(PKH_QUEUE_TYPE_NORMAL, &chan_data->media_in_queue), PK_SUCCESS, error);
 435                         TRY_OR_DIE(PKH_QUEUE_Attach(chan_data->media_in_queue, chan_data->media_in, (PK_VOID*) chan), PK_SUCCESS, error);
 436                         TRY_OR_DIE(PKH_QUEUE_Create(PKH_QUEUE_TYPE_CALLBACK, &chan_data->media_out_queue), PK_SUCCESS, error);
 437                         TRY_OR_DIE(PKH_QUEUE_SetEventHandler(chan_data->media_out_queue, media_out_callback), PK_SUCCESS, error);
 438                         TRY_OR_DIE(PKH_QUEUE_Attach(chan_data->media_out_queue, chan_data->media_out, (PK_VOID*) chan), PK_SUCCESS, error);
 439                         TRY_OR_DIE(PKH_TRUNK_Start(chan_data->handle), PK_SUCCESS, error);
 440                 } else if (type == FTDM_CHAN_TYPE_FXS) {
 441                         PKH_TPhoneConfig phoneConfig;
 442 
 443                         if (profile && profile->general_config.region == PKH_TRUNK_EU) {
 444                                 TRY_OR_DIE(PKH_PHONE_GetConfig(chan_data->handle, &phoneConfig), PK_SUCCESS, error);
 445                                 phoneConfig.internationalControl = PKH_PHONE_INTERNATIONAL_CONTROL_EU;
 446                                 phoneConfig.compandMode = PKH_PHONE_AUDIO_ALAW;
 447                                 chan->native_codec = chan->effective_codec = FTDM_CODEC_ALAW;
 448                                 TRY_OR_DIE(PKH_PHONE_SetConfig(chan_data->handle, &phoneConfig), PK_SUCCESS, error);
 449                         } else {
 450                                 chan->native_codec = chan->effective_codec = FTDM_CODEC_ULAW;
 451                         }
 452 
 453                         TRY_OR_DIE(PKH_PHONE_Open(globals.open_boards[boardno], x, &chan_data->handle), PK_SUCCESS, error);
 454                         TRY_OR_DIE(PKH_PHONE_Seize(chan_data->handle), PK_SUCCESS, error);
 455                         TRY_OR_DIE(PKH_PHONE_GetMediaStreams(chan_data->handle, &chan_data->media_in, &chan_data->media_out), PK_SUCCESS, error);
 456                         TRY_OR_DIE(PKH_QUEUE_Attach(span_data->event_queue, chan_data->handle, (PK_VOID*) chan), PK_SUCCESS, error);
 457                         TRY_OR_DIE(PKH_QUEUE_Create(PKH_QUEUE_TYPE_NORMAL, &chan_data->media_in_queue), PK_SUCCESS, error);
 458                         TRY_OR_DIE(PKH_QUEUE_Attach(chan_data->media_in_queue, chan_data->media_in, (PK_VOID*) chan), PK_SUCCESS, error);
 459                         TRY_OR_DIE(PKH_QUEUE_Create(PKH_QUEUE_TYPE_CALLBACK, &chan_data->media_out_queue), PK_SUCCESS, error);
 460                         TRY_OR_DIE(PKH_QUEUE_SetEventHandler(chan_data->media_out_queue, media_out_callback), PK_SUCCESS, error);
 461                         TRY_OR_DIE(PKH_QUEUE_Attach(chan_data->media_out_queue, chan_data->media_out, (PK_VOID*) chan), PK_SUCCESS, error);
 462                         TRY_OR_DIE(PKH_PHONE_Start(chan_data->handle), PK_SUCCESS, error);
 463                 } else if (type == FTDM_CHAN_TYPE_B) {
 464                         TRY_OR_DIE(PKH_SPAN_SeizeChannel(span_data->handle, x), PK_SUCCESS, error);
 465                         TRY_OR_DIE(PKH_SPAN_GetMediaStreams(span_data->handle, x, &chan_data->media_in, &chan_data->media_out), PK_SUCCESS, error);
 466                         TRY_OR_DIE(PKH_QUEUE_Create(PKH_QUEUE_TYPE_NORMAL, &chan_data->media_in_queue), PK_SUCCESS, error);
 467                         TRY_OR_DIE(PKH_QUEUE_Attach(chan_data->media_in_queue, chan_data->media_in, (PK_VOID*) chan), PK_SUCCESS, error);
 468                         TRY_OR_DIE(PKH_QUEUE_Create(PKH_QUEUE_TYPE_CALLBACK, &chan_data->media_out_queue), PK_SUCCESS, error);
 469                         TRY_OR_DIE(PKH_QUEUE_SetEventHandler(chan_data->media_out_queue, media_out_callback), PK_SUCCESS, error);
 470                         TRY_OR_DIE(PKH_QUEUE_Attach(chan_data->media_out_queue, chan_data->media_out, (PK_VOID*) chan), PK_SUCCESS, error);
 471                 } else if (type == FTDM_CHAN_TYPE_DQ921) {
 472                         TRY_OR_DIE(PKH_SPAN_HDLC_Open(span_data->handle, PKH_SPAN_HDLC_MODE_NORMAL, &chan_data->handle), PK_SUCCESS, error);
 473                         TRY_OR_DIE(PKH_SPAN_HDLC_GetConfig(chan_data->handle, &chan_data->hdlc_config), PK_SUCCESS, error);
 474                         chan_data->hdlc_config.channelId = x;
 475                         TRY_OR_DIE(PKH_SPAN_HDLC_SetConfig(chan_data->handle, &chan_data->hdlc_config), PK_SUCCESS, error);
 476                         TRY_OR_DIE(PKH_QUEUE_Create(PKH_QUEUE_TYPE_NORMAL, &chan_data->media_in_queue), PK_SUCCESS, error);
 477                         TRY_OR_DIE(PKH_QUEUE_Attach(chan_data->media_in_queue, chan_data->handle, (PK_VOID*) chan), PK_SUCCESS, error);
 478                         TRY_OR_DIE(PKH_QUEUE_Attach(span_data->event_queue, chan_data->handle, (PK_VOID*) chan), PK_SUCCESS, error);
 479 
 480                         if (profile) {
 481                                 if (profile->cust_span) {
 482                                         span_data->span_config.framing = profile->span_config.framing;
 483                                         span_data->span_config.encoding = profile->span_config.encoding;
 484                                         span_data->span_config.loopLength = profile->span_config.loopLength;
 485                                         span_data->span_config.buildOut = profile->span_config.buildOut;
 486                                         span_data->span_config.compandMode = profile->span_config.compandMode;
 487                                 } else {
 488                                         if (profile->general_config.region == PKH_TRUNK_EU) {
 489                                                 span_data->span_config = globals.e1_span_config;
 490                                         } else {
 491                                                 span_data->span_config = globals.t1_span_config;
 492                                         }
 493                                 }
 494                         } else {
 495                                 if (span->trunk_type == FTDM_TRUNK_E1) {
 496                                         span_data->span_config = globals.e1_span_config;
 497                                 } else {
 498                                         span_data->span_config = globals.t1_span_config;
 499                                 }
 500                         }
 501                         
 502                         PKH_SPAN_SetConfig(span_data->handle, &span_data->span_config);
 503                         TRY_OR_DIE(PKH_SPAN_Start(span_data->handle), PK_SUCCESS, error);
 504                 }
 505                 
 506                 goto ok;
 507 
 508         error:
 509                 PKH_ERROR_GetText(status, error_text, sizeof(error_text));
 510                 ftdm_log(FTDM_LOG_ERROR, "failure configuring device b%ds%dc%d [%s]\n", boardno, spanno, x, error_text);
 511                 continue;
 512         ok:
 513                 ftdm_set_flag(chan_data, PK_FLAG_READY);
 514                 status = PKH_RECORD_GetConfig(chan_data->media_in, &chan_data->record_config);
 515                 chan_data->record_config.encoding = PKH_RECORD_ENCODING_MU_LAW;
 516                 chan_data->record_config.samplingRate = PKH_RECORD_SAMPLING_RATE_8KHZ;
 517                 chan_data->record_config.bufferSize = PIKA_BLOCK_SIZE;
 518                 chan_data->record_config.numberOfBuffers = PIKA_NUM_BUFFERS;
 519                 chan_data->record_config.VAD.enabled = PK_FALSE;
 520                 //chan_data->record_config.speechSegmentEventsEnabled = PK_FALSE;
 521                 //chan_data->record_config.gain = rxgain;
 522 
 523                 status = PKH_PLAY_GetConfig(chan_data->media_out, &chan_data->play_config);
 524                 chan_data->play_config.encoding = PKH_RECORD_ENCODING_MU_LAW;
 525                 chan_data->play_config.samplingRate = PKH_RECORD_SAMPLING_RATE_8KHZ;
 526                 chan_data->play_config.AGC.enabled = PK_FALSE;
 527                 ftdm_log(FTDM_LOG_INFO, "configuring device b%ds%dc%d as FreeTDM device %d:%d\n", boardno, spanno, x, chan->span_id, chan->chan_id);
 528 
 529                 if (profile) {
 530                         ftdm_log(FTDM_LOG_INFO, "applying config profile %s to device %d:%d\n", profile->name, chan->span_id, chan->chan_id);
 531                         chan_data->record_config.gain = profile->record_config.gain;
 532                         chan_data->record_config.AGC = profile->record_config.AGC;
 533                         chan_data->record_config.VAD = profile->record_config.VAD;
 534                         chan_data->play_config.gain = profile->play_config.gain;
 535                         chan_data->play_config.AGC = profile->play_config.AGC;
 536                         chan_data->ec_enabled = profile->ec_enabled;
 537                         chan_data->ec_config = profile->ec_config;
 538                 }
 539                 
 540                 if (type == FTDM_CHAN_TYPE_B) {
 541                         if (span_data->span_config.compandMode == PKH_SPAN_COMPAND_MODE_A_LAW) {
 542                                 chan->native_codec = chan->effective_codec = FTDM_CODEC_ALAW;
 543                         } else {
 544                                 chan->native_codec = chan->effective_codec = FTDM_CODEC_ULAW;
 545                         }
 546                 }
 547 
 548                 status = PKH_RECORD_SetConfig(chan_data->media_in, &chan_data->record_config);
 549                 status = PKH_PLAY_SetConfig(chan_data->media_out, &chan_data->play_config);
 550 
 551                 chan->physical_span_id = spanno;
 552                 chan->physical_chan_id = x;
 553 
 554                 chan->rate = 8000;
 555                 chan->packet_len = (uint32_t)chan_data->record_config.bufferSize;
 556                 chan->effective_interval = chan->native_interval = chan->packet_len / 8;
 557 
 558                 PKH_RECORD_Start(chan_data->media_in);
 559                 PKH_PLAY_Start(chan_data->media_out);
 560                 if (chan_data->ec_enabled) {
 561                         PKH_EC_SetConfig(chan_data->media_in, &chan_data->ec_config);
 562                         PKH_EC_Start(chan_data->media_in, chan_data->media_in, chan_data->media_out);
 563                 }
 564 
 565                 if (!ftdm_strlen_zero(name)) {
 566                         ftdm_copy_string(chan->chan_name, name, sizeof(chan->chan_name));
 567                 }
 568                 
 569                 if (!ftdm_strlen_zero(number)) {
 570                         ftdm_copy_string(chan->chan_number, number, sizeof(chan->chan_number));
 571                 }
 572 
 573                 ftdm_channel_set_feature(chan, FTDM_CHANNEL_FEATURE_DTMF_GENERATE);
 574                 ftdm_buffer_create(&chan_data->digit_buffer, 128, 128, 0);
 575                 ftdm_mutex_create(&chan_data->digit_mutex);
 576 
 577                 configured++;
 578         } 
 579 
 580         
 581         return configured;
 582 }
 583 
 584 /**
 585  * \brief Initialises an freetdm pika span from a configuration string
 586  * \param span FreeTDM span
 587  * \param str Configuration string
 588  * \param type FreeTDM span type
 589  * \param name FreeTDM span name
 590  * \param number FreeTDM span number
 591  * \return Success or failure
 592  */
 593 static FIO_CONFIGURE_SPAN_FUNCTION(pika_configure_span)
 594 {
 595         int items, i;
 596     char *mydata, *item_list[10];
 597         char *bd, *sp, *ch = NULL, *mx;
 598         int boardno;
 599         int channo;
 600         int spanno;
 601         int top = 0;
 602         unsigned configured = 0;
 603         char *profile_name = NULL;
 604         pika_channel_profile_t *profile = NULL;
 605 
 606         assert(str != NULL);
 607 
 608         mydata = ftdm_strdup(str);
 609         assert(mydata != NULL);
 610 
 611         if ((profile_name = strchr(mydata, '@'))) {
 612                 *profile_name++ = '\0';
 613                 if (!ftdm_strlen_zero(profile_name)) {
 614                         profile = (pika_channel_profile_t *) hashtable_search(globals.profile_hash, (char *)profile_name);
 615                 }
 616         }
 617                 
 618         items = ftdm_separate_string(mydata, ',', item_list, (sizeof(item_list) / sizeof(item_list[0])));
 619 
 620         for(i = 0; i < items; i++) {
 621                 bd = item_list[i];
 622                 if ((sp = strchr(bd, ':'))) {
 623                         *sp++ = '\0';
 624                         if ((ch = strchr(sp, ':'))) {
 625                                 *ch++ = '\0';
 626                         }
 627                 }
 628                 
 629                 if (!(bd && sp && ch)) {
 630                         ftdm_log(FTDM_LOG_ERROR, "Invalid input\n");
 631                         continue;
 632                 }
 633 
 634                 boardno = atoi(bd);
 635                 channo = atoi(ch);
 636                 spanno = atoi(sp);
 637 
 638 
 639                 if (boardno < 0) {
 640                         ftdm_log(FTDM_LOG_ERROR, "Invalid board number %d\n", boardno);
 641                         continue;
 642                 }
 643 
 644                 if (channo < 0) {
 645                         ftdm_log(FTDM_LOG_ERROR, "Invalid channel number %d\n", channo);
 646                         continue;
 647                 }
 648 
 649                 if (spanno < 0) {
 650                         ftdm_log(FTDM_LOG_ERROR, "Invalid span number %d\n", channo);
 651                         continue;
 652                 }
 653                 
 654                 if ((mx = strchr(ch, '-'))) {
 655                         mx++;
 656                         top = atoi(mx) + 1;
 657                 } else {
 658                         top = channo + 1;
 659                 }
 660                 
 661                 
 662                 if (top < 0) {
 663                         ftdm_log(FTDM_LOG_ERROR, "Invalid range number %d\n", top);
 664                         continue;
 665                 }
 666 
 667                 configured += pika_open_range(span, boardno, spanno, channo, top, type, name, number, profile);
 668 
 669         }
 670         
 671         ftdm_safe_free(mydata);
 672 
 673         return configured;
 674 }
 675 
 676 /**
 677  * \brief Opens Pika channel
 678  * \param ftdmchan Channel to open
 679  * \return Success or failure
 680  */
 681 static FIO_OPEN_FUNCTION(pika_open) 
 682 {
 683         pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data;
 684 
 685         if (!chan_data && !ftdm_test_flag(chan_data, PK_FLAG_READY)) {
 686                 return FTDM_FAIL;
 687         }
 688 
 689         if (chan_data->media_in_queue) {
 690                 PKH_QUEUE_Flush(chan_data->media_in_queue);
 691         }
 692 
 693         if (ftdmchan->type == FTDM_CHAN_TYPE_FXS || ftdmchan->type == FTDM_CHAN_TYPE_FXO || ftdmchan->type == FTDM_CHAN_TYPE_B) {
 694                 PKH_PLAY_Start(chan_data->media_out);
 695         }
 696         return FTDM_SUCCESS;
 697 }
 698 
 699 /**
 700  * \brief Closes Pika channel
 701  * \param ftdmchan Channel to close
 702  * \return Success
 703  */
 704 static FIO_CLOSE_FUNCTION(pika_close)
 705 {
 706         return FTDM_SUCCESS;
 707 }
 708 
 709 /**
 710  * \brief Waits for an event on a Pika channel
 711  * \param ftdmchan Channel to open
 712  * \param flags Type of event to wait for
 713  * \param to Time to wait (in ms)
 714  * \return Success, failure or timeout
 715  */
 716 static FIO_WAIT_FUNCTION(pika_wait)
 717 {
 718         pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data;
 719         PK_STATUS status;
 720         ftdm_wait_flag_t myflags = *flags;
 721         PK_CHAR event_text[PKH_EVENT_MAX_NAME_LENGTH];
 722 
 723         *flags = FTDM_NO_FLAGS; 
 724 
 725         if (myflags & FTDM_READ) {
 726                 if (chan_data->hdlc_bytes) {
 727                         *flags |= FTDM_READ;
 728                         return FTDM_SUCCESS;
 729                 }
 730                 status = PKH_QUEUE_WaitOnEvent(chan_data->media_in_queue, to, &chan_data->last_media_event);
 731                 
 732                 if (status == PK_SUCCESS) {
 733                         if (chan_data->last_media_event.id == PKH_EVENT_QUEUE_TIMEOUT || chan_data->last_media_event.id == PKH_EVENT_RECORD_BUFFER_OVERFLOW) {
 734                                 return FTDM_TIMEOUT;
 735                         }
 736                         
 737                         *flags |= FTDM_READ;
 738                         return FTDM_SUCCESS;
 739                 }
 740 
 741                 PKH_EVENT_GetText(chan_data->last_media_event.id, event_text, sizeof(event_text));
 742                 ftdm_log(FTDM_LOG_DEBUG, "Event: %s\n", event_text);
 743         }
 744 
 745         return FTDM_SUCCESS;
 746 }
 747 
 748 /**
 749  * \brief Reads data from a Pika channel
 750  * \param ftdmchan Channel to read from
 751  * \param data Data buffer
 752  * \param datalen Size of data buffer
 753  * \return Success or failure
 754  */
 755 static FIO_READ_FUNCTION(pika_read)
 756 {
 757         pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data;
 758         PK_STATUS status;
 759         PK_CHAR event_text[PKH_EVENT_MAX_NAME_LENGTH];
 760         uint32_t len;
 761 
 762         if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) {
 763                 if ((status = PKH_SPAN_HDLC_GetMessage(chan_data->handle, data, *datalen)) == PK_SUCCESS) {
 764                         *datalen = chan_data->hdlc_bytes;
 765                         chan_data->hdlc_bytes = 0;
 766                         return FTDM_SUCCESS;
 767                 }
 768                 return FTDM_FAIL;
 769         }
 770 
 771         if (!(len = chan_data->last_media_event.p0)) {
 772                 len = ftdmchan->packet_len;
 773         }
 774         
 775         if (len < *datalen) {
 776                 *datalen = len;
 777         }
 778 
 779         if ((status = PKH_RECORD_GetData(chan_data->media_in, data, *datalen)) == PK_SUCCESS) {
 780                 return FTDM_SUCCESS;
 781         }
 782 
 783 
 784         PKH_ERROR_GetText(status, event_text, sizeof(event_text));
 785         ftdm_log(FTDM_LOG_DEBUG, "ERR: %s\n", event_text);
 786         return FTDM_FAIL;
 787 }
 788 
 789 /**
 790  * \brief Writes data to a Pika channel
 791  * \param ftdmchan Channel to write to
 792  * \param data Data buffer
 793  * \param datalen Size of data buffer
 794  * \return Success or failure
 795  */
 796 static FIO_WRITE_FUNCTION(pika_write)
 797 {
 798         pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data;
 799         PK_STATUS status;
 800 
 801         if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) {
 802                 if ((status = PKH_SPAN_HDLC_SendMessage(chan_data->handle, data, *datalen)) == PK_SUCCESS) {
 803                         return FTDM_SUCCESS;
 804                 }
 805                 return FTDM_FAIL;
 806         }
 807 
 808         if (PKH_PLAY_AddData(chan_data->media_out, 0, data, *datalen) == PK_SUCCESS) {
 809                 return FTDM_SUCCESS;
 810         }
 811 
 812         return FTDM_FAIL;
 813 }
 814 
 815 /**
 816  * \brief Executes an FreeTDM command on a Pika channel
 817  * \param ftdmchan Channel to execute command on
 818  * \param command FreeTDM command to execute
 819  * \param obj Object (unused)
 820  * \return Success or failure
 821  */
 822 static FIO_COMMAND_FUNCTION(pika_command)
 823 {
 824         pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data;
 825         //pika_span_data_t *span_data = (pika_span_data_t *) ftdmchan->span->io_data;
 826         PK_STATUS pk_status;
 827         ftdm_status_t status = FTDM_SUCCESS;
 828 
 829         switch(command) {
 830         case FTDM_COMMAND_OFFHOOK:
 831                 {
 832                         if ((pk_status = PKH_TRUNK_SetHookSwitch(chan_data->handle, PKH_TRUNK_OFFHOOK)) != PK_SUCCESS) {
 833                                 PKH_ERROR_GetText(pk_status, ftdmchan->last_error, sizeof(ftdmchan->last_error));
 834                                 GOTO_STATUS(done, FTDM_FAIL);
 835                         } else {
 836                                 ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK);
 837                         }
 838                 }
 839                 break;
 840         case FTDM_COMMAND_ONHOOK:
 841                 {
 842                         if ((pk_status = PKH_TRUNK_SetHookSwitch(chan_data->handle, PKH_TRUNK_ONHOOK)) != PK_SUCCESS) {
 843                                 PKH_ERROR_GetText(pk_status, ftdmchan->last_error, sizeof(ftdmchan->last_error));
 844                                 GOTO_STATUS(done, FTDM_FAIL);
 845                         } else {
 846                                 ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK);
 847                         }
 848                 }
 849                 break;
 850         case FTDM_COMMAND_GENERATE_RING_ON:
 851                 {
 852                         if ((pk_status = PKH_PHONE_RingStart(chan_data->handle, 0, 0)) != PK_SUCCESS) {
 853                                 PKH_ERROR_GetText(pk_status, ftdmchan->last_error, sizeof(ftdmchan->last_error));
 854                                 GOTO_STATUS(done, FTDM_FAIL);
 855                         } else {
 856                                 ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_RINGING);
 857                         }
 858                 }
 859                 break;
 860         case FTDM_COMMAND_GENERATE_RING_OFF:
 861                 {
 862                         if ((pk_status = PKH_PHONE_RingStop(chan_data->handle)) != PK_SUCCESS) {
 863                                 PKH_ERROR_GetText(pk_status, ftdmchan->last_error, sizeof(ftdmchan->last_error));
 864                                 GOTO_STATUS(done, FTDM_FAIL);
 865                         } else {
 866                                 ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_RINGING);
 867                         }
 868                 }
 869                 break;
 870         case FTDM_COMMAND_GET_INTERVAL:
 871                 {
 872 
 873                         FTDM_COMMAND_OBJ_INT = ftdmchan->native_interval;
 874 
 875                 }
 876                 break;
 877         case FTDM_COMMAND_SET_INTERVAL: 
 878                 {
 879                         int interval = FTDM_COMMAND_OBJ_INT;
 880                         int len = interval * 8;
 881                         chan_data->record_config.bufferSize = len;
 882                         chan_data->record_config.numberOfBuffers = (PK_UINT)chan_data->record_config.bufferSize;
 883                         ftdmchan->packet_len = (uint32_t)chan_data->record_config.bufferSize;
 884                         ftdmchan->effective_interval = ftdmchan->native_interval = ftdmchan->packet_len / 8;
 885                         PKH_RECORD_SetConfig(chan_data->media_in, &chan_data->record_config);
 886                         GOTO_STATUS(done, FTDM_SUCCESS);
 887                 }
 888                 break;
 889         case FTDM_COMMAND_GET_DTMF_ON_PERIOD:
 890                 {
 891 
 892                         FTDM_COMMAND_OBJ_INT = ftdmchan->dtmf_on;
 893                         GOTO_STATUS(done, FTDM_SUCCESS);
 894 
 895                 }
 896                 break;
 897         case FTDM_COMMAND_GET_DTMF_OFF_PERIOD:
 898                 {                       
 899                                 FTDM_COMMAND_OBJ_INT = ftdmchan->dtmf_on;
 900                                 GOTO_STATUS(done, FTDM_SUCCESS);
 901                 }
 902                 break;
 903         case FTDM_COMMAND_SET_DTMF_ON_PERIOD:
 904                 {
 905                         int val = FTDM_COMMAND_OBJ_INT;
 906                         if (val > 10 && val < 1000) {
 907                                 ftdmchan->dtmf_on = val;
 908                                 GOTO_STATUS(done, FTDM_SUCCESS);
 909                         } else {
 910                                 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "invalid value %d range 10-1000", val);
 911                                 GOTO_STATUS(done, FTDM_FAIL);
 912                         }
 913                 }
 914                 break;
 915         case FTDM_COMMAND_SET_DTMF_OFF_PERIOD:
 916                 {
 917                         int val = FTDM_COMMAND_OBJ_INT;
 918                         if (val > 10 && val < 1000) {
 919                                 ftdmchan->dtmf_off = val;
 920                                 GOTO_STATUS(done, FTDM_SUCCESS);
 921                         } else {
 922                                 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "invalid value %d range 10-1000", val);
 923                                 GOTO_STATUS(done, FTDM_FAIL);
 924                         }
 925                 }
 926                 break;
 927         case FTDM_COMMAND_SEND_DTMF:
 928                 {
 929                         char *digits = FTDM_COMMAND_OBJ_CHAR_P;
 930                         ftdm_log(FTDM_LOG_DEBUG, "Adding DTMF SEQ [%s]\n", digits);
 931                         ftdm_mutex_lock(chan_data->digit_mutex);
 932                         ftdm_buffer_write(chan_data->digit_buffer, digits, strlen(digits));
 933                         ftdm_mutex_unlock(chan_data->digit_mutex);
 934                         pk_status = PKH_PLAY_Stop(chan_data->media_out);
 935                         
 936                         if (pk_status != PK_SUCCESS) {
 937                                 PKH_ERROR_GetText(pk_status, ftdmchan->last_error, sizeof(ftdmchan->last_error));
 938                                 GOTO_STATUS(done, FTDM_FAIL);
 939                         }
 940                         GOTO_STATUS(done, FTDM_SUCCESS);
 941                 }
 942                 break;
 943         default:
 944                 break;
 945         };
 946 
 947  done:
 948         return status;
 949 }
 950 
 951 /**
 952  * \brief Checks for events on a Pika span
 953  * \param span Span to check for events
 954  * \param ms Time to wait for event
 955  * \return Success if event is waiting or failure if not
 956  */
 957 static FIO_SPAN_POLL_EVENT_FUNCTION(pika_poll_event)
 958 {
 959         pika_span_data_t *span_data = (pika_span_data_t *) span->io_data;
 960         PK_STATUS status;
 961         PK_CHAR event_text[PKH_EVENT_MAX_NAME_LENGTH];
 962 
 963         status = PKH_QUEUE_WaitOnEvent(span_data->event_queue, ms, &span_data->last_oob_event);
 964 
 965         if (status == PK_SUCCESS) {
 966                 ftdm_channel_t *ftdmchan = NULL;
 967                 uint32_t *data = (uint32_t *) span_data->last_oob_event.userData;
 968                 ftdm_data_type_t data_type = FTDM_TYPE_NONE;
 969 
 970                 if (span_data->last_oob_event.id == PKH_EVENT_QUEUE_TIMEOUT) {
 971                         return FTDM_TIMEOUT;
 972                 }
 973 
 974                 if (data) {
 975                         data_type = *data;
 976                 }
 977 
 978                 if (data_type == FTDM_TYPE_CHANNEL) {
 979                         ftdmchan = span_data->last_oob_event.userData;
 980                 } else if (data_type == FTDM_TYPE_SPAN) {
 981             ftdm_time_t last_event_time = ftdm_current_time_in_ms();
 982                         uint32_t event_id = 0;
 983 
 984                         switch (span_data->last_oob_event.id) {
 985                         case PKH_EVENT_SPAN_ALARM_T1_RED:
 986                         case PKH_EVENT_SPAN_ALARM_T1_YELLOW:
 987                         case PKH_EVENT_SPAN_ALARM_T1_AIS:
 988                         case PKH_EVENT_SPAN_ALARM_E1_RED:
 989                         case PKH_EVENT_SPAN_ALARM_E1_RAI:
 990                         case PKH_EVENT_SPAN_ALARM_E1_AIS:
 991                         case PKH_EVENT_SPAN_ALARM_E1_RMAI:
 992                         case PKH_EVENT_SPAN_ALARM_E1_TS16AIS:
 993                         case PKH_EVENT_SPAN_ALARM_E1_TS16LOS:
 994                         case PKH_EVENT_SPAN_OUT_OF_SYNC:
 995                         case PKH_EVENT_SPAN_FRAMING_ERROR:
 996                         case PKH_EVENT_SPAN_LOSS_OF_SIGNAL:
 997                         case PKH_EVENT_SPAN_OUT_OF_CRC_MF_SYNC:
 998                         case PKH_EVENT_SPAN_OUT_OF_CAS_MF_SYNC:
 999                                 event_id = FTDM_OOB_ALARM_TRAP;
1000                                 break;
1001                         case PKH_EVENT_SPAN_ALARM_T1_RED_CLEAR:
1002                         case PKH_EVENT_SPAN_ALARM_T1_YELLOW_CLEAR:
1003                         case PKH_EVENT_SPAN_ALARM_T1_AIS_CLEAR:
1004                         case PKH_EVENT_SPAN_ALARM_E1_RED_CLEAR:
1005                         case PKH_EVENT_SPAN_ALARM_E1_RAI_CLEAR:
1006                         case PKH_EVENT_SPAN_ALARM_E1_AIS_CLEAR:
1007                         case PKH_EVENT_SPAN_ALARM_E1_RMAI_CLEAR:
1008                         case PKH_EVENT_SPAN_ALARM_E1_TS16AIS_CLEAR:
1009                         case PKH_EVENT_SPAN_ALARM_E1_TS16LOS_CLEAR:
1010                         case PKH_EVENT_SPAN_IN_SYNC:
1011                         case PKH_EVENT_SPAN_LOSS_OF_SIGNAL_CLEAR:
1012                         case PKH_EVENT_SPAN_IN_CRC_MF_SYNC:
1013                         case PKH_EVENT_SPAN_IN_CAS_MF_SYNC:
1014                                 event_id = FTDM_OOB_ALARM_CLEAR;
1015                                 break;
1016                         case PKH_EVENT_SPAN_MESSAGE:
1017                         case PKH_EVENT_SPAN_ABCD_SIGNAL_CHANGE:
1018                                 break;
1019                         }
1020 
1021                         if (event_id) {
1022                                 uint32_t x = 0;
1023                                 ftdm_channel_t *ftdmchan;
1024                                 pika_chan_data_t *chan_data;
1025                                 for(x = 1; x <= span->chan_count; x++) {
1026                                         ftdmchan = span->channels[x];
1027                                         assert(ftdmchan != NULL);
1028                                         chan_data = (pika_chan_data_t *) ftdmchan->io_data;
1029                                         assert(chan_data != NULL);
1030                                         
1031 
1032                                         ftdm_set_flag(ftdmchan, FTDM_CHANNEL_EVENT);
1033                                         ftdmchan->last_event_time = last_event_time;
1034                                         chan_data->last_oob_event = span_data->last_oob_event;
1035                                 }
1036 
1037                         }
1038 
1039                 }
1040                 
1041                 PKH_EVENT_GetText(span_data->last_oob_event.id, event_text, sizeof(event_text));
1042                 //ftdm_log(FTDM_LOG_DEBUG, "Event: %s\n", event_text);
1043                 
1044                 if (ftdmchan) {
1045                         pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data;
1046 
1047                         assert(chan_data != NULL);
1048                         ftdm_set_flag(ftdmchan, FTDM_CHANNEL_EVENT);
1049             ftdmchan->last_event_time = ftdm_current_time_in_ms();
1050                         chan_data->last_oob_event = span_data->last_oob_event;
1051                 }
1052 
1053                 return FTDM_SUCCESS;
1054         }
1055 
1056         return FTDM_FAIL;
1057 }
1058 
1059 /**
1060  * \brief Retrieves an event from a Pika span
1061  * \param span Span to retrieve event from
1062  * \param event FreeTDM event to return
1063  * \return Success or failure
1064  */
1065 static FIO_SPAN_NEXT_EVENT_FUNCTION(pika_next_event)
1066 {
1067         uint32_t i, event_id = 0;
1068         
1069         for(i = 1; i <= span->chan_count; i++) {
1070                 if (ftdm_test_flag(span->channels[i], FTDM_CHANNEL_EVENT)) {
1071                         pika_chan_data_t *chan_data = (pika_chan_data_t *) span->channels[i]->io_data;
1072                         PK_CHAR event_text[PKH_EVENT_MAX_NAME_LENGTH];
1073                         
1074                         ftdm_clear_flag(span->channels[i], FTDM_CHANNEL_EVENT);
1075                         
1076                         PKH_EVENT_GetText(chan_data->last_oob_event.id, event_text, sizeof(event_text));
1077 
1078                         switch(chan_data->last_oob_event.id) {
1079                         case PKH_EVENT_HDLC_MESSAGE:
1080                                 chan_data->hdlc_bytes = chan_data->last_oob_event.p2;
1081                                 continue;
1082                         case PKH_EVENT_TRUNK_HOOKFLASH:
1083                                 event_id = FTDM_OOB_FLASH;
1084                                 break;
1085                         case PKH_EVENT_TRUNK_RING_OFF:
1086                                 event_id = FTDM_OOB_RING_STOP;
1087                                 break;
1088                         case PKH_EVENT_TRUNK_RING_ON:
1089                                 event_id = FTDM_OOB_RING_START;
1090                                 break;
1091 
1092                         case PKH_EVENT_PHONE_OFFHOOK:
1093                                 ftdm_set_flag_locked(span->channels[i], FTDM_CHANNEL_OFFHOOK);
1094                                 event_id = FTDM_OOB_OFFHOOK;
1095                                 break;
1096 
1097                         case PKH_EVENT_TRUNK_BELOW_THRESHOLD:
1098                         case PKH_EVENT_TRUNK_ABOVE_THRESHOLD:
1099                         case PKH_EVENT_PHONE_ONHOOK:
1100                                 ftdm_clear_flag_locked(span->channels[i], FTDM_CHANNEL_OFFHOOK);
1101                                 event_id = FTDM_OOB_ONHOOK;
1102                                 break;
1103 
1104 
1105 
1106                         case PKH_EVENT_SPAN_ALARM_T1_RED:
1107                                 ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_RED);
1108                                 snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "RED ALARM");
1109                                 event_id = FTDM_OOB_ALARM_TRAP;
1110                                 break;
1111                         case PKH_EVENT_SPAN_ALARM_T1_YELLOW:
1112                                 ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_YELLOW);
1113                                 snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "YELLOW ALARM");
1114                                 event_id = FTDM_OOB_ALARM_TRAP;
1115                                 break;
1116                         case PKH_EVENT_SPAN_ALARM_T1_AIS:
1117                                 ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_AIS);
1118                                 snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "AIS ALARM");
1119                                 event_id = FTDM_OOB_ALARM_TRAP;
1120                                 break;
1121                         case PKH_EVENT_SPAN_ALARM_E1_RED:
1122                                 ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_RED);
1123                                 snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "RED ALARM");
1124                                 event_id = FTDM_OOB_ALARM_TRAP;
1125                                 break;
1126                         case PKH_EVENT_SPAN_ALARM_E1_RAI:
1127                                 ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_RAI);
1128                                 snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "RAI ALARM");
1129                                 event_id = FTDM_OOB_ALARM_TRAP;
1130                                 break;
1131                         case PKH_EVENT_SPAN_ALARM_E1_AIS:
1132                                 ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_AIS);
1133                                 snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "AIS ALARM");
1134                                 event_id = FTDM_OOB_ALARM_TRAP;
1135                                 break;
1136                         case PKH_EVENT_SPAN_ALARM_E1_RMAI:
1137                         case PKH_EVENT_SPAN_ALARM_E1_TS16AIS:
1138                         case PKH_EVENT_SPAN_ALARM_E1_TS16LOS:
1139                         case PKH_EVENT_SPAN_OUT_OF_SYNC:
1140                         case PKH_EVENT_SPAN_FRAMING_ERROR:
1141                         case PKH_EVENT_SPAN_LOSS_OF_SIGNAL:
1142                         case PKH_EVENT_SPAN_OUT_OF_CRC_MF_SYNC:
1143                         case PKH_EVENT_SPAN_OUT_OF_CAS_MF_SYNC:
1144                                 ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_GENERAL);
1145                                 snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "GENERAL ALARM");
1146                                 event_id = FTDM_OOB_ALARM_TRAP;
1147                                 break;
1148                         case PKH_EVENT_SPAN_ALARM_T1_RED_CLEAR:
1149                                 ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_RED);
1150                         case PKH_EVENT_SPAN_ALARM_T1_YELLOW_CLEAR:
1151                                 ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_YELLOW);
1152                         case PKH_EVENT_SPAN_ALARM_T1_AIS_CLEAR:
1153                                 ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_AIS);
1154                         case PKH_EVENT_SPAN_ALARM_E1_RED_CLEAR:
1155                                 ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_RED);
1156                         case PKH_EVENT_SPAN_ALARM_E1_RAI_CLEAR:
1157                                 ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_RAI);
1158                         case PKH_EVENT_SPAN_ALARM_E1_AIS_CLEAR:
1159                                 ftdm_set_alarm_flag(span->channels[i], FTDM_ALARM_AIS);
1160                         case PKH_EVENT_SPAN_ALARM_E1_RMAI_CLEAR:
1161                         case PKH_EVENT_SPAN_ALARM_E1_TS16AIS_CLEAR:
1162                         case PKH_EVENT_SPAN_ALARM_E1_TS16LOS_CLEAR:
1163                         case PKH_EVENT_SPAN_IN_SYNC:
1164                         case PKH_EVENT_SPAN_LOSS_OF_SIGNAL_CLEAR:
1165                         case PKH_EVENT_SPAN_IN_CRC_MF_SYNC:
1166                         case PKH_EVENT_SPAN_IN_CAS_MF_SYNC:
1167                                 ftdm_clear_alarm_flag(span->channels[i], FTDM_ALARM_GENERAL);
1168                                 event_id = FTDM_OOB_ALARM_CLEAR;
1169                                 break;
1170                         case PKH_EVENT_SPAN_MESSAGE:
1171                         case PKH_EVENT_SPAN_ABCD_SIGNAL_CHANGE:
1172                                 break;
1173 
1174 
1175 
1176 
1177                         case PKH_EVENT_TRUNK_ONHOOK:
1178                         case PKH_EVENT_TRUNK_OFFHOOK:                           
1179                         case PKH_EVENT_TRUNK_DIALED :
1180                         case PKH_EVENT_TRUNK_REVERSAL:
1181                         case PKH_EVENT_TRUNK_LCSO:
1182                         case PKH_EVENT_TRUNK_DROPOUT:
1183                         case PKH_EVENT_TRUNK_LOF:
1184                         case PKH_EVENT_TRUNK_RX_OVERLOAD:
1185                         default:
1186                                 ftdm_log(FTDM_LOG_DEBUG, "Unhandled event %d on channel %d [%s]\n", chan_data->last_oob_event.id, i, event_text);
1187                                 event_id = FTDM_OOB_INVALID;
1188                                 break;
1189                         }
1190 
1191                         span->channels[i]->last_event_time = 0;
1192                         span->event_header.e_type = FTDM_EVENT_OOB;
1193                         span->event_header.enum_id = event_id;
1194                         span->event_header.channel = span->channels[i];
1195                         *event = &span->event_header;
1196                         return FTDM_SUCCESS;
1197                 }
1198         }
1199 
1200         return FTDM_FAIL;
1201 }
1202 
1203 /**
1204  * \brief Destroys a Pika Span
1205  * \param span Span to destroy
1206  * \return Success
1207  */
1208 static FIO_SPAN_DESTROY_FUNCTION(pika_span_destroy)
1209 {
1210         pika_span_data_t *span_data = (pika_span_data_t *) span->io_data;
1211         
1212         if (span_data) {
1213                 PKH_QUEUE_Destroy(span_data->event_queue);
1214                 ftdm_safe_free(span_data);
1215         }
1216         
1217         return FTDM_SUCCESS;
1218 }
1219 
1220 /**
1221  * \brief Destroys a Pika Channel
1222  * \param ftdmchan Channel to destroy
1223  * \return Success or failure
1224  */
1225 static FIO_CHANNEL_DESTROY_FUNCTION(pika_channel_destroy)
1226 {
1227         pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data;
1228         pika_span_data_t *span_data = (pika_span_data_t *) ftdmchan->span->io_data;
1229         
1230         if (!chan_data) {
1231                 return FTDM_FAIL;
1232         }
1233 
1234         if (!ftdm_test_flag(chan_data, PK_FLAG_READY)) {
1235                 goto end;
1236         }
1237 
1238         PKH_RECORD_Stop(chan_data->media_in);
1239         PKH_PLAY_Stop(chan_data->media_out);
1240         PKH_QUEUE_Destroy(chan_data->media_in_queue);
1241         PKH_QUEUE_Destroy(chan_data->media_out_queue);
1242         
1243         switch(ftdmchan->type) {
1244         case FTDM_CHAN_TYPE_FXS:
1245                 PKH_QUEUE_Detach(span_data->event_queue, chan_data->handle);
1246                 PKH_PHONE_Close(chan_data->handle);
1247                 break;
1248         case FTDM_CHAN_TYPE_FXO:
1249                 PKH_QUEUE_Detach(span_data->event_queue, chan_data->handle);
1250                 PKH_TRUNK_Close(chan_data->handle);
1251                 break;
1252         case FTDM_CHAN_TYPE_DQ921:
1253                 PKH_SPAN_Stop(span_data->handle);
1254                 break;
1255         default:
1256                 break;
1257         }
1258 
1259 
1260         ftdm_mutex_destroy(&chan_data->digit_mutex);
1261         ftdm_buffer_destroy(&chan_data->digit_buffer);
1262 
1263  end:
1264         ftdm_safe_free(chan_data);
1265         
1266         return FTDM_SUCCESS;
1267 }
1268 
1269 /**
1270  * \brief Gets alarms from a Pika Channel (does nothing)
1271  * \param ftdmchan Channel to get alarms from
1272  * \return Failure
1273  */
1274 static FIO_GET_ALARMS_FUNCTION(pika_get_alarms)
1275 {
1276         return FTDM_FAIL;
1277 }
1278 
1279 static ftdm_io_interface_t pika_interface;
1280 
1281 /**
1282  * \brief Loads Pika IO module
1283  * \param fio FreeTDM IO interface
1284  * \return Success or failure
1285  */
1286 static FIO_IO_LOAD_FUNCTION(pika_init)
1287 {
1288 
1289         PK_STATUS status;
1290         PK_CHAR error_text[PKH_ERROR_MAX_NAME_LENGTH];
1291         uint32_t i;
1292         int ok = 0;
1293         PKH_TLogMasks m;
1294         TPikaHandle tmpHandle;
1295 
1296         assert(fio != NULL);
1297         memset(&pika_interface, 0, sizeof(pika_interface));
1298         memset(&globals, 0, sizeof(globals));
1299         globals.general_config.region = PKH_TRUNK_NA;
1300 
1301         globals.profile_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys);
1302 
1303         // Open the system object, to enumerate boards configured for this system
1304         if ((status = PKH_SYSTEM_Open(&globals.system_handle)) != PK_SUCCESS) {
1305                 ftdm_log(FTDM_LOG_ERROR, "Error: PKH_SYSTEM_Open failed(%s)!\n",
1306                                 PKH_ERROR_GetText(status, error_text, sizeof(error_text)));
1307                 return FTDM_FAIL;
1308         }
1309 
1310         // Retrieves a list of all boards in this system, existing,
1311         // or listed in pika.cfg
1312         if ((status = PKH_SYSTEM_Detect(globals.system_handle, &globals.board_list)) != PK_SUCCESS) {
1313                 ftdm_log(FTDM_LOG_ERROR, "Error: PKH_SYSTEM_Detect failed(%s)!\n",
1314                                 PKH_ERROR_GetText(status, error_text, sizeof(error_text)));
1315                 return FTDM_FAIL;
1316         }
1317         
1318         PKH_SYSTEM_GetConfig(globals.system_handle, &globals.system_config);
1319         globals.system_config.maxAudioProcessBlockSize = PIKA_BLOCK_LEN;
1320         globals.system_config.playBufferSize = PIKA_BLOCK_SIZE;
1321         globals.system_config.recordBufferSize = PIKA_BLOCK_SIZE;
1322         globals.system_config.recordNumberOfBuffers = PIKA_NUM_BUFFERS;
1323         PKH_SYSTEM_SetConfig(globals.system_handle, &globals.system_config);
1324 
1325         status = PKH_MEDIA_STREAM_Create(&tmpHandle);
1326         status = PKH_RECORD_GetConfig(tmpHandle, &globals.record_config);
1327         status = PKH_PLAY_GetConfig(tmpHandle, &globals.play_config);
1328         status = PKH_EC_GetConfig(tmpHandle, &globals.ec_config);
1329         status = PKH_MEDIA_STREAM_Destroy(tmpHandle);
1330 
1331         
1332 
1333         ftdm_log(FTDM_LOG_DEBUG, "Found %u board%s\n", globals.board_list.numberOfBoards, globals.board_list.numberOfBoards == 1 ? "" : "s");
1334         for(i = 0; i < globals.board_list.numberOfBoards; ++i) {
1335                 ftdm_log(FTDM_LOG_INFO, "Found PIKA board type:[%s] id:[%u] serno:[%u]\n", 
1336                                 pika_board_type_string(globals.board_list.board[i].type), globals.board_list.board[i].id, (uint32_t)
1337                                 globals.board_list.board[i].serialNumber);
1338 
1339                 if (globals.board_list.board[i].type == PKH_BOARD_TYPE_DIGITAL_GATEWAY) {
1340                         TPikaHandle board_handle, span_handle;
1341                         PKH_TBoardConfig boardConfig;
1342                         PKH_BOARD_GetConfig(board_handle, &boardConfig);
1343                         PKH_BOARD_Open(globals.board_list.board[i].id, NULL, &board_handle);
1344                         PKH_SPAN_Open(board_handle, 0, NULL, &span_handle);
1345                         PKH_SPAN_GetConfig(span_handle, &globals.t1_span_config);
1346                         PKH_SPAN_Close(span_handle);
1347                         boardConfig.specific.DigitalGateway.interfaceType = PKH_BOARD_INTERFACE_TYPE_E1;
1348                         PKH_BOARD_SetConfig(board_handle, &boardConfig);
1349                         PKH_SPAN_Open(board_handle, 0, NULL, &span_handle);
1350                         PKH_SPAN_GetConfig(span_handle, &globals.e1_span_config);
1351                         PKH_SPAN_Close(span_handle);
1352                         boardConfig.specific.DigitalGateway.interfaceType = PKH_BOARD_INTERFACE_TYPE_T1;
1353                         PKH_BOARD_SetConfig(board_handle, &boardConfig);
1354                         PKH_BOARD_Close(board_handle);
1355                 }
1356                 ok++;
1357 
1358         }
1359 
1360         if (!ok) {
1361                 return FTDM_FAIL;
1362         }
1363         
1364         pika_interface.name = "pika";
1365         pika_interface.configure =  pika_configure;
1366         pika_interface.configure_span = pika_configure_span;
1367         pika_interface.open = pika_open;
1368         pika_interface.close = pika_close;
1369         pika_interface.wait = pika_wait;
1370         pika_interface.read = pika_read;
1371         pika_interface.write = pika_write;
1372         pika_interface.command = pika_command;
1373         pika_interface.poll_event = pika_poll_event;
1374         pika_interface.next_event = pika_next_event;
1375         pika_interface.channel_destroy = pika_channel_destroy;
1376         pika_interface.span_destroy = pika_span_destroy;
1377         pika_interface.get_alarms = pika_get_alarms;
1378         *fio = &pika_interface;
1379 
1380 
1381         ftdm_log(FTDM_LOG_INFO, "Dumping Default configs:\n");
1382         ftdm_log(FTDM_LOG_INFO, "rx-gain => %0.2f\n", (float)globals.record_config.gain);
1383         ftdm_log(FTDM_LOG_INFO, "rx-agc-enabled => %s\n", globals.record_config.AGC.enabled ? "true" : "false");
1384         ftdm_log(FTDM_LOG_INFO, "rx-agc-targetPower => %0.2f\n", (float)globals.record_config.AGC.targetPower);
1385         ftdm_log(FTDM_LOG_INFO, "rx-agc-minGain => %0.2f\n", (float)globals.record_config.AGC.minGain);
1386         ftdm_log(FTDM_LOG_INFO, "rx-agc-maxGain => %0.2f\n", (float)globals.record_config.AGC.maxGain);
1387         ftdm_log(FTDM_LOG_INFO, "rx-agc-attackRate => %d\n", (int)globals.record_config.AGC.attackRate);
1388         ftdm_log(FTDM_LOG_INFO, "rx-agc-decayRate => %d\n", (int)globals.record_config.AGC.decayRate);
1389         ftdm_log(FTDM_LOG_INFO, "rx-agc-speechThreshold => %0.2f\n", (float)globals.record_config.AGC.speechThreshold);
1390         ftdm_log(FTDM_LOG_INFO, "rx-vad-enabled => %s\n", globals.record_config.VAD.enabled ? "true" : "false");
1391         ftdm_log(FTDM_LOG_INFO, "rx-vad-activationThreshold => %0.2f\n", (float)globals.record_config.VAD.activationThreshold);
1392         ftdm_log(FTDM_LOG_INFO, "rx-vad-activationDebounceTime => %d\n", (int)globals.record_config.VAD.activationDebounceTime);
1393         ftdm_log(FTDM_LOG_INFO, "rx-vad-deactivationThreshold => %0.2f\n", (float)globals.record_config.VAD.deactivationThreshold);
1394         ftdm_log(FTDM_LOG_INFO, "rx-vad-deactivationDebounceTime => %d\n", (int)globals.record_config.VAD.deactivationDebounceTime);
1395         ftdm_log(FTDM_LOG_INFO, "rx-vad-preSpeechBufferSize => %d\n", (int)globals.record_config.VAD.preSpeechBufferSize);
1396         ftdm_log(FTDM_LOG_INFO, "tx-gain => %0.2f\n", (float)globals.play_config.gain);
1397         ftdm_log(FTDM_LOG_INFO, "tx-agc-enabled => %s\n", globals.play_config.AGC.enabled ? "true" : "false");
1398         ftdm_log(FTDM_LOG_INFO, "tx-agc-targetPower => %0.2f\n", (float)globals.play_config.AGC.targetPower);
1399         ftdm_log(FTDM_LOG_INFO, "tx-agc-minGain => %0.2f\n", (float)globals.play_config.AGC.minGain);
1400         ftdm_log(FTDM_LOG_INFO, "tx-agc-maxGain => %0.2f\n", (float)globals.play_config.AGC.maxGain);
1401         ftdm_log(FTDM_LOG_INFO, "tx-agc-attackRate => %d\n", (int)globals.play_config.AGC.attackRate);
1402         ftdm_log(FTDM_LOG_INFO, "tx-agc-decayRate => %d\n", (int)globals.play_config.AGC.decayRate);
1403         ftdm_log(FTDM_LOG_INFO, "tx-agc-speechThreshold => %0.2f\n", (float)globals.play_config.AGC.speechThreshold);
1404         ftdm_log(FTDM_LOG_INFO, "ec-doubleTalkerThreshold => %0.2f\n", (float)globals.ec_config.doubleTalkerThreshold);
1405         ftdm_log(FTDM_LOG_INFO, "ec-speechPresentThreshold => %0.2f\n", (float)globals.ec_config.speechPresentThreshold);
1406         ftdm_log(FTDM_LOG_INFO, "ec-echoSuppressionThreshold => %0.2f\n", (float)globals.ec_config.echoSuppressionThreshold);
1407         ftdm_log(FTDM_LOG_INFO, "ec-echoSuppressionEnabled => %s\n", globals.ec_config.echoSuppressionEnabled ? "true" : "false");
1408         ftdm_log(FTDM_LOG_INFO, "ec-comfortNoiseEnabled => %s\n", globals.ec_config.comfortNoiseEnabled ? "true" : "false");
1409         ftdm_log(FTDM_LOG_INFO, "ec-adaptationModeEnabled => %s\n", globals.ec_config.adaptationModeEnabled ? "true" : "false");
1410 
1411         
1412 
1413         memset(&m, 0, sizeof(m));
1414         //m.apiMask = 0xffffffff;
1415         //PKH_LOG_SetMasks(&m);
1416 
1417         return FTDM_SUCCESS;
1418 }
1419 
1420 /**
1421  * \brief Unloads Pika IO module
1422  * \return Success
1423  */
1424 static FIO_IO_UNLOAD_FUNCTION(pika_destroy)
1425 {
1426         uint32_t x;
1427         PK_STATUS status;
1428         PK_CHAR error_text[PKH_ERROR_MAX_NAME_LENGTH];
1429 
1430         for (x = 0; x < MAX_NUMBER_OF_TRUNKS; x++) {
1431                 if (globals.open_boards[x]) {
1432                         ftdm_log(FTDM_LOG_INFO, "Closing board %u\n", x);
1433                         PKH_BOARD_Close(globals.open_boards[x]);
1434                 }
1435         }
1436 
1437         // The system can now be closed.
1438         if ((status = PKH_SYSTEM_Close(globals.system_handle)) != PK_SUCCESS) {
1439                 ftdm_log(FTDM_LOG_ERROR, "Error: PKH_SYSTEM_Close failed(%s)!\n",
1440                                 PKH_ERROR_GetText(status, error_text, sizeof(error_text)));
1441         } else {
1442                 ftdm_log(FTDM_LOG_INFO, "Closing system handle\n");
1443         }
1444 
1445         hashtable_destroy(globals.profile_hash);
1446 
1447         return FTDM_SUCCESS;
1448 }
1449 
1450 /**
1451  * \brief Pika IO module definition
1452  */
1453 EX_DECLARE_DATA ftdm_module_t ftdm_module = { 
1454         "pika",
1455         pika_init,
1456         pika_destroy,
1457 };
1458 
1459 /* For Emacs:
1460  * Local Variables:
1461  * mode:c
1462  * indent-tabs-mode:t
1463  * tab-width:4
1464  * c-basic-offset:4
1465  * End:
1466  * For VIM:
1467  * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
1468  */
1469 

/* [<][>][^][v][top][bottom][index][help] */