Index: channels/chan_zap.c =================================================================== --- channels/chan_zap.c (revision 40883) +++ channels/chan_zap.c (working copy) @@ -210,8 +210,8 @@ static int transfertobusy = 1; static int use_callerid = 1; -static int cid_signalling = CID_SIG_BELL; -static int cid_start = CID_START_RING; +static int cid_signalling = 0; /*!< Initial value to zero since multiple choices can be made. */ +static int cid_start = 0; /*!< Initial value to zero since multiple choices can be made. */ static int zaptrcallerid = 0; static int cur_signalling = -1; @@ -631,8 +631,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 */ @@ -1575,9 +1575,12 @@ static inline int zt_set_hook(int fd, int hs) { - int x, res; - x = hs; - res = ioctl(fd, ZT_HOOK, &x); + int res; + ZT_HOOK_DATA hook_data; + hook_data.x = hs; + hook_data.polarity = 0; + *hook_data.dtmfCidData=0; + res = ioctl(fd, ZT_HOOK, &hook_data); if (res < 0) { if (errno == EINPROGRESS) return 0; @@ -1745,6 +1748,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)); @@ -1782,22 +1790,79 @@ /* 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) { - /* Generate the Caller-ID spill if desired */ - if (p->cidspill) { - ast_log(LOG_WARNING, "cidspill already exists??\n"); - free(p->cidspill); + if ((p->cid_start & CID_START_POLARITY) != 0) { + ast_log(LOG_DEBUG, "Do Polarity CID start\n"); + hook_data.polarity=1; } - 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; - send_callerid(p); - } else - ast_log(LOG_WARNING, "Unable to generate CallerID spill\n"); + + /* + * 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"); + } + } + + 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"); + free(p->cidspill); + } + 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; + send_callerid(p); + } else + ast_log(LOG_WARNING, "Unable to generate CallerID spill\n"); + } } + /* Choose proper cadence */ if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { if (ioctl(p->subs[SUB_REAL].zfd, ZT_SETCADENCE, &cadences[p->distinctivering-1])) @@ -1809,7 +1874,6 @@ p->cidrings = p->sendcalleridafter; } - /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ c = strchr(dest, '/'); if (c) @@ -1825,8 +1889,9 @@ } else { p->dop.dialstr[0] = '\0'; } - x = ZT_RING; - if (ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x) && (errno != EINPROGRESS)) { + + hook_data.x = ZT_RING; + if (ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &hook_data) && (errno != EINPROGRESS)) { ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); ast_mutex_unlock(&p->lock); return -1; @@ -1899,8 +1964,10 @@ /* Start the trunk, if not GR-303 */ if (!p->pri) { #endif - x = ZT_START; - res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x); + hook_data.x = ZT_START; + *hook_data.dtmfCidData=0; + + res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &hook_data); if (res < 0) { if (errno != EINPROGRESS) { ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); @@ -1976,8 +2043,9 @@ p->echobreak = 0; if (!res) { if (ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &p->dop)) { - x = ZT_ONHOOK; - ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x); + hook_data.x = ZT_ONHOOK; + *hook_data.dtmfCidData=0; + ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &hook_data); ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(errno)); ast_mutex_unlock(&p->lock); return -1; @@ -3297,15 +3365,16 @@ static int zt_ring_phone(struct zt_pvt *p) { - int x; int res; + ZT_HOOK_DATA hook_data; /* Make sure our transmit state is on hook */ - x = 0; - x = ZT_ONHOOK; - res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x); + hook_data.x = ZT_ONHOOK; + *hook_data.dtmfCidData=0; + res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &hook_data); do { - x = ZT_RING; - res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x); + hook_data.x = ZT_RING; + *hook_data.dtmfCidData=0; + res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &hook_data); if (res) { switch(errno) { case EBUSY: @@ -3509,13 +3578,15 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast) { - int res,x; + int x; + int res; int index; char *c; struct zt_pvt *p = ast->tech_pvt; pthread_t threadid; pthread_attr_t attr; struct ast_channel *chan; + ZT_HOOK_DATA hook_data; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); @@ -3801,8 +3872,9 @@ } else p->echobreak = 0; if (ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &p->dop)) { - x = ZT_ONHOOK; - ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x); + hook_data.x = ZT_ONHOOK; + *hook_data.dtmfCidData=0; + ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &hook_data); ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(errno)); return NULL; } @@ -4812,6 +4884,8 @@ int res=-1; int index; int func = ZT_FLASH; + ZT_HOOK_DATA hook_data; + ast_mutex_lock(&p->lock); index = zt_get_index(chan, p, 0); ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name); @@ -4954,7 +5028,9 @@ if (ISTRUNK(p) && (p->sig != SIG_PRI)) { /* Clear out the dial buffer */ p->dop.dialstr[0] = '\0'; - if ((ioctl(p->subs[SUB_REAL].zfd,ZT_HOOK,&func) == -1) && (errno != EINPROGRESS)) { + hook_data.x = func; + *hook_data.dtmfCidData=0; + if ((ioctl(p->subs[SUB_REAL].zfd,ZT_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 @@ -5229,6 +5305,8 @@ int len = 0; int res; int index; + ZT_HOOK_DATA hook_data; + if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name); index = zt_get_index(chan, p, 1); @@ -5753,6 +5831,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].zfd,ZT_HOOK,&func) == -1) && (errno != EINPROGRESS)) { ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", nbridge->name, strerror(errno)); @@ -5823,9 +5903,9 @@ /* If we want caller id, we're in a prering state due to a polarity reversal * and we're set to use a polarity reversal to trigger the start of caller id, * grab the caller id and wait for ringing to start... */ - if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) { + if (p->use_callerid && (chan->_state == AST_STATE_PRERING && ((p->cid_start & CID_START_POLARITY) != 0))) { /* 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 i = 0; cs = NULL; ast_log(LOG_DEBUG, "Receiving DTMF cid on " @@ -5865,7 +5945,7 @@ else number = 0; /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ - } else if (p->cid_signalling == CID_SIG_V23) { + } else if ((p->cid_signalling & CID_SIG_V23) != 0) { cs = callerid_new(p->cid_signalling); if (cs) { samples = 0; @@ -6036,7 +6116,7 @@ ast_hangup(chan); return NULL; } - } else if (p->use_callerid && p->cid_start == CID_START_RING) { + } else if (p->use_callerid && ((p->cid_start & CID_START_RING) != 0)) { /* FSK Bell202 callerID */ cs = callerid_new(p->cid_signalling); if (cs) { @@ -6410,7 +6490,7 @@ case SIG_FXSLS: case SIG_FXSKS: case SIG_FXSGS: - if (i->cid_start == CID_START_POLARITY) { + if ((i->cid_start & CID_START_POLARITY) != 0) { i->polarity = POLARITY_REV; ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity " "CID detection on channel %d\n", @@ -8040,6 +8120,7 @@ char plancallingnum[256]; char plancallingani[256]; char calledtonstr[10]; + ZT_HOOK_DATA hook_data; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); @@ -8765,8 +8846,9 @@ } if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) { ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n"); - x = ZT_START; - res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_HOOK, &x); + hook_data.x = ZT_START; + *hook_data.dtmfCidData=0; + res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_HOOK, &hook_data); if (res < 0) { if (errno != EINPROGRESS) { ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); @@ -10332,21 +10414,43 @@ } else if (!strcasecmp(v->name, "usecallerid")) { use_callerid = ast_true(v->value); } else if (!strcasecmp(v->name, "cidsignalling")) { - if (!strcasecmp(v->value, "bell")) - cid_signalling = CID_SIG_BELL; - else if (!strcasecmp(v->value, "v23")) - cid_signalling = CID_SIG_V23; - else if (!strcasecmp(v->value, "dtmf")) - cid_signalling = CID_SIG_DTMF; - else if (ast_true(v->value)) - cid_signalling = CID_SIG_BELL; + char *p=v->value; + 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")) + cid_signalling |= CID_SIG_BELL; + else if (!strcasecmp(p1, "v23")) + cid_signalling = (cid_signalling & ~CID_SIG_BELL) | CID_SIG_V23; + else if (!strcasecmp(p1, "dtmf")) + cid_signalling |= CID_SIG_DTMF; + else if (!strcasecmp(p1, "dtmf_astart")) + cid_signalling = (cid_signalling & ~CID_SIG_DTMF) | CID_SIG_DTMF_ASTART; + else if (!strcasecmp(p1, "dtmf_dk")) /* Denmark specific. */ + cid_signalling = (cid_signalling & ~CID_SIG_DTMF) | CID_SIG_DTMF_DK | CID_SIG_DTMF_ASTART; + } + ast_log(LOG_DEBUG, "cid_signalling=%d\n", cid_signalling); } else if (!strcasecmp(v->name, "cidstart")) { - if (!strcasecmp(v->value, "ring")) - cid_start = CID_START_RING; - else if (!strcasecmp(v->value, "polarity")) - cid_start = CID_START_POLARITY; - else if (ast_true(v->value)) - cid_start = CID_START_RING; + char *p=v->value; + 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")) + cid_start |= CID_START_RING; + else if (!strcasecmp(p1, "polarity")) + cid_start |= CID_START_POLARITY; + } + ast_log(LOG_DEBUG, "cid_start=%d\n", cid_start); } else if (!strcasecmp(v->name, "threewaycalling")) { threewaycalling = ast_true(v->value); } else if (!strcasecmp(v->name, "cancallforward")) { Index: apps/app_flash.c =================================================================== --- apps/app_flash.c (revision 40883) +++ apps/app_flash.c (working copy) @@ -79,14 +79,17 @@ int x; struct localuser *u; struct zt_params ztp; + ZT_HOOK_DATA hook_data; + LOCAL_USER_ADD(u); if (!strcasecmp(chan->type, "Zap")) { memset(&ztp, 0, sizeof(ztp)); res = ioctl(chan->fds[0], ZT_GET_PARAMS, &ztp); if (!res) { if (ztp.sigtype & __ZT_SIG_FXS) { - x = ZT_FLASH; - res = ioctl(chan->fds[0], ZT_HOOK, &x); + hook_data.x = ZT_FLASH; + *hook_data.dtmfCidData=0; + res = ioctl(chan->fds[0], ZT_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 40883) +++ include/asterisk/callerid.h (working copy) @@ -38,12 +38,22 @@ #define CID_UNKNOWN_NAME (1 << 2) #define CID_UNKNOWN_NUMBER (1 << 3) -#define CID_SIG_BELL 1 -#define CID_SIG_V23 2 -#define CID_SIG_DTMF 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_DTMF_ASTART 0x08 +#define CID_SIG_DTMF_DK 0x10 /* Special case for the DTMF sequences used in Denmark. */ -#define CID_START_RING 1 -#define CID_START_POLARITY 2 +/* + * In order to be able to handle both types a bitmap is used. + */ +#define CID_START_RING 0x01 +#define CID_START_POLARITY 0x02 #define AST_LIN2X(a) ((codec == AST_FORMAT_ALAW) ? (AST_LIN2A(a)) : (AST_LIN2MU(a))) Index: configs/zapata.conf.sample =================================================================== --- configs/zapata.conf.sample (revision 40883) +++ configs/zapata.conf.sample (working copy) @@ -219,17 +219,44 @@ usecallerid=yes ; ; Type of caller ID signalling in use -; bell = bell202 as used in US -; v23 = v23 as used in the UK -; dtmf = DTMF as used in Denmark, Sweden and Netherlands +; 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. ; -;cidsignalling=bell +; bell = bell202 as used in US +; v23 = v23 as used in the UK +; dtmf = DTMF 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'. +; dtmf_dk = DTMF as used in Denmark. ; +cidsignalling=bell +;cidsignalling=dtmf_dk +;cidsignalling=bell,dtmf +; ; What signals the start of caller ID +; 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 +; Used in Sweden, Finland and Netherlands. ; -;cidstart=ring +cidstart=ring +;cidstart=polarity +;cidstart=ring,polarity ; ; Whether or not to hide outgoing caller ID (Override with *67 or *82) ;