wanpipe commit we've all been waiting for, HW dtmf, ALARMS, proper bounce of PRIs (testers needed)
git-svn-id: http://svn.openzap.org/svn/openzap/trunk@719 a93c3328-9c30-0410-af19-c9cd2b2d52af
This commit is contained in:
parent
54c7bbecef
commit
bb53daeae2
|
@ -154,10 +154,12 @@ ozmod_skel_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
|
|||
ozmod_skel_la_LDFLAGS = -module -avoid-version
|
||||
ozmod_skel_la_LIBADD = $(MYLIB)
|
||||
|
||||
if LIBSANGOMA
|
||||
ozmod_wanpipe_la_SOURCES = $(SRC)/ozmod/ozmod_wanpipe/ozmod_wanpipe.c
|
||||
ozmod_wanpipe_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
|
||||
ozmod_wanpipe_la_LDFLAGS = -module -avoid-version
|
||||
ozmod_wanpipe_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -D__LINUX__ -I/usr/include/wanpipe
|
||||
ozmod_wanpipe_la_LDFLAGS = -module -avoid-version -lsangoma
|
||||
ozmod_wanpipe_la_LIBADD = $(MYLIB)
|
||||
endif
|
||||
|
||||
ozmod_isdn_la_SOURCES = \
|
||||
$(SRC)/isdn/EuroISDNStateNT.c \
|
||||
|
|
|
@ -155,6 +155,9 @@ AC_ARG_WITH([libpri],
|
|||
[AS_HELP_STRING([--with-libpri], [Install ozmod_libpri])], [enable_libpri="yes"], [enable_libpri="no"])
|
||||
AC_SUBST(enable_libpri)
|
||||
|
||||
AC_CHECK_LIB([sangoma], [sangoma_span_chan_toif], [have_libsangoma="yes"])
|
||||
AM_CONDITIONAL([LIBSANGOMA],[test "${have_libsangoma}" = "yes"])
|
||||
|
||||
AM_CONDITIONAL([LIBPRI],[test "${enable_libpri}" = "yes"])
|
||||
|
||||
COMP_VENDOR_CFLAGS="$COMP_VENDOR_CFLAGS"
|
||||
|
|
|
@ -475,7 +475,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session)
|
|||
break;
|
||||
default:
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled type for channel %s\n", switch_channel_get_name(channel));
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unhandled type for channel %s\n", switch_channel_get_name(channel));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -115,9 +115,14 @@ static int __pri_lpwrap_read(struct pri *pri, void *buf, int buflen)
|
|||
struct lpwrap_pri *spri = (struct lpwrap_pri *) pri_get_userdata(pri);
|
||||
zap_size_t len = buflen;
|
||||
int res;
|
||||
zap_status_t zst;
|
||||
|
||||
if (zap_channel_read(spri->dchan, buf, &len) != ZAP_SUCCESS) {
|
||||
zap_log(ZAP_LOG_CRIT, "span %d D-READ FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error);
|
||||
if ((zst = zap_channel_read(spri->dchan, buf, &len)) != ZAP_SUCCESS) {
|
||||
if (zst == ZAP_FAIL) {
|
||||
zap_log(ZAP_LOG_CRIT, "span %d D-READ FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error);
|
||||
} else {
|
||||
zap_log(ZAP_LOG_CRIT, "span %d D-READ TIMEOUT\n", spri->span->span_id);
|
||||
}
|
||||
zap_clear_flag(spri, LPWRAP_PRI_READY);
|
||||
return -1;
|
||||
}
|
||||
|
@ -145,7 +150,7 @@ static int __pri_lpwrap_write(struct pri *pri, void *buf, int buflen)
|
|||
if (zap_channel_write(spri->dchan, buf, buflen, &len) != ZAP_SUCCESS) {
|
||||
zap_log(ZAP_LOG_CRIT, "span %d D-WRITE FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error);
|
||||
zap_clear_flag(spri, LPWRAP_PRI_READY);
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef IODEBUG
|
||||
|
@ -198,9 +203,9 @@ int lpwrap_one_loop(struct lpwrap_pri *spri)
|
|||
}
|
||||
}
|
||||
|
||||
if (!zap_test_flag(spri, LPWRAP_PRI_READY)) {
|
||||
return -1;
|
||||
}
|
||||
//if (!zap_test_flag(spri, LPWRAP_PRI_READY)) {
|
||||
//return -1;
|
||||
//}
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&efds);
|
||||
|
@ -246,9 +251,9 @@ int lpwrap_one_loop(struct lpwrap_pri *spri)
|
|||
}
|
||||
}
|
||||
|
||||
if (zap_test_flag(spri, LPWRAP_PRI_READY)) {
|
||||
return sel;
|
||||
}
|
||||
|
||||
return sel;
|
||||
|
||||
|
||||
if ((handler = spri->eventmap[LPWRAP_PRI_EVENT_IO_FAIL] ? spri->eventmap[LPWRAP_PRI_EVENT_IO_FAIL] : spri->eventmap[0] ? spri->eventmap[0] : NULL)) {
|
||||
handler(spri, LPWRAP_PRI_EVENT_IO_FAIL, NULL);
|
||||
|
|
|
@ -691,16 +691,103 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static __inline__ zap_status_t process_event(zap_span_t *span, zap_event_t *event)
|
||||
{
|
||||
zap_sigmsg_t sig;
|
||||
zap_libpri_data_t *isdn_data = span->signal_data;
|
||||
|
||||
memset(&sig, 0, sizeof(sig));
|
||||
sig.chan_id = event->channel->chan_id;
|
||||
sig.span_id = event->channel->span_id;
|
||||
sig.channel = event->channel;
|
||||
|
||||
zap_log(ZAP_LOG_DEBUG, "EVENT [%s][%d][%d:%d] STATE [%s]\n",
|
||||
zap_oob_event2str(event->enum_id), event->enum_id, event->channel->span_id, event->channel->chan_id, zap_channel_state2str(event->channel->state));
|
||||
|
||||
switch(event->enum_id) {
|
||||
case ZAP_OOB_ALARM_TRAP:
|
||||
{
|
||||
sig.event_id = ZAP_OOB_ALARM_TRAP;
|
||||
if (event->channel->state != ZAP_CHANNEL_STATE_DOWN) {
|
||||
if (event->channel->type == ZAP_CHAN_TYPE_B) {
|
||||
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_RESTART);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
zap_set_flag(event->channel, ZAP_CHANNEL_SUSPENDED);
|
||||
|
||||
|
||||
zap_channel_get_alarms(event->channel);
|
||||
isdn_data->sig_cb(&sig);
|
||||
zap_log(ZAP_LOG_WARNING, "channel %d:%d (%d:%d) has alarms! [%s]\n",
|
||||
event->channel->span_id, event->channel->chan_id,
|
||||
event->channel->physical_span_id, event->channel->physical_chan_id,
|
||||
event->channel->last_error);
|
||||
}
|
||||
break;
|
||||
case ZAP_OOB_ALARM_CLEAR:
|
||||
{
|
||||
|
||||
zap_log(ZAP_LOG_WARNING, "channel %d:%d (%d:%d) alarms Cleared!\n", event->channel->span_id, event->channel->chan_id,
|
||||
event->channel->physical_span_id, event->channel->physical_chan_id);
|
||||
|
||||
sig.event_id = ZAP_OOB_ALARM_CLEAR;
|
||||
zap_clear_flag(event->channel, ZAP_CHANNEL_SUSPENDED);
|
||||
zap_channel_get_alarms(event->channel);
|
||||
isdn_data->sig_cb(&sig);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ZAP_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static __inline__ void check_events(zap_span_t *span)
|
||||
{
|
||||
zap_status_t status;
|
||||
|
||||
status = zap_span_poll_event(span, 5);
|
||||
|
||||
switch(status) {
|
||||
case ZAP_SUCCESS:
|
||||
{
|
||||
zap_event_t *event;
|
||||
while (zap_span_next_event(span, &event) == ZAP_SUCCESS) {
|
||||
if (event->enum_id == ZAP_OOB_NOOP) {
|
||||
continue;
|
||||
}
|
||||
if (process_event(span, event) != ZAP_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZAP_FAIL:
|
||||
{
|
||||
zap_log(ZAP_LOG_DEBUG, "Event Failure! %d\n", zap_running());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int check_flags(lpwrap_pri_t *spri)
|
||||
{
|
||||
zap_span_t *span = spri->private_info;
|
||||
|
||||
check_state(span);
|
||||
|
||||
if (!zap_running() || zap_test_flag(span, ZAP_SPAN_STOP_THREAD)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
check_state(span);
|
||||
check_events(span);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -769,27 +856,29 @@ static void *zap_libpri_run(zap_thread_t *me, void *obj)
|
|||
{
|
||||
zap_span_t *span = (zap_span_t *) obj;
|
||||
zap_libpri_data_t *isdn_data = span->signal_data;
|
||||
int x, i;
|
||||
int i, x = 0;
|
||||
int down = 0;
|
||||
int got_d = 0;
|
||||
|
||||
zap_set_flag(span, ZAP_SPAN_IN_THREAD);
|
||||
|
||||
while(zap_running() && !zap_test_flag(span, ZAP_SPAN_STOP_THREAD)) {
|
||||
x = 0;
|
||||
|
||||
for(i = 1; i <= span->chan_count; i++) {
|
||||
if (span->channels[i]->type == ZAP_CHAN_TYPE_DQ921) {
|
||||
if (zap_channel_open(span->span_id, i, &isdn_data->dchan) == ZAP_SUCCESS) {
|
||||
zap_log(ZAP_LOG_DEBUG, "opening d-channel #%d %d:%d\n", x, isdn_data->dchan->span_id, isdn_data->dchan->chan_id);
|
||||
isdn_data->dchan->state = ZAP_CHANNEL_STATE_UP;
|
||||
x++;
|
||||
break;
|
||||
if (!got_d) {
|
||||
for(i = 1; i <= span->chan_count; i++) {
|
||||
if (span->channels[i]->type == ZAP_CHAN_TYPE_DQ921) {
|
||||
if (zap_channel_open(span->span_id, i, &isdn_data->dchan) == ZAP_SUCCESS) {
|
||||
zap_log(ZAP_LOG_DEBUG, "opening d-channel #%d %d:%d\n", x, isdn_data->dchan->span_id, isdn_data->dchan->chan_id);
|
||||
isdn_data->dchan->state = ZAP_CHANNEL_STATE_UP;
|
||||
got_d = 1;
|
||||
x++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!x || lpwrap_init_pri(&isdn_data->spri,
|
||||
|
||||
if (lpwrap_init_pri(&isdn_data->spri,
|
||||
span, // span
|
||||
isdn_data->dchan, // dchan
|
||||
isdn_data->pswitch,
|
||||
|
@ -820,9 +909,8 @@ static void *zap_libpri_run(zap_thread_t *me, void *obj)
|
|||
|
||||
isdn_data->spri.on_loop = check_flags;
|
||||
isdn_data->spri.private_info = span;
|
||||
|
||||
lpwrap_run_pri(&isdn_data->spri);
|
||||
zap_channel_close(&isdn_data->dchan);
|
||||
|
||||
}
|
||||
|
||||
if (!zap_running() || zap_test_flag(span, ZAP_SPAN_STOP_THREAD)) {
|
||||
|
@ -830,9 +918,15 @@ static void *zap_libpri_run(zap_thread_t *me, void *obj)
|
|||
}
|
||||
|
||||
zap_log(ZAP_LOG_CRIT, "PRI down on span %d\n", isdn_data->spri.span->span_id);
|
||||
zap_set_state_all(span, ZAP_CHANNEL_STATE_RESTART);
|
||||
check_state(span);
|
||||
|
||||
if (!down) {
|
||||
zap_set_state_all(span, ZAP_CHANNEL_STATE_RESTART);
|
||||
check_state(span);
|
||||
}
|
||||
|
||||
check_state(span);
|
||||
check_events(span);
|
||||
|
||||
down++;
|
||||
zap_sleep(5000);
|
||||
}
|
||||
|
|
|
@ -215,7 +215,11 @@ static ZIO_CHANNEL_REQUEST_FUNCTION(ss7_boost_channel_request)
|
|||
|
||||
ss7bc_call_init(&event, caller_data->cid_num.digits, caller_data->ani.digits, r);
|
||||
zap_set_string(event.calling_name, caller_data->cid_name);
|
||||
zap_set_string(event.redirection_string, caller_data->rdnis.digits);
|
||||
zap_set_string(event.isup_in_rdnis, caller_data->rdnis.digits);
|
||||
if (strlen(caller_data->rdnis.digits)) {
|
||||
event.isup_in_rdnis_size = strlen(caller_data->rdnis.digits)+1;
|
||||
}
|
||||
|
||||
event.calling_number_screening_ind = caller_data->screen;
|
||||
event.calling_number_presentation = caller_data->pres;
|
||||
|
||||
|
@ -483,7 +487,7 @@ static void handle_call_start(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_
|
|||
}
|
||||
zap_set_string(zchan->caller_data.ani.digits, (char *)event->calling_number_digits);
|
||||
zap_set_string(zchan->caller_data.dnis.digits, (char *)event->called_number_digits);
|
||||
zap_set_string(zchan->caller_data.rdnis.digits, (char *)event->redirection_string);
|
||||
zap_set_string(zchan->caller_data.rdnis.digits, (char *)event->isup_in_rdnis);
|
||||
zchan->caller_data.screen = event->calling_number_screening_ind;
|
||||
zchan->caller_data.pres = event->calling_number_presentation;
|
||||
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_RING);
|
||||
|
@ -851,7 +855,7 @@ static void *zap_ss7_boost_run(zap_thread_t *me, void *obj)
|
|||
zap_span_t *span = (zap_span_t *) obj;
|
||||
zap_ss7_boost_data_t *ss7_boost_data = span->signal_data;
|
||||
ss7bc_connection_t *mcon, *pcon;
|
||||
uint32_t ms = 10, too_long = 20000;
|
||||
uint32_t ms = 10; //, too_long = 20000;
|
||||
|
||||
|
||||
ss7_boost_data->pcon = ss7_boost_data->mcon;
|
||||
|
@ -942,6 +946,8 @@ static void *zap_ss7_boost_run(zap_thread_t *me, void *obj)
|
|||
pcon->hb_elapsed = 0;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
if (pcon->hb_elapsed >= too_long) {
|
||||
zap_log(ZAP_LOG_CRIT, "Lost Heartbeat!\n");
|
||||
zap_set_flag_locked(span, ZAP_SPAN_SUSPENDED);
|
||||
|
@ -953,6 +959,7 @@ static void *zap_ss7_boost_run(zap_thread_t *me, void *obj)
|
|||
SIGBOOST_EVENT_SYSTEM_RESTART,
|
||||
0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (zap_running()) {
|
||||
check_state(span);
|
||||
|
@ -1094,7 +1101,7 @@ static ZIO_SIG_CONFIGURE_FUNCTION(zap_ss7_boost_configure_span)
|
|||
{
|
||||
zap_ss7_boost_data_t *ss7_boost_data = NULL;
|
||||
const char *local_ip = "127.0.0.65", *remote_ip = "127.0.0.66";
|
||||
int local_port = 5300, remote_port = 5300;
|
||||
int local_port = 53000, remote_port = 53000;
|
||||
char *var, *val;
|
||||
int *intval;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* sigboost.h $Revision: 1.5 $
|
||||
* sigboost.h $Revision: 1.13 $
|
||||
*
|
||||
* Definitions for the sigboost interface.
|
||||
*
|
||||
|
@ -14,6 +14,8 @@
|
|||
#ifndef _SIGBOOST_H_
|
||||
#define _SIGBOOST_H_
|
||||
|
||||
#define SIGBOOST_VERSION 100
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
|
@ -48,14 +50,22 @@ enum e_sigboost_release_cause_values
|
|||
|
||||
enum e_sigboost_call_setup_ack_nack_cause_values
|
||||
{
|
||||
SIGBOOST_CALL_SETUP_NACK_ALL_CKTS_BUSY = 117, /* unused Q.850 value */
|
||||
SIGBOOST_CALL_SETUP_NACK_TEST_CKT_BUSY = 118, /* unused Q.850 value */
|
||||
SIGBOOST_CALL_SETUP_NACK_INVALID_NUMBER = 28,
|
||||
/* probable elimination */
|
||||
//SIGBOOST_CALL_SETUP_RESERVED = 0x00,
|
||||
//SIGBOOST_CALL_SETUP_CIRCUIT_RESET = 0x10,
|
||||
//SIGBOOST_CALL_SETUP_NACK_CKT_START_TIMEOUT = 0x11,
|
||||
//SIGBOOST_CALL_SETUP_NACK_AUTO_CALL_GAP = 0x17,
|
||||
//SIGBOOST_CALL_SETUP_NACK_ALL_CKTS_BUSY = 34, /* Q.850 value - don't use */
|
||||
SIGBOOST_CALL_SETUP_NACK_ALL_CKTS_BUSY = 117, /* non Q.850 value indicates local all ckt busy
|
||||
causing sangoma_mgd to perform automatic call
|
||||
gapping*/
|
||||
SIGBOOST_CALL_SETUP_NACK_TEST_CKT_BUSY = 17, /* Q.850 value */
|
||||
SIGBOOST_CALL_SETUP_NACK_INVALID_NUMBER = 28, /* Q.850 value */
|
||||
SIGBOOST_CALL_SETUP_CSUPID_DBL_USE = 200, /* unused Q.850 value */
|
||||
};
|
||||
|
||||
|
||||
enum e_sigboost_huntgroup_values
|
||||
{
|
||||
SIGBOOST_HUNTGRP_SEQ_ASC = 0x00, /* sequential with lowest available first */
|
||||
SIGBOOST_HUNTGRP_SEQ_DESC = 0x01, /* sequential with highest available first */
|
||||
SIGBOOST_HUNTGRP_RR_ASC = 0x02, /* round-robin with lowest available first */
|
||||
SIGBOOST_HUNTGRP_RR_DESC = 0x03, /* round-robin with highest available first */
|
||||
};
|
||||
|
||||
#define MAX_DIALED_DIGITS 31
|
||||
|
@ -67,63 +77,73 @@ enum e_sigboost_call_setup_ack_nack_cause_values
|
|||
#define CORE_MAX_CHAN_PER_SPAN 30
|
||||
#define MAX_PENDING_CALLS CORE_MAX_SPANS * CORE_MAX_CHAN_PER_SPAN
|
||||
/* 0..(MAX_PENDING_CALLS-1) is range of call_setup_id below */
|
||||
#define SIZE_RDNIS 128
|
||||
#define SIZE_RDNIS 900
|
||||
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t event_id;
|
||||
uint8_t capability;
|
||||
uint8_t uil1p;
|
||||
}t_sigboost_bearer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t version;
|
||||
uint32_t event_id;
|
||||
/* delete sequence numbers - SCTP does not need them */
|
||||
uint32_t fseqno;
|
||||
uint32_t bseqno;
|
||||
uint16_t call_setup_id;
|
||||
uint32_t trunk_group;
|
||||
uint8_t span;
|
||||
uint8_t chan;
|
||||
struct timeval tv;
|
||||
uint8_t called_number_digits_count;
|
||||
char called_number_digits [MAX_DIALED_DIGITS + 1]; /* it's a null terminated string */
|
||||
uint8_t calling_number_digits_count; /* it's an array */
|
||||
char calling_number_digits [MAX_DIALED_DIGITS + 1]; /* it's a null terminated string */
|
||||
uint32_t fseqno;
|
||||
uint32_t bseqno;
|
||||
uint16_t call_setup_id;
|
||||
uint32_t trunk_group;
|
||||
uint8_t span;
|
||||
uint8_t chan;
|
||||
struct timeval tv;
|
||||
uint8_t called_number_digits_count;
|
||||
char called_number_digits [MAX_DIALED_DIGITS + 1]; /* it's a null terminated string */
|
||||
uint8_t calling_number_digits_count; /* it's an array */
|
||||
char calling_number_digits [MAX_DIALED_DIGITS + 1]; /* it's a null terminated string */
|
||||
/* ref. Q.931 Table 4-11 and Q.951 Section 3 */
|
||||
uint8_t calling_number_screening_ind;
|
||||
uint8_t calling_number_presentation;
|
||||
char calling_name[MAX_DIALED_DIGITS + 1];
|
||||
uint16_t redirection_string_size;
|
||||
char redirection_string [SIZE_RDNIS]; /* it's a null terminated string */
|
||||
/* redir string format:
|
||||
* http://www.ss7box.com/wiki/tiki-index.php?page=Call+Redirection
|
||||
* */
|
||||
uint8_t calling_number_screening_ind;
|
||||
uint8_t calling_number_presentation;
|
||||
char calling_name[MAX_DIALED_DIGITS + 1];
|
||||
t_sigboost_bearer bearer;
|
||||
uint8_t hunt_group;
|
||||
uint16_t isup_in_rdnis_size;
|
||||
char isup_in_rdnis [SIZE_RDNIS]; /* it's a null terminated string */
|
||||
} t_sigboost_callstart;
|
||||
|
||||
#define MIN_SIZE_CALLSTART_MSG (sizeof(t_sigboost_callstart) - SIZE_RDNIS)
|
||||
#define MIN_SIZE_CALLSTART_MSG sizeof(t_sigboost_callstart) - SIZE_RDNIS
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t event_id;
|
||||
uint16_t version;
|
||||
uint32_t event_id;
|
||||
/* delete sequence numbers - SCTP does not need them */
|
||||
uint32_t fseqno;
|
||||
uint32_t bseqno;
|
||||
uint16_t call_setup_id;
|
||||
uint32_t trunk_group;
|
||||
uint8_t span;
|
||||
uint8_t chan;
|
||||
struct timeval tv;
|
||||
uint8_t release_cause;
|
||||
uint32_t fseqno;
|
||||
uint32_t bseqno;
|
||||
uint16_t call_setup_id;
|
||||
uint32_t trunk_group;
|
||||
uint8_t span;
|
||||
uint8_t chan;
|
||||
struct timeval tv;
|
||||
uint8_t release_cause;
|
||||
} t_sigboost_short;
|
||||
#pragma pack()
|
||||
|
||||
static inline int boost_full_event(int event_id)
|
||||
{
|
||||
switch (event_id) {
|
||||
case SIGBOOST_EVENT_CALL_START:
|
||||
case SIGBOOST_EVENT_DIGIT_IN:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
switch (event_id) {
|
||||
case SIGBOOST_EVENT_CALL_START:
|
||||
case SIGBOOST_EVENT_DIGIT_IN:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -73,7 +73,7 @@ static void ss7bc_print_event_call(ss7bc_connection_t *mcon, ss7bc_event_t *even
|
|||
{
|
||||
if (event->event_id == SIGBOOST_EVENT_HEARTBEAT)
|
||||
return;
|
||||
zap_log(file, func, line, ZAP_LOG_LEVEL_DEBUG, "%s EVENT: %s:(%X) [w%dg%d] CSid=%i Seq=%i Cn=[%s] Cd=[%s] Ci=[%s]\n",
|
||||
zap_log(file, func, line, ZAP_LOG_LEVEL_WARNING, "%s EVENT: %s:(%X) [w%dg%d] CSid=%i Seq=%i Cn=[%s] Cd=[%s] Ci=[%s]\n",
|
||||
dir ? "TX":"RX",
|
||||
ss7bc_event_id_name(event->event_id),
|
||||
event->event_id,
|
||||
|
@ -91,7 +91,7 @@ static void ss7bc_print_event_short(ss7bc_connection_t *mcon, ss7bc_short_event_
|
|||
{
|
||||
if (event->event_id == SIGBOOST_EVENT_HEARTBEAT)
|
||||
return;
|
||||
zap_log(file, func, line, ZAP_LOG_LEVEL_DEBUG, "%s EVENT (%s): %s:(%X) [w%dg%d] Rc=%i CSid=%i Seq=%i \n",
|
||||
zap_log(file, func, line, ZAP_LOG_LEVEL_WARNING, "%s EVENT (%s): %s:(%X) [w%dg%d] Rc=%i CSid=%i Seq=%i \n",
|
||||
dir ? "TX":"RX",
|
||||
priority ? "P":"N",
|
||||
ss7bc_event_id_name(event->event_id),
|
||||
|
@ -261,6 +261,10 @@ ss7bc_event_t *__ss7bc_connection_read(ss7bc_connection_t *mcon, int iteration,
|
|||
bytes = recvfrom(mcon->socket, &mcon->event, sizeof(mcon->event), MSG_DONTWAIT,
|
||||
(struct sockaddr *) &mcon->local_addr, &fromlen);
|
||||
|
||||
if (mcon->event.version != SIGBOOST_VERSION) {
|
||||
zap_log(ZAP_LOG_CRIT, "Invalid Boost Version %i Expecting %i\n",mcon->event.version, SIGBOOST_VERSION);
|
||||
}
|
||||
|
||||
/* Must check for < 0 cannot rely on bytes > MIN_SIZE_... compiler issue */
|
||||
if (bytes < 0) {
|
||||
msg_ok=0;
|
||||
|
@ -293,7 +297,7 @@ ss7bc_event_t *__ss7bc_connection_read(ss7bc_connection_t *mcon, int iteration,
|
|||
ss7bc_print_event_short(mcon, (ss7bc_short_event_t*)&mcon->event, 0, 0, file, func, line);
|
||||
}
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
/* NC: NOT USED ANY MORE */
|
||||
if (mcon->rxseq_reset) {
|
||||
//if (mcon->event.event_id == SIGBOOST_EVENT_SYSTEM_RESTART_ACK) {
|
||||
|
@ -310,15 +314,17 @@ ss7bc_event_t *__ss7bc_connection_read(ss7bc_connection_t *mcon, int iteration,
|
|||
mcon->txwindow = mcon->txseq - mcon->event.bseqno;
|
||||
mcon->rxseq++;
|
||||
|
||||
#if 0
|
||||
if (mcon->rxseq != mcon->event.fseqno) {
|
||||
zap_log(ZAP_LOG_CRIT, "Invalid Sequence Number Expect=%i Rx=%i\n", mcon->rxseq, mcon->event.fseqno);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return &mcon->event;
|
||||
} else {
|
||||
if (iteration == 0) {
|
||||
zap_log(ZAP_LOG_CRIT, "Invalid Event length from boost rxlen=%i evsz=%i\n", bytes, sizeof(mcon->event));
|
||||
zap_log(ZAP_LOG_CRIT, "NC - Invalid Event length from boost rxlen=%i evsz=%i\n", bytes, sizeof(mcon->event));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -332,6 +338,10 @@ ss7bc_event_t *__ss7bc_connection_readp(ss7bc_connection_t *mcon, int iteration,
|
|||
int bytes = 0;
|
||||
|
||||
bytes = recvfrom(mcon->socket, &mcon->event, sizeof(mcon->event), MSG_DONTWAIT, (struct sockaddr *) &mcon->local_addr, &fromlen);
|
||||
|
||||
if (mcon->event.version != SIGBOOST_VERSION) {
|
||||
zap_log(ZAP_LOG_CRIT, "Invalid Boost Version %i Expecting %i\n",mcon->event.version, SIGBOOST_VERSION);
|
||||
}
|
||||
|
||||
if (bytes == sizeof(ss7bc_short_event_t)) {
|
||||
|
||||
|
@ -356,7 +366,7 @@ ss7bc_event_t *__ss7bc_connection_readp(ss7bc_connection_t *mcon, int iteration,
|
|||
int __ss7bc_connection_write(ss7bc_connection_t *mcon, ss7bc_event_t *event, const char *file, const char *func, int line)
|
||||
{
|
||||
int err;
|
||||
int event_size=sizeof(ss7bc_event_t);
|
||||
int event_size=MIN_SIZE_CALLSTART_MSG+event->isup_in_rdnis_size;
|
||||
|
||||
if (!event || mcon->socket < 0 || !mcon->mutex) {
|
||||
zap_log(file, func, line, ZAP_LOG_LEVEL_CRIT, "Critical Error: No Event Device\n");
|
||||
|
@ -395,6 +405,7 @@ int __ss7bc_connection_write(ss7bc_connection_t *mcon, ss7bc_event_t *event, con
|
|||
event->fseqno = mcon->txseq++;
|
||||
}
|
||||
event->bseqno = mcon->rxseq;
|
||||
event->version = SIGBOOST_VERSION;
|
||||
err = sendto(mcon->socket, event, event_size, 0, (struct sockaddr *) &mcon->remote_addr, sizeof(mcon->remote_addr));
|
||||
|
||||
zap_mutex_unlock(mcon->mutex);
|
||||
|
@ -432,6 +443,7 @@ int __ss7bc_connection_writep(ss7bc_connection_t *mcon, ss7bc_event_t *event, co
|
|||
gettimeofday(&event->tv, NULL);
|
||||
|
||||
zap_mutex_lock(mcon->mutex);
|
||||
event->version = SIGBOOST_VERSION;
|
||||
err = sendto(mcon->socket, event, event_size, 0, (struct sockaddr *) &mcon->remote_addr, sizeof(mcon->remote_addr));
|
||||
zap_mutex_unlock(mcon->mutex);
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#include "openzap.h"
|
||||
#include <poll.h>
|
||||
#include <sys/socket.h>
|
||||
#include "wanpipe_tdm_api_iface.h"
|
||||
#include "libsangoma.h"
|
||||
|
||||
typedef enum {
|
||||
WP_RINGING = (1 << 0)
|
||||
|
@ -57,196 +57,28 @@ static struct {
|
|||
ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event);
|
||||
ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event);
|
||||
|
||||
#define WP_INVALID_SOCKET -1
|
||||
/* on windows right now, there is no way to specify if we want to read events here or not, we allways get them here */
|
||||
/* we need some what to select if we are reading regular tdm msgs or events */
|
||||
/* need to either have 2 functions, 1 for events, 1 for regural read, or a flag on this function to choose */
|
||||
/* 2 functions preferred. Need implementation for the event function for both nix and windows that is threadsafe */
|
||||
static __inline__ int tdmv_api_readmsg_tdm(sng_fd_t fd, void *hdrbuf, int hdrlen, void *databuf, int datalen)
|
||||
{
|
||||
/* What do we need to do here to avoid having to do all */
|
||||
/* the memcpy's on windows and still maintain api compat with nix */
|
||||
uint32_t rx_len=0;
|
||||
#if defined(__WINDOWS__)
|
||||
static RX_DATA_STRUCT rx_data;
|
||||
api_header_t *pri;
|
||||
wp_tdm_api_rx_hdr_t *tdm_api_rx_hdr;
|
||||
wp_tdm_api_rx_hdr_t *user_buf = (wp_tdm_api_rx_hdr_t*)hdrbuf;
|
||||
DWORD ln;
|
||||
|
||||
if (hdrlen != sizeof(wp_tdm_api_rx_hdr_t)){
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!DeviceIoControl(
|
||||
fd,
|
||||
IoctlReadCommand,
|
||||
(LPVOID)NULL,
|
||||
0L,
|
||||
(LPVOID)&rx_data,
|
||||
sizeof(RX_DATA_STRUCT),
|
||||
(LPDWORD)(&ln),
|
||||
(LPOVERLAPPED)NULL
|
||||
)){
|
||||
return -1;
|
||||
}
|
||||
|
||||
pri = &rx_data.api_header;
|
||||
tdm_api_rx_hdr = (wp_tdm_api_rx_hdr_t*)rx_data.data;
|
||||
|
||||
user_buf->wp_tdm_api_event_type = pri->operation_status;
|
||||
|
||||
switch(pri->operation_status)
|
||||
{
|
||||
case SANG_STATUS_RX_DATA_AVAILABLE:
|
||||
if (pri->data_length > datalen){
|
||||
break;
|
||||
}
|
||||
memcpy(databuf, rx_data.data, pri->data_length);
|
||||
rx_len = pri->data_length;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#else
|
||||
struct msghdr msg;
|
||||
struct iovec iov[2];
|
||||
|
||||
memset(&msg,0,sizeof(struct msghdr));
|
||||
|
||||
iov[0].iov_len=hdrlen;
|
||||
iov[0].iov_base=hdrbuf;
|
||||
|
||||
iov[1].iov_len=datalen;
|
||||
iov[1].iov_base=databuf;
|
||||
|
||||
msg.msg_iovlen=2;
|
||||
msg.msg_iov=iov;
|
||||
|
||||
rx_len = read(fd,&msg,datalen+hdrlen);
|
||||
|
||||
if (rx_len <= sizeof(wp_tdm_api_rx_hdr_t)){
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rx_len-=sizeof(wp_tdm_api_rx_hdr_t);
|
||||
#endif
|
||||
return rx_len;
|
||||
}
|
||||
|
||||
static __inline__ int tdmv_api_writemsg_tdm(sng_fd_t fd, void *hdrbuf, int hdrlen, void *databuf, unsigned short datalen)
|
||||
{
|
||||
/* What do we need to do here to avoid having to do all */
|
||||
/* the memcpy's on windows and still maintain api compat with nix */
|
||||
int bsent = 0;
|
||||
#if defined(__WINDOWS__)
|
||||
static TX_DATA_STRUCT local_tx_data;
|
||||
api_header_t *pri;
|
||||
DWORD ln;
|
||||
|
||||
/* Are these really not needed or used??? What about for nix?? */
|
||||
(void)hdrbuf;
|
||||
(void)hdrlen;
|
||||
|
||||
pri = &local_tx_data.api_header;
|
||||
|
||||
pri->data_length = datalen;
|
||||
memcpy(local_tx_data.data, databuf, pri->data_length);
|
||||
|
||||
if (!DeviceIoControl(
|
||||
fd,
|
||||
IoctlWriteCommand,
|
||||
(LPVOID)&local_tx_data,
|
||||
(ULONG)sizeof(TX_DATA_STRUCT),
|
||||
(LPVOID)&local_tx_data,
|
||||
sizeof(TX_DATA_STRUCT),
|
||||
(LPDWORD)(&ln),
|
||||
(LPOVERLAPPED)NULL
|
||||
)){
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (local_tx_data.api_header.operation_status == SANG_STATUS_SUCCESS) {
|
||||
bsent = datalen;
|
||||
}
|
||||
#else
|
||||
struct msghdr msg;
|
||||
struct iovec iov[2];
|
||||
|
||||
memset(&msg,0,sizeof(struct msghdr));
|
||||
|
||||
iov[0].iov_len = hdrlen;
|
||||
iov[0].iov_base = hdrbuf;
|
||||
|
||||
iov[1].iov_len = datalen;
|
||||
iov[1].iov_base = databuf;
|
||||
|
||||
msg.msg_iovlen = 2;
|
||||
msg.msg_iov = iov;
|
||||
|
||||
bsent = write(fd, &msg, datalen + hdrlen);
|
||||
if (bsent > 0){
|
||||
bsent -= sizeof(wp_tdm_api_tx_hdr_t);
|
||||
}
|
||||
#endif
|
||||
return bsent;
|
||||
}
|
||||
#define WP_INVALID_SOCKET -1
|
||||
|
||||
/* a cross platform way to poll on an actual pollset (span and/or list of spans) will probably also be needed for analog */
|
||||
/* so we can have one analong handler thread that will deal with all the idle analog channels for events */
|
||||
/* the alternative would be for the driver to provide one socket for all of the oob events for all analog channels */
|
||||
static __inline__ int tdmv_api_wait_socket(sng_fd_t fd, int timeout, int *flags)
|
||||
{
|
||||
#if defined(__WINDOWS__)
|
||||
DWORD ln;
|
||||
API_POLL_STRUCT api_poll;
|
||||
|
||||
memset(&api_poll, 0x00, sizeof(API_POLL_STRUCT));
|
||||
|
||||
api_poll.user_flags_bitmap = *flags;
|
||||
api_poll.timeout = timeout;
|
||||
#ifdef LIBSANGOMA_VERSION
|
||||
int err;
|
||||
sangoma_wait_obj_t sangoma_wait_obj;
|
||||
|
||||
if (!DeviceIoControl(
|
||||
fd,
|
||||
IoctlApiPoll,
|
||||
(LPVOID)NULL,
|
||||
0L,
|
||||
(LPVOID)&api_poll,
|
||||
sizeof(API_POLL_STRUCT),
|
||||
(LPDWORD)(&ln),
|
||||
(LPOVERLAPPED)NULL)) {
|
||||
return -1;
|
||||
sangoma_init_wait_obj(&sangoma_wait_obj, fd, 1, 1, *flags, SANGOMA_WAIT_OBJ);
|
||||
|
||||
err=sangoma_socket_waitfor_many(&sangoma_wait_obj,1 , timeout);
|
||||
if (err > 0) {
|
||||
*flags=sangoma_wait_obj.flags_out;
|
||||
}
|
||||
return err;
|
||||
|
||||
*flags = 0;
|
||||
|
||||
switch(api_poll.operation_status)
|
||||
{
|
||||
case SANG_STATUS_RX_DATA_AVAILABLE:
|
||||
break;
|
||||
|
||||
case SANG_STATUS_RX_DATA_TIMEOUT:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (api_poll.poll_events_bitmap == 0){
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (api_poll.poll_events_bitmap & POLL_EVENT_TIMEOUT) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*flags = api_poll.poll_events_bitmap;
|
||||
|
||||
return 1;
|
||||
#else
|
||||
struct pollfd pfds[1];
|
||||
struct pollfd pfds[1];
|
||||
int res;
|
||||
|
||||
memset(&pfds[0], 0, sizeof(pfds[0]));
|
||||
|
@ -265,87 +97,18 @@ static __inline__ int tdmv_api_wait_socket(sng_fd_t fd, int timeout, int *flags)
|
|||
|
||||
return res;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#define FNAME_LEN 128
|
||||
static __inline__ sng_fd_t tdmv_api_open_span_chan(int span, int chan)
|
||||
{
|
||||
char fname[FNAME_LEN];
|
||||
sng_fd_t fd = WP_INVALID_SOCKET;
|
||||
#if defined(__WINDOWS__)
|
||||
DWORD ln;
|
||||
wan_udp_hdr_t wan_udp;
|
||||
|
||||
/* NOTE: under Windows Interfaces are zero based but 'chan' is 1 based. */
|
||||
/* Subtract 1 from 'chan'. */
|
||||
_snprintf(fname , FNAME_LEN, "\\\\.\\WANPIPE%d_IF%d", span, chan - 1);
|
||||
|
||||
fd = CreateFile( fname,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
(LPSECURITY_ATTRIBUTES)NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
|
||||
(HANDLE)NULL
|
||||
);
|
||||
|
||||
/* make sure that we are the only ones who have this chan open */
|
||||
/* is this a threadsafe way to make sure that we are ok and will */
|
||||
/* never return a valid handle to more than one thread for the same channel? */
|
||||
|
||||
wan_udp.wan_udphdr_command = GET_OPEN_HANDLES_COUNTER;
|
||||
wan_udp.wan_udphdr_data_len = 0;
|
||||
|
||||
DeviceIoControl(
|
||||
fd,
|
||||
IoctlManagementCommand,
|
||||
(LPVOID)&wan_udp,
|
||||
sizeof(wan_udp_hdr_t),
|
||||
(LPVOID)&wan_udp,
|
||||
sizeof(wan_udp_hdr_t),
|
||||
(LPDWORD)(&ln),
|
||||
(LPOVERLAPPED)NULL
|
||||
);
|
||||
|
||||
if ((wan_udp.wan_udphdr_return_code) || (*(int*)&wan_udp.wan_udphdr_data[0] != 1)){
|
||||
/* somone already has this channel, or somthing else is not right. */
|
||||
tdmv_api_close_socket(&fd);
|
||||
}
|
||||
|
||||
#else
|
||||
/* Does this fail if another thread already has this chan open? */
|
||||
/* if not, we need to add some code to make sure it does */
|
||||
snprintf(fname, FNAME_LEN, "/dev/wptdm_s%dc%d",span,chan);
|
||||
|
||||
fd = open(fname, O_RDWR);
|
||||
|
||||
if (fd < 0) {
|
||||
fd = WP_INVALID_SOCKET;
|
||||
}
|
||||
|
||||
#endif
|
||||
return fd;
|
||||
return sangoma_open_tdmapi_span_chan(span, chan);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static zap_io_interface_t wanpipe_interface;
|
||||
|
||||
static zap_status_t wp_tdm_cmd_exec(zap_channel_t *zchan, wanpipe_tdm_api_t *tdm_api)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* I'm told the 2nd arg is ignored but i send it as the cmd anyway for good measure */
|
||||
err = ioctl(zchan->sockfd, tdm_api->wp_tdm_cmd.cmd, &tdm_api->wp_tdm_cmd);
|
||||
|
||||
if (err) {
|
||||
snprintf(zchan->last_error, sizeof(zchan->last_error), "%s", strerror(errno));
|
||||
return ZAP_FAIL;
|
||||
}
|
||||
|
||||
return ZAP_SUCCESS;
|
||||
}
|
||||
|
||||
static unsigned char wanpipe_swap_bits(unsigned char cas_bits)
|
||||
{
|
||||
unsigned char swapped_bits = 0x0;
|
||||
|
@ -374,59 +137,60 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
|
|||
for(x = start; x < end; x++) {
|
||||
zap_channel_t *chan;
|
||||
zap_socket_t sockfd = WP_INVALID_SOCKET;
|
||||
|
||||
const char *dtmf = "none";
|
||||
|
||||
sockfd = tdmv_api_open_span_chan(spanno, x);
|
||||
|
||||
if (sockfd != WP_INVALID_SOCKET && zap_span_add_channel(span, sockfd, type, &chan) == ZAP_SUCCESS) {
|
||||
wanpipe_tdm_api_t tdm_api;
|
||||
zap_log(ZAP_LOG_INFO, "configuring device s%dc%d as OpenZAP device %d:%d fd:%d\n", spanno, x, chan->span_id, chan->chan_id, sockfd);
|
||||
memset(&tdm_api,0,sizeof(tdm_api));
|
||||
|
||||
chan->physical_span_id = spanno;
|
||||
chan->physical_chan_id = x;
|
||||
chan->rate = 8000;
|
||||
|
||||
if (type == ZAP_CHAN_TYPE_FXS || type == ZAP_CHAN_TYPE_FXO) {
|
||||
|
||||
|
||||
#if 1
|
||||
if (type == ZAP_CHAN_TYPE_FXO) {
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_ONHOOK;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
|
||||
wp_tdm_cmd_exec(chan, &tdm_api);
|
||||
}
|
||||
#endif
|
||||
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_RING_DETECT;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
|
||||
wp_tdm_cmd_exec(chan, &tdm_api);
|
||||
#if 1
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_RING_TRIP_DETECT;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
|
||||
wp_tdm_cmd_exec(chan, &tdm_api);
|
||||
#endif
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_RXHOOK;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
|
||||
wp_tdm_cmd_exec(chan, &tdm_api);
|
||||
|
||||
}
|
||||
|
||||
if (type == ZAP_CHAN_TYPE_FXS || type == ZAP_CHAN_TYPE_FXO || type == ZAP_CHAN_TYPE_B) {
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_GET_HW_CODING;
|
||||
wp_tdm_cmd_exec(chan, &tdm_api);
|
||||
int err;
|
||||
|
||||
dtmf = "software";
|
||||
|
||||
/* FIXME: Handle Error Conditino Check for return code */
|
||||
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 = ZAP_CODEC_ALAW;
|
||||
} else {
|
||||
chan->native_codec = chan->effective_codec = ZAP_CODEC_ULAW;
|
||||
}
|
||||
|
||||
err = sangoma_tdm_get_hw_dtmf(chan->sockfd, &tdm_api);
|
||||
if (err > 0) {
|
||||
err = sangoma_tdm_enable_dtmf_events(chan->sockfd, &tdm_api);
|
||||
if (err == 0) {
|
||||
zap_channel_set_feature(chan, ZAP_CHANNEL_FEATURE_DTMF_DETECT);
|
||||
dtmf = "hardware";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (type == ZAP_CHAN_TYPE_FXS || type == ZAP_CHAN_TYPE_FXO) {
|
||||
/* Enable FLASH/Wink Events */
|
||||
int err=sangoma_set_rm_rxflashtime(chan->sockfd, &tdm_api, wp_globals.flash_ms);
|
||||
if (err == 0) {
|
||||
zap_log(ZAP_LOG_ERROR, "flash enabled s%dc%d\n", spanno, x);
|
||||
} else {
|
||||
zap_log(ZAP_LOG_ERROR, "flash disabled s%dc%d\n", spanno, x);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (type == ZAP_CHAN_TYPE_CAS) {
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_WRITE_RBS_BITS;
|
||||
tdm_api.wp_tdm_cmd.rbs_tx_bits = wanpipe_swap_bits(cas_bits);
|
||||
wp_tdm_cmd_exec(chan, &tdm_api);
|
||||
#ifdef LIBSANGOMA_VERSION
|
||||
sangoma_tdm_write_rbs(chan->sockfd,&tdm_api,chan->physical_chan_id,wanpipe_swap_bits(cas_bits));
|
||||
#else
|
||||
sangoma_tdm_write_rbs(chan->sockfd,&tdm_api,wanpipe_swap_bits(cas_bits));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!zap_strlen_zero(name)) {
|
||||
|
@ -439,6 +203,9 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
|
|||
} else {
|
||||
zap_log(ZAP_LOG_ERROR, "failure configuring device s%dc%d\n", spanno, x);
|
||||
}
|
||||
|
||||
zap_log(ZAP_LOG_INFO, "configuring device s%dc%d as OpenZAP device %d:%d fd:%d DTMF: %s\n",
|
||||
spanno, x, chan->span_id, chan->chan_id, sockfd, dtmf);
|
||||
}
|
||||
|
||||
return configured;
|
||||
|
@ -552,16 +319,15 @@ static ZIO_OPEN_FUNCTION(wanpipe_open)
|
|||
|
||||
wanpipe_tdm_api_t tdm_api;
|
||||
|
||||
memset(&tdm_api,0,sizeof(tdm_api));
|
||||
|
||||
if (zchan->type == ZAP_CHAN_TYPE_DQ921 || zchan->type == ZAP_CHAN_TYPE_DQ931) {
|
||||
zchan->native_codec = zchan->effective_codec = ZAP_CODEC_NONE;
|
||||
} else {
|
||||
zchan->effective_codec = zchan->native_codec;
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_CODEC;
|
||||
tdm_api.wp_tdm_cmd.tdm_codec = 0;
|
||||
wp_tdm_cmd_exec(zchan, &tdm_api);
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_USR_PERIOD;
|
||||
tdm_api.wp_tdm_cmd.usr_period = wp_globals.codec_ms;
|
||||
wp_tdm_cmd_exec(zchan, &tdm_api);
|
||||
|
||||
sangoma_tdm_set_usr_period(zchan->sockfd, &tdm_api, wp_globals.codec_ms);
|
||||
|
||||
zap_channel_set_feature(zchan, ZAP_CHANNEL_FEATURE_INTERVAL);
|
||||
zchan->effective_interval = zchan->native_interval = wp_globals.codec_ms;
|
||||
zchan->packet_len = zchan->native_interval * 8;
|
||||
|
@ -585,10 +351,8 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
|
|||
switch(command) {
|
||||
case ZAP_COMMAND_OFFHOOK:
|
||||
{
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_OFFHOOK;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
|
||||
if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) {
|
||||
err=sangoma_tdm_txsig_offhook(zchan->sockfd,&tdm_api);
|
||||
if (err) {
|
||||
snprintf(zchan->last_error, sizeof(zchan->last_error), "OFFHOOK Failed");
|
||||
return ZAP_FAIL;
|
||||
}
|
||||
|
@ -597,10 +361,8 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
|
|||
break;
|
||||
case ZAP_COMMAND_ONHOOK:
|
||||
{
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_ONHOOK;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
|
||||
if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) {
|
||||
err=sangoma_tdm_txsig_onhook(zchan->sockfd,&tdm_api);
|
||||
if (err) {
|
||||
snprintf(zchan->last_error, sizeof(zchan->last_error), "ONHOOK Failed");
|
||||
return ZAP_FAIL;
|
||||
}
|
||||
|
@ -609,9 +371,8 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
|
|||
break;
|
||||
case ZAP_COMMAND_GENERATE_RING_ON:
|
||||
{
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_START;
|
||||
if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) {
|
||||
err=sangoma_tdm_txsig_start(zchan->sockfd,&tdm_api);
|
||||
if (err) {
|
||||
snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring Failed");
|
||||
return ZAP_FAIL;
|
||||
}
|
||||
|
@ -622,9 +383,8 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
|
|||
break;
|
||||
case ZAP_COMMAND_GENERATE_RING_OFF:
|
||||
{
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_OFFHOOK;
|
||||
if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) {
|
||||
err=sangoma_tdm_txsig_offhook(zchan->sockfd,&tdm_api);
|
||||
if (err) {
|
||||
snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring-off Failed");
|
||||
return ZAP_FAIL;
|
||||
}
|
||||
|
@ -634,27 +394,26 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
|
|||
break;
|
||||
case ZAP_COMMAND_GET_INTERVAL:
|
||||
{
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_GET_USR_PERIOD;
|
||||
|
||||
if (!(err = wp_tdm_cmd_exec(zchan, &tdm_api))) {
|
||||
ZAP_COMMAND_OBJ_INT = tdm_api.wp_tdm_cmd.usr_period;
|
||||
err=sangoma_tdm_get_usr_period(zchan->sockfd, &tdm_api);
|
||||
if (err > 0 ) {
|
||||
ZAP_COMMAND_OBJ_INT = err;
|
||||
err=0;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case ZAP_COMMAND_SET_INTERVAL:
|
||||
{
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_USR_PERIOD;
|
||||
tdm_api.wp_tdm_cmd.usr_period = ZAP_COMMAND_OBJ_INT;
|
||||
err = wp_tdm_cmd_exec(zchan, &tdm_api);
|
||||
err=sangoma_tdm_set_usr_period(zchan->sockfd, &tdm_api, ZAP_COMMAND_OBJ_INT);
|
||||
zchan->packet_len = zchan->native_interval * (zchan->effective_codec == ZAP_CODEC_SLIN ? 16 : 8);
|
||||
}
|
||||
break;
|
||||
case ZAP_COMMAND_SET_CAS_BITS:
|
||||
{
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_WRITE_RBS_BITS;
|
||||
tdm_api.wp_tdm_cmd.rbs_tx_bits = wanpipe_swap_bits(ZAP_COMMAND_OBJ_INT);
|
||||
err = wp_tdm_cmd_exec(zchan, &tdm_api);
|
||||
#ifdef LIBSANGOMA_VERSION
|
||||
err=sangoma_tdm_write_rbs(zchan->sockfd,&tdm_api,zchan->physical_chan_id,wanpipe_swap_bits(ZAP_COMMAND_OBJ_INT));
|
||||
#else
|
||||
err=sangoma_tdm_write_rbs(zchan->sockfd,&tdm_api,wanpipe_swap_bits(ZAP_COMMAND_OBJ_INT));
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case ZAP_COMMAND_GET_CAS_BITS:
|
||||
|
@ -683,14 +442,18 @@ static ZIO_READ_FUNCTION(wanpipe_read)
|
|||
|
||||
memset(&hdrframe, 0, sizeof(hdrframe));
|
||||
|
||||
rx_len = tdmv_api_readmsg_tdm(zchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (int)*datalen);
|
||||
|
||||
rx_len = sangoma_readmsg_tdm(zchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (int)*datalen,0);
|
||||
*datalen = rx_len;
|
||||
|
||||
if (rx_len <= 0) {
|
||||
if (rx_len == 0 || rx_len == -17) {
|
||||
return ZAP_TIMEOUT;
|
||||
}
|
||||
|
||||
if (rx_len < 0) {
|
||||
snprintf(zchan->last_error, sizeof(zchan->last_error), "%s", strerror(errno));
|
||||
return ZAP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ZAP_SUCCESS;
|
||||
}
|
||||
|
@ -702,7 +465,7 @@ static ZIO_WRITE_FUNCTION(wanpipe_write)
|
|||
|
||||
/* Do we even need the headerframe here? on windows, we don't even pass it to the driver */
|
||||
memset(&hdrframe, 0, sizeof(hdrframe));
|
||||
bsent = tdmv_api_writemsg_tdm(zchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (unsigned short)(*datalen));
|
||||
bsent = sangoma_writemsg_tdm(zchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (unsigned short)(*datalen),0);
|
||||
|
||||
/* should we be checking if bsent == *datalen here? */
|
||||
if (bsent > 0) {
|
||||
|
@ -759,19 +522,29 @@ static ZIO_WAIT_FUNCTION(wanpipe_wait)
|
|||
return ZAP_SUCCESS;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
|
||||
{
|
||||
#ifdef LIBSANGOMA_VERSION
|
||||
sangoma_wait_obj_t pfds[ZAP_MAX_CHANNELS_SPAN];
|
||||
#else
|
||||
struct pollfd pfds[ZAP_MAX_CHANNELS_SPAN];
|
||||
#endif
|
||||
|
||||
uint32_t i, j = 0, k = 0, l = 0;
|
||||
int objects=0;
|
||||
int r;
|
||||
|
||||
for(i = 1; i <= span->chan_count; i++) {
|
||||
zap_channel_t *zchan = span->channels[i];
|
||||
|
||||
#ifdef LIBSANGOMA_VERSION
|
||||
sangoma_init_wait_obj(&pfds[j], zchan->sockfd , 1, 1, POLLPRI, SANGOMA_WAIT_OBJ);
|
||||
#else
|
||||
memset(&pfds[j], 0, sizeof(pfds[j]));
|
||||
pfds[j].fd = span->channels[i]->sockfd;
|
||||
pfds[j].events = POLLPRI;
|
||||
|
||||
#endif
|
||||
objects++;
|
||||
/* The driver probably should be able to do this wink/flash/ringing by itself this is sort of a hack to make it work! */
|
||||
|
||||
if (zap_test_flag(zchan, ZAP_CHANNEL_WINK) || zap_test_flag(zchan, ZAP_CHANNEL_FLASH)) {
|
||||
|
@ -789,20 +562,16 @@ ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
|
|||
int err;
|
||||
memset(&tdm_api, 0, sizeof(tdm_api));
|
||||
if (zap_test_pflag(zchan, WP_RINGING)) {
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_OFFHOOK;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_DISABLE;
|
||||
if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) {
|
||||
err=sangoma_tdm_txsig_offhook(zchan->sockfd,&tdm_api);
|
||||
if (err) {
|
||||
snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring-off Failed");
|
||||
return ZAP_FAIL;
|
||||
}
|
||||
zap_clear_pflag_locked(zchan, WP_RINGING);
|
||||
zchan->ring_time = zap_current_time_in_ms() + wp_globals.ring_off_ms;
|
||||
} else {
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_START;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
|
||||
if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) {
|
||||
err=sangoma_tdm_txsig_start(zchan->sockfd,&tdm_api);
|
||||
if (err) {
|
||||
snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring Failed");
|
||||
return ZAP_FAIL;
|
||||
}
|
||||
|
@ -815,8 +584,11 @@ ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
|
|||
if (l) {
|
||||
ms = l;
|
||||
}
|
||||
|
||||
r = poll(pfds, j, ms);
|
||||
#ifdef LIBSANGOMA_VERSION
|
||||
r = sangoma_socket_waitfor_many(pfds,objects,ms);
|
||||
#else
|
||||
r = poll(pfds, j, ms);
|
||||
#endif
|
||||
|
||||
if (r == 0) {
|
||||
return l ? ZAP_SUCCESS : ZAP_TIMEOUT;
|
||||
|
@ -828,7 +600,11 @@ ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
|
|||
for(i = 1; i <= span->chan_count; i++) {
|
||||
zap_channel_t *zchan = span->channels[i];
|
||||
|
||||
#ifdef LIBSANGOMA_VERSION
|
||||
if (pfds[i-1].flags_out & POLLPRI) {
|
||||
#else
|
||||
if (pfds[i-1].revents & POLLPRI) {
|
||||
#endif
|
||||
zap_set_flag(zchan, ZAP_CHANNEL_EVENT);
|
||||
zchan->last_event_time = zap_current_time_in_ms();
|
||||
k++;
|
||||
|
@ -836,15 +612,43 @@ ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
|
|||
}
|
||||
|
||||
|
||||
|
||||
return k ? ZAP_SUCCESS : ZAP_FAIL;
|
||||
}
|
||||
|
||||
|
||||
static ZIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms)
|
||||
{
|
||||
wanpipe_tdm_api_t tdm_api;
|
||||
unsigned int alarms = 0;
|
||||
int err;
|
||||
|
||||
memset(&tdm_api,0,sizeof(tdm_api));
|
||||
|
||||
#ifdef LIBSANGOMA_VERSION
|
||||
if ((err = sangoma_tdm_get_fe_alarms(zchan->sockfd, &tdm_api, &alarms))) {
|
||||
snprintf(zchan->last_error, sizeof(zchan->last_error), "ioctl failed (%s)", strerror(errno));
|
||||
snprintf(zchan->span->last_error, sizeof(zchan->span->last_error), "ioctl failed (%s)", strerror(errno));
|
||||
return ZAP_FAIL;
|
||||
}
|
||||
#else
|
||||
if ((err = sangoma_tdm_get_fe_alarms(zchan->sockfd, &tdm_api)) < 0){
|
||||
snprintf(zchan->last_error, sizeof(zchan->last_error), "ioctl failed (%s)", strerror(errno));
|
||||
snprintf(zchan->span->last_error, sizeof(zchan->span->last_error), "ioctl failed (%s)", strerror(errno));
|
||||
return ZAP_FAIL;
|
||||
}
|
||||
alarms = tdm_api.wp_tdm_cmd.fe_alarms;
|
||||
#endif
|
||||
|
||||
|
||||
zchan->alarm_flags = alarms ? ZAP_ALARM_RED : ZAP_ALARM_NONE;
|
||||
|
||||
return ZAP_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t i,err;
|
||||
zap_oob_event_t event_id;
|
||||
|
||||
for(i = 1; i <= span->chan_count; i++) {
|
||||
|
@ -869,29 +673,43 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
|
|||
event_id = ZAP_OOB_ONHOOK;
|
||||
|
||||
if (span->channels[i]->type == ZAP_CHAN_TYPE_FXO) {
|
||||
zap_channel_t *zchan = span->channels[i];
|
||||
wanpipe_tdm_api_t tdm_api;
|
||||
memset(&tdm_api, 0, sizeof(tdm_api));
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_ONHOOK;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
|
||||
wp_tdm_cmd_exec(span->channels[i], &tdm_api);
|
||||
|
||||
sangoma_tdm_txsig_onhook(zchan->sockfd,&tdm_api);
|
||||
}
|
||||
goto event;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (zap_test_flag(span->channels[i], ZAP_CHANNEL_EVENT)) {
|
||||
wanpipe_tdm_api_t tdm_api;
|
||||
zap_channel_t *zchan = span->channels[i];
|
||||
memset(&tdm_api, 0, sizeof(tdm_api));
|
||||
zap_clear_flag(span->channels[i], ZAP_CHANNEL_EVENT);
|
||||
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_READ_EVENT;
|
||||
if (wp_tdm_cmd_exec(span->channels[i], &tdm_api) != ZAP_SUCCESS) {
|
||||
err=sangoma_tdm_read_event(zchan->sockfd,&tdm_api);
|
||||
if (err != ZAP_SUCCESS) {
|
||||
snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno));
|
||||
return ZAP_FAIL;
|
||||
}
|
||||
|
||||
switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type) {
|
||||
|
||||
case WP_TDMAPI_EVENT_LINK_STATUS:
|
||||
{
|
||||
switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_link_status) {
|
||||
case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED:
|
||||
event_id = ZAP_OOB_ALARM_CLEAR;
|
||||
break;
|
||||
default:
|
||||
event_id = ZAP_OOB_ALARM_TRAP;
|
||||
break;
|
||||
};
|
||||
}
|
||||
break;
|
||||
|
||||
case WP_TDMAPI_EVENT_RXHOOK:
|
||||
{
|
||||
if (span->channels[i]->type == ZAP_CHAN_TYPE_FXS) {
|
||||
|
@ -918,11 +736,9 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
|
|||
continue;
|
||||
} else {
|
||||
int err;
|
||||
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_ONHOOK;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
|
||||
if ((err = wp_tdm_cmd_exec(span->channels[i], &tdm_api))) {
|
||||
zap_channel_t *zchan = span->channels[i];
|
||||
err=sangoma_tdm_txsig_onhook(zchan->sockfd,&tdm_api);
|
||||
if (err) {
|
||||
snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "ONHOOK Failed");
|
||||
return ZAP_FAIL;
|
||||
}
|
||||
|
@ -948,6 +764,20 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
|
|||
span->channels[i]->cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits);
|
||||
}
|
||||
break;
|
||||
case WP_TDMAPI_EVENT_DTMF:
|
||||
{
|
||||
char tmp_dtmf[2] = { tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_digit, 0 };
|
||||
event_id = ZAP_OOB_NOOP;
|
||||
|
||||
//zap_log(ZAP_LOG_DEBUG, "%d:%d queue hardware dtmf %s\n", zchan->span_id, zchan->chan_id, tmp_dtmf);
|
||||
if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_STOP) {
|
||||
zap_channel_queue_dtmf(zchan, tmp_dtmf);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WP_TDMAPI_EVENT_ALARM:
|
||||
event_id = ZAP_OOB_NOOP;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
zap_log(ZAP_LOG_WARNING, "Unhandled event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type);
|
||||
|
@ -1005,6 +835,7 @@ static ZIO_IO_LOAD_FUNCTION(wanpipe_init)
|
|||
#endif
|
||||
wanpipe_interface.next_event = wanpipe_next_event;
|
||||
wanpipe_interface.channel_destroy = wanpipe_channel_destroy;
|
||||
wanpipe_interface.get_alarms = wanpipe_get_alarms;
|
||||
*zio = &wanpipe_interface;
|
||||
|
||||
return ZAP_SUCCESS;
|
||||
|
|
|
@ -868,6 +868,9 @@ static ZIO_READ_FUNCTION(zt_read)
|
|||
if ((r = read(zchan->sockfd, data, *datalen)) > 0) {
|
||||
break;
|
||||
}
|
||||
if (r == 0) {
|
||||
errs--;
|
||||
}
|
||||
}
|
||||
|
||||
if (r > 0) {
|
||||
|
@ -878,7 +881,7 @@ static ZIO_READ_FUNCTION(zt_read)
|
|||
return ZAP_SUCCESS;
|
||||
}
|
||||
|
||||
return ZAP_FAIL;
|
||||
return r == 0 ? ZAP_TIMEOUT : ZAP_FAIL;
|
||||
}
|
||||
|
||||
static ZIO_WRITE_FUNCTION(zt_write)
|
||||
|
|
Loading…
Reference in New Issue