void att_courtesy_transfer_complete(sngisdn_chan_data_t *sngisdn_info, ftdm_transfer_response_t response) { ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED); ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_DTMF_DETECT, NULL); sngisdn_info->transfer_data.type = SNGISDN_TRANSFER_NONE; sngisdn_info->transfer_data.response = response; ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Transfer Complete:%s\n", ftdm_transfer_response2str(sngisdn_info->transfer_data.response)); sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_TRANSFER_COMPLETED); ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_RX_BUFFERS, NULL); return; }
static switch_status_t channel_on_destroy(switch_core_session_t *session) { ctdm_private_t *tech_pvt = switch_core_session_get_private(session); if ((tech_pvt = switch_core_session_get_private(session))) { if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to enable echo cancellation.\n"); } if (tech_pvt->read_codec.implementation) { switch_core_codec_destroy(&tech_pvt->read_codec); } if (tech_pvt->write_codec.implementation) { switch_core_codec_destroy(&tech_pvt->write_codec); } switch_core_session_unset_read_codec(session); switch_core_session_unset_write_codec(session); ftdm_channel_close(&tech_pvt->ftdm_channel); } return SWITCH_STATUS_SUCCESS; }
static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf) { ctdm_private_t *tech_pvt = NULL; char tmp[2] = ""; tech_pvt = switch_core_session_get_private(session); assert(tech_pvt != NULL); tmp[0] = dtmf->digit; ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_SEND_DTMF, tmp); return SWITCH_STATUS_SUCCESS; }
int16_t sngisdn_rcv_l1_cmd_req(uint16_t spId, sng_l1_cmd_t *l1_cmd) { sngisdn_span_data_t *signal_data = g_sngisdn_data.dchans[spId].spans[1]; ftdm_assert(signal_data, "Received Data request on unconfigured span\n"); switch(l1_cmd->type) { case SNG_L1CMD_SET_LINK_STATUS: { ftdm_channel_hw_link_status_t status = FTDM_HW_LINK_CONNECTED; ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_SET_LINK_STATUS, &status); } break; case SNG_L1CMD_GET_LINK_STATUS: { ftdm_channel_hw_link_status_t status = 0; ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_GET_LINK_STATUS, &status); if (status == FTDM_HW_LINK_CONNECTED) { l1_cmd->cmd.status = 1; } else if (status == FTDM_HW_LINK_DISCONNECTED) { l1_cmd->cmd.status = 0; } else { ftdm_log_chan(signal_data->dchan, FTDM_LOG_CRIT, "Invalid link status reported %d\n", status); l1_cmd->cmd.status = 0; } } break; case SNG_L1CMD_FLUSH_STATS: ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_FLUSH_IOSTATS, NULL); break; case SNG_L1CMD_FLUSH_BUFFERS: ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_FLUSH_BUFFERS, NULL); break; default: ftdm_log_chan(signal_data->dchan, FTDM_LOG_CRIT, "Unsupported channel command:%d\n", l1_cmd->type); return -1; } return 0; }
static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event) { const char *command = switch_event_get_header(event, "command"); ctdm_private_t *tech_pvt = switch_core_session_get_private(session); if (!zstr(command)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeTDM received %s command \n",command); if (!strcasecmp(command, kPREBUFFER_LEN)) { const char *szval = switch_event_get_header(event, kPREBUFFER_LEN); int val = !zstr(szval) ? atoi(szval) : 0; if (tech_pvt->prebuffer_len == val) { tech_pvt->prebuffer_len = val; if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, &tech_pvt->prebuffer_len)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set channel pre buffer size.\n"); return SWITCH_STATUS_GENERR; } } } else if (!strcasecmp(command, kECHOCANCEL)) { const char *szval = switch_event_get_header(event, kECHOCANCEL); int enabled = !!switch_true(szval); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeTDM sending echo cancel [%s] command \n",enabled ? "enable" : "disable"); if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, enabled ? FTDM_COMMAND_ENABLE_ECHOCANCEL : FTDM_COMMAND_DISABLE_ECHOCANCEL, NULL)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to %s echo cancellation.\n", enabled ? "enable" : "disable"); } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeTDM received unknown command [%s] \n",command); } } return SWITCH_STATUS_SUCCESS; }
static void *test_call(ftdm_thread_t *me, void *obj) { ftdm_channel_t *chan = (ftdm_channel_t *) obj; uint8_t frame[1024]; ftdm_size_t len; char *number = strdup("5551212"); ftdm_sleep(10 * 1000); ftdm_log(FTDM_LOG_DEBUG, "answer call and start echo test\n"); ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_UP); ftdm_channel_command(chan, FTDM_COMMAND_SEND_DTMF, number); while (chan->state == FTDM_CHANNEL_STATE_UP) { ftdm_wait_flag_t flags = FTDM_READ; if (ftdm_channel_wait(chan, &flags, -1) == FTDM_FAIL) { break; } len = sizeof(frame); if (flags & FTDM_READ) { if (ftdm_channel_read(chan, frame, &len) == FTDM_SUCCESS) { //ftdm_log(FTDM_LOG_DEBUG, "WRITE %d\n", len); ftdm_channel_write(chan, frame, sizeof(frame), &len); } else { break; } } } if (chan->state == FTDM_CHANNEL_STATE_UP) { ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_BUSY); } ftdm_log(FTDM_LOG_DEBUG, "call over\n"); free(number); return NULL; }
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; }
int main(int argc, char *argv[]) { ftdm_global_set_default_logger(FTDM_LOG_LEVEL_DEBUG); ftdm_channel_t *chan; unsigned ms = 20; ftdm_codec_t codec = FTDM_CODEC_SLIN; unsigned runs = 1; int spanid, chanid; ftdm_unused_arg(argc); ftdm_unused_arg(argv); if (ftdm_global_init() != FTDM_SUCCESS) { fprintf(stderr, "Error loading FreeTDM\n"); exit(-1); } printf("FreeTDM loaded\n"); top: //if (ftdm_channel_open_any("wanpipe", 0, FTDM_TOP_DOWN, &chan) == FTDM_SUCCESS) { if (ftdm_channel_open(1, 1, &chan) == FTDM_SUCCESS) { int x = 0; spanid = ftdm_channel_get_span_id(chan); chanid = ftdm_channel_get_id(chan); printf("opened channel %d:%d\n", spanid, chanid); #if 1 if (ftdm_channel_command(chan, FTDM_COMMAND_SET_INTERVAL, &ms) == FTDM_SUCCESS) { ms = 0; ftdm_channel_command(chan, FTDM_COMMAND_GET_INTERVAL, &ms); printf("interval set to %u\n", ms); } else { printf("set interval failed [%s]\n", ftdm_channel_get_last_error(chan)); } #endif if (ftdm_channel_command(chan, FTDM_COMMAND_SET_CODEC, &codec) == FTDM_SUCCESS) { codec = 1; ftdm_channel_command(chan, FTDM_COMMAND_GET_CODEC, &codec); printf("codec set to %u\n", codec); } else { printf("set codec failed [%s]\n", ftdm_channel_get_last_error(chan)); } for(x = 0; x < 25; x++) { unsigned char buf[2048]; ftdm_size_t len = sizeof(buf); ftdm_wait_flag_t flags = FTDM_READ; if (ftdm_channel_wait(chan, &flags, -1) == FTDM_FAIL) { printf("wait FAIL! %u [%s]\n", (unsigned)len, ftdm_channel_get_last_error(chan)); } if (flags & FTDM_READ) { if (ftdm_channel_read(chan, buf, &len) == FTDM_SUCCESS) { printf("READ: %u\n", (unsigned)len); } else { printf("READ FAIL! %u [%s]\n", (unsigned)len, ftdm_channel_get_last_error(chan)); break; } } else { printf("wait fail [%s]\n", ftdm_channel_get_last_error(chan)); } } ftdm_channel_close(&chan); } else { printf("open fail [%s]\n", ftdm_channel_get_last_error(chan)); } if(--runs) { goto top; } ftdm_global_destroy(); return 0; }
static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, switch_caller_profile_t *outbound_profile, switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause) { const char *szchanid = switch_event_get_header(var_event, kCHAN_ID), *span_name = switch_event_get_header(var_event, kSPAN_NAME), *szprebuffer_len = switch_event_get_header(var_event, kPREBUFFER_LEN); int chan_id; int span_id; switch_caller_profile_t *caller_profile; ftdm_span_t *span; ftdm_channel_t *chan; switch_channel_t *channel; char name[128]; const char *dname; ftdm_codec_t codec; uint32_t interval; ctdm_private_t *tech_pvt = NULL; if (zstr(szchanid) || zstr(span_name)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Both ["kSPAN_ID"] and ["kCHAN_ID"] have to be set.\n"); goto fail; } chan_id = atoi(szchanid); if (ftdm_span_find_by_name(span_name, &span) == FTDM_SUCCESS) { span_id = ftdm_span_get_id(span); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find span [%s]\n", span_name); goto fail; } if (!(*new_session = switch_core_session_request(ctdm.endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, 0, pool))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't request session.\n"); goto fail; } channel = switch_core_session_get_channel(*new_session); if (ftdm_channel_open_ph(span_id, chan_id, &chan) != FTDM_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't open span or channel.\n"); goto fail; } span = ftdm_channel_get_span(chan); tech_pvt = switch_core_session_alloc(*new_session, sizeof *tech_pvt); tech_pvt->chan_id = chan_id; tech_pvt->span_id = span_id; tech_pvt->ftdm_channel = chan; tech_pvt->session = *new_session; tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf); tech_pvt->read_frame.data = tech_pvt->databuf; tech_pvt->prebuffer_len = zstr(szprebuffer_len) ? 0 : atoi(szprebuffer_len); switch_core_session_set_private(*new_session, tech_pvt); caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); switch_channel_set_caller_profile(channel, caller_profile); snprintf(name, sizeof(name), "tdm/%d:%d", span_id, chan_id); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connect outbound channel %s\n", name); switch_channel_set_name(channel, name); switch_channel_set_state(channel, CS_INIT); if (FTDM_SUCCESS != ftdm_channel_command(chan, FTDM_COMMAND_GET_CODEC, &codec)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to retrieve channel codec.\n"); return SWITCH_STATUS_GENERR; } if (FTDM_SUCCESS != ftdm_channel_command(chan, FTDM_COMMAND_GET_INTERVAL, &interval)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to retrieve channel interval.\n"); return SWITCH_STATUS_GENERR; } if (FTDM_SUCCESS != ftdm_channel_command(chan, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, &tech_pvt->prebuffer_len)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set channel pre buffer size.\n"); return SWITCH_STATUS_GENERR; } if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to set enable echo cancellation.\n"); } switch(codec) { case FTDM_CODEC_ULAW: { dname = "PCMU"; } break; case FTDM_CODEC_ALAW: { dname = "PCMA"; } break; case FTDM_CODEC_SLIN: { dname = "L16"; } break; default: { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid codec value retrieved from channel, codec value: %d\n", codec); goto fail; } } if (switch_core_codec_init(&tech_pvt->read_codec, dname, NULL, 8000, interval, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); goto fail; } else { if (switch_core_codec_init(&tech_pvt->write_codec, dname, NULL, 8000, interval, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); switch_core_codec_destroy(&tech_pvt->read_codec); goto fail; } } if (switch_core_session_set_read_codec(*new_session, &tech_pvt->read_codec) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set read codec?\n"); goto fail; } if (switch_core_session_set_write_codec(*new_session, &tech_pvt->write_codec) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set write codec?\n"); } if (switch_core_session_thread_launch(*new_session) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't start session thread.\n"); goto fail; } switch_channel_mark_answered(channel); return SWITCH_CAUSE_SUCCESS; fail: if (tech_pvt) { if (tech_pvt->ftdm_channel) { ftdm_channel_close(&tech_pvt->ftdm_channel); } if (tech_pvt->read_codec.implementation) { switch_core_codec_destroy(&tech_pvt->read_codec); } if (tech_pvt->write_codec.implementation) { switch_core_codec_destroy(&tech_pvt->write_codec); } } if (*new_session) { switch_core_session_destroy(new_session); } return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; }
static void ctdm_event_handler(switch_event_t *event) { ftdm_status_t status = FTDM_FAIL; switch(event->event_id) { case SWITCH_EVENT_TRAP: { ftdm_span_t *span = NULL; ftdm_channel_t *channel = NULL; const char *span_name = NULL; const char *cond = switch_event_get_header(event, "condition"); const char *command = switch_event_get_header(event, "command"); if (zstr(cond)) { return; } span_name = switch_event_get_header(event, "span-name"); if (ftdm_span_find_by_name(span_name, &span) != FTDM_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find span [%s]\n", span_name); return; } if (!strcmp(cond, "mg-tdm-prepare")) { status = ctdm_span_prepare(span); if (status == FTDM_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s:prepared successfully\n", span_name); } else if (status != FTDM_EINVAL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s:Failed to prepare span\n", span_name); } } else if (!strcmp(cond, "mg-tdm-check")) { channel = ctdm_get_channel_from_event(event, span); if (!channel) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find channel\n"); return; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Requesting alarm status for %s:%d\n", ftdm_channel_get_span_name(channel), ftdm_channel_get_id(channel)); ctdm_report_alarms(channel); } else if (!strcmp(cond, "mg-tdm-dtmfremoval")) { uint8_t enable = 0; channel = ctdm_get_channel_from_event(event, span); if (!channel) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find channel\n"); return; } if (zstr(command)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s:No command specified for mg-tdm-dtmfremoval\n", span_name); return; } if (!strcmp(command, "enable")) { enable = 1; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s DTMF-removal for %s:%d\n", enable ? "Enabling" : "Disabling", ftdm_channel_get_span_name(channel), ftdm_channel_get_id(channel)); ftdm_channel_command(channel, enable ? FTDM_COMMAND_ENABLE_DTMF_REMOVAL : FTDM_COMMAND_DISABLE_DTMF_REMOVAL, 0); } } break; default: break; } return; }
static ftdm_status_t att_courtesy_vru(ftdm_channel_t *ftdmchan, sngisdn_transfer_type_t type, char* args) { char dtmf_digits[64]; ftdm_status_t status = FTDM_FAIL; sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; char *p = args; uint8_t forced_answer = 0; switch (signal_data->switchtype) { case SNGISDN_SWITCH_5ESS: case SNGISDN_SWITCH_4ESS: break; default: ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "AT&T Courtesy Transfer not supported for switchtype\n"); return FTDM_FAIL; } while (!ftdm_strlen_zero(p)) { if (!isdigit(*p) && *p != 'w' && *p != 'W') { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot transfer to non-numeric number:%s\n", args); return FTDM_FAIL; } p++; } ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Performing AT&T Courtesy Transfer-VRU%s to %s\n", (type == SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA) ?"--data" : "", args); sprintf(dtmf_digits, "*8w%s", args); ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending digits %s\n", dtmf_digits); switch (ftdmchan->last_state) { case FTDM_CHANNEL_STATE_PROCEED: case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: /* Call has to be in answered state - so send a CONNECT message if we did not answer this call yet */ forced_answer++; sngisdn_snd_connect(ftdmchan); /* fall-through */ case FTDM_CHANNEL_STATE_UP: memset(&sngisdn_info->transfer_data.tdata.att_courtesy_vru.dtmf_digits, 0, sizeof(sngisdn_info->transfer_data.tdata.att_courtesy_vru.dtmf_digits)); sngisdn_info->transfer_data.type = type; /* We will be polling the channel for IO so that we can receive the DTMF events, * Disable user RX otherwise it is a race between who calls channel_read */ ftdm_set_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED); ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_DTMF_DETECT, NULL); ftdm_channel_command(ftdmchan, FTDM_COMMAND_SEND_DTMF, dtmf_digits); if (type == SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA) { /* We need to save transfer data, so we can send it in the disconnect msg */ const char *val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "transfer_data"); if (ftdm_strlen_zero(val)) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Cannot perform data transfer because transfer_data variable is not set\n"); goto done; } if (strlen(val) > COURTESY_TRANSFER_MAX_DATA_SIZE) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Data exceeds max size (len:%"FTDM_SIZE_FMT" max:%d), cannot perform transfer\n", strlen(val), COURTESY_TRANSFER_MAX_DATA_SIZE); goto done; } memcpy(sngisdn_info->transfer_data.tdata.att_courtesy_vru.data, val, strlen(val)); } ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); if (forced_answer) { /* Notify the user that we answered the call */ sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_UP); } if (signal_data->transfer_timeout) { ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "courtesy_transfer_timeout", signal_data->transfer_timeout, att_courtesy_transfer_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_CHAN_TIMER_ATT_TRANSFER]); } status = FTDM_SUCCESS; break; default: ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot perform transfer in state %s\n", ftdm_channel_state2str(ftdmchan->state)); break; } done: return status; }
static void launch_channel(struct sangoma_pri *spri, int channo) { pid_t pid; int fd = 0, file = 0, inlen = 0, outlen = 0; unsigned char inframe[MAX_BYTES], outframe[MAX_BYTES]; fd_set readfds; int mtu_mru=BYTES / 2; int err; ftdm_channel_t *chan; ftdm_codec_t codec = FTDM_CODEC_SLIN; unsigned ms = 20; unsigned int lead = 50; int ifd = -1; ftdm_tone_type_t tt = FTDM_TONE_DTMF; char dtmf[] = "1234567890"; int loops = 0; pid = fork(); if (pid) { pidmap[channo-1].pid = pid; printf("-- Launching process %d to handle channel %d\n", pid, channo); return; } signal(SIGINT, handle_SIGINT); //ifd = open("/nfs/sounds/ptest.raw", O_WRONLY|O_CREAT|O_TRUNC, 777); memset(inframe, 0, MAX_BYTES); memset(outframe, 0, MAX_BYTES); if (ftdm_channel_open(spri->span, channo, &chan) != FTDM_SUCCESS) { printf("DEBUG cant open fd!\n"); } #if 1 if (ftdm_channel_command(chan, FTDM_COMMAND_SET_CODEC, &codec) != FTDM_SUCCESS) { printf("Critical Error: Failed to set driver codec!\n"); ftdm_channel_close(&chan); exit(-1); } #endif #if 1 if (ftdm_channel_command(chan, FTDM_COMMAND_ENABLE_DTMF_DETECT, &tt) != FTDM_SUCCESS) { printf("Critical Error: Failed to set dtmf detect!\n"); ftdm_channel_close(&chan); exit(-1); } ftdm_channel_set_event_callback(chan, my_ftdm_event_handler); #endif if (ftdm_channel_command(chan, FTDM_COMMAND_SET_INTERVAL, &ms) != FTDM_SUCCESS) { printf("Critical Error: Failed to set codec interval!\n"); ftdm_channel_close(&chan); exit(-1); } file = open("sound.raw", O_RDONLY); if (file < 0) { printf("Critical Error: Failed to open sound file!\n"); ftdm_channel_close(&chan); exit(-1); } while(ready) { ftdm_wait_flag_t flags = FTDM_READ; ftdm_size_t len; loops++; if (lead) { lead--; } if (!lead && loops == 300) { #if 1 if (ftdm_channel_command(chan, FTDM_COMMAND_SEND_DTMF, dtmf) != FTDM_SUCCESS) { printf("Critical Error: Failed to send dtmf\n"); ftdm_channel_close(&chan); exit(-1); } #endif } if (ftdm_channel_wait(chan, &flags, 2000) != FTDM_SUCCESS) { printf("wait FAIL! [%s]\n", chan->last_error); break; } if (flags & FTDM_READ) { len = MAX_BYTES; if (ftdm_channel_read(chan, inframe, &len) == FTDM_SUCCESS) { //printf("READ: %d\n", len); //write(ifd, inframe, len); if(!lead && (outlen = read(file, outframe, len)) <= 0) { break; } } else { printf("READ FAIL! %d [%s]\n", len, chan->last_error); break; } if (lead) { continue; } ftdm_channel_write(chan, outframe, sizeof(outframe), &len); } else { printf("BREAK"); break; } } printf("loop done\n"); //sangoma_get_full_cfg(fd, &tdm_api); close(file); //close(ifd); pri_hangup(spri->pri, channo, 16); if (ftdm_channel_close(&chan) != FTDM_SUCCESS) { printf("Critical Error: Failed to close channel [%s]\n", chan->last_error); } printf("Call Handler: Process Finished\n"); exit(0); }