From f316f9307fbb91a89105fd583677200328c83738 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Mon, 7 May 2012 15:35:13 -0400 Subject: [PATCH] freetdm: First GSM working version - Manually merging latest code from gideon.gsm branch after review/inspection/modifications --- libs/freetdm/mod_freetdm/mod_freetdm.c | 25 +- libs/freetdm/src/ftmod/ftmod_gsm/ftmod_gsm.c | 868 ++++++++++++++---- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 42 +- libs/freetdm/src/include/freetdm.h | 8 +- 4 files changed, 751 insertions(+), 192 deletions(-) mode change 100644 => 100755 libs/freetdm/src/ftmod/ftmod_gsm/ftmod_gsm.c mode change 100644 => 100755 libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index e40ca5ef93..a31a5342c9 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -26,7 +26,7 @@ * Anthony Minessale II * Moises Silva * David Yat Sin - * + * Gideon Sadan * * mod_freetdm.c -- FreeTDM Endpoint Module * @@ -1887,6 +1887,24 @@ static FIO_SIGNAL_CB_FUNCTION(on_common_signal) switch (sigmsg->event_id) { + case FTDM_SIGEVENT_SMS: + { + ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(sigmsg->channel); + ftdm_sms_data_t *sms = (ftdm_sms_data_t*) caller_data->priv; + + + ftdm_log(FTDM_LOG_INFO,"FTDM_SIGEVENT_SMS from %s: %s", sms->from, sms->body); + if (switch_event_create(&event, SWITCH_EVENT_TRAP) != SWITCH_STATUS_SUCCESS) { + ftdm_log(FTDM_LOG_ERROR, "failed to create SMS event\n"); + return FTDM_FAIL; + } + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", sms->from); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "body", sms->body); + alarmbits = 0; + } + //return FTDM_BREAK; + break; + case FTDM_SIGEVENT_ALARM_CLEAR: case FTDM_SIGEVENT_ALARM_TRAP: { @@ -1936,6 +1954,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_common_signal) return FTDM_SUCCESS; } break; + case FTDM_SIGEVENT_RELEASED: case FTDM_SIGEVENT_INDICATION_COMPLETED: case FTDM_SIGEVENT_DIALING: @@ -1964,6 +1983,8 @@ static FIO_SIGNAL_CB_FUNCTION(on_common_signal) } if (event) { + + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-name", "%s", ftdm_channel_get_span_name(sigmsg->channel)); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-number", "%d", ftdm_channel_get_span_id(sigmsg->channel)); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "chan-number", "%d", ftdm_channel_get_id(sigmsg->channel)); @@ -2898,7 +2919,7 @@ static void parse_gsm_spans(switch_xml_t cfg, switch_xml_t spans) "gsm", on_clear_channel_signal, spanparameters) != FTDM_SUCCESS) { - CONFIG_ERROR("Error configuring Sangoma ISDN FreeTDM span %d\n", span_id); + CONFIG_ERROR("Error configuring Sangoma GSM FreeTDM span %d\n", span_id); continue; } SPAN_CONFIG[span_id].span = span; diff --git a/libs/freetdm/src/ftmod/ftmod_gsm/ftmod_gsm.c b/libs/freetdm/src/ftmod/ftmod_gsm/ftmod_gsm.c old mode 100644 new mode 100755 index dd46e0354c..35a7be22bb --- a/libs/freetdm/src/ftmod/ftmod_gsm/ftmod_gsm.c +++ b/libs/freetdm/src/ftmod/ftmod_gsm/ftmod_gsm.c @@ -37,6 +37,7 @@ * */ + #define _GNU_SOURCE #include @@ -48,31 +49,86 @@ #include #include #include -/*========================*/ +/*========================*/ #include #include #include + #include +// Debug +#define LOG_SIG_DATA 0 +#define DEBUG_STATES 0 + + +#if DEBUG_STATES // state debugging +#define STATE_ADVANCE_LOG_LEVEL FTDM_LOG_CRIT +#else +#define STATE_ADVANCE_LOG_LEVEL FTDM_LOG_DEBUG +#endif + + +/********************************************************************************/ +/* */ +/* MACROS */ +/* */ +/********************************************************************************/ +// Macro to send signals +#define SEND_STATE_SIGNAL(sig) \ + { \ + ftdm_sigmsg_t sigev; \ + memset(&sigev, 0, sizeof(sigev)); \ + sigev.event_id = sig; \ + sigev.channel = ftdmchan; \ + ftdm_span_send_signal(ftdmchan->span, &sigev); \ + } + +// Syntax message +#define FT_SYNTAX "USAGE:\n" \ +"--------------------------------------------------------------------------------\n" \ +"ftdm gsm version \n" \ +"ftdm gsm status \n" \ +"ftdm gsm sms \n" \ +"--------------------------------------------------------------------------------\n" + +// Used to declare command handler +#define COMMAND_HANDLER(name) \ + ftdm_status_t fCMD_##name(ftdm_stream_handle_t *stream, char *argv[], int argc); \ + ftdm_status_t fCMD_##name(ftdm_stream_handle_t *stream, char *argv[], int argc) + +// Used to define command entry in the command map. +#define COMMAND(name, argc) {#name, argc, fCMD_##name} + +/********************************************************************************/ +/* */ +/* types */ +/* */ +/********************************************************************************/ + +// private data typedef struct ftdm_gsm_span_data_s { ftdm_span_t *span; ftdm_channel_t *dchan; + ftdm_channel_t *bchan; + int32_t call_id; } ftdm_gsm_span_data_t; +// command handler function type. +typedef ftdm_status_t (*fCMD)(ftdm_stream_handle_t *stream, char *argv[], int argc); + + + +/********************************************************************************/ +/* */ +/* function declaration */ +/* */ +/********************************************************************************/ static ftdm_status_t init_wat_lib(void); static int wat_lib_initialized = 0; +static FIO_API_FUNCTION(ftdm_gsm_api); + -static int read_channel(ftdm_channel_t *ftdm_chan , const void *buf, int size) -{ - - ftdm_size_t outsize = size; - ftdm_status_t status = ftdm_channel_read(ftdm_chan, (void *)buf, &outsize); - if (FTDM_FAIL == status) { - return -1; - } - return (int)outsize; -} /* wat callbacks */ int on_wat_span_write(unsigned char span_id, void *buffer, unsigned len); @@ -91,9 +147,45 @@ void *on_wat_calloc(size_t nmemb, size_t size); void on_wat_free(void *ptr); void on_wat_log_span(uint8_t span_id, uint8_t level, char *fmt, ...); + +ftdm_span_t *GetSpanByID(unsigned char span_id, ftdm_gsm_span_data_t **gsm_data); + +static void *ftdm_gsm_run(ftdm_thread_t *me, void *obj); + +/********************************************************************************/ +/* */ +/* static & global data */ +/* */ +/********************************************************************************/ +int g_outbound_call_id = 8; + +/* IO interface for the command API */ +static ftdm_io_interface_t g_ftdm_gsm_interface; + +/********************************************************************************/ +/* */ +/* implementation */ +/* */ +/********************************************************************************/ +static int read_channel(ftdm_channel_t *ftdm_chan , const void *buf, int size) +{ + + ftdm_size_t outsize = size; + ftdm_status_t status = ftdm_channel_read(ftdm_chan, (void *)buf, &outsize); + if (FTDM_FAIL == status) { + return -1; + } + return (int)outsize; +} + + int on_wat_span_write(unsigned char span_id, void *buffer, unsigned len) { -/* ftdm_log(FTDM_LOG_DEBUG, "====================>>> %s (%d) - %d\n", buffer, len, (int) span_id);*/ + +#if LOG_SIG_DATA + fprintf(stdout, " Out Data ====================>>> %s \r\n (%d) - %d\n", (char *)buffer, len, (int) span_id); +#endif + ftdm_span_t *span = NULL; ftdm_status_t status = FTDM_FAIL; ftdm_gsm_span_data_t *gsm_data = NULL; @@ -104,14 +196,20 @@ int on_wat_span_write(unsigned char span_id, void *buffer, unsigned len) ftdm_log(FTDM_LOG_ERROR, "Failed to find span %d to write %d bytes\n", span_id, len); return -1; } - + gsm_data = span->signal_data; status = ftdm_channel_write(gsm_data->dchan, (void *)buffer, len, &outsize); if (status != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "Failed to write %d bytes to d-channel in span %s\n", len, span->name); return -1; } - return (int)outsize; + +//#if LOG_SIG_DATA +// fprintf(stdout, "\r\n==================== len=%d outsize=%d \r\n", len, (int)outsize); +//#endif + + fflush(stdout); + return len; } @@ -147,43 +245,200 @@ static void on_wat_span_status(unsigned char span_id, wat_span_status_t *status) { ftdm_log(FTDM_LOG_INFO, "span %d: Unhandled span status notification %d\n", span_id, status->type); } - break; + break; } } void on_wat_con_ind(unsigned char span_id, uint8_t call_id, wat_con_event_t *con_event) { - fprintf(stdout, "s%d: Incoming call (id:%d) Calling Number:%s type:%d plan:%d\n", span_id, call_id, con_event->calling_num.digits, con_event->calling_num.type, con_event->calling_num.plan); + //fprintf(stdout, "s%d: Incoming call (id:%d) Calling Number:%s Calling Name:\"%s\" type:%d plan:%d\n", span_id, call_id, con_event->calling_num.digits, con_event->calling_name, con_event->calling_num.type, con_event->calling_num.plan); + + ftdm_log(FTDM_LOG_INFO, "s%d: Incoming call (id:%d) Calling Number:%s Calling Name:\"%s\" type:%d plan:%d\n", span_id, call_id, con_event->calling_num.digits, con_event->calling_name, con_event->calling_num.type, con_event->calling_num.plan); + + ftdm_span_t *span = NULL; + //ftdm_status_t ftdm_status = FTDM_FAIL; + ftdm_gsm_span_data_t *gsm_data = NULL; + + if(!(span = GetSpanByID(span_id, &gsm_data))) { + return; + } + + gsm_data->call_id = call_id; + + #define ZERO_ARRAY(arr) memset(arr, 0, sizeof(arr)) + // cid date + { + time_t t; + struct tm *tmp; + t = time(NULL); + tmp = localtime(&t); + if (tmp == NULL) { + ZERO_ARRAY(gsm_data->bchan->caller_data.cid_date); + strftime(gsm_data->bchan->caller_data.cid_date, sizeof(gsm_data->bchan->caller_data.cid_date), "%y/%m/%d", tmp); + } + + } + + // cid name + ZERO_ARRAY(gsm_data->bchan->caller_data.cid_name); + strncpy(gsm_data->bchan->caller_data.cid_name, con_event->calling_name,sizeof(gsm_data->bchan->caller_data.cid_name)); + + // dnis + ZERO_ARRAY(gsm_data->bchan->caller_data.dnis.digits); + strncpy(gsm_data->bchan->caller_data.dnis.digits, con_event->calling_num.digits, FTDM_DIGITS_LIMIT); + + //collected + ZERO_ARRAY(gsm_data->bchan->caller_data.collected); + strncpy(gsm_data->bchan->caller_data.collected, con_event->calling_num.digits, FTDM_DIGITS_LIMIT); + + ftdm_set_state(gsm_data->bchan, FTDM_CHANNEL_STATE_RING); + + if (ftdm_channel_open_chan(gsm_data->bchan) != FTDM_SUCCESS) { + ftdm_log_chan(gsm_data->bchan, FTDM_LOG_ERROR, "Failed to open GSM b-channel of span %s!\n", span->name); + } + +} + + +ftdm_span_t *GetSpanByID(unsigned char span_id, ftdm_gsm_span_data_t **gsm_data) +{ + ftdm_status_t ftdm_status = FTDM_FAIL; + ftdm_span_t *span = NULL; + if(gsm_data) { + (*gsm_data) = NULL; + } + + ftdm_status = ftdm_span_find(span_id, &span); + if (ftdm_status != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_ERROR, "GetSpanByID - Failed to find span %d\n", span_id); + return NULL; + } + + if(gsm_data) { + (*gsm_data) = span->signal_data; + } + + return span; - - return; } void on_wat_con_sts(unsigned char span_id, uint8_t call_id, wat_con_status_t *status) { + + ftdm_span_t *span = NULL; + //ftdm_status_t ftdm_status = FTDM_FAIL; + ftdm_gsm_span_data_t *gsm_data = NULL; + + if(!(span = GetSpanByID(span_id, &gsm_data))) { + return; + } + + + + switch(status->type) { + + case WAT_CON_STATUS_TYPE_RINGING: + ftdm_log(FTDM_LOG_INFO, "on_wat_con_sts - WAT_CON_STATUS_TYPE_RINGING\r\n"); + ftdm_set_state(gsm_data->bchan, FTDM_CHANNEL_STATE_RINGING); + break; + + case WAT_CON_STATUS_TYPE_ANSWER: + ftdm_log(FTDM_LOG_INFO, "on_wat_con_sts - WAT_CON_STATUS_TYPE_ANSWER\r\n"); + ftdm_set_state(gsm_data->bchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); + break; + default: + ftdm_log(FTDM_LOG_INFO, "on_wat_con_sts - Unhandled state %d\n", span_id); + + }; + + return; } void on_wat_rel_ind(unsigned char span_id, uint8_t call_id, wat_rel_event_t *rel_event) { - fprintf(stdout, "s%d: Call hangup (id:%d) cause:%d\n", span_id, call_id, rel_event->cause); + ftdm_log(FTDM_LOG_INFO, "s%d: Call hangup (id:%d) cause:%d\n", span_id, call_id, rel_event->cause); - return; + ftdm_span_t *span = NULL; + //ftdm_status_t ftdm_status = FTDM_FAIL; + ftdm_gsm_span_data_t *gsm_data = NULL; + + if(!(span = GetSpanByID(span_id, &gsm_data))) { + return; + } + + ftdm_set_state(gsm_data->bchan, FTDM_CHANNEL_STATE_HANGUP); + + } void on_wat_rel_cfm(unsigned char span_id, uint8_t call_id) { - fprintf(stdout, "s%d: Call hangup complete (id:%d)\n", span_id, call_id); - return; + ftdm_log(FTDM_LOG_INFO, "s%d: Call hangup complete (id:%d)\n", span_id, call_id); + ftdm_span_t *span = NULL; + //ftdm_status_t ftdm_status = FTDM_FAIL; + ftdm_gsm_span_data_t *gsm_data = NULL; + + if(!(span = GetSpanByID(span_id, &gsm_data))) { + return; + } + + switch(gsm_data->dchan->state) { + case FTDM_CHANNEL_STATE_UP: + ftdm_set_state(gsm_data->bchan, FTDM_CHANNEL_STATE_HANGUP); + break; + default: + ftdm_set_state(gsm_data->bchan, FTDM_CHANNEL_STATE_DOWN); + break; + } + } void on_wat_sms_ind(unsigned char span_id, wat_sms_event_t *sms_event) { + //printf("on_wat_sms_ind\r\n"); + + ftdm_span_t *span = NULL; + ftdm_channel_t *ftdmchan; + + ftdm_gsm_span_data_t *gsm_data = NULL; + + if(!(span = GetSpanByID(span_id, &gsm_data))) { + return; + } + + ftdmchan = gsm_data->dchan; + + { + ftdm_sms_data_t sms_data; + memset(&sms_data, 0, sizeof(sms_data)); + + strncpy(sms_data.from, sms_event->from.digits, sizeof(sms_data.from)); + strncpy(sms_data.body, sms_event->content.data, sizeof(sms_data.body)); + + ftdm_sigmsg_t sigev; + memset(&sigev, 0, sizeof(sigev)); + sigev.event_id = FTDM_SIGEVENT_SMS; + sigev.channel = ftdmchan ; + gsm_data->dchan->caller_data.priv = (void *)&sms_data; + ftdm_span_send_signal(span, &sigev); + } +// SEND_STATE_SIGNAL(FTDM_SIGEVENT_SMS); return; } void on_wat_sms_sts(unsigned char span_id, uint8_t sms_id, wat_sms_status_t *status) { + + if(status->success) { + ftdm_log(FTDM_LOG_INFO, "Span %d SMS Send - OK\n", span_id ); + } + else { + ftdm_log(FTDM_LOG_CRIT, "Span %d SMS Send - FAIL (%s)\n", span_id, status->error); + + } + + return; } @@ -198,8 +453,7 @@ void on_wat_log(uint8_t level, char *fmt, ...) va_start(argptr, fmt); char buff[10001]; - switch(level) - { + switch(level) { case WAT_LOG_CRIT: ftdm_level = FTDM_LOG_LEVEL_CRIT; break; case WAT_LOG_ERROR: ftdm_level = FTDM_LOG_LEVEL_ERROR; break; default: @@ -223,27 +477,30 @@ void *on_wat_malloc(size_t size) { return ftdm_malloc(size); } + void *on_wat_calloc(size_t nmemb, size_t size) { return ftdm_calloc(nmemb, size); } + void on_wat_free(void *ptr) { ftdm_free(ptr); } + void on_wat_log_span(uint8_t span_id, uint8_t level, char *fmt, ...) { int ftdm_level; - +return; va_list argptr; va_start(argptr, fmt); char buff[10001]; - switch(level) - { + switch(level) { case WAT_LOG_CRIT: ftdm_level = FTDM_LOG_LEVEL_CRIT; break; case WAT_LOG_ERROR: ftdm_level = FTDM_LOG_LEVEL_ERROR; break; default: + case WAT_LOG_WARNING: ftdm_level = FTDM_LOG_LEVEL_WARNING; break; case WAT_LOG_INFO: ftdm_level = FTDM_LOG_LEVEL_INFO; break; case WAT_LOG_NOTICE: ftdm_level = FTDM_LOG_LEVEL_NOTICE; break; @@ -265,22 +522,17 @@ void on_wat_log_span(uint8_t span_id, uint8_t level, char *fmt, ...) /* END wat callbacks */ /* span monitor thread */ -static void *ftdm_gsm_run(ftdm_thread_t *me, void *obj); - -/* IO interface for the command API */ -static ftdm_io_interface_t g_ftdm_gsm_interface; - static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(gsm_outgoing_call) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "GSM place call not implemented yet!\n"); - return FTDM_FAIL; + + return FTDM_SUCCESS; } static ftdm_status_t ftdm_gsm_start(ftdm_span_t *span) { if (wat_span_start(span->span_id)) { ftdm_log(FTDM_LOG_ERROR, "Failed to start span %s!\n", span->name); - return FTDM_FAIL; + return FTDM_SUCCESS; } return ftdm_thread_create_detached(ftdm_gsm_run, span); @@ -288,32 +540,38 @@ static ftdm_status_t ftdm_gsm_start(ftdm_span_t *span) static ftdm_status_t ftdm_gsm_stop(ftdm_span_t *span) { - ftdm_log(FTDM_LOG_CRIT, "STOP not implemented yet!\n"); - return FTDM_FAIL; + return FTDM_SUCCESS; } static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_gsm_get_channel_sig_status) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "get sig status not implemented yet!\n"); - return FTDM_FAIL; + ftdm_log(FTDM_LOG_INFO, "\r\nftdm_gsm_get_channel_sig_status\r\n"); + + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { + *status = FTDM_SIG_STATE_UP; + } + else { + *status = FTDM_SIG_STATE_DOWN; + } + *status = FTDM_SIG_STATE_UP; + return FTDM_SUCCESS; + } static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_gsm_set_channel_sig_status) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "set sig status not implemented yet!\n"); - return FTDM_FAIL; + return FTDM_SUCCESS; } static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_gsm_get_span_sig_status) { - ftdm_log(FTDM_LOG_CRIT, "span get sig status not implemented yet!\n"); - return FTDM_FAIL; + *status = FTDM_SIG_STATE_UP; + return FTDM_SUCCESS; } static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_gsm_set_span_sig_status) { - ftdm_log(FTDM_LOG_CRIT, "span set sig status not implemented yet!\n"); - return FTDM_FAIL; + return FTDM_SUCCESS; } static ftdm_state_map_t gsm_state_map = { @@ -393,10 +651,12 @@ static ftdm_state_map_t gsm_state_map = { { ZSD_OUTBOUND, ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DIALING, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END} + {FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_RINGING, FTDM_END}, + {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_RINGING, FTDM_END} }, + + { ZSD_OUTBOUND, ZSM_UNACCEPTABLE, @@ -429,7 +689,135 @@ static ftdm_state_map_t gsm_state_map = { static ftdm_status_t ftdm_gsm_state_advance(ftdm_channel_t *ftdmchan) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Executing state handler for %s\n", ftdm_channel_state2str(ftdmchan->state)); + + ftdm_log_chan(ftdmchan, STATE_ADVANCE_LOG_LEVEL , "Executing state handler for %s\n", ftdm_channel_state2str(ftdmchan->state)); + + ftdm_channel_complete_state(ftdmchan); + + switch (ftdmchan->state) { + + /* starting an incoming call */ + case FTDM_CHANNEL_STATE_COLLECT: + { + + + } + break; + + /* starting an outgoing call */ + case FTDM_CHANNEL_STATE_DIALING: + { + uint32_t interval = 0; + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting outgoing call with interval %d\n", interval); + + { + + ftdm_gsm_span_data_t *gsm_data; + gsm_data = ftdmchan->span->signal_data; + gsm_data->call_id = g_outbound_call_id++; + wat_con_event_t con_event; + memset(&con_event, 0, sizeof(con_event)); + sprintf(con_event.called_num.digits, ftdmchan->caller_data.dnis.digits); + ftdm_log(FTDM_LOG_DEBUG, "Dialing number %s\n", con_event.called_num.digits); + wat_con_req(ftdmchan->span->span_id, gsm_data->call_id , &con_event); + + SEND_STATE_SIGNAL(FTDM_SIGEVENT_DIALING); + + + } + + + } + break; + + /* incoming call was offered */ + case FTDM_CHANNEL_STATE_RING: + + /* notify the user about the new call */ + + ftdm_log(FTDM_LOG_INFO, "Answering Incomming Call\r\n"); + SEND_STATE_SIGNAL(FTDM_SIGEVENT_START); + + break; + + /* the call is making progress */ + case FTDM_CHANNEL_STATE_PROGRESS: + case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: + { + SEND_STATE_SIGNAL(FTDM_SIGEVENT_PROGRESS_MEDIA); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); + } + break; + + /* the call was answered */ + case FTDM_CHANNEL_STATE_UP: + { + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { + + SEND_STATE_SIGNAL(FTDM_SIGEVENT_UP); + } + else { + ftdm_gsm_span_data_t *gsm_data; + gsm_data = ftdmchan->span->signal_data; + wat_con_cfm(ftdmchan->span->span_id, gsm_data->call_id); + } + + + } + break; + + /* just got hangup */ + case FTDM_CHANNEL_STATE_HANGUP: + { + ftdm_gsm_span_data_t *gsm_data; + gsm_data = ftdmchan->span->signal_data; + wat_rel_req(ftdmchan->span->span_id, gsm_data->call_id); + gsm_data->call_id = 0; + SEND_STATE_SIGNAL(FTDM_SIGEVENT_STOP); + } + break; + + case FTDM_CHANNEL_STATE_TERMINATING: + { + SEND_STATE_SIGNAL(FTDM_SIGEVENT_STOP); + } + break; + + /* finished call for good */ + case FTDM_CHANNEL_STATE_DOWN: + { + ftdm_channel_t *closed_chan; + closed_chan = ftdmchan; + ftdm_channel_close(&closed_chan); + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "State processing ended.\n"); + SEND_STATE_SIGNAL(FTDM_SIGEVENT_STOP); + } + break; + + /* INDICATE_RINGING doesn't apply to MFC/R2. maybe we could generate a tone */ + case FTDM_CHANNEL_STATE_RINGING: + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RINGING indicated, ignoring it as it doesn't apply to MFC/R2\n"); + SEND_STATE_SIGNAL(FTDM_SIGEVENT_RINGING); + + break; + + /* put the r2 channel back to IDLE, close ftdmchan and set it's state as DOWN */ + case FTDM_CHANNEL_STATE_RESET: + { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RESET indicated, putting the R2 channel back to IDLE\n"); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + } + break; + + default: + { + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Unhandled channel state change: %s\n", ftdm_channel_state2str(ftdmchan->state)); + } + break; + } + + return FTDM_SUCCESS; } @@ -465,8 +853,8 @@ static ftdm_status_t init_wat_lib(void) if (wat_register(&wat_interface)) { ftdm_log(FTDM_LOG_DEBUG, "Failed registering interface to WAT library ...\n"); return FTDM_FAIL; - } + ftdm_log(FTDM_LOG_DEBUG, "Registered interface to WAT library\n"); wat_lib_initialized = 1; @@ -482,10 +870,12 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling) 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)); @@ -508,6 +898,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling) /* 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; @@ -516,10 +907,14 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling) citer = ftdm_span_get_chan_iterator(span, chaniter); for ( ; citer; citer = ftdm_iterator_next(citer)) { ftdmchan = ftdm_iterator_current(citer); - if (FTDM_IS_DCHAN(ftdmchan)) { + + if ((NULL == dchan) && FTDM_IS_DCHAN(ftdmchan)) { dchan = ftdmchan; - break; } + if ((NULL == bchan) && FTDM_IS_VOICE_CHANNEL(ftdmchan)) { + bchan = ftdmchan; + } + } ftdm_iterator_free(chaniter); @@ -527,12 +922,24 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling) 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; @@ -569,6 +976,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling) 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; @@ -589,11 +997,21 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling) #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; } @@ -601,11 +1019,12 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling) #define GSM_POLL_INTERVAL_MS 20 static void *ftdm_gsm_run(ftdm_thread_t *me, void *obj) { + + ftdm_log(FTDM_LOG_INFO,"ftdm_gsm_run\r\n"); + ftdm_channel_t *ftdmchan = NULL; ftdm_span_t *span = (ftdm_span_t *) obj; ftdm_gsm_span_data_t *gsm_data = NULL; - ftdm_status_t status = FTDM_SUCCESS; - ftdm_wait_flag_t ioflags = FTDM_NO_FLAGS; ftdm_interrupt_t *data_sources[2] = {NULL, NULL}; int waitms = 0; @@ -620,16 +1039,8 @@ static void *ftdm_gsm_run(ftdm_thread_t *me, void *obj) goto done; } - /* create an interrupt object to wait for data from the d-channel device */ - if (ftdm_interrupt_create(&data_sources[0], gsm_data->dchan->sockfd, FTDM_READ) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed to create GSM d-channel interrupt for span %s\n", span->name); - goto done; - } - status = ftdm_queue_get_interrupt(span->pendingchans, &data_sources[1]); - if (status != FTDM_SUCCESS || data_sources[1] == NULL) { - ftdm_log(FTDM_LOG_CRIT, "Failed to retrieve channel queue interrupt for span %s\n", span->name); - goto done; - } + + while (ftdm_running()) { @@ -640,47 +1051,48 @@ static void *ftdm_gsm_run(ftdm_thread_t *me, void *obj) waitms = GSM_POLL_INTERVAL_MS; } -#if 0 - /* run any span timers */ - ftdm_sched_run(r2data->sched); +///////////////////// + + + { + ftdm_wait_flag_t flags = FTDM_READ | FTDM_EVENTS; + ftdm_status_t status = ftdm_channel_wait(gsm_data->dchan, &flags, waitms); + + /* double check that this channel has a state change pending */ + ftdm_channel_lock(gsm_data->bchan); + ftdm_channel_advance_states(gsm_data->bchan); + + if(FTDM_SUCCESS == status ) { + + if(flags &FTDM_READ ) { + char buffer[1025]; + int n = 0, m = 0; + memset(buffer, 0, sizeof(buffer)); + + n = read_channel(gsm_data->dchan, buffer, sizeof(buffer)-1); + m = strlen(buffer); + wat_span_process_read(span->span_id, buffer, m); +#if LOG_SIG_DATA + printf("<<======================= incomming data len = %d, %s\r\n", n, buffer); #endif - status = ftdm_interrupt_multiple_wait(data_sources, ftdm_array_len(data_sources), waitms); - switch (status) { - case FTDM_ETIMEDOUT: - break; - case FTDM_SUCCESS: - { - /* process first the d-channel if ready */ - if ((ioflags = ftdm_interrupt_device_ready(data_sources[0])) != FTDM_NO_FLAGS) { - char buffer[1024]; - unsigned int n = 0; - n = read_channel(gsm_data->dchan, buffer, sizeof(buffer)); - /* this may trigger any of the callbacks registered through wat_register() */ - wat_span_process_read(span->span_id, buffer, n); - } - /* now process all channels with state changes pending */ - while ((ftdmchan = ftdm_queue_dequeue(span->pendingchans))) { - /* double check that this channel has a state change pending */ - ftdm_channel_lock(ftdmchan); - ftdm_channel_advance_states(ftdmchan); - ftdm_channel_unlock(ftdmchan); } - - /* deliver the actual channel events to the user now without any channel locking */ - ftdm_span_trigger_signals(span); } - break; - case FTDM_FAIL: - ftdm_log(FTDM_LOG_ERROR, "%s: ftdm_interrupt_wait returned error!\n", span->name); - break; + + ftdm_channel_advance_states(gsm_data->bchan); + + ftdm_channel_unlock(gsm_data->bchan); + - default: - ftdm_log(FTDM_LOG_ERROR, "%s: ftdm_interrupt_wait returned with unknown code\n", span->name); - break; } + + + + ftdm_span_trigger_signals(span); + + } done: @@ -693,94 +1105,7 @@ done: return NULL; } -#define FT_SYNTAX "USAGE:\n" \ -"--------------------------------------------------------------------------------\n" \ -"ftdm gsm status \n" \ -"--------------------------------------------------------------------------------\n" -static FIO_API_FUNCTION(ftdm_gsm_api) -{ - ftdm_span_t *span = NULL; - int span_id = 0; - char *mycmd = NULL, *argv[10] = { 0 }; - int argc = 0; - if (data) { - mycmd = ftdm_strdup(data); - argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); - } - - if (!strcasecmp(argv[0], "version")) { - uint8_t current = 0, revision = 0, age = 0; - wat_version(¤t, &revision, &age); - stream->write_function(stream, "libwat version: %d.%d.%d\n", current, revision, age); - stream->write_function(stream, "+OK.\n"); - goto done; - - } else if (!strcasecmp(argv[0], "status")) { - const wat_chip_info_t *chip_info = NULL; - const wat_sim_info_t *sim_info = NULL; - const wat_net_info_t *net_info = NULL; - const wat_sig_info_t *sig_info = NULL; - const wat_pin_stat_t *pin_stat = NULL; - - if (argc < 2) { - goto syntax; - } - - span_id = atoi(argv[1]); - if (ftdm_span_find_by_name(argv[1], &span) != FTDM_SUCCESS && - ftdm_span_find(span_id, &span) != FTDM_SUCCESS) { - stream->write_function(stream, "-ERR Failed to find GSM span '%s'\n", argv[1]); - goto done; - } - - if (!span || !span->signal_data || (span->start != ftdm_gsm_start)) { - stream->write_function(stream, "-ERR '%s' is not a valid GSM span\n", argv[1]); - goto done; - } - - chip_info = wat_span_get_chip_info(span->span_id); - sim_info = wat_span_get_sim_info(span->span_id); - net_info = wat_span_get_net_info(span->span_id); - sig_info = wat_span_get_sig_info(span->span_id); - pin_stat = wat_span_get_pin_info(span->span_id); - - stream->write_function(stream, "Span %d (%s):\n", span->span_id, span->name); - - stream->write_function(stream, "CHIP - %s (%s), revision %s, serial %s \n", - chip_info->manufacturer_name, - chip_info->manufacturer_id, - chip_info->revision, - chip_info->serial); - - stream->write_function(stream, "SIM - Subscriber type %s, imsi %s\n", sim_info->subscriber_type, sim_info->imsi); - - stream->write_function(stream, "Subscriber - Number %s, Plan %s, validity %s\n", - sim_info->subscriber.digits, - wat_number_type2str(sim_info->subscriber.type), - wat_number_plan2str(sim_info->subscriber.plan), - wat_number_validity2str(sim_info->subscriber.validity)); - - stream->write_function(stream, "Network - status %s, Area Code %d, Cell ID %d, Operator %s\n", - wat_net_stat2str(net_info->stat), net_info->lac, net_info->ci, net_info->operator_name); - - - stream->write_function(stream, "\n"); - - stream->write_function(stream, "+OK.\n"); - goto done; - } - -syntax: - stream->write_function(stream, "%s", FT_SYNTAX); -done: - - ftdm_safe_free(mycmd); - - return FTDM_SUCCESS; - - -} static FIO_IO_LOAD_FUNCTION(ftdm_gsm_io_init) { @@ -827,3 +1152,178 @@ EX_DECLARE_DATA ftdm_module_t ftdm_module = { * For VIM: * vim:set softtabstop=4 shiftwidth=4 tabstop=4: */ + + +/********************************************************************************/ +/* */ +/* COMMAND HANDLERS */ +/* */ +/********************************************************************************/ + + +// Version Command Handler +COMMAND_HANDLER(version) +{ + uint8_t current = 0, revision = 0, age = 0; + wat_version(¤t, &revision, &age); + stream->write_function(stream, "libwat version: %d.%d.%d\n", current, revision, age); + stream->write_function(stream, "+OK.\n"); + return FTDM_SUCCESS; +} + + +// Status Command Handler +COMMAND_HANDLER(status) +{ + int span_id = 0; + ftdm_span_t *span = NULL; + const wat_chip_info_t *chip_info = NULL; + const wat_sim_info_t *sim_info = NULL; + const wat_net_info_t *net_info = NULL; + const wat_sig_info_t *sig_info = NULL; + const wat_pin_stat_t *pin_stat = NULL; + + + span_id = atoi(argv[0]); + if (ftdm_span_find_by_name(argv[0], &span) != FTDM_SUCCESS && ftdm_span_find(span_id, &span) != FTDM_SUCCESS) { + stream->write_function(stream, "-ERR Failed to find GSM span '%s'\n", argv[1]); + return FTDM_FAIL; + } + + if (!span || !span->signal_data || (span->start != ftdm_gsm_start)) { + stream->write_function(stream, "-ERR '%s' is not a valid GSM span\n", argv[1]); + return FTDM_FAIL; + } + + chip_info = wat_span_get_chip_info(span->span_id); + sim_info = wat_span_get_sim_info(span->span_id); + net_info = wat_span_get_net_info(span->span_id); + sig_info = wat_span_get_sig_info(span->span_id); + pin_stat = wat_span_get_pin_info(span->span_id); + + stream->write_function(stream, "Span %d (%s):\n", span->span_id, span->name); + + stream->write_function(stream, "CHIP type - %s (%s), revision %s, serial %s \n", + chip_info->manufacturer, + chip_info->model, + chip_info->revision, + chip_info->serial); + + stream->write_function(stream, "SIM - Subscriber type %s, imsi %s\n", sim_info->subscriber_type, sim_info->imsi); + + stream->write_function(stream, "Subscriber - Number %s, Plan %s, validity %s\n", + sim_info->subscriber.digits, + wat_number_type2str(sim_info->subscriber.type), + wat_number_plan2str(sim_info->subscriber.plan), + wat_number_validity2str(sim_info->subscriber.validity)); + + stream->write_function(stream, "Network - status %s, Area Code %d, Cell ID %d, Operator %s\n", + wat_net_stat2str(net_info->stat), net_info->lac, net_info->ci, net_info->operator_name); + + + stream->write_function(stream, "\n"); + + stream->write_function(stream, "+OK.\n"); + + return FTDM_SUCCESS; +} + +// SMS Command Handler +COMMAND_HANDLER(sms) +{ + int span_id = 0,i; + ftdm_span_t *span = NULL; + wat_sms_event_t sms; + + + span_id = atoi(argv[0]); + if (ftdm_span_find_by_name(argv[0], &span) != FTDM_SUCCESS && ftdm_span_find(span_id, &span) != FTDM_SUCCESS) { + stream->write_function(stream, "-ERR Failed to find GSM span '%s'\n", argv[1]); + return FTDM_FAIL; + } + + if (!span || !span->signal_data || (span->start != ftdm_gsm_start)) { + stream->write_function(stream, "-ERR '%s' is not a valid GSM span\n", argv[1]); + return FTDM_FAIL; + } + + memset(&sms, 0, sizeof(sms)); + + strcpy(sms.to.digits, argv[1]); + sms.type = WAT_SMS_TXT; + sms.content.data[0] = '\0'; + for(i=2;ispan_id, g_outbound_call_id++ , &sms)) { + stream->write_function(stream, "Failed to Send SMS \n"); + } + else { + stream->write_function(stream, "SMS Sent.\n"); + } + return FTDM_SUCCESS; +} + + + +// command map +struct { + const char*CMD; // command + int Argc; // minimum args + fCMD Handler; // handling function +} + GSM_COMMANDS[] = { + COMMAND(version, 0), + COMMAND(status, 1), + COMMAND(sms, 3) + }; + +// Commnand API entry point +static FIO_API_FUNCTION(ftdm_gsm_api) +{ + + char *mycmd = NULL, *argv[10] = { 0 }; + int argc = 0; + int i; + ftdm_status_t status = FTDM_FAIL; + ftdm_status_t syntax = FTDM_FAIL; + + + if (data) { + mycmd = ftdm_strdup(data); + argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + } + + if(argc > 0) { + for(i=0;i= GSM_COMMANDS[i].Argc) { + syntax = FTDM_SUCCESS; + status = GSM_COMMANDS[i].Handler(stream, &argv[1], argc-1); + + } + + break; + } + + } + } + + if(FTDM_SUCCESS != syntax) { + stream->write_function(stream, "%s", FT_SYNTAX); + } + else + if(FTDM_SUCCESS != status) { + stream->write_function(stream, "%s Command Failed\r\n", GSM_COMMANDS[i].CMD); + } + ftdm_safe_free(mycmd); + + return FTDM_SUCCESS; +} + + diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c old mode 100644 new mode 100755 index 1e9f3b059f..75d165be1d --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -36,9 +36,9 @@ * David Yat Sin * Nenad Corbic * Arnaldo Pereira + * Gideon Sadan * - */ - + */ #ifdef WP_DEBUG_IO #define _BSD_SOURCE #include @@ -121,6 +121,16 @@ FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event); FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event); FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event); +static void wp_swap16(char *data, int datalen) +{ + int i = 0; + uint16_t *samples = data; + for (i = 0; i < datalen/2; i++) { + uint16_t sample = ((samples[i] & 0x00FF) << 8) | ((samples[i] & 0xFF00) >> 8); + samples[i] = sample; + } +} + /** * \brief Poll for event on a wanpipe socket * \param fd Wanpipe socket descriptor @@ -305,11 +315,20 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start err = sangoma_tdm_get_hw_coding(chan->sockfd, &tdm_api); + + if (tdm_api.wp_tdm_cmd.hw_tdm_coding) { chan->native_codec = chan->effective_codec = FTDM_CODEC_ALAW; } else { chan->native_codec = chan->effective_codec = FTDM_CODEC_ULAW; } + + + if ((span->trunk_type == FTDM_TRUNK_GSM) && (chan->type == FTDM_CHAN_TYPE_B)) { + chan->native_codec = FTDM_CODEC_SLIN; + chan->native_interval = 20; + chan->packet_len = 320; + } err = sangoma_tdm_get_hw_dtmf(chan->sockfd, &tdm_api); if (err > 0) { @@ -580,8 +599,9 @@ static FIO_OPEN_FUNCTION(wanpipe_open) ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_INTERVAL); ftdmchan->effective_interval = ftdmchan->native_interval = wp_globals.codec_ms; - ftdmchan->packet_len = ftdmchan->native_interval * 8; - + + /* The packet len will depend on the codec and interval */ + ftdmchan->packet_len = ftdmchan->native_interval * ((ftdmchan->native_codec==FTDM_CODEC_SLIN) ? 16 : 8); if (wp_globals.txqueue_size > 0) { ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &wp_globals.txqueue_size); } @@ -772,6 +792,7 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) case FTDM_COMMAND_SET_INTERVAL: { err=sangoma_tdm_set_usr_period(ftdmchan->sockfd, &tdm_api, FTDM_COMMAND_OBJ_INT); + ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8); } break; @@ -793,7 +814,7 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) FTDM_COMMAND_OBJ_INT = wanpipe_swap_bits(rbsbits); } #else - // does sangoma_tdm_read_rbs is available here? + /* is sangoma_tdm_read_rbs available here? */ FTDM_COMMAND_OBJ_INT = ftdmchan->rx_cas_bits; #endif } @@ -969,12 +990,15 @@ static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx * \param datalen Size of data buffer * \return Success, failure or timeout */ + + static FIO_READ_FUNCTION(wanpipe_read) { int rx_len = 0; int rq_len = (int)*datalen; wp_tdm_api_rx_hdr_t hdrframe; + #ifdef WP_DEBUG_IO wp_channel_t *wchan = ftdmchan->io_data; ftdm_time_t time_diff = 0; @@ -1034,6 +1058,10 @@ static FIO_READ_FUNCTION(wanpipe_read) wanpipe_read_stats(ftdmchan, &hdrframe); } + if ((ftdmchan->type == FTDM_CHAN_TYPE_B) && (ftdmchan->span->trunk_type == FTDM_TRUNK_GSM)) { + wp_swap16(data, *datalen); + } + return FTDM_SUCCESS; } @@ -1050,6 +1078,10 @@ static FIO_WRITE_FUNCTION(wanpipe_write) int err = 0; wp_tdm_api_tx_hdr_t hdrframe; + if ((ftdmchan->type == FTDM_CHAN_TYPE_B) && (ftdmchan->span->trunk_type == FTDM_TRUNK_GSM)) { + wp_swap16(data, *datalen); + } + /* Do we even need the headerframe here? on windows, we don't even pass it to the driver */ memset(&hdrframe, 0, sizeof(hdrframe)); if (*datalen == 0) { diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 165f243cf3..b48bb50ae5 100755 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -346,6 +346,11 @@ typedef struct { uint8_t plan; } ftdm_number_t; +typedef struct { + char from[FTDM_MAX_NUMBER_STR_SZ]; + char body[FTDM_MAX_NAME_STR_SZ]; +} ftdm_sms_data_t; + /*! \brief Caller information */ typedef struct ftdm_caller_data { char cid_date[8]; /*!< Caller ID date */ @@ -456,12 +461,13 @@ typedef enum { FTDM_SIGEVENT_INDICATION_COMPLETED, /*!< Last requested indication was completed */ FTDM_SIGEVENT_DIALING, /*!< Outgoing call just started */ FTDM_SIGEVENT_TRANSFER_COMPLETED, /*!< Transfer request is completed */ + FTDM_SIGEVENT_SMS, FTDM_SIGEVENT_INVALID, /*!