static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling) { wat_span_config_t span_config; ftdm_gsm_span_data_t *gsm_data = NULL; ftdm_iterator_t *chaniter = NULL; ftdm_iterator_t *citer = NULL; ftdm_channel_t *ftdmchan = NULL; ftdm_channel_t *dchan = NULL; ftdm_channel_t *bchan = NULL; unsigned paramindex = 0; const char *var = NULL; const char *val = NULL; /* libwat is smart enough to set good default values for the timers if they are set to 0 */ memset(&span_config, 0, sizeof(span_config)); /* set some span defaults */ span_config.moduletype = WAT_MODULE_TELIT; if (FTDM_SUCCESS != init_wat_lib()) { return FTDM_FAIL; } if (!sig_cb) { ftdm_log(FTDM_LOG_ERROR, "No signaling callback provided\n"); return FTDM_FAIL; } if (span->signal_type) { ftdm_log(FTDM_LOG_ERROR, "Span %s is already configured for another signaling\n", span->name); return FTDM_FAIL; } /* verify the span has one d-channel */ chaniter = ftdm_span_get_chan_iterator(span, NULL); if (!chaniter) { ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); return FTDM_FAIL; } citer = ftdm_span_get_chan_iterator(span, chaniter); for ( ; citer; citer = ftdm_iterator_next(citer)) { ftdmchan = ftdm_iterator_current(citer); if ((NULL == dchan) && FTDM_IS_DCHAN(ftdmchan)) { dchan = ftdmchan; } if ((NULL == bchan) && FTDM_IS_VOICE_CHANNEL(ftdmchan)) { bchan = ftdmchan; } } ftdm_iterator_free(chaniter); if (!dchan) { ftdm_log(FTDM_LOG_CRIT, "Could not find a d-channel for GSM span %s!\n", span->name); return FTDM_FAIL; } if (!bchan) { ftdm_log(FTDM_LOG_CRIT, "Could not find a b-channel for GSM span %s!\n", span->name); return FTDM_FAIL; } gsm_data = ftdm_calloc(1, sizeof(*gsm_data)); if (!gsm_data) { return FTDM_FAIL; } gsm_data->dchan = dchan; gsm_data->bchan = bchan; //sprintf(gsm_data->dchan->chan_name, "%s\t\n", "GSM dchan"); //sprintf(gsm_data->bchan->chan_name, "%s\r\n", "GSM bchan"); for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) { var = ftdm_parameters[paramindex].var; val = ftdm_parameters[paramindex].val; if (!ftdm_strlen_zero_buf(val)) { ftdm_log(FTDM_LOG_WARNING, "Ignoring empty GSM parameter %s for span %s\n", var, span->name); continue; } ftdm_log(FTDM_LOG_DEBUG, "Reading GSM parameter %s=%s for span %s\n", var, val, span->name); if (!strcasecmp(var, "moduletype")) { span_config.moduletype = wat_str2wat_moduletype(val); if (span_config.moduletype == WAT_MODULE_INVALID) { ftdm_log(FTDM_LOG_DEBUG, "Unknown GSM module type %s for span %s\n", val, span->name); continue; } ftdm_log(FTDM_LOG_DEBUG, "Configuring GSM span %s with moduletype %s\n", span->name, val); } else { ftdm_log(FTDM_LOG_ERROR, "Ignoring unknown GSM parameter '%s'", var); } } /* Bind function pointers for control operations */ span->start = ftdm_gsm_start; span->stop = ftdm_gsm_stop; span->sig_read = NULL; span->sig_write = NULL; span->signal_cb = sig_cb; span->signal_type = FTDM_SIGTYPE_GSM; span->signal_data = gsm_data; /* Gideon, plz fill me with gsm span specific data (you allocate and free) */ span->outgoing_call = gsm_outgoing_call; span->get_span_sig_status = ftdm_gsm_get_span_sig_status; span->set_span_sig_status = ftdm_gsm_set_span_sig_status; span->get_channel_sig_status = ftdm_gsm_get_channel_sig_status; span->set_channel_sig_status = ftdm_gsm_set_channel_sig_status; //printf("\r\nspan->state_map = &gsm_state_map;\r\n"); span->state_map = &gsm_state_map; span->state_processor = ftdm_gsm_state_advance; /* use signals queue */ ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE); ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE); /* we can skip states (going straight from RING to UP) */ ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES); gsm_data->span = span; #if 0 /* setup the scheduler (create if needed) */ snprintf(schedname, sizeof(schedname), "ftmod_r2_%s", span->name); ftdm_assert(ftdm_sched_create(&r2data->sched, schedname) == FTDM_SUCCESS, "Failed to create schedule!\n"); spanpvt->sched = r2data->sched; #endif fprintf(stdout, "Configuring wat span %d %s \r\n", span->span_id, span->name); if (wat_span_config(span->span_id, &span_config)) { ftdm_log(FTDM_LOG_ERROR, "Failed to configure span %s for GSM signaling!!\n", span->name); return FTDM_FAIL; } { int codec = FTDM_CODEC_SLIN; int interval = 20; ftdm_channel_command(gsm_data->bchan, FTDM_COMMAND_SET_NATIVE_CODEC, &codec); ftdm_channel_command(gsm_data->bchan, FTDM_COMMAND_SET_CODEC, &codec); ftdm_channel_command(gsm_data->bchan, FTDM_COMMAND_SET_INTERVAL, &interval); } return FTDM_SUCCESS; }
static ftdm_status_t ftdm_pritap_sig_read(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t size) { ftdm_status_t status; fio_codec_t codec_func; ftdm_channel_t *peerchan = ftdmchan->call_data; pritap_t *pritap = ftdmchan->span->signal_data; int16_t chanbuf[size]; int16_t peerbuf[size]; int16_t mixedbuf[size]; int i = 0; ftdm_size_t sizeread = size; if (!FTDM_IS_VOICE_CHANNEL(ftdmchan) || !ftdmchan->call_data) { return FTDM_SUCCESS; } if (pritap->mixaudio == PRITAP_MIX_SELF) { return FTDM_SUCCESS; } if (pritap->mixaudio == PRITAP_MIX_PEER) { /* start out by clearing the self audio to make sure we don't return audio we were * not supposed to in an error condition */ memset(data, FTDM_SILENCE_VALUE(ftdmchan), size); } if (ftdmchan->native_codec != peerchan->native_codec) { ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Invalid peer channel with format %d, ours = %d\n", peerchan->native_codec, ftdmchan->native_codec); return FTDM_FAIL; } memcpy(chanbuf, data, size); status = peerchan->fio->read(peerchan, peerbuf, &sizeread); if (status != FTDM_SUCCESS) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to read from peer channel!\n"); return FTDM_FAIL; } if (sizeread != size) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "read from peer channel only %"FTDM_SIZE_FMT" bytes!\n", sizeread); return FTDM_FAIL; } if (pritap->mixaudio == PRITAP_MIX_PEER) { /* only the peer audio is requested */ memcpy(data, peerbuf, size); return FTDM_SUCCESS; } codec_func = peerchan->native_codec == FTDM_CODEC_ULAW ? fio_ulaw2slin : peerchan->native_codec == FTDM_CODEC_ALAW ? fio_alaw2slin : NULL; if (codec_func) { sizeread = size; codec_func(chanbuf, sizeof(chanbuf), &sizeread); sizeread = size; codec_func(peerbuf, sizeof(peerbuf), &sizeread); } for (i = 0; i < size; i++) { mixedbuf[i] = ftdm_saturated_add(chanbuf[i], peerbuf[i]); } codec_func = peerchan->native_codec == FTDM_CODEC_ULAW ? fio_slin2ulaw : peerchan->native_codec == FTDM_CODEC_ALAW ? fio_slin2alaw : NULL; if (codec_func) { size = sizeof(mixedbuf); codec_func(mixedbuf, size, &size); } memcpy(data, mixedbuf, size); return FTDM_SUCCESS; }