[asterisk-commits] moy: branch moy/mfcr2-1.2 r128120 - in /team/moy/mfcr2-1.2: channels/ configs/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Jul 4 21:40:31 CDT 2008
Author: moy
Date: Fri Jul 4 21:40:29 2008
New Revision: 128120
URL: http://svn.digium.com/view/asterisk?view=rev&rev=128120
Log:
added MFCR2 support to this branch
Modified:
team/moy/mfcr2-1.2/channels/Makefile
team/moy/mfcr2-1.2/channels/chan_zap.c
team/moy/mfcr2-1.2/configs/zapata.conf.sample
Modified: team/moy/mfcr2-1.2/channels/Makefile
URL: http://svn.digium.com/view/asterisk/team/moy/mfcr2-1.2/channels/Makefile?view=diff&rev=128120&r1=128119&r2=128120
==============================================================================
--- team/moy/mfcr2-1.2/channels/Makefile (original)
+++ team/moy/mfcr2-1.2/channels/Makefile Fri Jul 4 21:40:29 2008
@@ -107,9 +107,9 @@
ZAPPRI=-lpri
endif
-ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/lib/libmfcr2.so.1)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/lib/libmfcr2.so.1),)
- CFLAGS+=-DZAPATA_R2
- ZAPR2=-lmfcr2
+ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/lib/libopenr2.so.0)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/lib/libopenr2.so.0),)
+ CFLAGS+=-DHAVE_OPENR2
+ ZAPR2=-lopenr2
endif
ALSA_SRC=chan_alsa.c
Modified: team/moy/mfcr2-1.2/channels/chan_zap.c
URL: http://svn.digium.com/view/asterisk/team/moy/mfcr2-1.2/channels/chan_zap.c?view=diff&rev=128120&r1=128119&r2=128120
==============================================================================
--- team/moy/mfcr2-1.2/channels/chan_zap.c (original)
+++ team/moy/mfcr2-1.2/channels/chan_zap.c Fri Jul 4 21:40:29 2008
@@ -62,8 +62,8 @@
#error "You need newer libpri"
#endif
#endif
-#ifdef ZAPATA_R2
-#include <libmfcr2.h>
+#ifdef HAVE_OPENR2
+#include <openr2.h>
#endif
#include "asterisk.h"
@@ -142,8 +142,8 @@
#ifdef ZAPATA_PRI
" w/PRI"
#endif
-#ifdef ZAPATA_R2
- " w/R2"
+#ifdef HAVE_OPENR2
+ " w/OpenR2"
#endif
;
@@ -151,8 +151,8 @@
#ifdef ZAPATA_PRI
" w/PRI"
#endif
-#ifdef ZAPATA_R2
- " w/R2"
+#ifdef HAVE_OPENR2
+ " w/OpenR2"
#endif
;
@@ -173,7 +173,7 @@
#define SIG_FXOGS ZT_SIG_FXOGS
#define SIG_FXOKS ZT_SIG_FXOKS
#define SIG_PRI ZT_SIG_CLEAR
-#define SIG_R2 ZT_SIG_CAS
+#define SIG_MFCR2 ZT_SIG_CAS
#define SIG_SF ZT_SIG_SF
#define SIG_SFWINK (0x0100000 | ZT_SIG_SF)
#define SIG_SF_FEATD (0x0200000 | ZT_SIG_SF)
@@ -282,10 +282,6 @@
struct zt_pvt;
-
-#ifdef ZAPATA_R2
-static int r2prot = -1;
-#endif
static int ringt_base = DEFAULT_RINGT;
@@ -361,6 +357,32 @@
#else
/*! Shut up the compiler */
struct zt_pri;
+#endif
+
+#ifdef HAVE_OPENR2
+
+struct zt_mfcr2 {
+ pthread_t master; /*!< Thread of master */
+ openr2_context_t *protocol_context; /*!< OpenR2 context handle */
+ struct zt_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
+ int numchans; /*!< Number of channels in this R2 block */
+ int monitored_count; /*!< Number of channels being monitored */
+ ast_mutex_t monitored_count_lock; /*!< lock access to the counter */
+ ast_cond_t do_monitor; /*!< Condition to wake up the monitor thread when there's work to do */
+};
+
+static struct zt_mfcr2 r2links[NUM_SPANS];
+static openr2_variant_t mfcr2_cur_variant = OR2VAR_UNKNOWN;
+static int mfcr2_cur_mfback_timeout = -1;
+static int mfcr2_cur_metering_pulse_timeout = -1;
+static int mfcr2_cur_max_ani = 10;
+static int mfcr2_cur_max_dnis = 4;
+static int mfcr2_cur_get_ani_first = 0;
+static int mfcr2_cur_context_index = 0;
+static char mfcr2_cur_logdir[OR2_MAX_LOGDIR];
+static openr2_log_level_t mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING;
+static openr2_calling_party_category_t mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
+
#endif
#define SUB_REAL 0 /*!< Active call */
@@ -745,10 +767,12 @@
unsigned int resetting:1;
unsigned int setup_ack:1;
#endif
-#if defined(ZAPATA_R2)
- unsigned int hasr2call:1;
- unsigned int r2blocked:1;
- unsigned int sigchecked:1;
+#if defined(HAVE_OPENR2)
+ int mfcr2call;
+ struct zt_mfcr2 *mfcr2;
+ openr2_chan_t *r2chan;
+ openr2_calling_party_category_t mfcr2_recvd_category;
+ openr2_calling_party_category_t mfcr2_category;
#endif
struct zt_distRings drings;
@@ -831,10 +855,6 @@
int prioffset;
int logicalspan;
#endif
-#ifdef ZAPATA_R2
- int r2prot;
- mfcr2_t *r2;
-#endif
int polarity;
int dsp_features;
@@ -1264,20 +1284,296 @@
}
#endif
-#ifdef ZAPATA_R2
-static int str2r2prot(char *swtype)
-{
- if (!strcasecmp(swtype, "ar"))
- return MFCR2_PROT_ARGENTINA;
- /*endif*/
- if (!strcasecmp(swtype, "cn"))
- return MFCR2_PROT_CHINA;
- /*endif*/
- if (!strcasecmp(swtype, "kr"))
- return MFCR2_PROT_KOREA;
- /*endif*/
- return -1;
-}
+static struct ast_channel *zt_new(struct zt_pvt *, int, int, int, int, int);
+#ifdef HAVE_OPENR2
+static openr2_calling_party_category_t zt_r2_get_channel_category(struct ast_channel *c)
+{
+ openr2_calling_party_category_t cat;
+ const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
+ struct zt_pvt *p = c->tech_pvt;
+ if (ast_strlen_zero(catstr)) {
+ ast_log(LOG_DEBUG, "no MFC/R2 category specified for chan %s, using default %s\n",
+ c->name, openr2_proto_get_category_string(p->mfcr2_category));
+ return p->mfcr2_category;
+ }
+ if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
+ ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
+ catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
+ return p->mfcr2_category;
+ }
+ ast_log(LOG_DEBUG, "Using category %s\n", catstr);
+ return cat;
+}
+
+static void zt_r2_on_call_init(openr2_chan_t *r2chan)
+{
+ struct zt_pvt *p = openr2_chan_get_client_data(r2chan);
+ p->mfcr2call = 1;
+ ast_log(LOG_NOTICE, "New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
+}
+
+static void zt_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
+{
+ struct zt_pvt *p = openr2_chan_get_client_data(r2chan);
+ ast_log(LOG_WARNING, "Zap alarm on chan %d.\n", openr2_chan_get_number(r2chan));
+ p->inalarm = alarm ? 1 : 0;
+}
+
+static void zt_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
+{
+ ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
+}
+
+static void zt_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
+{
+ struct zt_pvt *p = openr2_chan_get_client_data(r2chan);
+ ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
+ if (p->owner) {
+ p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
+ p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ }
+}
+
+static void zt_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
+{
+ struct zt_pvt *p;
+ ast_log(LOG_NOTICE, "MFC/R2 call offered on chan %d. DNIS = %s, ANI = %s, Category = %s\n",
+ openr2_chan_get_number(r2chan), dnis, ani, openr2_proto_get_category_string(category));
+ p = openr2_chan_get_client_data(r2chan);
+ ast_mutex_lock(&p->lock);
+ p->mfcr2_recvd_category = category;
+ if (p->use_callerid && ani) {
+ ast_copy_string(p->cid_num, ani, sizeof(p->cid_num));
+ ast_copy_string(p->cid_name, ani, sizeof(p->cid_name));
+ } else {
+ p->cid_num[0] = 0;
+ p->cid_num[0] = 0;
+ }
+ ast_copy_string(p->rdnis, dnis, sizeof(p->rdnis));
+ if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
+ ast_log(LOG_DEBUG, "setting exten => s because of immediate or 0 DNIS configured\n");
+ ast_copy_string(p->exten, "s", sizeof(p->exten));
+ } else {
+ ast_copy_string(p->exten, dnis, sizeof(p->exten));
+ }
+ ast_mutex_unlock(&p->lock);
+ if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
+ ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
+ p->channel, p->exten, p->context);
+ openr2_chan_disconnect_call(r2chan, OR2_CAUSE_UNALLOCATED_NUMBER);
+ } else {
+ openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
+ }
+}
+
+static void zt_r2_on_call_end(openr2_chan_t *r2chan)
+{
+ ast_log(LOG_NOTICE, "MFC/R2 call end on chan %d\n", openr2_chan_get_number(r2chan));
+}
+
+static void zt_r2_update_monitor_count(struct zt_mfcr2 *mfcr2, int increment)
+{
+ ast_mutex_lock(&mfcr2->monitored_count_lock);
+ if (increment) {
+ mfcr2->monitored_count++;
+ if (mfcr2->monitored_count == 1) {
+ ast_log(LOG_DEBUG, "At least one device needs monitoring, let's wake up that lazy bastard.\n");
+ ast_cond_signal(&mfcr2->do_monitor);
+ }
+ } else {
+ mfcr2->monitored_count--;
+ if (mfcr2->monitored_count < 0) {
+ ast_log(LOG_ERROR, "wtf? we have a bug here!.\n");
+ }
+ }
+ ast_mutex_unlock(&mfcr2->monitored_count_lock);
+}
+
+static void zt_enable_ec(struct zt_pvt *p);
+static void zt_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
+{
+ struct zt_pvt *p = NULL;
+ struct ast_channel *c = NULL;
+ ast_log(LOG_NOTICE, "MFC/R2 call has been accepted on chan %d\n", openr2_chan_get_number(r2chan));
+ p = openr2_chan_get_client_data(r2chan);
+ zt_enable_ec(p);
+ if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
+ c = zt_new(p, AST_STATE_RING, 1, SUB_REAL, ZT_LAW_ALAW, 0);
+ if (c) {
+ zt_r2_update_monitor_count(p->mfcr2, 0);
+ /* chan_zap will take care of reading from now on, tell the library to forget about it */
+ openr2_chan_disable_read(r2chan);
+ } else {
+ ast_log(LOG_WARNING, "Unable to start PBX on chan %d\n", p->channel);
+ openr2_chan_disconnect_call(r2chan, OR2_CAUSE_OUT_OF_ORDER);
+ return;
+ }
+ pbx_builtin_setvar_helper(c, "MFCR2_CATEGORY", openr2_proto_get_category_string(p->mfcr2_recvd_category));
+ } else {
+ if (p->owner) {
+ pbx_builtin_setvar_helper(p->owner, "MFCR2_CALL_MODE", openr2_proto_get_call_mode_string(mode));
+ } else {
+ ast_log(LOG_WARNING, "odd ... we should have an owner, right? right?!\n");
+ }
+ ast_log(LOG_NOTICE, "Call accepted on forward channel %d\n", p->channel);
+ p->subs[SUB_REAL].needringing = 1;
+ p->dialing = 0;
+ /* chan_zap will take care of reading from now on, tell the library to forget about it */
+ openr2_chan_disable_read(r2chan);
+ }
+}
+
+static void zt_r2_on_call_answered(openr2_chan_t *r2chan)
+{
+ struct zt_pvt *p = openr2_chan_get_client_data(r2chan);
+ ast_log(LOG_DEBUG, "MFC/R2 call has been answered on chan %d\n", openr2_chan_get_number(r2chan));
+ p->subs[SUB_REAL].needanswer = 1;
+}
+
+static void zt_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
+{
+ /*ast_log(LOG_DEBUG, "Read data from zap channel %d\n", openr2_chan_get_number(r2chan));*/
+}
+
+static int zt_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
+{
+ switch (cause) {
+ case OR2_CAUSE_BUSY_NUMBER:
+ return AST_CAUSE_BUSY;
+ case OR2_CAUSE_NETWORK_CONGESTION:
+ return AST_CAUSE_CONGESTION;
+ case OR2_CAUSE_OUT_OF_ORDER:
+ return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
+ case OR2_CAUSE_UNALLOCATED_NUMBER:
+ return AST_CAUSE_UNREGISTERED;
+ case OR2_CAUSE_NO_ANSWER:
+ return AST_CAUSE_NO_ANSWER;
+ case OR2_CAUSE_NORMAL_CLEARING:
+ return AST_CAUSE_NORMAL_CLEARING;
+ case OR2_CAUSE_UNSPECIFIED:
+ default:
+ return AST_CAUSE_NOTDEFINED;
+ }
+}
+
+static void zt_r2_on_call_disconnected(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
+{
+ struct zt_pvt *p = openr2_chan_get_client_data(r2chan);
+ ast_log(LOG_NOTICE, "MFC/R2 call disconnected on chan %d\n", openr2_chan_get_number(r2chan));
+ if (p->owner) {
+ if (p->owner->_state == AST_STATE_UP) {
+ p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
+ /* being the forward side we must report what happened to the call to whoever requested it */
+ switch (cause) {
+ case OR2_CAUSE_BUSY_NUMBER:
+ p->subs[SUB_REAL].needbusy = 1;
+ break;
+ case OR2_CAUSE_NETWORK_CONGESTION:
+ case OR2_CAUSE_OUT_OF_ORDER:
+ case OR2_CAUSE_UNALLOCATED_NUMBER:
+ case OR2_CAUSE_NO_ANSWER:
+ case OR2_CAUSE_UNSPECIFIED:
+ case OR2_CAUSE_NORMAL_CLEARING:
+ p->subs[SUB_REAL].needcongestion = 1;
+ break;
+ default:
+ p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ }
+ } else {
+ /* being the backward side and not UP yet, we only need to request hangup */
+ /* TODO: what about doing this same thing when were AST_STATE_UP? */
+ p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ }
+ } else {
+ /* no owner, let's just disconnect our side */
+ openr2_chan_disconnect_call(r2chan, OR2_CAUSE_NORMAL_CLEARING);
+ }
+}
+
+static void zt_r2_write_log(openr2_log_level_t level, char *logmessage)
+{
+ switch (level) {
+ case OR2_LOG_NOTICE:
+ ast_log(LOG_NOTICE, logmessage);
+ break;
+ case OR2_LOG_WARNING:
+ ast_log(LOG_WARNING, logmessage);
+ break;
+ case OR2_LOG_ERROR:
+ ast_log(LOG_ERROR, logmessage);
+ break;
+ case OR2_LOG_STACK_TRACE:
+ case OR2_LOG_MF_TRACE:
+ case OR2_LOG_CAS_TRACE:
+ case OR2_LOG_DEBUG:
+ ast_log(LOG_DEBUG, logmessage);
+ break;
+ default:
+ ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
+ ast_log(LOG_DEBUG, logmessage);
+ break;
+ }
+}
+
+static void zt_r2_on_line_blocked(openr2_chan_t *r2chan)
+{
+ ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
+}
+
+static void zt_r2_on_line_idle(openr2_chan_t *r2chan)
+{
+ ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
+}
+
+static void zt_r2_on_context_logging(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
+{
+ char logmsg[256];
+ char completemsg[sizeof(logmsg)+50];
+ vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
+ snprintf(completemsg, sizeof(completemsg), "Context - %s", logmsg);
+ zt_r2_write_log(level, completemsg);
+}
+
+static void zt_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
+{
+ char logmsg[256];
+ char completemsg[sizeof(logmsg)+50];
+ vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
+ snprintf(completemsg, sizeof(completemsg), "Chan %d - %s", openr2_chan_get_number(r2chan), logmsg);
+ zt_r2_write_log(level, completemsg);
+}
+
+static openr2_event_interface_t zt_r2_event_iface = {
+ zt_r2_on_call_init,
+ zt_r2_on_call_offered,
+ zt_r2_on_call_accepted,
+ zt_r2_on_call_answered,
+ zt_r2_on_call_disconnected,
+ zt_r2_on_call_end,
+ zt_r2_on_call_read,
+ zt_r2_on_hardware_alarm,
+ zt_r2_on_os_error,
+ zt_r2_on_protocol_error,
+ zt_r2_on_line_blocked,
+ zt_r2_on_line_idle,
+ zt_r2_on_context_logging
+};
+
+static inline int16_t zt_r2_alaw_to_linear(uint8_t sample)
+{
+ return AST_ALAW(sample);
+}
+
+static inline uint8_t zt_r2_linear_to_alaw(int sample)
+{
+ return AST_LIN2A(sample);
+}
+
+static openr2_transcoder_interface_t zt_r2_transcode_iface = {
+ zt_r2_alaw_to_linear,
+ zt_r2_linear_to_alaw
+};
#endif
static char *zap_sig2str(int sig)
@@ -1314,8 +1610,8 @@
return "FXO Kewlstart";
case SIG_PRI:
return "PRI Signalling";
- case SIG_R2:
- return "R2 Signalling";
+ case SIG_MFCR2:
+ return "MFC/R2 Signalling";
case SIG_SF:
return "SF (Tone) Signalling Immediate";
case SIG_SFWINK:
@@ -2148,6 +2444,7 @@
ast_setstate(ast, AST_STATE_UP);
break;
case SIG_PRI:
+ case SIG_MFCR2:
/* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
p->dialdest[0] = '\0';
break;
@@ -2296,6 +2593,35 @@
pri_rel(p->pri);
}
#endif
+#ifdef HAVE_OPENR2
+ if (p->mfcr2) {
+ int strip = p->stripmsd;
+ int callres = 0;
+ c = strchr(dest, '/');
+ if (c) {
+ c++;
+ } else {
+ c = dest;
+ }
+ if (!p->hidecallerid) {
+ l = ast->cid.cid_num;
+ } else {
+ l = NULL;
+ }
+ if (strlen(c) < strip) {
+ ast_log(LOG_WARNING, "Destiny number '%s' is shorter than stripmsd(%d)? hum, you should fix that. Assuming stripmsd = 0\n", c, strip);
+ strip = 0;
+ }
+ p->dialing = 1;
+ callres = openr2_chan_make_call(p->r2chan, l, (c + strip), zt_r2_get_channel_category(ast));
+ if (-1 == callres) {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
+ return -1;
+ }
+ ast_setstate(ast, AST_STATE_DIALING);
+ }
+#endif
ast_mutex_unlock(&p->lock);
return 0;
}
@@ -2672,18 +2998,14 @@
}
}
#endif
-#ifdef ZAPATA_R2
- if (p->sig == SIG_R2) {
- if (p->hasr2call) {
- mfcr2_DropCall(p->r2, NULL, UC_NORMAL_CLEARING);
- p->hasr2call = 0;
- res = 0;
- } else
- res = 0;
-
- }
-#endif
- if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_R2))
+#ifdef HAVE_OPENR2
+ if (p->mfcr2) {
+ ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
+ openr2_chan_disconnect_call(p->r2chan, OR2_CAUSE_NORMAL_CLEARING);
+ zt_r2_update_monitor_count(p->mfcr2, 1);
+ }
+#endif
+ if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_MFCR2))
res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_ONHOOK);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
@@ -2858,13 +3180,12 @@
}
break;
#endif
-#ifdef ZAPATA_R2
- case SIG_R2:
- res = mfcr2_AnswerCall(p->r2, NULL);
- if (res)
- ast_log(LOG_WARNING, "R2 Answer call failed :( on %s\n", ast->name);
+#ifdef HAVE_OPENR2
+ case SIG_MFCR2:
+ ast_log(LOG_DEBUG, "Accepting MFC/R2 call on chan %d\n", p->channel);
+ openr2_chan_answer_call(p->r2chan);
break;
-#endif
+#endif
case 0:
ast_mutex_unlock(&p->lock);
return 0;
@@ -3481,8 +3802,6 @@
static void *ss_thread(void *data);
-static struct ast_channel *zt_new(struct zt_pvt *, int, int, int, int, int);
-
static int attempt_transfer(struct zt_pvt *p)
{
/* In order to transfer, we need at least one of the channels to
@@ -3552,78 +3871,6 @@
}
return 0;
}
-
-#ifdef ZAPATA_R2
-static struct ast_frame *handle_r2_event(struct zt_pvt *p, mfcr2_event_t *e, int index)
-{
- struct ast_frame *f;
- f = &p->subs[index].f;
- if (!p->r2) {
- ast_log(LOG_WARNING, "Huh? No R2 structure :(\n");
- return NULL;
- }
- switch(e->e) {
- case MFCR2_EVENT_BLOCKED:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Channel %d blocked\n", p->channel);
- break;
- case MFCR2_EVENT_UNBLOCKED:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Channel %d unblocked\n", p->channel);
- break;
- case MFCR2_EVENT_CONFIG_ERR:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Config error on channel %d\n", p->channel);
- break;
- case MFCR2_EVENT_RING:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Ring on channel %d\n", p->channel);
- break;
- case MFCR2_EVENT_HANGUP:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Hangup on channel %d\n", p->channel);
- break;
- case MFCR2_EVENT_RINGING:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Ringing on channel %d\n", p->channel);
- break;
- case MFCR2_EVENT_ANSWER:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Answer on channel %d\n", p->channel);
- break;
- case MFCR2_EVENT_HANGUP_ACK:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Hangup ACK on channel %d\n", p->channel);
- break;
- case MFCR2_EVENT_IDLE:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Idle on channel %d\n", p->channel);
- break;
- default:
- ast_log(LOG_WARNING, "Unknown MFC/R2 event %d\n", e->e);
- break;
- }
- return f;
-}
-
-static mfcr2_event_t *r2_get_event_bits(struct zt_pvt *p)
-{
- int x;
- int res;
- mfcr2_event_t *e;
- res = ioctl(p->subs[SUB_REAL].zfd, ZT_GETRXBITS, &x);
- if (res) {
- ast_log(LOG_WARNING, "Unable to check received bits\n");
- return NULL;
- }
- if (!p->r2) {
- ast_log(LOG_WARNING, "Odd, no R2 structure on channel %d\n", p->channel);
- return NULL;
- }
- e = mfcr2_cas_signaling_event(p->r2, x);
- return e;
-}
-#endif
static int check_for_conference(struct zt_pvt *p)
{
@@ -3792,25 +4039,28 @@
switch(res) {
case ZT_EVENT_BITSCHANGED:
- if (p->sig == SIG_R2) {
-#ifdef ZAPATA_R2
- struct ast_frame *f = &p->subs[index].f;
- mfcr2_event_t *e;
- e = r2_get_event_bits(p);
- if (e)
- f = handle_r2_event(p, e, index);
- return f;
-#else
+#ifdef HAVE_OPENR2
+ if (p->sig == SIG_MFCR2) {
+ ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
+ openr2_proto_handle_abcd_change(p->r2chan);
break;
-#endif
- }
+ }
+#endif
ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
+ break;
case ZT_EVENT_PULSE_START:
/* Stop tone if there's a pulse start and the PBX isn't started */
if (!ast->pbx)
tone_zone_play_tone(p->subs[index].zfd, -1);
break;
case ZT_EVENT_DIALCOMPLETE:
+#ifdef HAVE_OPENR2
+ if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
+ /* we don't need to do anything for this event for R2 signaling
+ if the call is being setup */
+ break;
+ }
+#endif
if (p->inalarm) break;
if (p->radio) break;
if (ioctl(p->subs[index].zfd,ZT_DIALING,&x) == -1) {
@@ -4655,6 +4905,12 @@
else if (p->ringt > 0)
p->ringt--;
+#ifdef HAVE_OPENR2
+ if (p->mfcr2) {
+ openr2_chan_process_event(p->r2chan);
+ }
+#endif
+
if (p->subs[index].needringing) {
/* Send ringing frame if requested */
p->subs[index].needringing = 0;
@@ -4698,8 +4954,24 @@
p->subs[index].f.subclass = AST_CONTROL_ANSWER;
ast_mutex_unlock(&p->lock);
return &p->subs[index].f;
- }
-
+ }
+#ifdef HAVE_OPENR2
+ if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
+ /* openr2 took care of reading and handling any event
+ (needanswer, needbusy etc), if we continue we will read()
+ twice, lets just return a null frame. This should only
+ happen when openr2 is dialing out */
+ p->subs[index].f.frametype = AST_FRAME_NULL;
+ p->subs[index].f.subclass = 0;
+ p->subs[index].f.samples = 0;
+ p->subs[index].f.mallocd = 0;
+ p->subs[index].f.offset = 0;
+ p->subs[index].f.data = NULL;
+ p->subs[index].f.datalen= 0;
+ ast_mutex_unlock(&p->lock);
+ return &p->subs[index].f;
+ }
+#endif
if (p->subs[index].needflash) {
/* Send answer frame if requested */
p->subs[index].needflash = 0;
@@ -6367,47 +6639,14 @@
return NULL;
}
-#ifdef ZAPATA_R2
-static int handle_init_r2_event(struct zt_pvt *i, mfcr2_event_t *e)
-{
- struct ast_channel *chan;
-
- switch(e->e) {
- case MFCR2_EVENT_UNBLOCKED:
- i->r2blocked = 0;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "R2 Channel %d unblocked\n", i->channel);
- break;
- case MFCR2_EVENT_BLOCKED:
- i->r2blocked = 1;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "R2 Channel %d unblocked\n", i->channel);
- break;
- case MFCR2_EVENT_IDLE:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "R2 Channel %d idle\n", i->channel);
- break;
- case MFCR2_EVENT_RINGING:
- /* This is what Asterisk refers to as a "RING" event. For some reason they're reversed in
- Steve's code */
- /* Check for callerid, digits, etc */
- i->hasr2call = 1;
- chan = zt_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
- if (!chan) {
- ast_log(LOG_WARNING, "Unable to create channel for channel %d\n", i->channel);
- mfcr2_DropCall(i->r2, NULL, UC_NETWORK_CONGESTION);
- i->hasr2call = 0;
- }
- if (ast_pbx_start(chan)) {
- ast_log(LOG_WARNING, "Unable to start PBX on channel %s\n", chan->name);
- ast_hangup(chan);
- }
- break;
- default:
- ast_log(LOG_WARNING, "Don't know how to handle initial R2 event %s on channel %d\n", mfcr2_event2str(e->e), i->channel);
- return -1;
- }
- return 0;
+#ifdef HAVE_OPENR2
+static struct zt_mfcr2 *mfcr2_get_context(int id)
+{
+ if ((id < 0) || (id > sizeof(r2links))) {
+ ast_log(LOG_ERROR, "Wah! you surely did not mean to do this\n.");
+ return NULL;
+ }
+ return &r2links[id];
}
#endif
@@ -6424,15 +6663,6 @@
case ZT_EVENT_NONE:
case ZT_EVENT_BITSCHANGED:
if (i->radio) break;
-#ifdef ZAPATA_R2
- if (i->r2) {
- mfcr2_event_t *e;
- e = r2_get_event_bits(i);
- i->sigchecked = 1;
- if (e)
- handle_init_r2_event(i, e);
- }
-#endif
break;
case ZT_EVENT_WINKFLASH:
case ZT_EVENT_RINGOFFHOOK:
@@ -6652,18 +6882,14 @@
count = 0;
i = iflist;
while(i) {
- if ((i->subs[SUB_REAL].zfd > -1) && i->sig && (!i->radio)) {
+ if ((i->subs[SUB_REAL].zfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
if (!i->owner && !i->subs[SUB_REAL].owner) {
/* This needs to be watched, as it lacks an owner */
pfds[count].fd = i->subs[SUB_REAL].zfd;
pfds[count].events = POLLPRI;
pfds[count].revents = 0;
/* Message waiting or r2 channels also get watched for reading */
-#ifdef ZAPATA_R2
- if (i->cidspill || i->r2)
-#else
if (i->cidspill)
-#endif
pfds[count].events |= POLLIN;
count++;
}
@@ -6752,22 +6978,6 @@
i = i->next;
continue;
}
-#ifdef ZAPATA_R2
- if (i->r2) {
- /* If it's R2 signalled, we always have to check for events */
- mfcr2_event_t *e;
- e = mfcr2_check_event(i->r2);
- if (e)
- handle_init_r2_event(i, e);
- else {
- e = mfcr2_schedule_run(i->r2);
- if (e)
- handle_init_r2_event(i, e);
- }
- i = i->next;
- continue;
- }
-#endif
if (!i->cidspill) {
ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].zfd);
i = i->next;
@@ -6801,11 +7011,7 @@
handle_init_event(i, res);
ast_mutex_lock(&iflock);
}
-#ifdef ZAPATA_R2
- if ((pollres & POLLPRI) || (i->r2 && !i->sigchecked))
-#else
if (pollres & POLLPRI)
-#endif
{
if (i->owner || i->subs[SUB_REAL].owner) {
#ifdef ZAPATA_PRI
@@ -7197,24 +7403,68 @@
tmp->prioffset = 0;
}
#endif
-#ifdef ZAPATA_R2
- if (chan_conf.signalling == SIG_R2) {
- if (r2prot < 0) {
- ast_log(LOG_WARNING, "R2 Country not specified for channel %d -- Assuming China\n", tmp->channel);
- tmp->r2prot = MFCR2_PROT_CHINA;
- } else
- tmp->r2prot = r2prot;
- tmp->r2 = mfcr2_new(tmp->subs[SUB_REAL].zfd, tmp->r2prot, 1);
- if (!tmp->r2) {
- ast_log(LOG_WARNING, "Unable to create r2 call :(\n");
- zt_close(tmp->subs[SUB_REAL].zfd);
- destroy_zt_pvt(&tmp);
- return NULL;
- }
- } else {
- if (tmp->r2)
- mfcr2_free(tmp->r2);
- tmp->r2 = NULL;
+#ifdef HAVE_OPENR2
+ if (chan_conf.signalling == SIG_MFCR2 && !reloading) {
+ char logdir[OR2_MAX_LOGDIR];
+ struct zt_mfcr2 *zap_r2;
+ int threshold = 0;
+ int snres = 0;
+ zap_r2 = mfcr2_get_context(mfcr2_cur_context_index);
+ if (!zap_r2) {
+ ast_log(LOG_WARNING, "Cannot get another R2 zap context!\n");
+ } else if (!zap_r2->protocol_context){
+ char tmplogdir[] = "/tmp";
+ zap_r2->protocol_context = openr2_context_new(NULL, &zt_r2_event_iface,
+ &zt_r2_transcode_iface, mfcr2_cur_variant, mfcr2_cur_max_ani, mfcr2_cur_max_dnis);
+ if (!zap_r2->protocol_context) {
+ ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
+ destroy_zt_pvt(&tmp);
+ return NULL;
+ }
+ openr2_context_set_log_level(zap_r2->protocol_context, mfcr2_cur_loglevel);
+ openr2_context_set_ani_first(zap_r2->protocol_context, mfcr2_cur_get_ani_first);
+ openr2_context_set_mf_threshold(zap_r2->protocol_context, threshold);
+ openr2_context_set_mf_back_timeout(zap_r2->protocol_context, mfcr2_cur_mfback_timeout);
+ openr2_context_set_metering_pulse_timeout(zap_r2->protocol_context, mfcr2_cur_metering_pulse_timeout);
+ if (ast_strlen_zero(mfcr2_cur_logdir)) {
+ if (openr2_context_set_log_directory(zap_r2->protocol_context, tmplogdir)) {
+ ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
+ }
+ } else {
+ snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", mfcr2_cur_logdir);
+ if (snres >= sizeof(logdir)) {
+ ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
+ if (openr2_context_set_log_directory(zap_r2->protocol_context, logdir)) {
+ ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
+ }
+ } else {
+ if (openr2_context_set_log_directory(zap_r2->protocol_context, logdir)) {
+ ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
+ }
+ }
+ }
+ ast_cond_init(&zap_r2->do_monitor, NULL);
+ ast_mutex_init(&zap_r2->monitored_count_lock);
+ zap_r2->monitored_count = 0;
+ }
+ if (zap_r2) {
+ /* TODO: should we check numchans overflow, or is it already done by zap? */
+ zap_r2->pvts[zap_r2->numchans++] = tmp;
+ tmp->r2chan = openr2_chan_new_from_fd(zap_r2->protocol_context, tmp->subs[SUB_REAL].zfd,
+ NULL, NULL);
+ if (!tmp->r2chan) {
+ ast_log(LOG_ERROR, "Cannot create OpenR2 channel.\n");
+ destroy_zt_pvt(&tmp);
+ return NULL;
+ }
+ openr2_chan_set_client_data(tmp->r2chan, tmp);
+ openr2_chan_set_logging_func(tmp->r2chan, zt_r2_on_chan_log);
+ openr2_chan_set_log_level(tmp->r2chan, mfcr2_cur_loglevel);
+ tmp->mfcr2_category = mfcr2_cur_category;
+ tmp->mfcr2 = zap_r2;
+ tmp->mfcr2call = 0;
+ zap_r2->monitored_count++;
+ }
}
#endif
} else {
@@ -7368,7 +7618,7 @@
ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
update_conf(tmp);
if (!here) {
- if ((chan_conf.signalling != SIG_PRI) && (chan_conf.signalling != SIG_R2))
+ if ((chan_conf.signalling != SIG_PRI) && (chan_conf.signalling != SIG_MFCR2))
/* Hang it up to be sure it's good */
zt_set_hook(tmp->subs[SUB_REAL].zfd, ZT_ONHOOK);
}
@@ -7482,10 +7732,9 @@
return 1;
}
#endif
-#ifdef ZAPATA_R2
- /* Trust R2 as well */
- if (p->r2) {
- if (p->hasr2call || p->r2blocked)
+#ifdef HAVE_OPENR2
+ if (p->mfcr2) {
+ if (p->mfcr2call)
return 0;
else
return 1;
@@ -7788,6 +8037,11 @@
}
p->outgoing = 1;
tmp = zt_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
+#ifdef HAVE_OPENR2
+ if (p->mfcr2) {
+ zt_r2_update_monitor_count(p->mfcr2, 0);
+ }
+#endif
#ifdef ZAPATA_PRI
if (p->bearer) {
/* Log owner to bearer channel, too */
@@ -9613,80 +9867,368 @@
#endif /* ZAPATA_PRI */
-#ifdef ZAPATA_R2
-static int handle_r2_no_debug(int fd, int argc, char *argv[])
-{
- int chan;
- struct zt_pvt *tmp = NULL;;
- if (argc < 5)
+#ifdef HAVE_OPENR2
+static void *mfcr2_monitor(void *data)
+{
+ struct zt_mfcr2 *mfcr2 = data;
+ /* we should be using pthread_key_create
+ and allocate pollers dynamically.
+ I think do_monitor() could be leaking, since it
+ could be cancelled at any time and is not
+ using thread keys, why?, */
+ struct pollfd pollers[sizeof(mfcr2->pvts)];
+ int nextms = 0;
+ int res = 0;
+ int i = 0;
+ int oldstate = 0;
+ /* now that we're ready to get calls, unblock our side and
+ get current line state */
+ for (i = 0; i < mfcr2->numchans; i++) {
+ openr2_proto_set_idle(mfcr2->pvts[i]->r2chan);
+ openr2_proto_handle_abcd_change(mfcr2->pvts[i]->r2chan);
+ }
+ while(1) {
+ /* we trust here that the mfcr2 channel list will not ever change once
+ the module is loaded */
+ nextms = openr2_context_get_time_to_next_event(mfcr2->protocol_context);
+ ast_mutex_lock(&mfcr2->monitored_count_lock);
+ if (mfcr2->monitored_count == 0) {
+ ast_log(LOG_DEBUG, "No one requires my monitoring services :-(\n");
+ ast_cond_wait(&mfcr2->do_monitor, &mfcr2->monitored_count_lock);
+ ast_log(LOG_DEBUG, "Alright, back to work!\n");
+ }
+
+ for (i = 0; i < mfcr2->numchans; i++) {
+ pollers[i].revents = 0;
+ pollers[i].events = 0;
+ if (mfcr2->pvts[i]->owner) {
+ continue;
+ }
+ if (mfcr2->pvts[i]->mfcr2call) {
+ mfcr2->pvts[i]->mfcr2call = 0;
+ }
+ openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
+ pollers[i].events = POLLIN | POLLPRI;
+ pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].zfd;
+ }
+ ast_mutex_unlock(&mfcr2->monitored_count_lock);
+ /* probably poll() is a valid cancel point, lets just be on the safe side
+ by calling pthread_testcancel */
+ pthread_testcancel();
+ res = poll(pollers, mfcr2->numchans, nextms);
+ pthread_testcancel();
+ if ((res < 0) && (errno != EINTR)) {
+ ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
+ break;
+ }
+ /* do we want to allow to cancel while processing events? */
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
+ for (i = 0; i < mfcr2->numchans; i++) {
+ if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
+ openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
+ }
+ }
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
+ }
+ return 0;
+}
+
+static int handle_mfcr2_version(int fd, int argc, char *argv[])
+{
+ ast_cli(fd, "OpenR2 version: %s\n", openr2_get_version());
+ return RESULT_SUCCESS;
+}
+
+static int handle_mfcr2_show_channels(int fd, int argc, char *argv[])
+{
+#define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
+#define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
+ int filtertype = 0;
+ int targetnum;
+ char channo[5];
+ char anino[5];
+ char dnisno[5];
+ struct zt_pvt *p;
+ openr2_context_t *r2context;
+ openr2_variant_t r2variant;
+ if (!((argc == 3) || (argc == 5))) {
return RESULT_SHOWUSAGE;
- chan = atoi(argv[4]);
- if ((chan < 1) || (chan > NUM_SPANS)) {
- ast_cli(fd, "Invalid channel %s. Should be a number greater than 0\n", argv[4]);
- return RESULT_SUCCESS;
- }
- tmp = iflist;
- while(tmp) {
- if (tmp->channel == chan) {
- if (tmp->r2) {
- mfcr2_set_debug(tmp->r2, 0);
- ast_cli(fd, "Disabled R2 debugging on channel %d\n", chan);
- return RESULT_SUCCESS;
- }
- break;
- }
- tmp = tmp->next;
- }
- if (tmp)
- ast_cli(fd, "No R2 running on channel %d\n", chan);
- else
- ast_cli(fd, "No such zap channel %d\n", chan);
+ }
+ if (argc == 5) {
+ if (!strcasecmp(argv[3], "group")) {
+ targetnum = atoi(argv[4]);
+ if ((targetnum < 0) || (targetnum > 63))
+ return RESULT_SHOWUSAGE;
+ targetnum = 1 << targetnum;
+ filtertype = 1;
+ } else if (!strcasecmp(argv[3], "context")) {
+ filtertype = 2;
+ } else {
+ return RESULT_SHOWUSAGE;
+ }
+ }
+ ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Tx State", "Rx State");
+ ast_mutex_lock(&iflock);
+ p = iflist;
+ while (p) {
+ if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
+ p = p->next;
+ continue;
+ }
+ if (filtertype) {
+ switch(filtertype) {
+ case 1: /* mfcr2 show channels group <group> */
+ if (p->group != targetnum) {
+ p = p->next;
+ continue;
+ }
+ break;
+ case 2: /* mfcr2 show channels context <context> */
+ if (strcasecmp(p->context, argv[4])) {
+ p= p->next;
+ continue;
+ }
+ break;
+ default:
+ ;
+ }
+ }
+ r2context = openr2_chan_get_context(p->r2chan);
+ r2variant = openr2_context_get_variant(r2context);
+ snprintf(channo, sizeof(channo), "%d", p->channel);
+ snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
+ snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
+ ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
+ anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
+ openr2_proto_get_tx_state_string(p->r2chan), openr2_proto_get_rx_state_string(p->r2chan));
+ p = p->next;
+ }
+ ast_mutex_unlock(&iflock);
return RESULT_SUCCESS;
-}
-
-static int handle_r2_debug(int fd, int argc, char *argv[])
-{
- int chan;
- struct zt_pvt *tmp = NULL;;
+#undef FORMAT
+#undef FORMAT2
+}
+
+static int handle_mfcr2_set_debug(int fd, int argc, char *argv[])
+{
+ struct zt_pvt *p = NULL;
+ int channo = 0;
+ char *toklevel = NULL;
+ char *saveptr = NULL;
+ char *logval = NULL;
+ openr2_log_level_t loglevel = OR2_LOG_NOTHING;
+ openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
if (argc < 4) {
return RESULT_SHOWUSAGE;
}
- chan = atoi(argv[3]);
- if ((chan < 1) || (chan > NUM_SPANS)) {
- ast_cli(fd, "Invalid channel %s. Should be a number greater than 0\n", argv[3]);
- return RESULT_SUCCESS;
- }
- tmp = iflist;
- while(tmp) {
- if (tmp->channel == chan) {
- if (tmp->r2) {
- mfcr2_set_debug(tmp->r2, 0xFFFFFFFF);
- ast_cli(fd, "Enabled R2 debugging on channel %d\n", chan);
- return RESULT_SUCCESS;
- }
+ channo = (argc == 5) ? atoi(argv[4]) : -1;
+ logval = ast_strdupa(argv[3]);
+ toklevel = strtok_r(logval, ",", &saveptr);
+ if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
+ ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]);
+ return RESULT_FAILURE;
+ } else if (OR2_LOG_NOTHING == tmplevel) {
+ loglevel = tmplevel;
+ } else {
+ loglevel |= tmplevel;
+ while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
+ if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
+ ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
+ continue;
+ }
+ loglevel |= tmplevel;
+ }
+ }
+ ast_mutex_lock(&iflock);
+ p = iflist;
+ while (p) {
+ if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
+ p = p->next;
+ continue;
+ }
+ if ((channo != -1) && (p->channel != channo )) {
+ p = p->next;
+ continue;
+ }
+ openr2_chan_set_log_level(p->r2chan, loglevel);
+ if (channo != -1) {
+ ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel);
break;
- }
- tmp = tmp->next;
- }
- if (tmp)
- ast_cli(fd, "No R2 running on channel %d\n", chan);
- else
- ast_cli(fd, "No such zap channel %d\n", chan);
+ } else {
+ p = p->next;
+ }
+ }
+ if ((channo != -1) && !p) {
+ ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
+ }
+ if (channo == -1) {
+ ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]);
+ }
+ ast_mutex_unlock(&iflock);
return RESULT_SUCCESS;
}
-static char r2_debug_help[] =
- "Usage: r2 debug channel <channel>\n"
- " Enables R2 protocol level debugging on a given channel\n";
-
-static char r2_no_debug_help[] =
- "Usage: r2 no debug channel <channel>\n"
- " Enables R2 protocol level debugging on a given channel\n";
-
-static struct ast_cli_entry zap_r2_cli[] = {
- { { "r2", "debug", "channel", NULL }, handle_r2_debug,
- "Enables R2 debugging on a channel", r2_debug_help },
- { { "r2", "no", "debug", "channel", NULL }, handle_r2_no_debug,
- "Disables R2 debugging on a channel", r2_no_debug_help },
+
+static int handle_mfcr2_call_files(int fd, int argc, char *argv[])
+{
+ struct zt_pvt *p = NULL;
+ int channo = 0;
+ if (argc < 4) {
+ return RESULT_SHOWUSAGE;
+ }
+ channo = (argc == 5) ? atoi(argv[4]) : -1;
+ ast_mutex_lock(&iflock);
+ p = iflist;
+ while (p) {
+ if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
+ p = p->next;
+ continue;
+ }
+ if ((channo != -1) && (p->channel != channo )) {
+ p = p->next;
+ continue;
+ }
+ if (ast_true(argv[3])) {
+ openr2_chan_enable_call_files(p->r2chan);
+ } else {
+ openr2_chan_disable_call_files(p->r2chan);
+ }
+ if (channo != -1) {
+ if (ast_true(argv[3])) {
+ ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
+ } else {
+ ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
+ }
+ break;
+ } else {
+ p = p->next;
+ }
+ }
+ if ((channo != -1) && !p) {
+ ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
+ }
+ if (channo == -1) {
+ if (ast_true(argv[3])) {
+ ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n");
+ } else {
+ ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n");
+ }
+ }
+ ast_mutex_unlock(&iflock);
+ return RESULT_SUCCESS;
+}
+
+static int handle_mfcr2_set_idle(int fd, int argc, char *argv[])
+{
+ struct zt_pvt *p = NULL;
[... 415 lines stripped ...]
More information about the asterisk-commits
mailing list