Merge branch 'master' into smgmaster

This commit is contained in:
Moises Silva committed 2011-09-15 09:53:55 -04:00
commit ccdd76b126
47 files changed
+1601 -900

No files matched your search

+46 -11
View File
@@ -2825,9 +2825,9 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "No channel\n");
ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "No IO attached to channel\n");
ftdm_mutex_lock(ftdmchan->mutex);
ftdm_channel_lock(ftdmchan);
switch(command) {
switch (command) {
case FTDM_COMMAND_ENABLE_CALLERID_DETECT:
{
@@ -3278,12 +3278,31 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
GOTO_STATUS(done, FTDM_SUCCESS);
}
break;
case FTDM_COMMAND_GET_IOSTATS:
{
if (!obj) {
GOTO_STATUS(done, FTDM_EINVAL);
}
memcpy(obj, &ftdmchan->iostats, sizeof(ftdmchan->iostats));
GOTO_STATUS(done, FTDM_SUCCESS);
}
break;
case FTDM_COMMAND_SWITCH_IOSTATS:
{
ftdm_bool_t enable = *(ftdm_bool_t *)obj;
if (enable) {
ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS);
} else {
ftdm_channel_clear_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS);
}
GOTO_STATUS(done, FTDM_SUCCESS);
}
break;
default:
break;
}
if (!ftdmchan->fio->command) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "method not implemented");
ftdm_log(FTDM_LOG_ERROR, "no command function defined by the I/O freetdm module!\n");
GOTO_STATUS(done, FTDM_FAIL);
}
@@ -3291,11 +3310,12 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
status = ftdmchan->fio->command(ftdmchan, command, obj);
if (status == FTDM_NOTIMPL) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "I/O command %d not implemented in backend", command);
ftdm_log(FTDM_LOG_ERROR, "I/O backend does not support command %d!\n", command);
}
done:
ftdm_mutex_unlock(ftdmchan->mutex);
ftdm_channel_unlock(ftdmchan);
return status;
}
@@ -4564,14 +4584,20 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const
return FTDM_FAIL;
}
if (chan_config->debugdtmf) {
for (chan_index = currindex+1; chan_index <= span->chan_count; chan_index++) {
if (!FTDM_IS_VOICE_CHANNEL(span->channels[chan_index])) {
continue;
}
span->channels[chan_index]->dtmfdbg.requested = 1;
for (chan_index = currindex + 1; chan_index <= span->chan_count; chan_index++) {
if (chan_config->iostats) {
ftdm_channel_set_feature(span->channels[chan_index], FTDM_CHANNEL_FEATURE_IO_STATS);
}
if (!FTDM_IS_VOICE_CHANNEL(span->channels[chan_index])) {
continue;
}
if (chan_config->debugdtmf) {
span->channels[chan_index]->dtmfdbg.requested = 1;
}
}
return FTDM_SUCCESS;
}
@@ -4638,6 +4664,8 @@ static ftdm_status_t load_config(void)
/* it is confusing that parameters from one span affect others, so let's clear them */
memset(&chan_config, 0, sizeof(chan_config));
sprintf(chan_config.group_name, "__default");
/* default to storing iostats */
chan_config.iostats = FTDM_TRUE;
} else {
ftdm_log(FTDM_LOG_CRIT, "failure creating span of type %s\n", type);
span = NULL;
@@ -4764,6 +4792,13 @@ static ftdm_status_t load_config(void)
} else if (!strcasecmp(var, "debugdtmf")) {
chan_config.debugdtmf = ftdm_true(val);
ftdm_log(FTDM_LOG_DEBUG, "Setting debugdtmf to '%s'\n", chan_config.debugdtmf ? "yes" : "no");
} else if (!strncasecmp(var, "iostats", sizeof("iostats")-1)) {
if (ftdm_true(val)) {
chan_config.iostats = FTDM_TRUE;
} else {
chan_config.iostats = FTDM_FALSE;
}
ftdm_log(FTDM_LOG_DEBUG, "Setting iostats to '%s'\n", chan_config.iostats ? "yes" : "no");
} else if (!strcasecmp(var, "group")) {
len = strlen(val);
if (len >= FTDM_MAX_NAME_STR_SZ) {
+13 -1
View File
@@ -111,7 +111,7 @@ FT_DECLARE(void) ftdm_thread_override_default_stacksize(ftdm_size_t size)
static void * FTDM_THREAD_CALLING_CONVENTION thread_launch(void *args)
{
void *exit_val;
ftdm_thread_t *thread = (ftdm_thread_t *)args;
ftdm_thread_t *thread = (ftdm_thread_t *)args;
exit_val = thread->function(thread, thread->private_data);
#ifndef WIN32
pthread_attr_destroy(&thread->attribute);
@@ -247,6 +247,10 @@ FT_DECLARE(ftdm_status_t) ftdm_mutex_destroy(ftdm_mutex_t **mutex)
FT_DECLARE(ftdm_status_t) _ftdm_mutex_lock(const char *file, int line, const char *func, ftdm_mutex_t *mutex)
{
#ifdef WIN32
UNREFERENCED_PARAMETER(file);
UNREFERENCED_PARAMETER(line);
UNREFERENCED_PARAMETER(func);
EnterCriticalSection(&mutex->mutex);
#else
int err;
@@ -264,6 +268,10 @@ FT_DECLARE(ftdm_status_t) _ftdm_mutex_lock(const char *file, int line, const cha
FT_DECLARE(ftdm_status_t) _ftdm_mutex_trylock(const char *file, int line, const char *func, ftdm_mutex_t *mutex)
{
#ifdef WIN32
UNREFERENCED_PARAMETER(file);
UNREFERENCED_PARAMETER(line);
UNREFERENCED_PARAMETER(func);
if (!TryEnterCriticalSection(&mutex->mutex))
return FTDM_FAIL;
#else
@@ -297,6 +305,10 @@ FT_DECLARE(ftdm_status_t) _ftdm_mutex_unlock(const char *file, int line, const c
mutex->reentrancy--;
#endif
#ifdef WIN32
UNREFERENCED_PARAMETER(file);
UNREFERENCED_PARAMETER(line);
UNREFERENCED_PARAMETER(func);
LeaveCriticalSection(&mutex->mutex);
#else
if (pthread_mutex_unlock(&mutex->mutex)) {
@@ -63,6 +63,10 @@
#define SNGISDN_NUM_LOCAL_NUMBERS 8
#define SNGISDN_DCHAN_QUEUE_LEN 200
#ifndef MI_NOTIFY
#define MI_NOTIFY 0x14
#endif
/* TODO: rename all *_cc_* to *_an_* */
typedef enum {
@@ -380,6 +384,7 @@ void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan);
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
void sngisdn_snd_notify_req(ftdm_channel_t *ftdmchan);
void sngisdn_snd_connect(ftdm_channel_t *ftdmchan);
void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan);
void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare);
@@ -480,7 +485,7 @@ ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr
ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len);
ftdm_status_t set_user_to_user_ie(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr);
ftdm_status_t set_cause_ie(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn);
ftdm_status_t set_not_ind_ie(ftdm_channel_t *ftdmchan, NotInd *notInd);
ftdm_status_t sngisdn_add_var(sngisdn_chan_data_t *sngisdn_info, const char* var, const char* val);
ftdm_status_t sngisdn_add_raw_data(sngisdn_chan_data_t *sngisdn_info, uint8_t* data, ftdm_size_t data_len);
@@ -361,8 +361,9 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
(evntType == MI_CALLPROC)?"PROCEED":
(evntType == MI_PROGRESS)?"PROGRESS":
(evntType == MI_SETUPACK)?"SETUP ACK":
(evntType == MI_INFO)?"INFO":"UNKNOWN",
suId, suInstId, spInstId, ces);
(evntType == MI_NOTIFY)?"NOTIFY":
(evntType == MI_INFO)?"INFO":"UNKNOWN",
suId, suInstId, spInstId, ces);
switch(evntType) {
case MI_CALLPROC:
@@ -493,7 +494,10 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
break;
}
}
break;
case MI_NOTIFY:
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing NOTIFY (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
/* Do nothing */
break;
default:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Unhandled STATUS event\n");
@@ -317,11 +317,7 @@ void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan)
}
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
//ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ\n");
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_con_status(signal_data->cc_id, 0, 0, &cnStEvnt, MI_INFO, signal_data->dchan_id, sngisdn_info->ces)) {
@@ -330,6 +326,32 @@ void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan)
return;
}
void sngisdn_snd_notify_req(ftdm_channel_t *ftdmchan)
{
CnStEvnt cnStEvnt;
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending NOTIFY, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
return;
}
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
set_not_ind_ie(ftdmchan, &cnStEvnt.notInd);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending NOTIFY (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_NOTIFY, signal_data->dchan_id, sngisdn_info->ces)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused NOTIFY request\n");
}
return;
}
void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan)
{
@@ -168,7 +168,8 @@ void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, C
(evntType == MI_CALLPROC)?"PROCEED":
(evntType == MI_PROGRESS)?"PROGRESS":
(evntType == MI_SETUPACK)?"SETUP ACK":
(evntType == MI_INFO)?"INFO":"UNKNOWN",
(evntType == MI_NOTIFY)?"NOTIFY":
(evntType == MI_INFO)?"INFO":"UNKNOWN",
suId, suInstId, spInstId, ces);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
@@ -1021,6 +1021,14 @@ ftdm_status_t set_restart_ind_ie(ftdm_channel_t *ftdmchan, RstInd *rstInd)
return FTDM_SUCCESS;
}
ftdm_status_t set_not_ind_ie(ftdm_channel_t *ftdmchan, NotInd *notInd)
{
notInd->eh.pres = PRSNT_NODEF;
notInd->notDesc.pres = PRSNT_NODEF;
notInd->notDesc.val = 0x71; /* Call information event */
return FTDM_SUCCESS;
}
void sngisdn_t3_timeout(void *p_sngisdn_info)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
@@ -737,8 +737,16 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
calling_subaddr_string, (j-1), get_code_2_str(type, dcodQ931TypeOfSubaddressTable), type);
}
break;
case PROT_Q931_IE_REDIRECTION_NUMBER:
case PROT_Q931_IE_NOTIFICATION_IND:
{
uint8_t desc;
desc = get_bits(OCTET(3),1,7);
*str_len += sprintf(&str[*str_len], "%s (%d)\n",
get_code_2_str(desc, dcodQ931NotificationIndTable), desc);
}
break;
case PROT_Q931_IE_REDIRECTION_NUMBER:
case PROT_Q931_IE_DATE_TIME:
case PROT_Q931_IE_INFORMATION_REQUEST:
case PROT_Q931_IE_SIGNAL:
@@ -591,4 +591,9 @@ struct code2str dcodQ931AssocInfoTable[] = {
{ -1, "Invalid"},
};
struct code2str dcodQ931NotificationIndTable[] = {
{ 0x71, "Call Information/event"},
{ -1, "Invalid"},
};
#endif /* __FTMOD_SANGOMA_ISDN_TRACE_H__ */
@@ -656,10 +656,10 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
/* inform the user there is media avai */
sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_PROGRESS_MEDIA);
} else {
ft_to_sngss7_cpg(ftdmchan);
}
/* nothing to do at this time */
break;
/**************************************************************************/
case FTDM_CHANNEL_STATE_UP: /*call is accpeted...both incoming and outgoing */
@@ -751,6 +751,7 @@ int ftmod_ss7_isup_ckt_sta(uint32_t id, unsigned char *state);
/* in ftmod_sangoma_ss7_out.c */
void ft_to_sngss7_iam(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_acm(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_cpg (ftdm_channel_t *ftdmchan);
void ft_to_sngss7_anm(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_rel(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_rlc(ftdm_channel_t *ftdmchan);
@@ -36,6 +36,8 @@
/******************************************************************************/
/* DEFINES ********************************************************************/
#define SNGSS7_EVNTINFO_IND_INBAND_AVAIL 0x03
/******************************************************************************/
/* GLOBALS ********************************************************************/
@@ -171,6 +173,7 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
acm.optBckCalInd.simpleSegmInd.pres = PRSNT_DEF;
acm.optBckCalInd.mlppUserInd.pres = PRSNT_DEF;
acm.optBckCalInd.usrNetIneractInd.pres = PRSNT_DEF;
acm.optBckCalInd.netExcDelInd.pres = PRSNT_DEF;
} /* if (sngss7_test_options(isup_intf, SNGSS7_ACM_OBCI_BITA)) */
/* send the ACM request to LibSngSS7 */
@@ -187,6 +190,32 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
return;
}
void ft_to_sngss7_cpg (ftdm_channel_t *ftdmchan)
{
SiCnStEvnt cpg;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
memset (&cpg, 0, sizeof (cpg));
cpg.evntInfo.eh.pres = PRSNT_NODEF;
cpg.evntInfo.evntInd.pres = PRSNT_NODEF;
cpg.evntInfo.evntInd.val = SNGSS7_EVNTINFO_IND_INBAND_AVAIL; /* Event Indicator = In-band info is now available */
cpg.evntInfo.evntPresResInd.pres = PRSNT_NODEF;
cpg.evntInfo.evntPresResInd.val = 0; /* Event presentation restricted indicator = no indication */
/* send the CPG request to LibSngSS7 */
sng_cc_con_status (1, sngss7_info->suInstId, sngss7_info->spInstId, sngss7_info->circuit->id, &cpg, PROGRESS);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "[CIC:%d]Tx CPG\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
@@ -144,14 +144,16 @@ ftdm_status_t copy_cgPtyNum_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *cg
ftdm_status_t copy_cgPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *cgPtyNum)
{
const char *val;
const char *val = NULL;
const char *clg_nadi = NULL;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
cgPtyNum->eh.pres = PRSNT_NODEF;
cgPtyNum->natAddrInd.pres = PRSNT_NODEF;
cgPtyNum->natAddrInd.val = 0x03;
cgPtyNum->natAddrInd.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].clg_nadi;
cgPtyNum->scrnInd.pres = PRSNT_NODEF;
@@ -178,6 +180,14 @@ ftdm_status_t copy_cgPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *cgPt
cgPtyNum->niInd.pres = PRSNT_NODEF;
cgPtyNum->niInd.val = 0x00;
/* check if the user would like a custom NADI value for the calling Pty Num */
clg_nadi = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_clg_nadi");
if (!ftdm_strlen_zero(clg_nadi)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Calling NADI value \"%s\"\n", clg_nadi);
cgPtyNum->natAddrInd.val = atoi(clg_nadi);
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Calling Party Number Presentation Ind %d\n", cgPtyNum->presRest.val);
return copy_tknStr_to_sngss7(caller_data->cid_num.digits, &cgPtyNum->addrSig, &cgPtyNum->oddEven);
}
+40
View File
@@ -487,6 +487,7 @@ typedef struct ftdm_channel_config {
float rxgain;
float txgain;
uint8_t debugdtmf;
uint8_t iostats;
} ftdm_channel_config_t;
/*!
@@ -707,7 +708,10 @@ typedef enum {
FTDM_COMMAND_FLUSH_TX_BUFFERS = 45,
FTDM_COMMAND_FLUSH_RX_BUFFERS = 46,
FTDM_COMMAND_FLUSH_BUFFERS = 47,
/*!< Flush IO statistics */
FTDM_COMMAND_FLUSH_IOSTATS = 48,
FTDM_COMMAND_SET_PRE_BUFFER_SIZE = 49,
FTDM_COMMAND_SET_LINK_STATUS = 50,
FTDM_COMMAND_GET_LINK_STATUS = 51,
@@ -719,6 +723,11 @@ typedef enum {
FTDM_COMMAND_START_MF_PLAYBACK = 57,
FTDM_COMMAND_STOP_MF_PLAYBACK = 58,
/*!< Get a copy of the current IO stats */
FTDM_COMMAND_GET_IOSTATS = 59,
/*!< Enable/disable IO stats in the channel */
FTDM_COMMAND_SWITCH_IOSTATS = 60,
FTDM_COMMAND_COUNT,
} ftdm_command_t;
@@ -903,6 +912,37 @@ typedef enum {
FTDM_MF_DIRECTION_BACKWARD = (1 << 9)
} ftdm_mf_direction_flag_t;
/*! \brief IO Error statistics */
typedef enum {
FTDM_IOSTATS_ERROR_CRC = (1 << 0),
FTDM_IOSTATS_ERROR_FRAME = (1 << 1),
FTDM_IOSTATS_ERROR_ABORT = (1 << 2),
FTDM_IOSTATS_ERROR_FIFO = (1 << 3),
FTDM_IOSTATS_ERROR_DMA = (1 << 4),
FTDM_IOSTATS_ERROR_QUEUE_THRES = (1 << 5), /* Queue reached high threshold */
FTDM_IOSTATS_ERROR_QUEUE_FULL = (1 << 6), /* Queue is full */
} ftdm_iostats_error_type_t;
/*! \brief IO statistics */
typedef struct {
struct {
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 {
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;
/*! \brief Override the default queue handler */
FT_DECLARE(ftdm_status_t) ftdm_global_set_queue_handler(ftdm_queue_handler_t *handler);
@@ -359,35 +359,6 @@ typedef struct {
ftdm_mutex_t *mutex;
} ftdm_dtmf_debug_t;
typedef enum {
FTDM_IOSTATS_ERROR_CRC = (1 << 0),
FTDM_IOSTATS_ERROR_FRAME = (1 << 1),
FTDM_IOSTATS_ERROR_ABORT = (1 << 2),
FTDM_IOSTATS_ERROR_FIFO = (1 << 3),
FTDM_IOSTATS_ERROR_DMA = (1 << 4),
FTDM_IOSTATS_ERROR_QUEUE_THRES = (1 << 5), /* Queue reached high threshold */
FTDM_IOSTATS_ERROR_QUEUE_FULL = (1 << 6), /* Queue is full */
} ftdm_iostats_error_type_t;
typedef struct {
struct {
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 {
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;
/* 2^8 table size, one for each byte (sample) value */
#define FTDM_GAINS_TABLE_SIZE 256
struct ftdm_channel {