mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-14 08:05:37 +00:00
freetdm: refactor ftmod_gsm.c code to use proper core functions and interrupts to wait for io and state changes
This commit is contained in:
parent
de98034145
commit
cc79163da3
@ -55,78 +55,14 @@
|
|||||||
#include <freetdm.h>
|
#include <freetdm.h>
|
||||||
#include <private/ftdm_core.h>
|
#include <private/ftdm_core.h>
|
||||||
|
|
||||||
#define MAX_SPANS 32
|
|
||||||
typedef struct ftdm_gsm_span_data_s {
|
typedef struct ftdm_gsm_span_data_s {
|
||||||
ftdm_span_t *span;
|
ftdm_span_t *span;
|
||||||
fio_signal_cb_t sig_cb;
|
ftdm_channel_t *dchan;
|
||||||
ftdm_conf_parameter_t *ftdm_parameters;
|
} ftdm_gsm_span_data_t;
|
||||||
}ftdm_gsm_span_data_t;
|
|
||||||
|
|
||||||
|
static ftdm_status_t init_wat_lib(void);
|
||||||
static ftdm_gsm_span_data_t spans_info[MAX_SPANS];
|
|
||||||
static int n_spans_info = 0;
|
|
||||||
|
|
||||||
typedef struct ftdm_gsm_data_s {
|
|
||||||
|
|
||||||
wat_interface_t wat_interface;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} ftdm_gsm_data_t;
|
|
||||||
|
|
||||||
|
|
||||||
static ftdm_status_t init_wat_lib(void);
|
|
||||||
static int wat_lib_initialized = 0;
|
static int wat_lib_initialized = 0;
|
||||||
|
|
||||||
ftdm_span_t *get_span(int span_id);
|
|
||||||
|
|
||||||
ftdm_span_t *get_span(int span_id)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for(i=0; i< n_spans_info;i++)
|
|
||||||
{
|
|
||||||
if(spans_info[i].span->span_id == span_id) {
|
|
||||||
|
|
||||||
return spans_info[i].span;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ftdm_channel_t *get_channel(int span_id, int channel_id);
|
|
||||||
ftdm_channel_t *get_channel(int span_id, int channel_id)
|
|
||||||
{
|
|
||||||
ftdm_channel_t *ftdmchan = NULL;
|
|
||||||
ftdm_span_t * span = get_span(span_id);
|
|
||||||
|
|
||||||
if(!span){
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ftdm_iterator_t *citer = ftdm_span_get_chan_iterator(span, NULL);
|
|
||||||
|
|
||||||
for ( ; citer; citer = ftdm_iterator_next(citer)) {
|
|
||||||
ftdmchan = ftdm_iterator_current(citer);
|
|
||||||
if(ftdmchan->chan_id == channel_id) {
|
|
||||||
ftdm_iterator_free(citer);
|
|
||||||
return ftdmchan;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ftdm_iterator_free(citer);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int read_channel(ftdm_channel_t *ftdm_chan , const void *buf, int size)
|
static int read_channel(ftdm_channel_t *ftdm_chan , const void *buf, int size)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -139,7 +75,7 @@ static int read_channel(ftdm_channel_t *ftdm_chan , const void *buf, int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* wat callbacks */
|
/* wat callbacks */
|
||||||
int on_wat_span_write(unsigned char span_id, void *buffer, unsigned len);
|
int on_wat_span_write(unsigned char span_id, void *buffer, unsigned len);
|
||||||
|
|
||||||
void on_wat_con_ind(unsigned char span_id, uint8_t call_id, wat_con_event_t *con_event);
|
void on_wat_con_ind(unsigned char span_id, uint8_t call_id, wat_con_event_t *con_event);
|
||||||
void on_wat_con_sts(unsigned char span_id, uint8_t call_id, wat_con_status_t *status);
|
void on_wat_con_sts(unsigned char span_id, uint8_t call_id, wat_con_status_t *status);
|
||||||
@ -155,28 +91,24 @@ void *on_wat_calloc(size_t nmemb, size_t size);
|
|||||||
void on_wat_free(void *ptr);
|
void on_wat_free(void *ptr);
|
||||||
void on_wat_log_span(uint8_t span_id, uint8_t level, char *fmt, ...);
|
void on_wat_log_span(uint8_t span_id, uint8_t level, char *fmt, ...);
|
||||||
|
|
||||||
|
|
||||||
/* gsm_data->wat_interface.wat_log = on_log; */
|
|
||||||
|
|
||||||
/* gsm_data->wat_interface.wat
|
|
||||||
_log_span = on_log_span; */
|
|
||||||
|
|
||||||
/* gsm_data->wat_interface.wat_malloc = on_wat_malloc;*/
|
|
||||||
/* gsm_data->wat_interface.wat_calloc = on_wat_calloc;*/
|
|
||||||
/* gsm_data->wat_interface.wat_free = on_wat_frspanee;*/
|
|
||||||
|
|
||||||
|
|
||||||
int on_wat_span_write(unsigned char span_id, void *buffer, unsigned len)
|
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);*/
|
/* ftdm_log(FTDM_LOG_DEBUG, "====================>>> %s (%d) - %d\n", buffer, len, (int) span_id);*/
|
||||||
|
ftdm_span_t *span = NULL;
|
||||||
ftdm_channel_t * ftdm_chan = get_channel(span_id, 2);
|
ftdm_status_t status = FTDM_FAIL;
|
||||||
|
ftdm_gsm_span_data_t *gsm_data = NULL;
|
||||||
ftdm_size_t outsize = len;
|
ftdm_size_t outsize = len;
|
||||||
ftdm_channel_lock(ftdm_chan);
|
|
||||||
ftdm_status_t status = ftdm_channel_write(ftdm_chan, (void *)buffer, len, &outsize);
|
status = ftdm_span_find(span_id, &span);
|
||||||
ftdm_channel_unlock(ftdm_chan);
|
if (status != FTDM_SUCCESS) {
|
||||||
if (FTDM_FAIL == status) {
|
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 -1;
|
||||||
}
|
}
|
||||||
return (int)outsize;
|
return (int)outsize;
|
||||||
@ -346,6 +278,11 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(gsm_outgoing_call)
|
|||||||
|
|
||||||
static ftdm_status_t ftdm_gsm_start(ftdm_span_t *span)
|
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_thread_create_detached(ftdm_gsm_run, span);
|
return ftdm_thread_create_detached(ftdm_gsm_run, span);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,17 +437,15 @@ static ftdm_status_t ftdm_gsm_state_advance(ftdm_channel_t *ftdmchan)
|
|||||||
|
|
||||||
static ftdm_status_t init_wat_lib(void)
|
static ftdm_status_t init_wat_lib(void)
|
||||||
{
|
{
|
||||||
|
if (wat_lib_initialized) {
|
||||||
if(wat_lib_initialized)
|
|
||||||
{
|
|
||||||
return FTDM_SUCCESS;
|
return FTDM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
wat_interface_t wat_interface;
|
wat_interface_t wat_interface;
|
||||||
|
|
||||||
ftdm_log(FTDM_LOG_DEBUG, "Registering interface to WAT Library...\n");
|
ftdm_log(FTDM_LOG_DEBUG, "Registering interface to WAT Library...\n");
|
||||||
fprintf(stdout, "Registering interface to WAT Library...\n");
|
|
||||||
|
|
||||||
|
memset(&wat_interface, 0, sizeof(wat_interface));
|
||||||
wat_interface.wat_span_write = on_wat_span_write;
|
wat_interface.wat_span_write = on_wat_span_write;
|
||||||
|
|
||||||
wat_interface.wat_log = on_wat_log;
|
wat_interface.wat_log = on_wat_log;
|
||||||
@ -528,13 +463,12 @@ static ftdm_status_t init_wat_lib(void)
|
|||||||
wat_interface.wat_span_sts = on_wat_span_status;
|
wat_interface.wat_span_sts = on_wat_span_status;
|
||||||
|
|
||||||
if (wat_register(&wat_interface)) {
|
if (wat_register(&wat_interface)) {
|
||||||
ftdm_log(FTDM_LOG_DEBUG, "FAILED Registering interface to WAT Library...\n");
|
ftdm_log(FTDM_LOG_DEBUG, "Failed registering interface to WAT library ...\n");
|
||||||
return FTDM_FAIL;
|
return FTDM_FAIL;
|
||||||
|
|
||||||
}
|
}
|
||||||
ftdm_log(FTDM_LOG_DEBUG, "Registered interface to WAT Library\n");
|
ftdm_log(FTDM_LOG_DEBUG, "Registered interface to WAT library\n");
|
||||||
|
|
||||||
fprintf(stdout, "Registered interface to WAT Library\n");
|
|
||||||
wat_lib_initialized = 1;
|
wat_lib_initialized = 1;
|
||||||
return FTDM_SUCCESS;
|
return FTDM_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -542,70 +476,81 @@ static ftdm_status_t init_wat_lib(void)
|
|||||||
|
|
||||||
static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling)
|
static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling)
|
||||||
{
|
{
|
||||||
|
wat_span_config_t span_config;
|
||||||
|
ftdm_gsm_span_data_t *gsm_data = NULL;
|
||||||
|
ftdm_iterator_t *chaniter = NULL;
|
||||||
|
ftdm_iterator_t *citer = NULL;
|
||||||
|
ftdm_channel_t *ftdmchan = NULL;
|
||||||
|
ftdm_channel_t *dchan = NULL;
|
||||||
unsigned paramindex = 0;
|
unsigned paramindex = 0;
|
||||||
const char *var = NULL;
|
const char *var = NULL;
|
||||||
const char *val = NULL;
|
const char *val = NULL;
|
||||||
|
|
||||||
if(FTDM_SUCCESS != init_wat_lib())
|
/* libwat is smart enough to set good default values for the timers if they are set to 0 */
|
||||||
{
|
memset(&span_config, 0, sizeof(span_config));
|
||||||
|
|
||||||
|
/* set some span defaults */
|
||||||
|
span_config.moduletype = WAT_MODULE_TELIT;
|
||||||
|
|
||||||
|
if (FTDM_SUCCESS != init_wat_lib()) {
|
||||||
return FTDM_FAIL;
|
return FTDM_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n_spans_info >= MAX_SPANS) {
|
if (!sig_cb) {
|
||||||
snprintf(span->last_error, sizeof(span->last_error), "MAX_SPANS Exceeded !!!\n");
|
ftdm_log(FTDM_LOG_ERROR, "No signaling callback provided\n");
|
||||||
ftdm_log(FTDM_LOG_DEBUG, span->last_error);
|
|
||||||
return FTDM_FAIL;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&spans_info[n_spans_info], 0 ,sizeof(spans_info[n_spans_info]));
|
|
||||||
|
|
||||||
spans_info[n_spans_info].span = span;
|
|
||||||
spans_info[n_spans_info].sig_cb = sig_cb;
|
|
||||||
spans_info[n_spans_info].ftdm_parameters = ftdm_parameters;
|
|
||||||
n_spans_info ++;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ftdm_gsm_data_t *gsm_data = malloc(sizeof(*gsm_data));
|
|
||||||
if (!gsm_data) {
|
|
||||||
|
|
||||||
snprintf(span->last_error, sizeof(span->last_error), "Failed to allocate GSM data.");
|
|
||||||
return FTDM_FAIL;
|
return FTDM_FAIL;
|
||||||
}
|
}
|
||||||
memset(gsm_data,0, sizeof(*gsm_data));
|
|
||||||
|
|
||||||
|
|
||||||
/* */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ftdm_assert_return(sig_cb != NULL, FTDM_FAIL, "No signaling cb provided\n");
|
|
||||||
|
|
||||||
if (span->signal_type) {
|
if (span->signal_type) {
|
||||||
snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling.");
|
ftdm_log(FTDM_LOG_ERROR, "Span %s is already configured for another signaling\n", span->name);
|
||||||
return FTDM_FAIL;
|
return FTDM_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* verify the span has one d-channel */
|
||||||
|
chaniter = ftdm_span_get_chan_iterator(span, NULL);
|
||||||
|
if (!chaniter) {
|
||||||
|
ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
|
||||||
|
return FTDM_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
for (; ftdm_parameters[paramindex].var; paramindex++) {
|
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)) {
|
||||||
|
dchan = ftdmchan;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ftdm_iterator_free(chaniter);
|
||||||
|
|
||||||
|
if (!dchan) {
|
||||||
|
ftdm_log(FTDM_LOG_CRIT, "Could not find a d-channel for GSM span %s!\n", span->name);
|
||||||
|
return FTDM_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gsm_data = ftdm_calloc(1, sizeof(*gsm_data));
|
||||||
|
if (!gsm_data) {
|
||||||
|
return FTDM_FAIL;
|
||||||
|
}
|
||||||
|
gsm_data->dchan = dchan;
|
||||||
|
|
||||||
|
for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) {
|
||||||
var = ftdm_parameters[paramindex].var;
|
var = ftdm_parameters[paramindex].var;
|
||||||
val = ftdm_parameters[paramindex].val;
|
val = ftdm_parameters[paramindex].val;
|
||||||
ftdm_log(FTDM_LOG_DEBUG, "Reading GSM parameter %s for span %d\n", var, span->span_id);
|
if (!ftdm_strlen_zero_buf(val)) {
|
||||||
|
ftdm_log(FTDM_LOG_WARNING, "Ignoring empty GSM parameter %s for span %s\n", var, val, span->name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ftdm_log(FTDM_LOG_DEBUG, "Reading GSM parameter %s=%s for span %s\n", var, val, span->name);
|
||||||
if (!strcasecmp(var, "moduletype")) {
|
if (!strcasecmp(var, "moduletype")) {
|
||||||
if (!val) {
|
span_config.moduletype = wat_str2wat_moduletype(val);
|
||||||
break;
|
if (span_config.moduletype == WAT_MODULE_INVALID) {
|
||||||
}
|
ftdm_log(FTDM_LOG_DEBUG, "Unknown GSM module type %s for span %s\n", val, span->name);
|
||||||
if (ftdm_strlen_zero_buf(val)) {
|
|
||||||
ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty moduletype parameter\n");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ftdm_log(FTDM_LOG_DEBUG, "Configuring GSM span %d for moduletype %s\n", span->span_id, val);
|
ftdm_log(FTDM_LOG_DEBUG, "Configuring GSM span %s with moduletype %s\n", span->name, val);
|
||||||
} else {
|
} else {
|
||||||
snprintf(span->last_error, sizeof(span->last_error), "Unknown GSM parameter [%s]", var);
|
ftdm_log(FTDM_LOG_ERROR, "Ignoring unknown GSM parameter '%s'", var);
|
||||||
return FTDM_FAIL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -629,11 +574,12 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling)
|
|||||||
|
|
||||||
/* use signals queue */
|
/* use signals queue */
|
||||||
ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE);
|
ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE);
|
||||||
|
ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE);
|
||||||
|
|
||||||
/* we can skip states (going straight from RING to UP) */
|
/* we can skip states (going straight from RING to UP) */
|
||||||
ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES);
|
ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES);
|
||||||
|
|
||||||
|
gsm_data->span = span;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* setup the scheduler (create if needed) */
|
/* setup the scheduler (create if needed) */
|
||||||
@ -642,208 +588,105 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling)
|
|||||||
spanpvt->sched = r2data->sched;
|
spanpvt->sched = r2data->sched;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
ftdm_log(FTDM_LOG_DEBUG, "Registering interface to WAT Library...\n");
|
|
||||||
|
|
||||||
gsm_data->wat_interface.wat_sigstatus_change = on_wat_sigstatus_change;
|
|
||||||
gsm_data->wat_interface.wat_span_write = on_wat_span_write;
|
|
||||||
|
|
||||||
gsm_data->wat_interface.wat_log = on_wat_log;
|
if (wat_span_config(span->span_id, &span_config)) {
|
||||||
gsm_data->wat_interface.wat_log_span = on_wat_log_span;
|
ftdm_log(FTDM_LOG_ERROR, "Failed to configure span %s for GSM signaling!!\n", span->name);
|
||||||
gsm_data->wat_interface.wat_malloc = on_wat_malloc;
|
|
||||||
gsm_data->wat_interface.wat_calloc = on_wat_calloc;
|
|
||||||
gsm_data->wat_interface.wat_free = on_wat_free;
|
|
||||||
|
|
||||||
gsm_data->wat_interface.wat_alarm = on_wat_span_alarm;
|
|
||||||
gsm_data->wat_interface.wat_con_ind = on_wat_con_ind;
|
|
||||||
gsm_data->wat_interface.wat_con_sts = on_wat_con_sts;
|
|
||||||
gsm_data->wat_interface.wat_rel_ind = on_wat_rel_ind;
|
|
||||||
gsm_data->wat_interface.wat_rel_cfm = on_wat_rel_cfm;
|
|
||||||
gsm_data->wat_interface.wat_sms_ind = on_wat_sms_ind;
|
|
||||||
gsm_data->wat_interface.wat_sms_sts = on_wat_sms_sts;
|
|
||||||
|
|
||||||
if (wat_register(&gsm_data->wat_interface)) {
|
|
||||||
snprintf(span->last_error, sizeof(span->last_error), "Failed to register WAT Library !!!\n");
|
|
||||||
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");
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ftdm_log(FTDM_LOG_DEBUG, "Configuring span\n");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
wat_span_config_t _wat_span_config;
|
|
||||||
|
|
||||||
|
|
||||||
_wat_span_config.moduletype = WAT_MODULE_TELIT;
|
|
||||||
_wat_span_config.timeout_cid_num = 10;
|
|
||||||
|
|
||||||
if (wat_span_config(span->span_id, &_wat_span_config)) {
|
|
||||||
fprintf(stderr, "Failed to configure span!!\n");
|
|
||||||
return FTDM_FAIL;
|
return FTDM_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
fprintf(stdout, "Starting span %d\n", span->span_id);
|
|
||||||
if (wat_span_start(span->span_id)) {
|
|
||||||
fprintf(stderr, "Failed to start span %d!!\n", span->span_id);
|
|
||||||
return FTDM_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fprintf(stdout, "SUCCESS Starting span %d\n", span->span_id);
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return FTDM_SUCCESS;
|
return FTDM_SUCCESS;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define GSM_POLL_INTERVAL_MS 20
|
||||||
static void *ftdm_gsm_run(ftdm_thread_t *me, void *obj)
|
static void *ftdm_gsm_run(ftdm_thread_t *me, void *obj)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ftdm_channel_t *ftdmchan = NULL;
|
ftdm_channel_t *ftdmchan = NULL;
|
||||||
ftdm_span_t *span = (ftdm_span_t *) obj;
|
ftdm_span_t *span = (ftdm_span_t *) obj;
|
||||||
ftdm_iterator_t *chaniter = NULL;
|
ftdm_gsm_span_data_t *gsm_data = NULL;
|
||||||
ftdm_iterator_t *citer = NULL;
|
ftdm_status_t status = FTDM_SUCCESS;
|
||||||
int waitms = 10, i;
|
ftdm_wait_flag_t ioflags = FTDM_NO_FLAGS;
|
||||||
ftdm_status_t status;
|
ftdm_interrupt_t *data_sources[2] = {NULL, NULL};
|
||||||
|
int waitms = 0;
|
||||||
|
|
||||||
|
gsm_data = span->signal_data;
|
||||||
|
|
||||||
|
ftdm_assert_return(gsm_data != NULL, NULL, "No gsm data attached to span\n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fprintf(stdout, "Starting span %d\n", span->span_id);
|
|
||||||
|
|
||||||
if (wat_span_start(span->span_id)) {
|
|
||||||
|
|
||||||
fprintf(stderr, "Failed to start span %d!!\n", span->span_id);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fprintf(stdout, "SUCCESS Starting span %d\n", span->span_id);
|
|
||||||
|
|
||||||
|
|
||||||
short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count);
|
|
||||||
|
|
||||||
unsigned next;
|
|
||||||
ftdm_log(FTDM_LOG_DEBUG, "GSM monitor thread for span %s started\n", span->name);
|
ftdm_log(FTDM_LOG_DEBUG, "GSM monitor thread for span %s started\n", span->name);
|
||||||
|
if (!gsm_data->dchan || ftdm_channel_open_chan(gsm_data->dchan) != FTDM_SUCCESS) {
|
||||||
chaniter = ftdm_span_get_chan_iterator(span, NULL);
|
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to open GSM d-channel of span %s!\n", span->name);
|
||||||
if (!chaniter) {
|
gsm_data->dchan = NULL;
|
||||||
ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
ftdmchan = get_channel(span->span_id, 2);
|
/* 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) {
|
||||||
if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
|
ftdm_log(FTDM_LOG_CRIT, "Failed to create GSM d-channel interrupt for span %s\n", span->name);
|
||||||
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to open channel during incoming call! [%s]\n", ftdmchan->last_error);
|
goto done;
|
||||||
return NULL;
|
}
|
||||||
|
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()) {
|
while (ftdm_running()) {
|
||||||
|
|
||||||
|
wat_span_run(span->span_id);
|
||||||
|
|
||||||
wat_span_run(span->span_id);
|
waitms = wat_span_schedule_next(span->span_id);
|
||||||
next = wat_span_schedule_next(span->span_id);
|
if (waitms > GSM_POLL_INTERVAL_MS) {
|
||||||
if(next < waitms) {
|
waitms = GSM_POLL_INTERVAL_MS;
|
||||||
next = waitms;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* run any span timers */
|
/* run any span timers */
|
||||||
ftdm_sched_run(r2data->sched);
|
ftdm_sched_run(r2data->sched);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
/* deliver the actual channel events to the user now without any channel locking */
|
status = ftdm_interrupt_multiple_wait(data_sources, ftdm_array_len(data_sources), waitms);
|
||||||
ftdm_span_trigger_signals(span);
|
switch (status) {
|
||||||
#if 0
|
case FTDM_ETIMEDOUT:
|
||||||
/* figure ouwat_chip_info_tt what event to poll each channel for. POLLPRI when the channel is down,
|
break;
|
||||||
* POLLPRI|POLLIN|POLLOUT otherwise */
|
case FTDM_SUCCESS:
|
||||||
memset(poll_events, 0, sizeof(short)*span->chan_count);
|
{
|
||||||
citer = ftdm_span_get_chan_iterator(span, chaniter);
|
/* process first the d-channel if ready */
|
||||||
if (!citer) {
|
if ((ioflags = ftdm_interrupt_device_ready(data_sources[0])) != FTDM_NO_FLAGS) {
|
||||||
ftdm_log(Fshort *poll_events = ftdm_malloc(sizeof(short) * span->chan_count);TDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
|
char buffer[1024];
|
||||||
goto done;short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count);
|
unsigned int n = 0;
|
||||||
}
|
n = read_channel(gsm_data->dchan, buffer, sizeof(buffer));
|
||||||
for (i = 0; citer; citer = ftdm_iterator_next(citer), i++) {
|
/* this may trigger any of the callbacks registered through wat_register() */
|
||||||
ftdmchan = ftdm_iterator_current(citer);
|
wat_span_process_read(span->span_id, buffer, n);
|
||||||
r2chan = R2CALL(ftdmchan)->r2chan;
|
}
|
||||||
poll_events[i] = FTDM_EVENTS;
|
|
||||||
if (openr2_chan_get_read_enabled(r2chan)) {
|
/* now process all channels with state changes pending */
|
||||||
poll_events[i] |= FTDM_READ;
|
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;
|
||||||
status = ftdm_span_poll_event(span, waitms, poll_events);
|
case FTDM_FAIL:
|
||||||
|
ftdm_log(FTDM_LOG_ERROR, "%s: ftdm_interrupt_wait returned error!\n", span->name);
|
||||||
/* run any span timers */
|
break;
|
||||||
ftdm_sched_runshort *poll_events = ftdm_malloc(sizeof(short) * span->chan_count);(r2data->sched);
|
|
||||||
#endif
|
|
||||||
ftdm_sleep(waitms);
|
|
||||||
|
|
||||||
|
|
||||||
/* this main loop takes care of MF and CAS signaling during call setup and tear down
|
|
||||||
* for every single channel in the span, do not perform blocking operations here! */
|
|
||||||
citer = ftdm_span_get_chan_iterator(span, chaniter);
|
|
||||||
for ( ; citer; citer = ftdm_iterator_next(citer)) {
|
|
||||||
ftdmchan = ftdm_iterator_current(citer);
|
|
||||||
|
|
||||||
ftdm_channel_lock(ftdmchan);
|
|
||||||
|
|
||||||
|
|
||||||
ftdm_channel_advance_states(ftdmchan);
|
|
||||||
|
|
||||||
ftdm_channel_unlock(ftdmchan);
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
ftdm_log(FTDM_LOG_ERROR, "%s: ftdm_interrupt_wait returned with unknown code\n", span->name);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i=0;i< span->chan_count; i++)
|
|
||||||
poll_events[i] = FTDM_EVENTS;
|
|
||||||
|
|
||||||
poll_events[1] |= FTDM_READ;
|
|
||||||
status = ftdm_span_poll_event(span, next, poll_events);
|
|
||||||
|
|
||||||
if(FTDM_SUCCESS == status)
|
|
||||||
{
|
|
||||||
ftdm_channel_lock(ftdmchan);
|
|
||||||
ftdm_channel_t * ftdm_chan = get_channel(span->span_id, 2);
|
|
||||||
char buffer[2001];
|
|
||||||
memset(buffer, 0, sizeof(buffer));
|
|
||||||
unsigned int n = 0;
|
|
||||||
n = read_channel(ftdm_chan , buffer, sizeof(buffer));
|
|
||||||
|
|
||||||
ftdm_channel_unlock(ftdmchan);
|
|
||||||
if(n > 0) {
|
|
||||||
|
|
||||||
wat_span_process_read(span->span_id, buffer, n);
|
|
||||||
/*ftdm_log(FTDM_LOG_DEBUG, "<<<<<<<<<<<<<<<<<<<<<<===== %s (%d) - %d\n", buffer, n, (int) span->span_id);*/
|
|
||||||
/*
|
|
||||||
ftdm_log(FTDM_LOG_DEBUG, "!!! read_channel got %d bytes\n", n);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ftdm_sleep(waitms);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
ftdm_iterator_free(chaniter);
|
if (data_sources[0]) {
|
||||||
|
ftdm_interrupt_destroy(&data_sources[0]);
|
||||||
|
}
|
||||||
|
|
||||||
ftdm_log(FTDM_LOG_DEBUG, "GSM thread ending.\n");
|
ftdm_log(FTDM_LOG_DEBUG, "GSM thread ending.\n");
|
||||||
|
|
||||||
@ -856,86 +699,80 @@ done:
|
|||||||
"--------------------------------------------------------------------------------\n"
|
"--------------------------------------------------------------------------------\n"
|
||||||
static FIO_API_FUNCTION(ftdm_gsm_api)
|
static FIO_API_FUNCTION(ftdm_gsm_api)
|
||||||
{
|
{
|
||||||
|
ftdm_span_t *span = NULL;
|
||||||
|
int span_id = 0;
|
||||||
char *mycmd = NULL, *argv[10] = { 0 };
|
char *mycmd = NULL, *argv[10] = { 0 };
|
||||||
int argc = 0;
|
int argc = 0;
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
mycmd = ftdm_strdup(data);
|
mycmd = ftdm_strdup(data);
|
||||||
|
|
||||||
argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
|
argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc == 1) {
|
if (!strcasecmp(argv[0], "version")) {
|
||||||
if (!strcasecmp(argv[0], "version")) {
|
uint8_t current = 0, revision = 0, age = 0;
|
||||||
uint8_t current = 0, revision = 0, age = 0;
|
wat_version(¤t, &revision, &age);
|
||||||
wat_version(¤t, &revision, &age);
|
stream->write_function(stream, "libwat version: %d.%d.%d\n", current, revision, age);
|
||||||
stream->write_function(stream, "libwat GSM VERSION: %d.%d.%d\n", current, revision, age);
|
stream->write_function(stream, "+OK.\n");
|
||||||
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;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcasecmp(argv[0], "status")) {
|
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]);
|
||||||
int n;
|
|
||||||
for(n = 0; n < n_spans_info; n++)
|
|
||||||
{
|
|
||||||
ftdm_span_t *span = spans_info[n].span;
|
|
||||||
wat_chip_info_t* chip_info = (wat_chip_info_t*)wat_span_get_chip_info(span->span_id);
|
|
||||||
wat_sim_info_t* sim_info = (wat_sim_info_t*)wat_span_get_sim_info(span->span_id);
|
|
||||||
wat_net_info_t* net_info = (wat_net_info_t*)wat_span_get_net_info(span->span_id);
|
|
||||||
/*wat_sig_info_t* sig_info = (wat_sig_info_t*)wat_span_get_sig_info(span->span_id);*/
|
|
||||||
/*wat_pin_stat_t* pin_stat = (wat_pin_stat_t*)wat_span_get_pin_info(span->span_id);*/
|
|
||||||
|
|
||||||
stream->write_function(stream, "Span %d:\n", span->span_id);
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
const char *stypes[] = {WAT_NUMBER_TYPE_STRINGS };
|
|
||||||
const char *ptypes[] = {WAT_NUMBER_PLAN_STRINGS };
|
|
||||||
const char *validities[] = {WAT_NUMBER_VALIDITY_STRINGS };
|
|
||||||
|
|
||||||
stream->write_function(stream, "Subscriber - Number %s, Plan %s, validity %s\n",
|
|
||||||
sim_info->subscriber.digits,
|
|
||||||
stypes[sim_info->subscriber.type],
|
|
||||||
ptypes[sim_info->subscriber.plan],
|
|
||||||
validities[sim_info->subscriber.validity]
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
const char *net_stats[] = {WAT_NET_STAT_STRINGS};
|
|
||||||
|
|
||||||
|
|
||||||
stream->write_function(stream, "Network - status %s, Area Code %d, Cell ID %d, Operator %s\n",
|
|
||||||
net_stats[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;
|
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);
|
stream->write_function(stream, "%s", FT_SYNTAX);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
ftdm_safe_free(mycmd);
|
ftdm_safe_free(mycmd);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user