[asterisk-commits] dbailey: branch dbailey/mwi_rpas r117771 - in /team/dbailey/mwi_rpas: channel...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu May 22 09:16:34 CDT 2008
Author: dbailey
Date: Thu May 22 09:16:33 2008
New Revision: 117771
URL: http://svn.digium.com/view/asterisk?view=rev&rev=117771
Log:
per issue 8587
Pulled sending MWI messages from do_monitor and implemetned a separate thread
Added the ability to generate a Ring Pulse - Alert Signal when sending the MWI message
Incorporated many of meneault's original changes
Modified:
team/dbailey/mwi_rpas/channels/chan_zap.c
team/dbailey/mwi_rpas/include/asterisk/callerid.h
team/dbailey/mwi_rpas/main/callerid.c
Modified: team/dbailey/mwi_rpas/channels/chan_zap.c
URL: http://svn.digium.com/view/asterisk/team/dbailey/mwi_rpas/channels/chan_zap.c?view=diff&rev=117771&r1=117770&r2=117771
==============================================================================
--- team/dbailey/mwi_rpas/channels/chan_zap.c (original)
+++ team/dbailey/mwi_rpas/channels/chan_zap.c Thu May 22 09:16:33 2008
@@ -241,6 +241,7 @@
/*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
static char mwimonitornotify[PATH_MAX] = "";
+static int mwisend_rpas = 0;
static char progzone[10] = "";
@@ -572,6 +573,7 @@
unsigned int mwimonitor_neon:1; /*!< monitor this FXO port for neon type MWI indication from other end */
unsigned int mwimonitor_fsk:1; /*!< monitor this FXO port for fsk MWI indication from other end */
unsigned int mwimonitoractive:1; /*!< an MWI monitor thread is currently active */
+ unsigned int mwisendactive:1; /*!< a MWI message sending thread is active */
/* Channel state or unavilability flags */
unsigned int inservice:1;
unsigned int locallyblocked:1;
@@ -844,6 +846,7 @@
static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
static int zt_setoption(struct ast_channel *chan, int option, void *data, int datalen);
static int zt_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
+static int handle_init_event(struct zt_pvt *i, int event);
static const struct ast_channel_tech zap_tech = {
.type = "Zap",
@@ -939,6 +942,9 @@
3, /*!< After third chirp */
2, /*!< Second spell */
};
+
+/* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
+static struct zt_ring_cadence AS_RP_cadence = {{250, 10000}};
#define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
(p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
@@ -6830,7 +6836,7 @@
samples = 0;
#if 1
bump_gains(p);
-#endif
+#endif
/* Take out of linear mode for Caller*ID processing */
zt_setlinear(p->subs[index].zfd, 0);
@@ -7257,6 +7263,18 @@
if (cs)
callerid_free(cs);
+ /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
+ if (flags & CID_MSGWAITING) {
+ ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
+ notify_message(p->mailbox, 1);
+ ast_hangup(chan);
+ return NULL;
+ } else if (flags & CID_NOMSGWAITING) {
+ ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
+ notify_message(p->mailbox, 0);
+ ast_hangup(chan);
+ return NULL;
+ }
ast_setstate(chan, AST_STATE_RING);
chan->rings = 1;
@@ -7441,6 +7459,159 @@
return NULL;
}
+/* States for sending MWI message
+ * First three states are required for send Ring Pulse Alert Signal
+ */
+enum mwisend_states {
+ MWI_SEND_SA,
+ MWI_SEND_SA_WAIT,
+ MWI_SEND_PAUSE,
+ MWI_SEND_SPILL,
+ MWI_SEND_CLEANUP,
+ MWI_SEND_DONE
+};
+
+static void *mwi_send_thread(void *data)
+{
+ struct mwi_thread_data *mtd = data;
+ struct timeval timeout_basis, pause, now;
+ int x, i, res;
+ int num_read;
+ enum mwisend_states mwi_send_state = MWI_SEND_SPILL; /*Assume FSK only */
+
+ /* Determine how this spill is to be sent */
+ if(mwisend_rpas) {
+ mwi_send_state = MWI_SEND_SA;
+ }
+
+ gettimeofday(&timeout_basis, NULL);
+
+ mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
+ if (!mtd->pvt->cidspill) {
+ mtd->pvt->mwisendactive = 0;
+ ast_free(mtd);
+ return NULL;
+ }
+ x = ZT_FLUSH_BOTH;
+ res = ioctl(mtd->pvt->subs[SUB_REAL].zfd, ZT_FLUSH, &x);
+ x = 3000;
+ ioctl(mtd->pvt->subs[SUB_REAL].zfd, ZT_ONHOOKTRANSFER, &x);
+ mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL,
+ AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0);
+ mtd->pvt->cidpos = 0;
+
+ while (MWI_SEND_DONE != mwi_send_state) {
+ num_read = 0;
+ gettimeofday(&now, NULL);
+ if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) {
+ ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state);
+ goto quit;
+ }
+
+ i = ZT_IOMUX_READ | ZT_IOMUX_SIGEVENT;
+ if ((res = ioctl(mtd->pvt->subs[SUB_REAL].zfd, ZT_IOMUX, &i))) {
+ ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
+ goto quit;
+ }
+
+ if (i & ZT_IOMUX_SIGEVENT) {
+ /* If we get an event, screen out events that we do not act on.
+ * Otherwise, let handle_init_event determine what is needed
+ */
+ res = zt_get_event(mtd->pvt->subs[SUB_REAL].zfd);
+ switch (res) {
+ case ZT_EVENT_RINGEROFF:
+ if(mwi_send_state == MWI_SEND_SA_WAIT) {
+ if (zt_set_hook(mtd->pvt->subs[SUB_REAL].zfd, ZT_RINGOFF) ) {
+ ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno));
+ goto quit;
+ }
+ mwi_send_state = MWI_SEND_PAUSE;
+ gettimeofday(&pause, NULL);
+ }
+ break;
+ case ZT_EVENT_RINGERON:
+ case ZT_EVENT_HOOKCOMPLETE:
+ break;
+ default:
+ /* Got to the default init event handler */
+ if (0 < handle_init_event(mtd->pvt, res)) {
+ /* I've spawned a thread, get out */
+ goto quit;
+ }
+ break;
+ }
+ } else if (i & ZT_IOMUX_READ) {
+ if ((num_read = read(mtd->pvt->subs[SUB_REAL].zfd, mtd->buf, sizeof(mtd->buf))) < 0) {
+ if (errno != ELAST) {
+ ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
+ goto quit;
+ }
+ break;
+ }
+ }
+ /* Perform mwi send action */
+ switch ( mwi_send_state) {
+ case MWI_SEND_SA:
+ /* Send the Ring Pulse Signal Alert */
+ res = ioctl(mtd->pvt->subs[SUB_REAL].zfd, ZT_SETCADENCE, &AS_RP_cadence);
+ if (res) {
+ ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence\n");
+ goto quit;
+ }
+ zt_set_hook(mtd->pvt->subs[SUB_REAL].zfd, ZT_RING);
+ mwi_send_state = MWI_SEND_SA_WAIT;
+ break;
+ case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */
+ break;
+ case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/
+ gettimeofday(&now, NULL);
+ if ((int)(now.tv_sec - pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pause.tv_usec > 500000) {
+ mwi_send_state = MWI_SEND_SPILL;
+ }
+ break;
+ case MWI_SEND_SPILL:
+ /* We read some number of bytes. Write an equal amount of data */
+ if(0 < num_read) {
+ if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos)
+ num_read = mtd->pvt->cidlen - mtd->pvt->cidpos;
+ res = write(mtd->pvt->subs[SUB_REAL].zfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read);
+ if (res > 0) {
+ mtd->pvt->cidpos += res;
+ if (mtd->pvt->cidpos >= mtd->pvt->cidlen) {
+ ast_free(mtd->pvt->cidspill);
+ mtd->pvt->cidspill = NULL;
+ mtd->pvt->cidpos = 0;
+ mtd->pvt->cidlen = 0;
+ mwi_send_state = MWI_SEND_CLEANUP;
+ }
+ } else {
+ ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno));
+ goto quit;
+ }
+ }
+ case MWI_SEND_CLEANUP:
+ /* For now, do nothing */
+ mwi_send_state = MWI_SEND_DONE;
+ break;
+ default:
+ /* Should not get here, punt*/
+ goto quit;
+ break;
+ }
+ }
+quit:
+ if(mtd->pvt->cidspill) {
+ ast_free(mtd->pvt->cidspill);
+ mtd->pvt->cidspill = NULL;
+ }
+ mtd->pvt->mwisendactive = 0;
+ ast_free(mtd);
+
+ return NULL;
+}
+
+
/* destroy a Zaptel channel, identified by its number */
static int zap_destroy_channel_bynum(int channel)
{
@@ -7459,9 +7630,11 @@
return RESULT_FAILURE;
}
+/* returns < 0 = error, 0 event handled, >0 event handled and thread spawned */
static int handle_init_event(struct zt_pvt *i, int event)
{
int res;
+ int thread_spawned = 0;
pthread_t threadid;
struct ast_channel *chan;
@@ -7515,6 +7688,8 @@
if (res < 0)
ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
ast_hangup(chan);
+ } else {
+ thread_spawned = 1;
}
} else
ast_log(LOG_WARNING, "Unable to create channel\n");
@@ -7546,14 +7721,17 @@
} else {
chan = zt_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
}
- if (chan && ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
+
+ if (!chan) {
+ ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
+ } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
if (res < 0)
ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
ast_hangup(chan);
- } else if (!chan) {
- ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
+ } else {
+ thread_spawned = 1;
}
break;
default:
@@ -7650,8 +7828,12 @@
"CID detection on channel %d\n",
i->channel);
chan = zt_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
- if (chan && ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
+ if (!chan) {
+ ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
+ } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
+ } else {
+ thread_spawned = 1;
}
}
break;
@@ -7682,7 +7864,7 @@
break;
#endif
}
- return 0;
+ return thread_spawned;
}
static void *do_monitor(void *data)
@@ -7727,7 +7909,7 @@
i = iflist;
while (i) {
if ((i->subs[SUB_REAL].zfd > -1) && i->sig && (!i->radio)) {
- if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive) {
+ if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) {
/* This needs to be watched, as it lacks an owner */
pfds[count].fd = i->subs[SUB_REAL].zfd;
pfds[count].events = POLLPRI;
@@ -7767,29 +7949,33 @@
if (!found && ((i == last) || ((i == iflist) && !last))) {
last = i;
if (last) {
- if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
- (last->sig & __ZT_SIG_FXO)) {
+ if (!last->mwisendactive && last->sig & __ZT_SIG_FXO) {
res = has_voicemail(last);
if (last->msgstate != res) {
- int x;
- ast_debug(1, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
+
+ /* This channel has a new voicemail state,
+ * initiate a thread to send an MWI message
+ */
+ pthread_attr_t attr;
+ pthread_t threadid;
+ struct mwi_thread_data *mtd;
#ifdef ZT_VMWI
res2 = ioctl(last->subs[SUB_REAL].zfd, ZT_VMWI, res);
- if (res2)
+ if (res2) {
ast_log(LOG_DEBUG, "Unable to control message waiting led on channel %d\n", last->channel);
-#endif
- x = ZT_FLUSH_BOTH;
- res2 = ioctl(last->subs[SUB_REAL].zfd, ZT_FLUSH, &x);
- if (res2)
- ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", last->channel);
- if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
- /* Turn on on hook transfer for 4 seconds */
- x = 4000;
- ioctl(last->subs[SUB_REAL].zfd, ZT_ONHOOKTRANSFER, &x);
- last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
- last->cidpos = 0;
+ }
+#endif
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
last->msgstate = res;
- last->onhooktime = thispass;
+ mtd->pvt = last;
+ last->mwisendactive = 1;
+ if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) {
+ ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel);
+ ast_free(mtd);
+ last->mwisendactive = 0;
+ }
}
found ++;
}
@@ -7850,23 +8036,6 @@
}
i->mwimonitoractive = 1;
}
- }
- } else if (i->cidspill) {
- /* We read some number of bytes. Write an equal amount of data */
- if (res > i->cidlen - i->cidpos)
- res = i->cidlen - i->cidpos;
- res2 = write(i->subs[SUB_REAL].zfd, i->cidspill + i->cidpos, res);
- if (res2 > 0) {
- i->cidpos += res2;
- if (i->cidpos >= i->cidlen) {
- free(i->cidspill);
- i->cidspill = 0;
- i->cidpos = 0;
- i->cidlen = 0;
- }
- } else {
- ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
- i->msgstate = -1;
}
}
} else {
@@ -13596,7 +13765,13 @@
confp->chan.sendcalleridafter = atoi(v->value);
} else if (!strcasecmp(v->name, "mwimonitornotify")) {
ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
- } else if (!reload){
+ } else if (!strcasecmp(v->name, "mwisendtype")) {
+ if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
+ mwisend_rpas = 1;
+ } else {
+ mwisend_rpas = 0;
+ }
+ } else if (!reload){
if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
int orig_radio = confp->chan.radio;
int orig_outsigmod = confp->chan.outsigmod;
Modified: team/dbailey/mwi_rpas/include/asterisk/callerid.h
URL: http://svn.digium.com/view/asterisk/team/dbailey/mwi_rpas/include/asterisk/callerid.h?view=diff&rev=117771&r1=117770&r2=117771
==============================================================================
--- team/dbailey/mwi_rpas/include/asterisk/callerid.h (original)
+++ team/dbailey/mwi_rpas/include/asterisk/callerid.h Thu May 22 09:16:33 2008
@@ -64,6 +64,13 @@
#define CID_START_POLARITY 2
#define CID_START_POLARITY_IN 3
+/* defines dealing with message waiting indication generation */
+/*! MWI SDMF format */
+#define CID_MWI_TYPE_SDMF 0x00
+/*! MWI MDMF format -- generate only MWI field */
+#define CID_MWI_TYPE_MDMF 0x01
+/*! MWI MDMF format -- generate name, callerid, date and MWI fields */
+#define CID_MWI_TYPE_MDMF_FULL 0x02
#define AST_LIN2X(a) ((codec == AST_FORMAT_ALAW) ? (AST_LIN2A(a)) : (AST_LIN2MU(a)))
#define AST_XLAW(a) ((codec == AST_FORMAT_ALAW) ? (AST_ALAW(a)) : (AST_MULAW(a)))
@@ -162,8 +169,14 @@
*/
int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int codec);
-/*! \brief Generate message waiting indicator (stutter tone) */
-int vmwi_generate(unsigned char *buf, int active, int mdmf, int codec);
+/*! \brief Generate message waiting indicator
+ * \param active The message indicator state
+ * -- either 0 no messages in mailbox or 1 messages in mailbox
+ * \param type Format of message (any of CID_MWI_TYPE_*)
+ * \see callerid_generate() for more info as it use the same encoding
+*/
+int vmwi_generate(unsigned char *buf, int active, int type, int codec, const char *name,
+ const char *number, int flags);
/*! \brief Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm)
* See ast_callerid_generate() for other details
Modified: team/dbailey/mwi_rpas/main/callerid.c
URL: http://svn.digium.com/view/asterisk/team/dbailey/mwi_rpas/main/callerid.c?view=diff&rev=117771&r1=117770&r2=117771
==============================================================================
--- team/dbailey/mwi_rpas/main/callerid.c (original)
+++ team/dbailey/mwi_rpas/main/callerid.c Thu May 22 09:16:33 2008
@@ -769,9 +769,10 @@
}
-int vmwi_generate(unsigned char *buf, int active, int mdmf, int codec)
-{
- unsigned char msg[256];
+int vmwi_generate(unsigned char *buf, int active, int type, int codec,
+ const char* name, const char* number, int flags)
+{
+ char msg[256];
int len = 0;
int sum;
int x;
@@ -779,14 +780,38 @@
float cr = 1.0;
float ci = 0.0;
float scont = 0.0;
-
- if (mdmf) {
- /* MDMF Message waiting */
+
+ if (type == CID_MWI_TYPE_MDMF_FULL) {
+ /* MDMF Message waiting with date, number, name and MWI parameter */
+ msg[0] = 0x82;
+
+ /* put date, number info at the right place */
+ len = callerid_genmsg(msg+2, sizeof(msg)-2, number, name, flags);
+
+ /* length of MDMF CLI plus Message Waiting Structure */
+ msg[1] = len+3;
+
+ /* Go to the position to write to */
+ len = len+2;
+
+ /* "Message Waiting Parameter" */
+ msg[len++] = 0x0b;
+ /* Length of IE is one */
+ msg[len++] = 1;
+ /* Active or not */
+ if (active)
+ msg[len++] = 0xff;
+ else
+ msg[len++] = 0x00;
+
+ } else if (type == CID_MWI_TYPE_MDMF) {
+ /* MDMF Message waiting only */
+ /* same as above except that the we only put MWI parameter */
msg[len++] = 0x82;
/* Length is 3 */
msg[len++] = 3;
/* IE is "Message Waiting Parameter" */
- msg[len++] = 0xb;
+ msg[len++] = 0x0b;
/* Length of IE is one */
msg[len++] = 1;
/* Active or not */
More information about the asterisk-commits
mailing list