mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-25 20:54:15 +00:00
Merge branch 'smgmaster' into releases.3.4.experimental_head
Conflicts: libs/freetdm/mod_freetdm/mod_freetdm.c libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c src/mod/endpoints/mod_sofia/mod_sofia.c src/mod/endpoints/mod_sofia/sofia_glue.c
This commit is contained in:
commit
7bd2d154d6
615 files changed
+41286
-47127
No files matched your search
@@ -6,7 +6,7 @@ int main(int argc, char *argv[])
|
||||
int fd, b;
|
||||
short sln[512] = {0};
|
||||
teletone_dtmf_detect_state_t dtmf_detect = {0};
|
||||
char digit_str[128] = "";
|
||||
teletone_hit_type_t hit;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Arg Error!\n");
|
||||
@@ -21,10 +21,31 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
while((b = read(fd, sln, 320)) > 0) {
|
||||
char digit_char;
|
||||
unsigned int dur;
|
||||
|
||||
teletone_dtmf_detect(&dtmf_detect, sln, b / 2);
|
||||
teletone_dtmf_get(&dtmf_detect, digit_str, sizeof(digit_str));
|
||||
if (*digit_str) {
|
||||
printf("digit: %s\n", digit_str);
|
||||
if ((hit = teletone_dtmf_get(&dtmf_detect, &digit_char, &dur))) {
|
||||
const char *hs = NULL;
|
||||
|
||||
|
||||
switch(hit) {
|
||||
case TT_HIT_BEGIN:
|
||||
hs = "begin";
|
||||
break;
|
||||
|
||||
case TT_HIT_MIDDLE:
|
||||
hs = "middle";
|
||||
break;
|
||||
|
||||
case TT_HIT_END:
|
||||
hs = "end";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
printf("%s digit: %c\n", hs, digit_char);
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
|
||||
+30
-15
@@ -649,9 +649,6 @@ static ftdm_status_t ftdm_span_destroy(ftdm_span_t *span)
|
||||
if (span->fio->span_destroy(span) != FTDM_SUCCESS) {
|
||||
status = FTDM_FAIL;
|
||||
}
|
||||
ftdm_safe_free(span->type);
|
||||
ftdm_safe_free(span->name);
|
||||
ftdm_safe_free(span->dtmf_hangup);
|
||||
}
|
||||
|
||||
/* destroy final basic resources of the span data structure */
|
||||
@@ -1858,7 +1855,14 @@ static ftdm_status_t _ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm
|
||||
goto done;
|
||||
}
|
||||
|
||||
ftdm_mutex_lock(check->mutex);
|
||||
ftdm_channel_lock(check);
|
||||
|
||||
if (ftdm_test_flag(check, FTDM_CHANNEL_OPEN)) {
|
||||
/* let them know is already open, but return the channel anyway */
|
||||
status = FTDM_EBUSY;
|
||||
*ftdmchan = check;
|
||||
goto unlockchan;
|
||||
}
|
||||
|
||||
/* The following if's and gotos replace a big if (this || this || this || this) else { nothing; } */
|
||||
|
||||
@@ -1905,7 +1909,7 @@ openchan:
|
||||
goto done;
|
||||
|
||||
unlockchan:
|
||||
ftdm_mutex_unlock(check->mutex);
|
||||
ftdm_channel_unlock(check);
|
||||
|
||||
done:
|
||||
ftdm_mutex_unlock(globals.mutex);
|
||||
@@ -3855,7 +3859,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v
|
||||
uint8_t sln_buf[1024] = {0};
|
||||
int16_t *sln;
|
||||
ftdm_size_t slen = 0;
|
||||
char digit_str[80] = "";
|
||||
|
||||
if (ftdmchan->effective_codec == FTDM_CODEC_SLIN) {
|
||||
sln = data;
|
||||
@@ -3956,13 +3959,20 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v
|
||||
}
|
||||
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT) && !ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
|
||||
teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen);
|
||||
teletone_dtmf_get(&ftdmchan->dtmf_detect, digit_str, sizeof(digit_str));
|
||||
teletone_hit_type_t hit;
|
||||
char digit_char;
|
||||
uint32_t dur;
|
||||
|
||||
if(*digit_str) {
|
||||
if (ftdmchan->state == FTDM_CHANNEL_STATE_CALLWAITING && (*digit_str == 'D' || *digit_str == 'A')) {
|
||||
if ((hit = teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen)) == TT_HIT_END) {
|
||||
teletone_dtmf_get(&ftdmchan->dtmf_detect, &digit_char, &dur);
|
||||
|
||||
if (ftdmchan->state == FTDM_CHANNEL_STATE_CALLWAITING && (digit_char == 'D' || digit_char == 'A')) {
|
||||
ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK]++;
|
||||
} else {
|
||||
char digit_str[2] = { 0 };
|
||||
|
||||
digit_str[0] = digit_char;
|
||||
|
||||
if (!ftdmchan->span->sig_dtmf || (ftdmchan->span->sig_dtmf(ftdmchan, (const char*)digit_str) != FTDM_BREAK)) {
|
||||
ftdm_channel_queue_dtmf(ftdmchan, digit_str);
|
||||
}
|
||||
@@ -4568,7 +4578,7 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const
|
||||
*configured = 0;
|
||||
*configured = span->fio->configure_span(span, str, chan_config->type, chan_config->name, chan_config->number);
|
||||
if (!*configured) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "%d:Failed to configure span", span->span_id);
|
||||
ftdm_log(FTDM_LOG_ERROR, "%d:Failed to configure span\n", span->span_id);
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
@@ -5469,10 +5479,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
|
||||
if (sigmsg->channel) {
|
||||
fchan = sigmsg->channel;
|
||||
ftdm_channel_lock(fchan);
|
||||
sigmsg->chan_id = fchan->chan_id;
|
||||
sigmsg->span_id = fchan->span_id;
|
||||
sigmsg->call_id = fchan->caller_data.call_id;
|
||||
sigmsg->call_priv = fchan->caller_data.priv;
|
||||
}
|
||||
|
||||
/* some core things to do on special events */
|
||||
@@ -5562,6 +5568,14 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
|
||||
|
||||
}
|
||||
|
||||
if (fchan) {
|
||||
/* set members of the sigmsg that must be present for all events */
|
||||
sigmsg->chan_id = fchan->chan_id;
|
||||
sigmsg->span_id = fchan->span_id;
|
||||
sigmsg->call_id = fchan->caller_data.call_id;
|
||||
sigmsg->call_priv = fchan->caller_data.priv;
|
||||
}
|
||||
|
||||
/* if the signaling module uses a queue for signaling notifications, then enqueue it */
|
||||
if (ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE)) {
|
||||
ftdm_span_queue_signal(span, sigmsg);
|
||||
@@ -5783,6 +5797,7 @@ FT_DECLARE(ftdm_status_t) ftdm_global_destroy(void)
|
||||
}
|
||||
|
||||
hashtable_remove(globals.span_hash, (void *)cur_span->name);
|
||||
ftdm_safe_free(cur_span->dtmf_hangup);
|
||||
ftdm_safe_free(cur_span->type);
|
||||
ftdm_safe_free(cur_span->name);
|
||||
ftdm_safe_free(cur_span);
|
||||
|
||||
@@ -39,7 +39,8 @@ typedef enum {
|
||||
FTDM_ANALOG_RUNNING = (1 << 0),
|
||||
FTDM_ANALOG_CALLERID = (1 << 1),
|
||||
FTDM_ANALOG_ANSWER_POLARITY_REVERSE = (1 << 2),
|
||||
FTDM_ANALOG_HANGUP_POLARITY_REVERSE = (1 << 3)
|
||||
FTDM_ANALOG_HANGUP_POLARITY_REVERSE = (1 << 3),
|
||||
FTDM_ANALOG_POLARITY_CALLERID = (1 << 4)
|
||||
} ftdm_analog_flag_t;
|
||||
|
||||
#define FTDM_MAX_HOTLINE_STR 20
|
||||
|
||||
@@ -275,6 +275,15 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
|
||||
break;
|
||||
}
|
||||
hotline = val;
|
||||
} else if (!strcasecmp(var, "polarity_callerid")) {
|
||||
if (!(val = va_arg(ap, char *))) {
|
||||
break;
|
||||
}
|
||||
if (ftdm_true(val)) {
|
||||
flags |= FTDM_ANALOG_POLARITY_CALLERID;
|
||||
} else {
|
||||
flags &= ~FTDM_ANALOG_POLARITY_CALLERID;
|
||||
}
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Unknown parameter %s in span %s\n", var, span->name);
|
||||
}
|
||||
@@ -1130,8 +1139,18 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
|
||||
break;
|
||||
}
|
||||
if (event->channel->state == FTDM_CHANNEL_STATE_DOWN) {
|
||||
ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG,
|
||||
"Ignoring polarity reversal because this channel is down\n");
|
||||
if (ftdm_test_flag(analog_data, FTDM_ANALOG_CALLERID)
|
||||
&& ftdm_test_flag(analog_data, FTDM_ANALOG_POLARITY_CALLERID)) {
|
||||
ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG, "Polarity reversal detected while down, getting caller id now\n");
|
||||
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_GET_CALLERID);
|
||||
event->channel->ring_count = 1;
|
||||
ftdm_mutex_unlock(event->channel->mutex);
|
||||
locked = 0;
|
||||
ftdm_thread_create_detached(ftdm_analog_channel_run, event->channel);
|
||||
} else {
|
||||
ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG,
|
||||
"Ignoring polarity reversal because this channel is down\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* we have a good channel, set the polarity flag and let the channel thread deal with it */
|
||||
|
||||
@@ -204,6 +204,32 @@ static int parse_debug(const char *in, uint32_t *flags)
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Parses a change status string to flags
|
||||
* \param in change status string to parse for
|
||||
* \return Flags
|
||||
*/
|
||||
static int parse_change_status(const char *in)
|
||||
{
|
||||
int flags = 0;
|
||||
if (!in) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strstr(in, "in_service") || strstr(in, "in")) {
|
||||
flags = SERVICE_CHANGE_STATUS_INSERVICE;
|
||||
}
|
||||
if (strstr(in, "maintenance") || strstr(in, "maint")) {
|
||||
flags = SERVICE_CHANGE_STATUS_MAINTENANCE;
|
||||
}
|
||||
if (strstr(in, "out_of_service") || strstr(in, "out")) {
|
||||
flags = SERVICE_CHANGE_STATUS_OUTOFSERVICE;
|
||||
}
|
||||
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static int print_debug(uint32_t flags, char *tmp, const int size)
|
||||
{
|
||||
int offset = 0;
|
||||
@@ -240,6 +266,9 @@ static ftdm_io_interface_t ftdm_libpri_interface;
|
||||
static const char *ftdm_libpri_usage =
|
||||
"Usage:\n"
|
||||
"libpri kill <span>\n"
|
||||
"libpri reset <span>\n"
|
||||
"libpri restart <span> <channel/all>\n"
|
||||
"libpri maintenance <span> <channel/all> <in/maint/out>\n"
|
||||
"libpri debug <span> [all|none|flag,...flagN]\n"
|
||||
"\n"
|
||||
"Possible debug flags:\n"
|
||||
@@ -281,9 +310,7 @@ static FIO_API_FUNCTION(ftdm_libpri_api)
|
||||
stream->write_function(stream, ftdm_libpri_usage);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc == 2) {
|
||||
} else if (argc == 2) {
|
||||
if (!strcasecmp(argv[0], "kill")) {
|
||||
int span_id = atoi(argv[1]);
|
||||
ftdm_span_t *span = NULL;
|
||||
@@ -292,7 +319,8 @@ static FIO_API_FUNCTION(ftdm_libpri_api)
|
||||
ftdm_libpri_data_t *isdn_data = span->signal_data;
|
||||
|
||||
if (span->start != ftdm_libpri_start) {
|
||||
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
|
||||
stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n",
|
||||
__FILE__, ftdm_span_get_name(span));
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -300,13 +328,12 @@ static FIO_API_FUNCTION(ftdm_libpri_api)
|
||||
stream->write_function(stream, "%s: +OK killed.\n", __FILE__);
|
||||
goto done;
|
||||
} else {
|
||||
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
|
||||
stream->write_function(stream, "%s: -ERR span '%s' not found.\n",
|
||||
__FILE__, argv[0]);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (argc >= 2) {
|
||||
} else if (argc >= 2) {
|
||||
if (!strcasecmp(argv[0], "debug")) {
|
||||
ftdm_span_t *span = NULL;
|
||||
|
||||
@@ -315,7 +342,8 @@ static FIO_API_FUNCTION(ftdm_libpri_api)
|
||||
uint32_t flags = 0;
|
||||
|
||||
if (span->start != ftdm_libpri_start) {
|
||||
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
|
||||
stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n",
|
||||
__FILE__, ftdm_span_get_name(span));
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -335,12 +363,95 @@ static FIO_API_FUNCTION(ftdm_libpri_api)
|
||||
stream->write_function(stream, "%s: +OK debug %s.\n", __FILE__, (flags) ? "enabled" : "disabled");
|
||||
goto done;
|
||||
} else {
|
||||
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
|
||||
stream->write_function(stream, "%s: -ERR span '%s' not found.\n",
|
||||
__FILE__, argv[0]);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (!strcasecmp(argv[0], "reset")) {
|
||||
ftdm_span_t *span = NULL;
|
||||
if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) {
|
||||
ftdm_libpri_data_t *isdn_data = span->signal_data;
|
||||
|
||||
if (span->start != ftdm_libpri_start) {
|
||||
stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n",
|
||||
__FILE__, ftdm_span_get_name(span));
|
||||
goto done;
|
||||
}
|
||||
|
||||
pri_restart(isdn_data->spri.pri);
|
||||
stream->write_function(stream, "%s: +OK reset.\n", __FILE__);
|
||||
goto done;
|
||||
} else {
|
||||
stream->write_function(stream, "%s: -ERR span '%s' not found.\n",
|
||||
__FILE__, argv[0]);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (!strcasecmp(argv[0], "restart") && argc == 3) {
|
||||
ftdm_span_t *span = NULL;
|
||||
if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) {
|
||||
ftdm_libpri_data_t *isdn_data = span->signal_data;
|
||||
|
||||
if (span->start != ftdm_libpri_start) {
|
||||
stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n",
|
||||
__FILE__, ftdm_span_get_name(span));
|
||||
goto done;
|
||||
}
|
||||
if (!strcasecmp(argv[2], "all")) {
|
||||
int j;
|
||||
for(j = 1; j <= span->chan_count; j++) {
|
||||
pri_reset(isdn_data->spri.pri, j);
|
||||
ftdm_sleep(50);
|
||||
}
|
||||
} else {
|
||||
pri_reset(isdn_data->spri.pri, atoi(argv[2]));
|
||||
}
|
||||
stream->write_function(stream, "%s: +OK restart set.\n", __FILE__);
|
||||
goto done;
|
||||
} else {
|
||||
stream->write_function(stream, "%s: -ERR span '%s' not found.\n",
|
||||
__FILE__, argv[0]);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (!strcasecmp(argv[0], "maintenance") && argc > 3) {
|
||||
ftdm_span_t *span = NULL;
|
||||
if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) {
|
||||
ftdm_libpri_data_t *isdn_data = span->signal_data;
|
||||
|
||||
if (span->start != ftdm_libpri_start) {
|
||||
stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n",
|
||||
__FILE__, ftdm_span_get_name(span));
|
||||
goto done;
|
||||
}
|
||||
if (!isdn_data->service_message_support) {
|
||||
stream->write_function(stream, "%s: -ERR service message support is disabled\n", __FILE__);
|
||||
goto done;
|
||||
}
|
||||
if (!strcasecmp(argv[2], "all")) {
|
||||
int j;
|
||||
for(j = 1; j <= span->chan_count; j++) {
|
||||
pri_maintenance_service(isdn_data->spri.pri, atoi(argv[1]), j, parse_change_status(argv[3]));
|
||||
ftdm_sleep(50);
|
||||
}
|
||||
} else {
|
||||
pri_maintenance_service(isdn_data->spri.pri, atoi(argv[1]), atoi(argv[2]), parse_change_status(argv[3]));
|
||||
}
|
||||
stream->write_function(stream, "%s: +OK change status set.\n", __FILE__);
|
||||
goto done;
|
||||
} else {
|
||||
stream->write_function(stream, "%s: -ERR span '%s' not found.\n",
|
||||
__FILE__, argv[0]);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* zero args print usage */
|
||||
stream->write_function(stream, ftdm_libpri_usage);
|
||||
goto done;
|
||||
}
|
||||
|
||||
stream->write_function(stream, "%s: -ERR invalid command.\n", __FILE__);
|
||||
|
||||
done:
|
||||
@@ -1066,7 +1177,7 @@ static int on_proceeding(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_
|
||||
|
||||
if (chan) {
|
||||
/* Open channel if inband information is available */
|
||||
if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
|
||||
if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE || pevent->proceeding.progressmask & PRI_PROG_CALL_NOT_E2E_ISDN) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, B-Channel %d:%d\n",
|
||||
ftdm_channel_get_span_id(chan),
|
||||
ftdm_channel_get_id(chan));
|
||||
@@ -1108,7 +1219,7 @@ static int on_progress(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev
|
||||
|
||||
if (chan) {
|
||||
/* Open channel if inband information is available */
|
||||
if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
|
||||
if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE || pevent->proceeding.progressmask & PRI_PROG_CALL_NOT_E2E_ISDN) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, B-Channel %d:%d\n",
|
||||
ftdm_channel_get_span_id(chan),
|
||||
ftdm_channel_get_id(chan));
|
||||
@@ -1780,6 +1891,10 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
|
||||
pri_facility_enable(isdn_data->spri.pri);
|
||||
}
|
||||
#endif
|
||||
/* Support the different switch of service status */
|
||||
if (isdn_data->service_message_support) {
|
||||
pri_set_service_message_support(isdn_data->spri.pri, 1 /* True */);
|
||||
}
|
||||
|
||||
if (res == 0) {
|
||||
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANY, on_anything);
|
||||
@@ -1835,6 +1950,14 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
|
||||
ftdm_sleep(5000);
|
||||
}
|
||||
out:
|
||||
/* close d-channel, if set */
|
||||
if (isdn_data->dchan) {
|
||||
if (ftdm_channel_close(&isdn_data->dchan) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Failed to close D-Channel %d:%d\n",
|
||||
ftdm_channel_get_span_id(isdn_data->dchan), ftdm_channel_get_id(isdn_data->dchan));
|
||||
}
|
||||
}
|
||||
|
||||
ftdm_log(FTDM_LOG_DEBUG, "PRI thread ended on span %d\n", ftdm_span_get_id(span));
|
||||
|
||||
ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
|
||||
@@ -2159,6 +2282,11 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
|
||||
isdn_data->debug_mask = 0;
|
||||
}
|
||||
}
|
||||
else if (!strcasecmp(var, "service_message_support")) {
|
||||
if (ftdm_true(val)) {
|
||||
isdn_data->service_message_support = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Unknown parameter '%s', aborting configuration\n", var);
|
||||
snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var);
|
||||
|
||||
@@ -31,6 +31,11 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
SERVICE_CHANGE_STATUS_INSERVICE = 0,
|
||||
SERVICE_CHANGE_STATUS_MAINTENANCE = 1,
|
||||
SERVICE_CHANGE_STATUS_OUTOFSERVICE = 2
|
||||
} service_change_status_t;
|
||||
|
||||
#ifndef FTMOD_LIBPRI_H
|
||||
#define FTMOD_LIBPRI_H
|
||||
@@ -69,6 +74,7 @@ struct ftdm_libpri_data {
|
||||
int overlap; /*!< Overlap dial flags */
|
||||
unsigned int layer1;
|
||||
unsigned int ton;
|
||||
unsigned int service_message_support;
|
||||
|
||||
lpwrap_pri_t spri;
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -547,7 +547,7 @@ static void handle_pri_passive_event(pritap_t *pritap, pri_event *e)
|
||||
break;
|
||||
|
||||
case PRI_EVENT_PROGRESS:
|
||||
crv = tap_pri_get_crv(pritap->pri, e->ring.call);
|
||||
crv = tap_pri_get_crv(pritap->pri, e->proceeding.call);
|
||||
ftdm_log(FTDM_LOG_DEBUG, "Progress on channel %s:%d:%d with callref %d\n",
|
||||
pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
|
||||
break;
|
||||
|
||||
@@ -1155,6 +1155,77 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
if (span_data->cid_name_method == SNGISDN_CID_NAME_AUTO) {
|
||||
switch (span_data->switchtype) {
|
||||
case SNGISDN_SWITCH_EUROISDN:
|
||||
if (FTDM_SPAN_IS_BRI(span)) {
|
||||
span_data->cid_name_method = SNGISDN_CID_NAME_USR_USR_IE;
|
||||
} else {
|
||||
span_data->cid_name_method = SNGISDN_CID_NAME_DISPLAY_IE;
|
||||
}
|
||||
break;
|
||||
case SNGISDN_SWITCH_DMS100:
|
||||
span_data->cid_name_method = SNGISDN_CID_NAME_DISPLAY_IE;
|
||||
break;
|
||||
case SNGISDN_SWITCH_NI2:
|
||||
case SNGISDN_SWITCH_5ESS:
|
||||
case SNGISDN_SWITCH_4ESS:
|
||||
span_data->cid_name_method = SNGISDN_CID_NAME_FACILITY_IE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (span_data->send_cid_name == SNGISDN_OPT_DEFAULT) {
|
||||
switch (span_data->switchtype) {
|
||||
case SNGISDN_SWITCH_EUROISDN:
|
||||
#ifdef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY
|
||||
case SNGISDN_SWITCH_NI2:
|
||||
case SNGISDN_SWITCH_5ESS:
|
||||
case SNGISDN_SWITCH_4ESS:
|
||||
#endif
|
||||
if (span_data->signalling == SNGISDN_SIGNALING_NET) {
|
||||
span_data->send_cid_name = SNGISDN_OPT_TRUE;
|
||||
} else {
|
||||
span_data->send_cid_name = SNGISDN_OPT_FALSE;
|
||||
}
|
||||
break;
|
||||
case SNGISDN_SWITCH_DMS100:
|
||||
span_data->send_cid_name = SNGISDN_OPT_TRUE;
|
||||
break;
|
||||
#ifndef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY
|
||||
case SNGISDN_SWITCH_NI2:
|
||||
case SNGISDN_SWITCH_5ESS:
|
||||
case SNGISDN_SWITCH_4ESS:
|
||||
span_data->send_cid_name = SNGISDN_OPT_FALSE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
span_data->send_cid_name = SNGISDN_OPT_FALSE;
|
||||
break;
|
||||
}
|
||||
} else if (span_data->send_cid_name == SNGISDN_OPT_TRUE) {
|
||||
switch (span_data->switchtype) {
|
||||
case SNGISDN_SWITCH_NI2:
|
||||
case SNGISDN_SWITCH_5ESS:
|
||||
case SNGISDN_SWITCH_4ESS:
|
||||
#ifndef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY
|
||||
ftdm_log(FTDM_LOG_WARNING, "Sending Calling Name in Facility IE not supported, please update your libsng_isdn library\n");
|
||||
span_data->send_cid_name = SNGISDN_OPT_FALSE;
|
||||
#endif
|
||||
break;
|
||||
case SNGISDN_SWITCH_INSNET: /* Don't know how to transmit caller ID name on INSNET */
|
||||
case SNGISDN_SWITCH_QSIG: /* It seems like QSIG does not support Caller ID */
|
||||
span_data->send_cid_name = SNGISDN_OPT_FALSE;
|
||||
break;
|
||||
case SNGISDN_SWITCH_EUROISDN:
|
||||
break;
|
||||
default:
|
||||
span_data->send_cid_name = SNGISDN_OPT_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
span->start = ftdm_sangoma_isdn_start;
|
||||
span->stop = ftdm_sangoma_isdn_stop;
|
||||
|
||||
@@ -132,6 +132,13 @@ typedef enum {
|
||||
SNGISDN_AVAIL_UP = 10,
|
||||
} sngisdn_avail_t;
|
||||
|
||||
typedef enum {
|
||||
SNGISDN_CID_NAME_AUTO,
|
||||
SNGISDN_CID_NAME_DISPLAY_IE,
|
||||
SNGISDN_CID_NAME_USR_USR_IE,
|
||||
SNGISDN_CID_NAME_FACILITY_IE,
|
||||
} sngisdn_cid_name_t;
|
||||
|
||||
typedef enum {
|
||||
SNGISDN_EVENT_CON_IND = 1,
|
||||
SNGISDN_EVENT_CON_CFM,
|
||||
@@ -264,6 +271,8 @@ typedef struct sngisdn_span_data {
|
||||
uint8_t restart_opt;
|
||||
uint8_t restart_timeout;
|
||||
uint8_t force_sending_complete;
|
||||
uint8_t cid_name_method;
|
||||
uint8_t send_cid_name;
|
||||
char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS];
|
||||
ftdm_timer_id_t timers[SNGISDN_NUM_SPAN_TIMERS];
|
||||
ftdm_sched_t *sched;
|
||||
|
||||
@@ -289,6 +289,9 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
|
||||
signal_data->att_remove_dtmf = SNGISDN_OPT_DEFAULT;
|
||||
signal_data->force_sending_complete = SNGISDN_OPT_DEFAULT;
|
||||
|
||||
signal_data->cid_name_method = SNGISDN_CID_NAME_AUTO;
|
||||
signal_data->send_cid_name = SNGISDN_OPT_DEFAULT;
|
||||
|
||||
span->default_caller_data.dnis.plan = FTDM_NPI_INVALID;
|
||||
span->default_caller_data.dnis.type = FTDM_TON_INVALID;
|
||||
span->default_caller_data.cid_num.plan = FTDM_NPI_INVALID;
|
||||
@@ -361,7 +364,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
|
||||
parse_yesno(var, val, &signal_data->restart_opt);
|
||||
} else if (!strcasecmp(var, "channel-restart-timeout")) {
|
||||
signal_data->restart_timeout = atoi(val);
|
||||
} else if (!strcasecmp(var, "local-number")) {
|
||||
} else if (!strcasecmp(var, "local-number")) {
|
||||
if (add_local_number(val, span) != FTDM_SUCCESS) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
@@ -401,6 +404,30 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
|
||||
#else
|
||||
ftdm_log(FTDM_LOG_WARNING, "chan-id-invert-extend-bit is not supported in your version of libsng_isdn\n");
|
||||
#endif
|
||||
} else if (!strcasecmp(var, "cid-name-transmit-method")) {
|
||||
if (!strcasecmp(val, "display-ie")) {
|
||||
signal_data->cid_name_method = SNGISDN_CID_NAME_DISPLAY_IE;
|
||||
} else if (!strcasecmp(val, "user-user-ie")) {
|
||||
signal_data->cid_name_method = SNGISDN_CID_NAME_USR_USR_IE;
|
||||
} else if (!strcasecmp(val, "facility-ie")) {
|
||||
signal_data->cid_name_method = SNGISDN_CID_NAME_FACILITY_IE;
|
||||
} else if (!strcasecmp(val, "auto") || !strcasecmp(val, "automatic") || !strcasecmp(val, "default")) {
|
||||
signal_data->cid_name_method = SNGISDN_CID_NAME_AUTO;
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_WARNING, "Invalid option %s for parameter %s\n", val, var);
|
||||
signal_data->cid_name_method = SNGISDN_CID_NAME_AUTO;
|
||||
}
|
||||
} else if (!strcasecmp(var, "send-cid-name")) {
|
||||
if (!strcasecmp(val, "yes")) {
|
||||
signal_data->send_cid_name = SNGISDN_OPT_TRUE;
|
||||
} else if (!strcasecmp(val, "no")) {
|
||||
signal_data->send_cid_name = SNGISDN_OPT_FALSE;
|
||||
} else if (!strcasecmp(val, "auto") || !strcasecmp(val, "automatic") || !strcasecmp(val, "default")) {
|
||||
signal_data->send_cid_name = SNGISDN_OPT_DEFAULT;
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_WARNING, "Invalid option %s for parameter %s\n", val, var);
|
||||
signal_data->send_cid_name = SNGISDN_OPT_DEFAULT;
|
||||
}
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
|
||||
}
|
||||
|
||||
@@ -681,7 +681,11 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
|
||||
cfg.t.cfg.s.inDLSAP.clrGlr = FALSE; /* in case of glare, do not clear local call */
|
||||
cfg.t.cfg.s.inDLSAP.statEnqOpt = TRUE;
|
||||
|
||||
cfg.t.cfg.s.inDLSAP.rstOpt = TRUE;
|
||||
if (signal_data->ftdm_span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
|
||||
cfg.t.cfg.s.inDLSAP.rstOpt = FALSE;
|
||||
} else {
|
||||
cfg.t.cfg.s.inDLSAP.rstOpt = TRUE;
|
||||
}
|
||||
} else {
|
||||
cfg.t.cfg.s.inDLSAP.ackOpt = FALSE;
|
||||
cfg.t.cfg.s.inDLSAP.intType = USER;
|
||||
@@ -772,15 +776,13 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
|
||||
cfg.t.cfg.s.inDLSAP.tmr.t307.val = 35;
|
||||
cfg.t.cfg.s.inDLSAP.tmr.t308.enb = TRUE;
|
||||
cfg.t.cfg.s.inDLSAP.tmr.t308.val = 4;
|
||||
cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE;
|
||||
cfg.t.cfg.s.inDLSAP.tmr.t310.val = 120;
|
||||
|
||||
if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
|
||||
cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE;
|
||||
cfg.t.cfg.s.inDLSAP.tmr.t310.val = 10;
|
||||
cfg.t.cfg.s.inDLSAP.tmr.t312.enb = TRUE;
|
||||
cfg.t.cfg.s.inDLSAP.tmr.t312.val = cfg.t.cfg.s.inDLSAP.tmr.t303.val+2;
|
||||
} else {
|
||||
cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE;
|
||||
cfg.t.cfg.s.inDLSAP.tmr.t310.val = 120;
|
||||
cfg.t.cfg.s.inDLSAP.tmr.t312.enb = FALSE;
|
||||
}
|
||||
|
||||
@@ -846,7 +848,7 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
|
||||
cfg.t.cfg.s.inDLSAP.dChannelNum = 0; /* Unused for BRI */
|
||||
cfg.t.cfg.s.inDLSAP.nmbBearChan = NUM_BRI_CHANNELS_PER_SPAN;
|
||||
cfg.t.cfg.s.inDLSAP.firstBChanNum = 1;
|
||||
cfg.t.cfg.s.inDLSAP.callRefLen = 1;
|
||||
cfg.t.cfg.s.inDLSAP.callRefLen = 1;
|
||||
cfg.t.cfg.s.inDLSAP.teiAlloc = IN_STATIC;
|
||||
cfg.t.cfg.s.inDLSAP.intCfg = IN_INTCFG_PTPT;
|
||||
break;
|
||||
@@ -902,7 +904,14 @@ ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span)
|
||||
|
||||
cfg.t.cfg.s.inLCe.sapId = signal_data->dchan_id;
|
||||
|
||||
cfg.t.cfg.s.inLCe.lnkUpDwnInd = TRUE;
|
||||
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
|
||||
/* Stack will send Restart CFM's each time link is established (TEI negotiated),
|
||||
and we do not want thi s event */
|
||||
cfg.t.cfg.s.inLCe.lnkUpDwnInd = FALSE;
|
||||
} else {
|
||||
cfg.t.cfg.s.inLCe.lnkUpDwnInd = TRUE;
|
||||
}
|
||||
|
||||
cfg.t.cfg.s.inLCe.tCon.enb = TRUE;
|
||||
cfg.t.cfg.s.inLCe.tCon.val = 35;
|
||||
cfg.t.cfg.s.inLCe.tDisc.enb = TRUE;
|
||||
|
||||
@@ -1178,7 +1178,16 @@ void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
|
||||
ftdm_log(FTDM_LOG_CRIT, "Received RESTART CFM on unconfigured span (suId:%d)\n", suId);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%s: Processing RESTART CFM (suId:%u dChan:%d ces:%d %s(%d))\n",
|
||||
signal_data->ftdm_span->name,
|
||||
suId, dChan, ces,
|
||||
(evntType == IN_LNK_DWN)?"LNK_DOWN":
|
||||
(evntType == IN_LNK_UP)?"LNK_UP":
|
||||
(evntType == IN_INDCHAN)?"b-channel":
|
||||
(evntType == IN_LNK_DWN_DM_RLS)?"NFAS service procedures":
|
||||
(evntType == IN_SWCHD_BU_DCHAN)?"NFAS switchover to backup":"Unknown", evntType);
|
||||
|
||||
if (rstEvnt->rstInd.eh.pres == PRSNT_NODEF && rstEvnt->rstInd.rstClass.pres == PRSNT_NODEF) {
|
||||
switch(rstEvnt->rstInd.rstClass.val) {
|
||||
case IN_CL_INDCHAN: /* Indicated b-channel */
|
||||
@@ -1212,19 +1221,29 @@ void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
|
||||
}
|
||||
|
||||
if (chan_no) { /* For a single channel */
|
||||
if (chan_no > ftdm_span_get_chan_count(signal_data->ftdm_span)) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Received RESTART on invalid channel:%d\n", chan_no);
|
||||
} else {
|
||||
ftdm_channel_t *ftdmchan = ftdm_span_get_channel(signal_data->ftdm_span, chan_no);
|
||||
sngisdn_bring_down(ftdmchan);
|
||||
ftdm_iterator_t *chaniter = NULL;
|
||||
ftdm_iterator_t *curr = NULL;
|
||||
|
||||
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
|
||||
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
|
||||
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
|
||||
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
|
||||
if (sngisdn_info->ces == ces && ftdmchan->physical_chan_id == chan_no) {
|
||||
sngisdn_bring_down(ftdmchan);
|
||||
}
|
||||
}
|
||||
ftdm_iterator_free(chaniter);
|
||||
} else { /* for all channels */
|
||||
ftdm_iterator_t *chaniter = NULL;
|
||||
ftdm_iterator_t *curr = NULL;
|
||||
|
||||
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
|
||||
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
|
||||
sngisdn_bring_down((ftdm_channel_t*)ftdm_iterator_current(curr));
|
||||
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
|
||||
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
|
||||
if (sngisdn_info->ces == ces) {
|
||||
sngisdn_bring_down(ftdmchan);
|
||||
}
|
||||
}
|
||||
ftdm_iterator_free(chaniter);
|
||||
}
|
||||
@@ -1305,28 +1324,29 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
|
||||
}
|
||||
|
||||
if (chan_no) { /* For a single channel */
|
||||
if (chan_no > ftdm_span_get_chan_count(signal_data->ftdm_span)) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Received RESTART IND on invalid channel:%d\n", chan_no);
|
||||
} else {
|
||||
ftdm_iterator_t *chaniter = NULL;
|
||||
ftdm_iterator_t *curr = NULL;
|
||||
|
||||
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
|
||||
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
|
||||
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
|
||||
if (ftdmchan->physical_chan_id == chan_no) {
|
||||
sngisdn_bring_down(ftdmchan);
|
||||
}
|
||||
ftdm_iterator_t *chaniter = NULL;
|
||||
ftdm_iterator_t *curr = NULL;
|
||||
|
||||
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
|
||||
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
|
||||
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
|
||||
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
|
||||
if (sngisdn_info->ces == ces && ftdmchan->physical_chan_id == chan_no) {
|
||||
sngisdn_bring_down(ftdmchan);
|
||||
}
|
||||
ftdm_iterator_free(chaniter);
|
||||
}
|
||||
ftdm_iterator_free(chaniter);
|
||||
} else { /* for all channels */
|
||||
ftdm_iterator_t *chaniter = NULL;
|
||||
ftdm_iterator_t *curr = NULL;
|
||||
|
||||
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
|
||||
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
|
||||
sngisdn_bring_down((ftdm_channel_t*)ftdm_iterator_current(curr));
|
||||
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
|
||||
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
|
||||
if (sngisdn_info->ces == ces) {
|
||||
sngisdn_bring_down(ftdmchan);
|
||||
}
|
||||
}
|
||||
ftdm_iterator_free(chaniter);
|
||||
}
|
||||
|
||||
@@ -69,6 +69,8 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
|
||||
set_calling_subaddr(ftdmchan, &conEvnt.cgPtySad);
|
||||
set_redir_num(ftdmchan, &conEvnt.redirNmb);
|
||||
set_calling_name(ftdmchan, &conEvnt);
|
||||
|
||||
/* set_facility_ie will overwrite Calling Name for NI-2 if user specifies custom Facility IE */
|
||||
set_facility_ie(ftdmchan, &conEvnt.facilityStr);
|
||||
set_prog_ind_ie(ftdmchan, &conEvnt.progInd, prog_ind);
|
||||
|
||||
|
||||
@@ -897,12 +897,19 @@ int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame)
|
||||
do {
|
||||
flags = FTDM_WRITE;
|
||||
status = signal_data->dchan->fio->wait(signal_data->dchan, &flags, 1000);
|
||||
if (status != FTDM_SUCCESS) {
|
||||
ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_WARNING, "transmit timed-out\n");
|
||||
return -1;
|
||||
switch(status) {
|
||||
case FTDM_SUCCESS:
|
||||
break;
|
||||
case FTDM_TIMEOUT:
|
||||
continue;
|
||||
case FTDM_FAIL:
|
||||
default:
|
||||
ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_WARNING, "failed to poll for channel\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* status = FTDM_SUCCESS */
|
||||
if ((flags & FTDM_WRITE)) {
|
||||
#if 0
|
||||
int i;
|
||||
@@ -990,27 +997,29 @@ void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...)
|
||||
|
||||
switch (level) {
|
||||
case SNG_LOGLEVEL_DEBUG:
|
||||
ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s", data);
|
||||
ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s\n", data);
|
||||
break;
|
||||
case SNG_LOGLEVEL_WARN:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
|
||||
if ( strncmp(data, "Invalid Q.921/Q.931 frame", 25) ) {
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
|
||||
}
|
||||
break;
|
||||
case SNG_LOGLEVEL_INFO:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data);
|
||||
break;
|
||||
case SNG_LOGLEVEL_STATS:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data);
|
||||
break;
|
||||
case SNG_LOGLEVEL_ERROR:
|
||||
ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s", data);
|
||||
ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s\n", data);
|
||||
/*ftdm_assert(0, "Got an error from stack");*/
|
||||
break;
|
||||
case SNG_LOGLEVEL_CRIT:
|
||||
ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s", data);
|
||||
ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s\n", data);
|
||||
/* ftdm_assert(0, "Got an error from stack"); */
|
||||
break;
|
||||
default:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data);
|
||||
break;
|
||||
}
|
||||
ftdm_safe_free(data);
|
||||
|
||||
@@ -567,7 +567,7 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
|
||||
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
|
||||
|
||||
string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.digits");
|
||||
if ((string == NULL) || !(*string)) {
|
||||
if (ftdm_strlen_zero(string)) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
@@ -696,63 +696,71 @@ ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb)
|
||||
ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt)
|
||||
{
|
||||
uint8_t len;
|
||||
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
|
||||
/* sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; */
|
||||
const char *string = NULL;
|
||||
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
|
||||
|
||||
ftdm_bool_t force_send_cid_name = FTDM_FALSE;
|
||||
|
||||
len = strlen(caller_data->cid_name);
|
||||
if (!len) {
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
|
||||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
|
||||
|
||||
conEvnt->usrUsr.eh.pres = PRSNT_NODEF;
|
||||
conEvnt->usrUsr.protocolDisc.pres = PRSNT_NODEF;
|
||||
conEvnt->usrUsr.protocolDisc.val = PD_IA5; /* IA5 chars */
|
||||
conEvnt->usrUsr.usrInfo.pres = PRSNT_NODEF;
|
||||
conEvnt->usrUsr.usrInfo.len = len;
|
||||
/* in sangoma_brid we used to send usr-usr info as <cid_name>!<calling_number>,
|
||||
change to previous style if current one does not work */
|
||||
memcpy(conEvnt->usrUsr.usrInfo.val, caller_data->cid_name, len);
|
||||
} else {
|
||||
switch (signal_data->switchtype) {
|
||||
case SNGISDN_SWITCH_NI2:
|
||||
/* TODO: Need to send the caller ID as a facility IE */
|
||||
|
||||
break;
|
||||
case SNGISDN_SWITCH_EUROISDN:
|
||||
if (signal_data->signalling != SNGISDN_SIGNALING_NET) {
|
||||
break;
|
||||
}
|
||||
/* follow through */
|
||||
case SNGISDN_SWITCH_5ESS:
|
||||
case SNGISDN_SWITCH_4ESS:
|
||||
conEvnt->display.dispInfo.pres = PRSNT_NODEF;
|
||||
conEvnt->display.dispInfo.len = len;
|
||||
memcpy(conEvnt->display.dispInfo.val, caller_data->cid_name, len);
|
||||
break;
|
||||
case SNGISDN_SWITCH_DMS100:
|
||||
conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF;
|
||||
conEvnt->ntDisplay[0].dispTypeNt.pres = PRSNT_NODEF;
|
||||
conEvnt->ntDisplay[0].dispTypeNt.val = 0x01; /* Calling Party Name */
|
||||
conEvnt->ntDisplay[0].assocInfo.pres = PRSNT_NODEF;
|
||||
conEvnt->ntDisplay[0].assocInfo.val = 0x03; /* Included */
|
||||
conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF;
|
||||
conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF;
|
||||
conEvnt->ntDisplay[0].dispInfo.pres = PRSNT_NODEF;
|
||||
conEvnt->ntDisplay[0].dispInfo.len = len;
|
||||
memcpy(conEvnt->ntDisplay[0].dispInfo.val, caller_data->cid_name, len);
|
||||
break;
|
||||
case SNGISDN_SWITCH_QSIG:
|
||||
/* It seems like QSIG does not support Caller ID Name */
|
||||
break;
|
||||
case SNGISDN_SWITCH_INSNET:
|
||||
/* Don't know how to transmit caller ID name on INSNET */
|
||||
break;
|
||||
string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.send_cid_name");
|
||||
if (!ftdm_strlen_zero(string)) {
|
||||
if (!strcasecmp(string, "no")) {
|
||||
return FTDM_SUCCESS;
|
||||
} else if (!strcasecmp(string, "yes")) {
|
||||
force_send_cid_name = FTDM_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (force_send_cid_name == FTDM_FALSE && signal_data->send_cid_name == SNGISDN_OPT_FALSE) {
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
switch(signal_data->cid_name_method) {
|
||||
case SNGISDN_CID_NAME_FACILITY_IE:
|
||||
#ifdef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY
|
||||
/* Note: The Facility IE will be overwritten if user chose to transmit a Raw Facility IE */
|
||||
sng_isdn_encode_facility_caller_name(caller_data->cid_name, conEvnt->facilityStr.facilityStr.val, &conEvnt->facilityStr.facilityStr.len);
|
||||
conEvnt->facilityStr.eh.pres = PRSNT_NODEF;
|
||||
conEvnt->facilityStr.facilityStr.pres = PRSNT_NODEF;
|
||||
#endif
|
||||
break;
|
||||
case SNGISDN_CID_NAME_USR_USR_IE:
|
||||
conEvnt->usrUsr.eh.pres = PRSNT_NODEF;
|
||||
conEvnt->usrUsr.protocolDisc.pres = PRSNT_NODEF;
|
||||
conEvnt->usrUsr.protocolDisc.val = PD_IA5; /* IA5 chars */
|
||||
conEvnt->usrUsr.usrInfo.pres = PRSNT_NODEF;
|
||||
conEvnt->usrUsr.usrInfo.len = len;
|
||||
/* in sangoma_brid we used to send usr-usr info as <cid_name>!<calling_number>,
|
||||
change to previous style if current one does not work */
|
||||
memcpy(conEvnt->usrUsr.usrInfo.val, caller_data->cid_name, len);
|
||||
break;
|
||||
case SNGISDN_CID_NAME_DISPLAY_IE:
|
||||
if (signal_data->switchtype == SNGISDN_SWITCH_DMS100) {
|
||||
conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF;
|
||||
conEvnt->ntDisplay[0].dispTypeNt.pres = PRSNT_NODEF;
|
||||
conEvnt->ntDisplay[0].dispTypeNt.val = 0x01; /* Calling Party Name */
|
||||
conEvnt->ntDisplay[0].assocInfo.pres = PRSNT_NODEF;
|
||||
conEvnt->ntDisplay[0].assocInfo.val = 0x03; /* Included */
|
||||
conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF;
|
||||
conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF;
|
||||
conEvnt->ntDisplay[0].dispInfo.pres = PRSNT_NODEF;
|
||||
conEvnt->ntDisplay[0].dispInfo.len = len;
|
||||
memcpy(conEvnt->ntDisplay[0].dispInfo.val, caller_data->cid_name, len);
|
||||
} else {
|
||||
conEvnt->display.eh.pres = PRSNT_NODEF;
|
||||
conEvnt->display.dispInfo.pres = PRSNT_NODEF;
|
||||
conEvnt->display.dispInfo.len = len;
|
||||
memcpy(conEvnt->display.dispInfo.val, caller_data->cid_name, len);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -760,7 +768,7 @@ ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
|
||||
{
|
||||
const char* clg_subaddr = NULL;
|
||||
clg_subaddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.calling_subaddr");
|
||||
if ((clg_subaddr != NULL) && (*clg_subaddr)) {
|
||||
if (!ftdm_strlen_zero(clg_subaddr)) {
|
||||
unsigned len = strlen (clg_subaddr);
|
||||
cgPtySad->eh.pres = PRSNT_NODEF;
|
||||
cgPtySad->typeSad.pres = 1;
|
||||
|
||||
@@ -249,6 +249,34 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
|
||||
SS7_DEBUG_CHAN(ftdmchan, "No Location Number information in IAM%s\n", " ");
|
||||
}
|
||||
|
||||
/* Retrieve the Location Number if present (see ITU Q.763, 3.30) */
|
||||
if (siConEvnt->cgPtyNum1.eh.pres) {
|
||||
if (siConEvnt->cgPtyNum1.addrSig.pres) {
|
||||
/* fill in the ss7 location address number */
|
||||
copy_tknStr_from_sngss7(siConEvnt->cgPtyNum1.addrSig, var, siConEvnt->cgPtyNum1.oddEven);
|
||||
sngss7_add_var(sngss7_info, "ss7_loc_digits", var);
|
||||
}
|
||||
|
||||
if (siConEvnt->cgPtyNum1.scrnInd.pres) {
|
||||
/* fill in the screening indication value */
|
||||
sprintf(var, "%d", siConEvnt->cgPtyNum1.scrnInd.val);
|
||||
sngss7_add_var(sngss7_info, "ss7_loc_screen_ind", var);
|
||||
}
|
||||
|
||||
if (siConEvnt->cgPtyNum1.presRest.pres) {
|
||||
/* fill in the presentation value */
|
||||
sprintf(var, "%d", siConEvnt->cgPtyNum1.presRest.val);
|
||||
sngss7_add_var(sngss7_info, "ss7_loc_pres_ind", var);
|
||||
}
|
||||
|
||||
if (siConEvnt->cgPtyNum1.natAddrInd.pres) {
|
||||
sprintf(var, "%d", siConEvnt->cgPtyNum1.natAddrInd.val);
|
||||
sngss7_add_var(sngss7_info, "ss7_loc_nadi", var);
|
||||
}
|
||||
} else {
|
||||
SS7_DEBUG_CHAN(ftdmchan, "No Location Number information in IAM%s\n", " ");
|
||||
}
|
||||
|
||||
sprintf(var, "%d", sngss7_info->circuit->cic);
|
||||
sngss7_add_var(sngss7_info, "ss7_cic", var);
|
||||
|
||||
@@ -256,11 +284,10 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
|
||||
sngss7_add_var(sngss7_info, "ss7_opc", var);
|
||||
|
||||
if (siConEvnt->callRef.callId.pres) {
|
||||
/* %x expect an unsigned int so as callId is a U32, casting to uint32_t
|
||||
* is safe */
|
||||
sprintf(var, "%x", (uint32_t)siConEvnt->callRef.callId.val);
|
||||
sngss7_add_var(sngss7_info, "ss7_callref", var);
|
||||
}
|
||||
ftdmchan->caller_data.call_reference = (unsigned int)siConEvnt->callRef.callId.val;
|
||||
} else {
|
||||
ftdmchan->caller_data.call_reference = 0;
|
||||
}
|
||||
|
||||
if (sngss7_info->circuit->transparent_iam) {
|
||||
sngss7_save_iam(ftdmchan, siConEvnt);
|
||||
|
||||
@@ -39,6 +39,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef WP_DEBUG_IO
|
||||
#define _BSD_SOURCE
|
||||
#include <syscall.h>
|
||||
#endif
|
||||
|
||||
#ifdef __sun
|
||||
#include <unistd.h>
|
||||
#include <stropts.h>
|
||||
@@ -99,6 +104,17 @@ static struct {
|
||||
uint32_t ring_off_ms;
|
||||
} wp_globals;
|
||||
|
||||
typedef struct {
|
||||
sangoma_wait_obj_t *waitobj;
|
||||
#ifdef WP_DEBUG_IO
|
||||
/* record the last reader threads */
|
||||
pid_t readers[10];
|
||||
int rindex;
|
||||
ftdm_time_t last_read;
|
||||
#endif
|
||||
} wp_channel_t;
|
||||
#define WP_GET_WAITABLE(fchan) ((wp_channel_t *)((fchan)->io_data))->waitobj
|
||||
|
||||
/* a bunch of this stuff should go into the wanpipe_tdm_api_iface.h */
|
||||
|
||||
FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event);
|
||||
@@ -123,7 +139,7 @@ static __inline__ int tdmv_api_wait_socket(ftdm_channel_t *ftdmchan, int timeout
|
||||
int err;
|
||||
uint32_t inflags = *flags;
|
||||
uint32_t outflags = 0;
|
||||
sangoma_wait_obj_t *sangoma_wait_obj = ftdmchan->io_data;
|
||||
sangoma_wait_obj_t *sangoma_wait_obj = WP_GET_WAITABLE(ftdmchan);
|
||||
|
||||
if (timeout == -1) {
|
||||
timeout = SANGOMA_WAIT_INFINITE;
|
||||
@@ -254,9 +270,13 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
|
||||
}
|
||||
|
||||
if (ftdm_span_add_channel(span, sockfd, type, &chan) == FTDM_SUCCESS) {
|
||||
wp_channel_t *wpchan = NULL;
|
||||
wanpipe_tdm_api_t tdm_api;
|
||||
memset(&tdm_api, 0, sizeof(tdm_api));
|
||||
#ifdef LIBSANGOMA_VERSION
|
||||
wpchan = ftdm_calloc(1, sizeof(*wpchan));
|
||||
ftdm_assert(wpchan != NULL, "wpchan alloc failed\n");
|
||||
chan->io_data = wpchan;
|
||||
/* we need SANGOMA_DEVICE_WAIT_OBJ_SIG and not SANGOMA_DEVICE_WAIT_OBJ alone because we need to call
|
||||
* sangoma_wait_obj_sig to wake up any I/O waiters when closing the channel (typically on ftdm shutdown)
|
||||
* this adds an extra pair of file descriptors to the waitable object
|
||||
@@ -266,7 +286,7 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
|
||||
ftdm_log(FTDM_LOG_ERROR, "failure create waitable object for s%dc%d\n", spanno, x);
|
||||
continue;
|
||||
}
|
||||
chan->io_data = sangoma_wait_obj;
|
||||
WP_GET_WAITABLE(chan) = sangoma_wait_obj;
|
||||
#endif
|
||||
|
||||
chan->physical_span_id = spanno;
|
||||
@@ -580,9 +600,16 @@ static FIO_OPEN_FUNCTION(wanpipe_open)
|
||||
static FIO_CLOSE_FUNCTION(wanpipe_close)
|
||||
{
|
||||
#ifdef LIBSANGOMA_VERSION
|
||||
sangoma_wait_obj_t *waitobj = ftdmchan->io_data;
|
||||
sangoma_wait_obj_t *waitobj = WP_GET_WAITABLE(ftdmchan);
|
||||
/* kick any I/O waiters */
|
||||
sangoma_wait_obj_signal(waitobj);
|
||||
#ifdef WP_DEBUG_IO
|
||||
{
|
||||
wp_channel_t *wchan = ftdmchan->io_data;
|
||||
memset(wchan->readers, 0, sizeof(wchan->readers));
|
||||
wchan->rindex = 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
@@ -944,10 +971,44 @@ static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx
|
||||
static FIO_READ_FUNCTION(wanpipe_read)
|
||||
{
|
||||
int rx_len = 0;
|
||||
int rq_len = (int)*datalen;
|
||||
wp_tdm_api_rx_hdr_t hdrframe;
|
||||
|
||||
memset(&hdrframe, 0, sizeof(hdrframe));
|
||||
#ifdef WP_DEBUG_IO
|
||||
wp_channel_t *wchan = ftdmchan->io_data;
|
||||
ftdm_time_t time_diff = 0;
|
||||
pid_t previous_thread = 1;
|
||||
pid_t current_thread = 0;
|
||||
int previous_thread_index = 0;
|
||||
|
||||
previous_thread_index = wchan->rindex == 0 ? (ftdm_array_len(wchan->readers) - 1) : wchan->rindex - 1;
|
||||
previous_thread = wchan->readers[previous_thread_index];
|
||||
current_thread = syscall(SYS_gettid);
|
||||
if (current_thread && current_thread != wchan->readers[wchan->rindex]) {
|
||||
if (!wchan->readers[wchan->rindex]) {
|
||||
wchan->readers[wchan->rindex] = current_thread;
|
||||
/* first read */
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Initial reader thread is %d\n", current_thread);
|
||||
previous_thread = current_thread;
|
||||
} else {
|
||||
previous_thread = wchan->readers[wchan->rindex];
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Changed reader thread from %d to %d (rindex = %d)\n",
|
||||
previous_thread, current_thread, wchan->rindex);
|
||||
if (wchan->rindex == (ftdm_array_len(wchan->readers) - 1)) {
|
||||
wchan->rindex = 0;
|
||||
} else {
|
||||
wchan->rindex++;
|
||||
}
|
||||
wchan->readers[wchan->rindex] = current_thread;
|
||||
}
|
||||
}
|
||||
ftdm_time_t curr = ftdm_current_time_in_ms();
|
||||
if (wchan->last_read) {
|
||||
time_diff = curr - wchan->last_read;
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&hdrframe, 0, sizeof(hdrframe));
|
||||
rx_len = sangoma_readmsg_tdm(ftdmchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (int)*datalen, 0);
|
||||
*datalen = rx_len;
|
||||
|
||||
@@ -957,14 +1018,20 @@ static FIO_READ_FUNCTION(wanpipe_read)
|
||||
}
|
||||
|
||||
if (rx_len < 0) {
|
||||
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno));
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read from sangoma device: %s (%d)\n", strerror(errno), rx_len);
|
||||
#ifdef WP_DEBUG_IO
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read %d bytes from sangoma device: %s (%d) "
|
||||
"(read time diff = %llums, prev thread = %d, curr thread = %d)\n", rq_len, strerror(errno), rx_len,
|
||||
time_diff, previous_thread, current_thread);
|
||||
#else
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read %d bytes from sangoma device: %s (%d)\n", rq_len, strerror(errno), rx_len);
|
||||
#endif
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS)) {
|
||||
wanpipe_read_stats(ftdmchan, &hdrframe);
|
||||
}
|
||||
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1110,7 +1177,7 @@ FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
|
||||
if (!ftdmchan->io_data) {
|
||||
continue; /* should never happen but happens when shutting down */
|
||||
}
|
||||
pfds[j] = ftdmchan->io_data;
|
||||
pfds[j] = WP_GET_WAITABLE(ftdmchan);
|
||||
inflags[j] = chan_events;
|
||||
#else
|
||||
memset(&pfds[j], 0, sizeof(pfds[j]));
|
||||
@@ -1572,10 +1639,10 @@ static FIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy)
|
||||
{
|
||||
#ifdef LIBSANGOMA_VERSION
|
||||
if (ftdmchan->io_data) {
|
||||
sangoma_wait_obj_t *sangoma_wait_obj;
|
||||
sangoma_wait_obj = ftdmchan->io_data;
|
||||
ftdmchan->io_data = NULL;
|
||||
sangoma_wait_obj_t *sangoma_wait_obj = WP_GET_WAITABLE(ftdmchan);
|
||||
sangoma_wait_obj_delete(&sangoma_wait_obj);
|
||||
ftdm_safe_free(ftdmchan->io_data);
|
||||
ftdmchan->io_data = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1606,7 +1673,8 @@ static FIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy)
|
||||
*/
|
||||
static FIO_IO_LOAD_FUNCTION(wanpipe_init)
|
||||
{
|
||||
assert(fio != NULL);
|
||||
ftdm_assert(fio != NULL, "fio should not be null\n");
|
||||
|
||||
memset(&wanpipe_interface, 0, sizeof(wanpipe_interface));
|
||||
|
||||
wp_globals.codec_ms = 20;
|
||||
|
||||
@@ -29,6 +29,12 @@
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Contributors:
|
||||
*
|
||||
* Moises Silva <moy@sangoma.com>
|
||||
* W McRoberts <fs@whmcr.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "private/ftdm_core.h"
|
||||
@@ -94,6 +100,7 @@ struct ioctl_codes {
|
||||
ioctlcmd ECHOTRAIN;
|
||||
ioctlcmd SETTXBITS;
|
||||
ioctlcmd GETRXBITS;
|
||||
ioctlcmd SETPOLARITY;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -169,7 +176,8 @@ static struct ioctl_codes dahdi_ioctl_codes = {
|
||||
.GETCONFMUTE = DAHDI_GETCONFMUTE,
|
||||
.ECHOTRAIN = DAHDI_ECHOTRAIN,
|
||||
.SETTXBITS = DAHDI_SETTXBITS,
|
||||
.GETRXBITS = DAHDI_GETRXBITS
|
||||
.GETRXBITS = DAHDI_GETRXBITS,
|
||||
.SETPOLARITY = DAHDI_SETPOLARITY
|
||||
};
|
||||
|
||||
#define ZT_INVALID_SOCKET -1
|
||||
@@ -248,7 +256,7 @@ static void zt_build_gains(struct zt_gains *g, float rxgain, float txgain, int c
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initialises a range of ftdmtel channels
|
||||
* \brief Initialises a range of Zaptel/DAHDI channels
|
||||
* \param span FreeTDM span
|
||||
* \param start Initial wanpipe channel number
|
||||
* \param end Final wanpipe channel number
|
||||
@@ -341,7 +349,7 @@ static unsigned zt_open_range(ftdm_span_t *span, unsigned start, unsigned end, f
|
||||
}
|
||||
|
||||
if (ioctl(CONTROL_FD, codes.CHANCONFIG, &cc)) {
|
||||
ftdm_log(FTDM_LOG_WARNING, "this ioctl fails on older ftdmtel but is harmless if you used ztcfg\n[device %s chan %d fd %d (%s)]\n", chanpath, x, CONTROL_FD, strerror(errno));
|
||||
ftdm_log(FTDM_LOG_WARNING, "this ioctl fails in older zaptel but is harmless if you used ztcfg\n[device %s chan %d fd %d (%s)]\n", chanpath, x, CONTROL_FD, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,7 +453,7 @@ static unsigned zt_open_range(ftdm_span_t *span, unsigned start, unsigned end, f
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initialises an freetdm ftdmtel span from a configuration string
|
||||
* \brief Initialises a freetdm Zaptel/DAHDI span from a configuration string
|
||||
* \param span FreeTDM span
|
||||
* \param str Configuration string
|
||||
* \param type FreeTDM span type
|
||||
@@ -515,7 +523,7 @@ static FIO_CONFIGURE_SPAN_FUNCTION(zt_configure_span)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Process configuration variable for a ftdmtel profile
|
||||
* \brief Process configuration variable for a Zaptel/DAHDI profile
|
||||
* \param category Wanpipe profile name
|
||||
* \param var Variable name
|
||||
* \param val Variable value
|
||||
@@ -593,7 +601,7 @@ static FIO_CONFIGURE_FUNCTION(zt_configure)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Opens a ftdmtel channel
|
||||
* \brief Opens a Zaptel/DAHDI channel
|
||||
* \param ftdmchan Channel to open
|
||||
* \return Success or failure
|
||||
*/
|
||||
@@ -663,7 +671,7 @@ static FIO_OPEN_FUNCTION(zt_open)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Closes ftdmtel channel
|
||||
* \brief Closes Zaptel/DAHDI channel
|
||||
* \param ftdmchan Channel to close
|
||||
* \return Success
|
||||
*/
|
||||
@@ -681,7 +689,7 @@ static FIO_CLOSE_FUNCTION(zt_close)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Executes an FreeTDM command on a ftdmtel channel
|
||||
* \brief Executes a FreeTDM command on a Zaptel/DAHDI channel
|
||||
* \param ftdmchan Channel to execute command on
|
||||
* \param command FreeTDM command to execute
|
||||
* \param obj Object (unused)
|
||||
@@ -826,6 +834,15 @@ static FIO_COMMAND_FUNCTION(zt_command)
|
||||
err = ioctl(ftdmchan->sockfd, codes.FLUSH, &flushmode);
|
||||
}
|
||||
break;
|
||||
case FTDM_COMMAND_SET_POLARITY:
|
||||
{
|
||||
ftdm_polarity_t polarity = FTDM_COMMAND_OBJ_INT;
|
||||
err = ioctl(ftdmchan->sockfd, codes.SETPOLARITY, polarity);
|
||||
if (!err) {
|
||||
ftdmchan->polarity = polarity;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FTDM_COMMAND_FLUSH_RX_BUFFERS:
|
||||
{
|
||||
int flushmode = ZT_FLUSH_READ;
|
||||
@@ -853,7 +870,7 @@ static FIO_COMMAND_FUNCTION(zt_command)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Gets alarms from a ftdmtel Channel
|
||||
* \brief Gets alarms from a Zaptel/DAHDI channel
|
||||
* \param ftdmchan Channel to get alarms from
|
||||
* \return Success or failure
|
||||
*/
|
||||
@@ -876,7 +893,7 @@ static FIO_GET_ALARMS_FUNCTION(zt_get_alarms)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Waits for an event on a ftdmtel channel
|
||||
* \brief Waits for an event on a Zaptel/DAHDI channel
|
||||
* \param ftdmchan Channel to open
|
||||
* \param flags Type of event to wait for
|
||||
* \param to Time to wait (in ms)
|
||||
@@ -950,7 +967,7 @@ pollagain:
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Checks for events on a ftdmtel span
|
||||
* \brief Checks for events on a Zaptel/DAHDI span
|
||||
* \param span Span to check for events
|
||||
* \param ms Time to wait for event
|
||||
* \return Success if event is waiting or failure if not
|
||||
@@ -1088,6 +1105,12 @@ static __inline__ ftdm_status_t zt_channel_process_event(ftdm_channel_t *fchan,
|
||||
*event_id = FTDM_OOB_NOOP; /* What else could we do? */
|
||||
}
|
||||
break;
|
||||
case ZT_EVENT_POLARITY:
|
||||
{
|
||||
ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Got polarity reverse (ZT_EVENT_POLARITY)\n");
|
||||
*event_id = FTDM_OOB_POLARITY_REVERSE;
|
||||
}
|
||||
break;
|
||||
case ZT_EVENT_NONE:
|
||||
{
|
||||
ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "No event\n");
|
||||
@@ -1141,7 +1164,7 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(zt_channel_next_event)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves an event from a ftdmtel span
|
||||
* \brief Retrieves an event from a Zaptel/DAHDI span
|
||||
* \param span Span to retrieve event from
|
||||
* \param event FreeTDM event to return
|
||||
* \return Success or failure
|
||||
@@ -1181,7 +1204,7 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reads data from a ftdmtel channel
|
||||
* \brief Reads data from a Zaptel/DAHDI channel
|
||||
* \param ftdmchan Channel to read from
|
||||
* \param data Data buffer
|
||||
* \param datalen Size of data buffer
|
||||
@@ -1223,7 +1246,7 @@ static FIO_READ_FUNCTION(zt_read)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Writes data to a ftdmtel channel
|
||||
* \brief Writes data to a Zaptel/DAHDI channel
|
||||
* \param ftdmchan Channel to write to
|
||||
* \param data Data buffer
|
||||
* \param datalen Size of data buffer
|
||||
@@ -1262,7 +1285,7 @@ tryagain:
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Destroys a ftdmtel Channel
|
||||
* \brief Destroys a Zaptel/DAHDI Channel
|
||||
* \param ftdmchan Channel to destroy
|
||||
* \return Success
|
||||
*/
|
||||
@@ -1275,12 +1298,12 @@ static FIO_CHANNEL_DESTROY_FUNCTION(zt_channel_destroy)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Global FreeTDM IO interface for ftdmtel
|
||||
* \brief Global FreeTDM IO interface for Zaptel/DAHDI
|
||||
*/
|
||||
static ftdm_io_interface_t zt_interface;
|
||||
|
||||
/**
|
||||
* \brief Loads ftdmtel IO module
|
||||
* \brief Loads Zaptel/DAHDI IO module
|
||||
* \param fio FreeTDM IO interface
|
||||
* \return Success or failure
|
||||
*/
|
||||
@@ -1335,7 +1358,7 @@ static FIO_IO_LOAD_FUNCTION(zt_init)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Unloads ftdmtel IO module
|
||||
* \brief Unloads Zaptel/DAHDI IO module
|
||||
* \return Success
|
||||
*/
|
||||
static FIO_IO_UNLOAD_FUNCTION(zt_destroy)
|
||||
@@ -1346,7 +1369,7 @@ static FIO_IO_UNLOAD_FUNCTION(zt_destroy)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief FreeTDM ftdmtel IO module definition
|
||||
* \brief FreeTDM Zaptel/DAHDI IO module definition
|
||||
*/
|
||||
ftdm_module_t ftdm_module = {
|
||||
"zt",
|
||||
|
||||
@@ -29,6 +29,12 @@
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Contributors:
|
||||
*
|
||||
* Moises Silva <moy@sangoma.com>
|
||||
* W McRoberts <fs@whmcr.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FTDM_ZT_H
|
||||
@@ -349,6 +355,7 @@ ZT_ABIT = 8
|
||||
#define DAHDI_SETTXBITS _IOW (DAHDI_CODE, 43, int)
|
||||
#define DAHDI_GETRXBITS _IOR (DAHDI_CODE, 43, int)
|
||||
|
||||
#define DAHDI_SETPOLARITY _IOW (DAHDI_CODE, 92, int) /* Polarity setting for FXO lines */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -928,20 +928,20 @@ typedef enum {
|
||||
/*! \brief IO statistics */
|
||||
typedef struct {
|
||||
struct {
|
||||
uint64_t packets;
|
||||
uint32_t errors;
|
||||
uint16_t flags;
|
||||
uint8_t queue_size; /*!< max queue size configured */
|
||||
uint8_t queue_len; /*!< Current number of elements in queue */
|
||||
uint64_t packets;
|
||||
} rx;
|
||||
|
||||
struct {
|
||||
uint64_t idle_packets;
|
||||
uint64_t packets;
|
||||
uint32_t errors;
|
||||
uint16_t flags;
|
||||
uint8_t idle_packets;
|
||||
uint8_t queue_size; /*!< max queue size configured */
|
||||
uint8_t queue_len; /*!< Current number of elements in queue */
|
||||
uint64_t packets;
|
||||
} tx;
|
||||
} ftdm_channel_iostats_t;
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mftilla Public License Version
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mftilla.org/MPL/
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
@@ -33,8 +33,8 @@
|
||||
* Exception:
|
||||
* The author hereby grants the use of this source code under the
|
||||
* following license if and only if the source code is distributed
|
||||
* as part of the freetdm library. Any use or distribution of this
|
||||
* source code outside the scope of the freetdm library will nullify the
|
||||
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
|
||||
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
|
||||
* following license and reinact the MPL 1.1 as stated above.
|
||||
*
|
||||
* Copyright (c) 2007, Anthony Minessale II
|
||||
|
||||
@@ -2,13 +2,60 @@
|
||||
* libteletone
|
||||
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is tone_detect.c - General telephony tone detection, and specific detection of DTMF.
|
||||
*
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Stephen Underwood <steveu@coppice.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* The the original interface designed by Steve Underwood was preserved to retain
|
||||
*the optimizations when considering DTMF tones though the names were changed in the interest
|
||||
* of namespace.
|
||||
*
|
||||
* Much less efficient expansion interface was added to allow for the detection of
|
||||
* a single arbitrary tone combination which may also exceed 2 simultaneous tones.
|
||||
* (controlled by compile time constant TELETONE_MAX_TONES)
|
||||
*
|
||||
* Copyright (C) 2006 Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
*
|
||||
* libteletone_detect.c Tone Detection Code
|
||||
*
|
||||
*
|
||||
*********************************************************************************
|
||||
*
|
||||
* Derived from tone_detect.h - General telephony tone detection, and specific
|
||||
* detection of DTMF.
|
||||
*
|
||||
* Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Despite my general liking of the GPL, I place this code in the
|
||||
* public domain for the benefit of all mankind - even the slimy
|
||||
* ones who might try to proprietize my work and use it to my
|
||||
* detriment.
|
||||
*
|
||||
*
|
||||
* Exception:
|
||||
* The author hereby grants the use of this source code under the
|
||||
* following license if and only if the source code is distributed
|
||||
* as part of the freetdm library. Any use or distribution of this
|
||||
* source code outside the scope of the freetdm library will nullify the
|
||||
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
|
||||
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
|
||||
* following license and reinact the MPL 1.1 as stated above.
|
||||
*
|
||||
* Copyright (c) 2007, Anthony Minessale II
|
||||
@@ -41,20 +88,6 @@
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*********************************************************************************
|
||||
*
|
||||
* Derived from tone_detect.h - General telephony tone detection, and specific
|
||||
* detection of DTMF.
|
||||
*
|
||||
* Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Despite my general liking of the GPL, I place this code in the
|
||||
* public domain for the benefit of all mankind - even the slimy
|
||||
* ones who might try to proprietize my work and use it to my
|
||||
* detriment.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LIBTELETONE_DETECT_H
|
||||
@@ -101,6 +134,14 @@ extern "C" {
|
||||
#define BLOCK_LEN 102
|
||||
#define M_TWO_PI 2.0*M_PI
|
||||
|
||||
typedef enum {
|
||||
TT_HIT_NONE = 0,
|
||||
TT_HIT_BEGIN = 1,
|
||||
TT_HIT_MIDDLE = 2,
|
||||
TT_HIT_END = 3
|
||||
} teletone_hit_type_t;
|
||||
|
||||
|
||||
/*! \brief A continer for the elements of a Goertzel Algorithm (The names are from his formula) */
|
||||
typedef struct {
|
||||
float v2;
|
||||
@@ -114,16 +155,19 @@ extern "C" {
|
||||
int hit2;
|
||||
int hit3;
|
||||
int hit4;
|
||||
int mhit;
|
||||
int dur;
|
||||
int zc;
|
||||
|
||||
|
||||
teletone_goertzel_state_t row_out[GRID_FACTOR];
|
||||
teletone_goertzel_state_t col_out[GRID_FACTOR];
|
||||
teletone_goertzel_state_t row_out2nd[GRID_FACTOR];
|
||||
teletone_goertzel_state_t col_out2nd[GRID_FACTOR];
|
||||
float energy;
|
||||
float lenergy;
|
||||
|
||||
int current_sample;
|
||||
char digits[TELETONE_MAX_DTMF_DIGITS + 1];
|
||||
char digit;
|
||||
int current_digits;
|
||||
int detected_digits;
|
||||
int lost_digits;
|
||||
@@ -196,7 +240,7 @@ TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf
|
||||
\param samples the number of samples present in sample_buffer
|
||||
\return true when DTMF was detected or false when it is not
|
||||
*/
|
||||
TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
int16_t sample_buffer[],
|
||||
int samples);
|
||||
/*!
|
||||
@@ -206,9 +250,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
|
||||
\param max the maximum length of buf
|
||||
\return the number of characters written to buf
|
||||
*/
|
||||
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
char *buf,
|
||||
int max);
|
||||
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur);
|
||||
|
||||
/*!
|
||||
\brief Step through the Goertzel Algorithm for each sample in a buffer
|
||||
|
||||
@@ -2,6 +2,41 @@
|
||||
* libteletone
|
||||
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libteletone
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
*
|
||||
* libteletone.h -- Tone Generator
|
||||
*
|
||||
*
|
||||
*
|
||||
* Exception:
|
||||
* The author hereby grants the use of this source code under the
|
||||
* following license if and only if the source code is distributed
|
||||
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
|
||||
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
|
||||
* following license and reinact the MPL 1.1 as stated above.
|
||||
*
|
||||
* Copyright (c) 2007, Anthony Minessale II
|
||||
* All rights reserved.
|
||||
*
|
||||
|
||||
@@ -2,14 +2,62 @@
|
||||
* libteletone
|
||||
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is tone_detect.c - General telephony tone detection, and specific detection of DTMF.
|
||||
*
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Stephen Underwood <steveu@coppice.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* The the original interface designed by Steve Underwood was preserved to retain
|
||||
*the optimizations when considering DTMF tones though the names were changed in the interest
|
||||
* of namespace.
|
||||
*
|
||||
* Much less efficient expansion interface was added to allow for the detection of
|
||||
* a single arbitrary tone combination which may also exceed 2 simultaneous tones.
|
||||
* (controlled by compile time constant TELETONE_MAX_TONES)
|
||||
*
|
||||
* Copyright (C) 2006 Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
*
|
||||
* libteletone_detect.c Tone Detection Code
|
||||
*
|
||||
*
|
||||
*********************************************************************************
|
||||
*
|
||||
* Derived from tone_detect.c - General telephony tone detection, and specific
|
||||
* detection of DTMF.
|
||||
*
|
||||
* Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Despite my general liking of the GPL, I place this code in the
|
||||
* public domain for the benefit of all mankind - even the slimy
|
||||
* ones who might try to proprietize my work and use it to my
|
||||
* detriment.
|
||||
*
|
||||
*
|
||||
* Exception:
|
||||
* The author hereby grants the use of this source code under the
|
||||
* following license if and only if the source code is distributed
|
||||
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
|
||||
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
|
||||
* following license and reinact the MPL 1.1 as stated above.
|
||||
*
|
||||
* Copyright (c) 2007, Anthony Minessale II
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -40,21 +88,6 @@
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*********************************************************************************
|
||||
*
|
||||
* Derived from tone_detect.c - General telephony tone detection, and specific
|
||||
* detection of DTMF.
|
||||
*
|
||||
* Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Despite my general liking of the GPL, I place this code in the
|
||||
* public domain for the benefit of all mankind - even the slimy
|
||||
* ones who might try to proprietize my work and use it to my
|
||||
* detriment.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <libteletone_detect.h>
|
||||
@@ -67,7 +100,8 @@
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
#define LOW_ENG 10000000
|
||||
#define ZC 2
|
||||
static teletone_detection_descriptor_t dtmf_detect_row[GRID_FACTOR];
|
||||
static teletone_detection_descriptor_t dtmf_detect_col[GRID_FACTOR];
|
||||
static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR];
|
||||
@@ -132,8 +166,8 @@ TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf
|
||||
dtmf_detect_state->current_sample = 0;
|
||||
dtmf_detect_state->detected_digits = 0;
|
||||
dtmf_detect_state->lost_digits = 0;
|
||||
dtmf_detect_state->digits[0] = '\0';
|
||||
dtmf_detect_state->mhit = 0;
|
||||
dtmf_detect_state->digit = 0;
|
||||
dtmf_detect_state->dur = 0;
|
||||
}
|
||||
|
||||
TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map)
|
||||
@@ -266,7 +300,7 @@ TELETONE_API(int) teletone_multi_tone_detect (teletone_multi_tone_t *mt,
|
||||
}
|
||||
|
||||
|
||||
TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
int16_t sample_buffer[],
|
||||
int samples)
|
||||
{
|
||||
@@ -281,6 +315,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
|
||||
int best_col;
|
||||
char hit;
|
||||
int limit;
|
||||
teletone_hit_type_t r = 0;
|
||||
|
||||
hit = 0;
|
||||
for (sample = 0; sample < samples; sample = limit) {
|
||||
@@ -317,6 +352,32 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
|
||||
|
||||
}
|
||||
|
||||
if (dtmf_detect_state->zc > 0) {
|
||||
if (dtmf_detect_state->energy < LOW_ENG && dtmf_detect_state->lenergy < LOW_ENG) {
|
||||
if (!--dtmf_detect_state->zc) {
|
||||
/* Reinitialise the detector for the next block */
|
||||
dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0;
|
||||
for (i = 0; i < GRID_FACTOR; i++) {
|
||||
goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
|
||||
goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
|
||||
goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
|
||||
goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
|
||||
}
|
||||
dtmf_detect_state->dur -= samples;
|
||||
return TT_HIT_END;
|
||||
}
|
||||
}
|
||||
|
||||
dtmf_detect_state->dur += samples;
|
||||
dtmf_detect_state->lenergy = dtmf_detect_state->energy;
|
||||
dtmf_detect_state->energy = 0.0;
|
||||
dtmf_detect_state->current_sample = 0;
|
||||
return TT_HIT_MIDDLE;
|
||||
} else if (dtmf_detect_state->digit) {
|
||||
return TT_HIT_END;
|
||||
}
|
||||
|
||||
|
||||
dtmf_detect_state->current_sample += (limit - sample);
|
||||
if (dtmf_detect_state->current_sample < BLOCK_LEN) {
|
||||
continue;
|
||||
@@ -361,58 +422,55 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
|
||||
back to back differing digits. More importantly, it
|
||||
can work with nasty phones that give a very wobbly start
|
||||
to a digit. */
|
||||
if (hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) {
|
||||
dtmf_detect_state->mhit = hit;
|
||||
if (! r && hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) {
|
||||
dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++;
|
||||
dtmf_detect_state->detected_digits++;
|
||||
if (dtmf_detect_state->current_digits < TELETONE_MAX_DTMF_DIGITS) {
|
||||
dtmf_detect_state->digits[dtmf_detect_state->current_digits++] = hit;
|
||||
dtmf_detect_state->digits[dtmf_detect_state->current_digits] = '\0';
|
||||
dtmf_detect_state->digit = hit;
|
||||
} else {
|
||||
dtmf_detect_state->lost_digits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
dtmf_detect_state->lost_digits++;
|
||||
}
|
||||
|
||||
if (!dtmf_detect_state->zc) {
|
||||
dtmf_detect_state->zc = ZC;
|
||||
dtmf_detect_state->dur = 0;
|
||||
r = TT_HIT_BEGIN;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dtmf_detect_state->hit1 = dtmf_detect_state->hit2;
|
||||
dtmf_detect_state->hit2 = dtmf_detect_state->hit3;
|
||||
dtmf_detect_state->hit3 = hit;
|
||||
/* Reinitialise the detector for the next block */
|
||||
for (i = 0; i < GRID_FACTOR; i++) {
|
||||
goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
|
||||
goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
|
||||
goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
|
||||
goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
|
||||
}
|
||||
|
||||
dtmf_detect_state->energy = 0.0;
|
||||
dtmf_detect_state->current_sample = 0;
|
||||
|
||||
}
|
||||
if ((!dtmf_detect_state->mhit) || (dtmf_detect_state->mhit != hit)) {
|
||||
dtmf_detect_state->mhit = 0;
|
||||
return(0);
|
||||
}
|
||||
return (hit);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
char *buf,
|
||||
int max)
|
||||
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur)
|
||||
{
|
||||
teletone_assert(dtmf_detect_state->current_digits <= TELETONE_MAX_DTMF_DIGITS);
|
||||
if (!dtmf_detect_state->digit) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (max > dtmf_detect_state->current_digits) {
|
||||
max = dtmf_detect_state->current_digits;
|
||||
*buf = dtmf_detect_state->digit;
|
||||
|
||||
*dur = dtmf_detect_state->dur;
|
||||
|
||||
if (!dtmf_detect_state->zc) {
|
||||
dtmf_detect_state->dur = 0;
|
||||
dtmf_detect_state->digit = 0;
|
||||
}
|
||||
if (max > 0) {
|
||||
memcpy (buf, dtmf_detect_state->digits, max);
|
||||
memmove (dtmf_detect_state->digits, dtmf_detect_state->digits + max, dtmf_detect_state->current_digits - max);
|
||||
dtmf_detect_state->current_digits -= max;
|
||||
}
|
||||
buf[max] = '\0';
|
||||
return max;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
|
||||
@@ -1,5 +1,41 @@
|
||||
/*
|
||||
* libteletone_generate.c -- Tone Generator
|
||||
* libteletone
|
||||
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libteletone
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
*
|
||||
* libteletone.c -- Tone Generator
|
||||
*
|
||||
*
|
||||
*
|
||||
* Exception:
|
||||
* The author hereby grants the use of this source code under the
|
||||
* following license if and only if the source code is distributed
|
||||
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
|
||||
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
|
||||
* following license and reinact the MPL 1.1 as stated above.
|
||||
*
|
||||
* Copyright (c) 2007, Anthony Minessale II
|
||||
* All rights reserved.
|
||||
@@ -34,7 +70,6 @@
|
||||
*/
|
||||
|
||||
#include <libteletone.h>
|
||||
#include "private/ftdm_core.h"
|
||||
|
||||
#define SMAX 32767
|
||||
#define SMIN -32768
|
||||
@@ -111,7 +146,7 @@ TELETONE_API(int) teletone_init_session(teletone_generation_session_t *ts, int b
|
||||
ts->decay_step = 0;
|
||||
ts->decay_factor = 1;
|
||||
if (buflen) {
|
||||
if ((ts->buffer = ftdm_calloc(buflen, sizeof(teletone_audio_t))) == 0) {
|
||||
if ((ts->buffer = calloc(buflen, sizeof(teletone_audio_t))) == 0) {
|
||||
return -1;
|
||||
}
|
||||
ts->datalen = buflen;
|
||||
@@ -142,7 +177,7 @@ TELETONE_API(int) teletone_init_session(teletone_generation_session_t *ts, int b
|
||||
TELETONE_API(int) teletone_destroy_session(teletone_generation_session_t *ts)
|
||||
{
|
||||
if (ts->buffer) {
|
||||
ftdm_safe_free(ts->buffer);
|
||||
free(ts->buffer);
|
||||
ts->buffer = NULL;
|
||||
ts->samples = 0;
|
||||
}
|
||||
@@ -270,6 +305,19 @@ TELETONE_API(int) teletone_mux_tones(teletone_generation_session_t *ts, teletone
|
||||
return ts->samples / ts->channels;
|
||||
}
|
||||
|
||||
/* don't ask */
|
||||
static char *my_strdup (const char *s)
|
||||
{
|
||||
size_t len = strlen (s) + 1;
|
||||
void *new = malloc (len);
|
||||
|
||||
if (new == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (char *) memcpy (new, s, len);
|
||||
}
|
||||
|
||||
TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cmd)
|
||||
{
|
||||
char *data = NULL, *cur = NULL, *end = NULL;
|
||||
@@ -280,7 +328,7 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm
|
||||
}
|
||||
|
||||
do {
|
||||
if (!(data = ftdm_strdup(cmd))) {
|
||||
if (!(data = my_strdup(cmd))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -363,6 +411,9 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm
|
||||
*e++ = '\0';
|
||||
}
|
||||
do {
|
||||
if (!p) {
|
||||
break;
|
||||
}
|
||||
if ((next = strchr(p, ',')) != 0) {
|
||||
*next++ = '\0';
|
||||
}
|
||||
@@ -427,7 +478,7 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm
|
||||
}
|
||||
}
|
||||
bottom:
|
||||
ftdm_safe_free(data);
|
||||
free(data);
|
||||
data = NULL;
|
||||
if (ts->LOOPS > 0) {
|
||||
ts->LOOPS--;
|
||||
|
||||
Reference in new issue
Block a user