Index: channels/chan_dahdi.c =================================================================== --- channels/chan_dahdi.c (revision 206080) +++ channels/chan_dahdi.c (working copy) @@ -901,8 +901,8 @@ int channel; /*!< Channel Number or CRV */ int span; /*!< Span number */ time_t guardtime; /*!< Must wait this much time before using for new call */ - int cid_signalling; /*!< CID signalling type bell202 or v23 */ - int cid_start; /*!< CID start indicator, polarity or ring */ + int cid_signalling; /*!< CID signalling type (bell202 or v23) and/or (dtmf or dtmf_astart or dtmf_dk) */ + int cid_start; /*!< CID start indicator, polarity and/or ring */ int callingpres; /*!< The value of callling presentation that we're going to use when placing a PRI call */ int callwaitingrepeat; /*!< How many samples to wait before repeating call waiting */ int cidcwexpire; /*!< When to expire our muting for CID/CW */ @@ -1133,8 +1133,8 @@ .parkinglot = "", .transfertobusy = 1, - .cid_signalling = CID_SIG_BELL, - .cid_start = CID_START_RING, + .cid_signalling = 0, /* CID_SIG_BELL Changed default value to NO Caller ID set. This is done to enable possibility for multiple Caller id's on each FXS line */ + .cid_start = 0, /* Changed from CID_START_RING to no value set. THis to enable possibility for multiple settings. */ .dahditrcallerid = 0, .use_callerid = 1, .sig = -1, @@ -2206,11 +2206,13 @@ static inline int dahdi_set_hook(int fd, int hs) { - int x, res; + int res; + ZT_HOOK_DATA hook_data; + hook_data.x = hs; + hook_data.polarity = 0; + *hook_data.dtmfCidData=0; + res = ioctl(fd, DAHDI_HOOK, &hook_data); - x = hs; - res = ioctl(fd, DAHDI_HOOK, &x); - if (res < 0) { if (errno == EINPROGRESS) return 0; @@ -2449,6 +2451,11 @@ char *s = NULL; #endif char dest[256]; /* must be same length as p->dialdest */ + ZT_HOOK_DATA hook_data; + + /* Make sure that the polarity switch is disabled and the caller-ID string is empty first. */ + hook_data.polarity=0; + *hook_data.dtmfCidData=0; ast_mutex_lock(&p->lock); ast_copy_string(dest, rdest, sizeof(dest)); ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); @@ -2490,18 +2497,78 @@ /* Normal ring, on hook */ /* Don't send audio while on hook, until the call is answered */ + /* Above statement not entirely true - caller-ID is actually sent while on-hook. */ p->dialing = 1; if (p->use_callerid) { + if ((p->cid_start & CID_START_POLARITY) != 0) { + ast_log(LOG_DEBUG, "Do Polarity CID start\n"); + hook_data.polarity=1; + } + + /* + * Compose a DTMF caller-ID. + * + * Some devices requires a DTMF 'D' to start the caller-ID, + * while other devices requires an 'A'. + * + * Most countries using the DTMF signalling are ending with + * a DTMF 'C' but Denmark is using a DTMF '#'. + * + * Notice that Denmark actually doesn't require a polarity + * switch before transmitting the caller-ID, and sending one + * may cause the equipment to go blind. + * (this is why this code is 'standalone' outside the 'cid_start' + * checks.) + * TODO: This has to be tested by somebody that has access to + * a broad range of Danish equipment. + */ + if ((((p->cid_signalling & CID_SIG_DTMF) != 0) + || ((p->cid_signalling & CID_SIG_DTMF_ASTART) != 0))) { + + char startChar='A'; + char endChar='C'; + + if ((p->cid_signalling & CID_SIG_DTMF) != 0) + startChar='D'; + + if ((p->cid_signalling & CID_SIG_DTMF_DK) != 0) + endChar='#'; + + if (ast->cid.cid_num) { + snprintf(hook_data.dtmfCidData, sizeof(hook_data.dtmfCidData), "Tw%c%s%cw", startChar, ast->cid.cid_num, endChar); + ast_log(LOG_DEBUG, "Caller-ID Signalling is DTMF %c-start, string='%s'.\n", startChar, hook_data.dtmfCidData); + } else { + ast_log(LOG_DEBUG, "No Caller-ID available - send info code to device.\n"); + /* + * Note that Denmark uses a different code for missing number. + * Code "D3# means that there is technical reason for not + * providing the number. + * Code "B00C" means that the number is unavailable. + */ + if ((p->cid_signalling & CID_SIG_DTMF_DK) != 0) + snprintf(hook_data.dtmfCidData, sizeof(hook_data.dtmfCidData), "TwD3#w"); + else + snprintf(hook_data.dtmfCidData, sizeof(hook_data.dtmfCidData), "TwB00Cw"); + } + } + ast_log(LOG_DEBUG, "Before CID_START_RING\n"); + + if ((p->cid_start & CID_START_RING) != 0) { + ast_log(LOG_DEBUG, "Do Ring CID start\n"); /* Generate the Caller-ID spill if desired */ if (p->cidspill) { - ast_log(LOG_WARNING, "cidspill already exists??\n"); + ast_log(LOG_DEBUG, "cidspill already exists??\n"); ast_free(p->cidspill); } - p->callwaitcas = 0; - if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { + p->cidspill = malloc(MAX_CALLERID_SIZE); + p->callwaitcas = 0; + if (p->cidspill) { p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); p->cidpos = 0; + ast_log(LOG_DEBUG, "Sending callerid1 %s\n",ast->cid.cid_name); send_callerid(p); + } else + ast_log(LOG_WARNING, "Unable to generate CallerID spill\n"); } } /* Choose proper cadence */ @@ -2530,8 +2597,9 @@ } else { p->dop.dialstr[0] = '\0'; } - x = DAHDI_RING; - if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { + ast_log(LOG_DEBUG, "Sending callerid2 %s\n",ast->cid.cid_name); + hook_data.x = DAHDI_RING; + if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &hook_data) && (errno != EINPROGRESS)) { ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); ast_mutex_unlock(&p->lock); return -1; @@ -2606,8 +2674,10 @@ /* Start the trunk, if not GR-303 */ if (!p->pri) { #endif - x = DAHDI_START; - res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); + + hook_data.x = DAHDI_START; + *hook_data.dtmfCidData=0; + res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &hook_data); if (res < 0) { if (errno != EINPROGRESS) { ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); @@ -2689,8 +2759,9 @@ if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { int saveerr = errno; - x = DAHDI_ONHOOK; - ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); + hook_data.x = DAHDI_ONHOOK; + *hook_data.dtmfCidData=0; + ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &hook_data); ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); ast_mutex_unlock(&p->lock); return -1; @@ -4454,15 +4525,16 @@ static int dahdi_ring_phone(struct dahdi_pvt *p) { - int x; int res; + ZT_HOOK_DATA hook_data; /* Make sure our transmit state is on hook */ - x = 0; - x = DAHDI_ONHOOK; - res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); + hook_data.x = DAHDI_ONHOOK; + *hook_data.dtmfCidData=0; + res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &hook_data); do { - x = DAHDI_RING; - res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); + hook_data.x = DAHDI_RING; + *hook_data.dtmfCidData=0; + res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &hook_data); if (res) { switch (errno) { case EBUSY: @@ -4677,6 +4749,7 @@ pthread_t threadid; struct ast_channel *chan; struct ast_frame *f; + ZT_HOOK_DATA hook_data; idx = dahdi_get_index(ast, p, 0); mysig = p->sig; @@ -4990,8 +5063,9 @@ if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { int saveerr = errno; - x = DAHDI_ONHOOK; - ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); + hook_data.x = DAHDI_ONHOOK; + *hook_data.dtmfCidData=0; + ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &hook_data); ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); return NULL; } @@ -6030,6 +6104,7 @@ int res=-1; int idx; int func = DAHDI_FLASH; + ZT_HOOK_DATA hook_data; ast_mutex_lock(&p->lock); idx = dahdi_get_index(chan, p, 0); ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name); @@ -6230,7 +6305,9 @@ if (ISTRUNK(p) && (p->sig != SIG_PRI)) { /* Clear out the dial buffer */ p->dop.dialstr[0] = '\0'; - if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { + hook_data.x = func; + *hook_data.dtmfCidData=0; + if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&hook_data) == -1) && (errno != EINPROGRESS)) { ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", chan->name, strerror(errno)); } else @@ -6528,6 +6605,7 @@ int len = 0; int res; int idx; + ZT_HOOK_DATA hook_data; ast_mutex_lock(&ss_thread_lock); ss_thread_count++; @@ -7062,6 +7140,7 @@ len = 0; } } else if (p->hidecallerid && !strcmp(exten, "*82")) { + if (option_verbose > 2) ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); /* Enable Caller*ID if enabled */ p->hidecallerid = 0; @@ -7095,6 +7174,8 @@ /* Clear out the dial buffer */ p->dop.dialstr[0] = '\0'; /* flash hookswitch */ + hook_data.x = func; + *hook_data.dtmfCidData=0; if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", nbridge->name, strerror(errno)); @@ -7187,7 +7268,7 @@ * grab the caller id and wait for ringing to start... */ } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) { /* If set to use DTMF CID signalling, listen for DTMF */ - if (p->cid_signalling == CID_SIG_DTMF) { + if ((p->cid_signalling & CID_SIG_DTMF) != 0) { int k = 0; cs = NULL; ast_debug(1, "Receiving DTMF cid on " @@ -7229,7 +7310,7 @@ else number = NULL; /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ - } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { + } else if (((p->cid_signalling & CID_SIG_V23) || (p->cid_signalling & CID_SIG_V23_JP))!=0) { cs = callerid_new(p->cid_signalling); if (cs) { samples = 0; @@ -7429,7 +7510,7 @@ ast_hangup(chan); goto quit; } - } else if (p->use_callerid && p->cid_start == CID_START_RING) { + } else if (p->use_callerid && ((p->cid_start & CID_START_RING) != 0)) { if (p->cid_signalling == CID_SIG_DTMF) { int k = 0; cs = NULL; @@ -10856,7 +10937,7 @@ char plancallingnum[256]; char plancallingani[256]; char calledtonstr[10]; - + ZT_HOOK_DATA hook_data; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); gettimeofday(&lastidle, NULL); @@ -11621,8 +11702,9 @@ } if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) { ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n"); - x = DAHDI_START; - res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); + hook_data.x = DAHDI_START; + *hook_data.dtmfCidData=0; + res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &hook_data); if (res < 0) { if (errno != EINPROGRESS) { ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); @@ -14261,27 +14343,52 @@ } else if (!strcasecmp(v->name, "usecallerid")) { confp->chan.use_callerid = ast_true(v->value); } else if (!strcasecmp(v->name, "cidsignalling")) { - if (!strcasecmp(v->value, "bell")) - confp->chan.cid_signalling = CID_SIG_BELL; - else if (!strcasecmp(v->value, "v23")) - confp->chan.cid_signalling = CID_SIG_V23; - else if (!strcasecmp(v->value, "dtmf")) - confp->chan.cid_signalling = CID_SIG_DTMF; - else if (!strcasecmp(v->value, "smdi")) - confp->chan.cid_signalling = CID_SIG_SMDI; - else if (!strcasecmp(v->value, "v23_jp")) - confp->chan.cid_signalling = CID_SIG_V23_JP; - else if (ast_true(v->value)) - confp->chan.cid_signalling = CID_SIG_BELL; + char *p=(char *)v->value; + confp->chan.cid_signalling = 0; + /* + * Set the caller-ID signalling for the channel. + * Multiple selections are possible separated with a comma (','). + */ + while(p != NULL) { + char *p1=strsep(&p, ","); + if (!strcasecmp(p1, "bell")) + confp->chan.cid_signalling |= CID_SIG_BELL; + else if (!strcasecmp(p1, "v23")) + confp->chan.cid_signalling = (confp->chan.cid_signalling & ~CID_SIG_BELL) | CID_SIG_V23; + else if (!strcasecmp(p1, "dtmf")) + confp->chan.cid_signalling |= CID_SIG_DTMF; + else if (!strcasecmp(p1,"dtmf_astart")) + confp->chan.cid_signalling = (confp->chan.cid_signalling & ~CID_SIG_DTMF) | CID_SIG_DTMF_ASTART; + else if (!strcasecmp(p1,"dtmf_dk")) + confp->chan.cid_signalling = (confp->chan.cid_signalling & ~CID_SIG_DTMF) | CID_SIG_DTMF_DK | CID_SIG_DTMF_ASTART; + else if (!strcasecmp(p1, "smdi")) + confp->chan.cid_signalling = (confp->chan.cid_signalling & ~CID_SIG_BELL) | CID_SIG_SMDI; + else if (!strcasecmp(p1, "v23_jp")) + confp->chan.cid_signalling = (confp->chan.cid_signalling & ~CID_SIG_BELL) | CID_SIG_V23_JP; + else if (ast_true(v->value)) + confp->chan.cid_signalling = CID_SIG_BELL; + } + ast_log(LOG_DEBUG, "cid_signalling=%d\n", confp->chan.cid_signalling); } else if (!strcasecmp(v->name, "cidstart")) { - if (!strcasecmp(v->value, "ring")) - confp->chan.cid_start = CID_START_RING; - else if (!strcasecmp(v->value, "polarity_in")) - confp->chan.cid_start = CID_START_POLARITY_IN; - else if (!strcasecmp(v->value, "polarity")) - confp->chan.cid_start = CID_START_POLARITY; - else if (ast_true(v->value)) - confp->chan.cid_start = CID_START_RING; + char *p=(char *)v->value; + confp->chan.cid_start = 0; + /* + * Set the caller-ID start indication for the channel. + * Multiple selections are possible separated with a comma (','). + */ + while(p != NULL) { + char *p1=strsep(&p, ","); + + if (!strcasecmp(p1, "ring")) + confp->chan.cid_start |= CID_START_RING; + else if (!strcasecmp(p1, "polarity")) + confp->chan.cid_start |= CID_START_POLARITY_IN; + else if (!strcasecmp(p1, "polarity")) + confp->chan.cid_start |= CID_START_POLARITY; + else if (ast_true(v->value)) + confp->chan.cid_start = CID_START_RING; + } + ast_log(LOG_DEBUG, "cid_start=%d\n", confp->chan.cid_start); } else if (!strcasecmp(v->name, "threewaycalling")) { confp->chan.threewaycalling = ast_true(v->value); } else if (!strcasecmp(v->name, "cancallforward")) { Index: apps/app_flash.c =================================================================== --- apps/app_flash.c (revision 206080) +++ apps/app_flash.c (working copy) @@ -69,6 +69,7 @@ int res = -1; int x; struct dahdi_params dahdip; + ZT_HOOK_DATA hook_data; if (strcasecmp(chan->tech->type, "DAHDI")) { ast_log(LOG_WARNING, "%s is not a DAHDI channel\n", chan->name); @@ -80,7 +81,9 @@ if (!res) { if (dahdip.sigtype & __DAHDI_SIG_FXS) { x = DAHDI_FLASH; - res = ioctl(chan->fds[0], DAHDI_HOOK, &x); + hook_data.x = DAHDI_FLASH; + *hook_data.dtmfCidData=0; + res = ioctl(chan->fds[0], DAHDI_HOOK, &hook_data); if (!res || (errno == EINPROGRESS)) { if (res) { /* Wait for the event to finish */ Index: include/asterisk/callerid.h =================================================================== --- include/asterisk/callerid.h (revision 206080) +++ include/asterisk/callerid.h (working copy) @@ -54,16 +54,24 @@ #define CID_MSGWAITING (1 << 4) #define CID_NOMSGWAITING (1 << 5) -#define CID_SIG_BELL 1 -#define CID_SIG_V23 2 -#define CID_SIG_DTMF 3 -#define CID_SIG_V23_JP 4 -#define CID_SIG_SMDI 5 -#define CID_START_RING 1 -#define CID_START_POLARITY 2 -#define CID_START_POLARITY_IN 3 +/* + * Since one type of caller-ID doesn't exclude the other type a bitmap + * is used to allow for combinations. + * Any conflicting combinations should be handled in code. + */ +#define CID_SIG_BELL 0x01 +#define CID_SIG_V23 0x02 +#define CID_SIG_DTMF 0x04 +#define CID_SIG_V23_JP 0x08 +#define CID_SIG_SMDI 0x10 +#define CID_SIG_DTMF_ASTART 0x20 +#define CID_SIG_DTMF_DK 0x40 +#define CID_START_RING 0x01 +#define CID_START_POLARITY 0x02 +#define CID_START_POLARITY_IN 0x04 + /* defines dealing with message waiting indication generation */ /*! MWI SDMF format */ #define CID_MWI_TYPE_SDMF 0x00 Index: configs/chan_dahdi.conf.sample =================================================================== --- configs/chan_dahdi.conf.sample (revision 206080) +++ configs/chan_dahdi.conf.sample (working copy) @@ -328,22 +328,43 @@ ; Hide the name part and leave just the number part of the caller ID ; string. Only applies to PRI channels. ;hidecalleridname=yes -; + ; Type of caller ID signalling in use -; bell = bell202 as used in US (default) -; v23 = v23 as used in the UK -; v23_jp = v23 as used in Japan -; dtmf = DTMF as used in Denmark, Sweden and Netherlands -; smdi = Use SMDI for caller ID. Requires SMDI to be enabled (usesmdi). +; It is possible to combine one of bell or v23 with one +; of dtmf, dtmf_astart or dtmf_dk for FXS devices. +; If multiple choices are made separate them with a comma +; and NO spaces. +; Which one of 'dtmf' or 'dtmf_astart' to use for FXS depends on your +; phone, some listens to both others may be listening to +; 'A' only while others may be listening to 'D' only. +; Type of caller ID signalling in use +; bell = bell202 as used in US (default) +; v23 = v23 as used in the UK +; v23_jp = v23 as used in Japan +; dtmf = DTMF as used in Denmark, Sweden and NetherlandsDTMF as used in Sweden, Finland and Netherlands +; for fxs, caller-ID starts with 'D'. +; dtmf_astart = DTMF as used in Sweden, Finland and Netherlands + dtmf_astart is for use with fxs, and may be +; needed by some devices not listening for +; a caller-ID starting with a DTMF 'D'. +; If your phone doesn't display the caller-ID, +; try alternating between 'dtmf' and 'dtmf_astart'. +; smdi = Use SMDI for caller ID. Requires SMDI to be enabled (usesmdi). +; dtmf_dk = DTMF as used in Denmark. ; ;cidsignalling=v23 ; ; What signals the start of caller ID -; ring = a ring signals the start (default) -; polarity = polarity reversal signals the start -; polarity_IN = polarity reversal signals the start, for India, +; It is possible to select both at the same time for FXS devices. +; If multiple choices are made separate them with a comma +; and NO spaces. +; Notice that the caller-ID in Denmark does not specify +; that the DTMF shall be preceded by a polarity switch. +; +; ring = a ring signals the start +; polarity = polarity reversal signals the start ; for dtmf dialtone detection; using DTMF. -; (see doc/India-CID.txt) +; Used in Sweden, Finland and Netherlands. ; ;cidstart=polarity ;