diff -u before-did/chan_zap.c with-did/chan_zap.c --- before-did/chan_zap.c Sun Dec 10 04:04:18 2006 +++ with-did/chan_zap.c Sat Feb 3 21:30:02 2007 @@ -176,6 +176,7 @@ #define SIG_FXSKS ZT_SIG_FXSKS #define SIG_FXOLS ZT_SIG_FXOLS #define SIG_FXOGS ZT_SIG_FXOGS +#define SIG_FXODS ZT_SIG_FXODS #define SIG_FXOKS ZT_SIG_FXOKS #define SIG_PRI ZT_SIG_CLEAR #define SIG_SF ZT_SIG_SF @@ -297,6 +298,11 @@ static int cur_debounce = -1; static int cur_priexclusive = 0; +static int cur_pulsecountzerofirst = 0; +static int cur_pulsebreaktime = 0; +static int cur_pulsemaketime = 0; +static int cur_pulseaftertime = 0; + static int priindication_oob = 0; #ifdef HAVE_PRI @@ -591,6 +597,7 @@ unsigned int priexclusive:1; unsigned int pulse:1; unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */ + unsigned int decadicdid:1; /*!< when decadic DID is in progress */ unsigned int restrictcid:1; /*!< Whether restrict the callerid -> only send ANI */ unsigned int threewaycalling:1; unsigned int transfer:1; @@ -1221,6 +1228,8 @@ return "FXO Groundstart"; case SIG_FXOKS: return "FXO Kewlstart"; + case SIG_FXODS: + return "FXO Decadicstart"; case SIG_PRI: return "PRI Signalling"; case SIG_SF: @@ -1835,6 +1844,7 @@ case SIG_FXOLS: case SIG_FXOGS: case SIG_FXOKS: + case SIG_FXODS: if (p->owner == ast) { /* Normal ring, on hook */ @@ -1874,11 +1884,18 @@ } if (c) { p->dop.op = ZT_DIAL_OP_REPLACE; - snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); + snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "%s%s", p->pulse ? "P": "Tw", c); ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c); + /* Decadic DID starts here */ + if (p->sig == SIG_FXODS) p->decadicdid = 1; } else { p->dop.dialstr[0] = '\0'; } + + /* Decadic dialing (DID), but only with a number to dial */ + if (c && (p->sig == SIG_FXODS)) + x = ZT_START; + else x = ZT_RING; if (ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x) && (errno != EINPROGRESS)) { ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); @@ -2582,6 +2599,7 @@ p->digital = 0; p->faxhandled = 0; p->pulsedial = 0; + p->decadicdid = 0; p->onhooktime = time(NULL); #ifdef HAVE_PRI p->proceeding = 0; @@ -2661,6 +2679,7 @@ case SIG_FXOGS: case SIG_FXOLS: case SIG_FXOKS: + case SIG_FXODS: res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &par); if (!res) { #if 0 @@ -2792,6 +2811,7 @@ case SIG_FXOLS: case SIG_FXOGS: case SIG_FXOKS: + case SIG_FXODS: /* Pick up the line */ ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name); if (p->hanguponpolarityswitch) { @@ -3790,11 +3810,22 @@ case SIG_FXOLS: case SIG_FXOGS: case SIG_FXOKS: + case SIG_FXODS: p->onhooktime = time(NULL); p->msgstate = -1; /* Check for some special conditions regarding call waiting */ if (index == SUB_REAL) { /* The normal line was hung up */ + + if ((p->sig == SIG_FXODS) && p->decadicdid) { + /* DID accepted number, wait for real off-hook */ + p->decadicdid = 0; + ast_log(LOG_DEBUG, "FXO Decadic DID accepted, channel %d\n", p->channel); + if (p->dialing) { + ast_log(LOG_WARNING, "Still dialing when FXO Decadic DID accepted, channel %d\n", p->channel); + } + break; + } if (p->subs[SUB_CALLWAIT].owner) { /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ swap_subs(p, SUB_CALLWAIT, SUB_REAL); @@ -3943,8 +3974,12 @@ case SIG_FXOLS: case SIG_FXOGS: case SIG_FXOKS: + case SIG_FXODS: switch (ast->_state) { case AST_STATE_RINGING: + if (p->sig == SIG_FXODS && p->decadicdid) { + ast_log(LOG_DEBUG, "FXO Decadic DID ready to dial, channel %d\n", p->channel); + } else { zt_enable_ec(p); zt_train_ec(p); p->subs[index].f.frametype = AST_FRAME_CONTROL; @@ -3952,6 +3987,7 @@ /* Make sure it stops ringing */ zt_set_hook(p->subs[index].zfd, ZT_OFFHOOK); ast_log(LOG_DEBUG, "channel %d answered\n", p->channel); + } if (p->cidspill) { /* Cancel any running CallerID spill */ free(p->cidspill); @@ -3977,7 +4013,10 @@ p->dialing = 1; } p->dop.dialstr[0] = '\0'; - ast_setstate(ast, AST_STATE_DIALING); + if (p->sig == SIG_FXODS && p->decadicdid) { + /* Stay in ringing state until the real answer */ + } + else ast_setstate(ast, AST_STATE_DIALING); } else ast_setstate(ast, AST_STATE_UP); return &p->subs[index].f; @@ -4128,6 +4167,7 @@ case SIG_FXOLS: case SIG_FXOGS: case SIG_FXOKS: + case SIG_FXODS: ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd); p->callwaitcas = 0; @@ -4137,6 +4177,12 @@ goto winkflashdone; } + if ((p->sig == SIG_FXODS) && p->decadicdid) { + ast_log(LOG_DEBUG, "Winkflash ignored during decadic DID channel %d\n", p->channel); + + break; + } + if (p->subs[SUB_CALLWAIT].owner) { /* Swap to call-wait */ swap_subs(p, SUB_REAL, SUB_CALLWAIT); @@ -5284,7 +5330,7 @@ if (state == AST_STATE_RING) tmp->rings = 1; tmp->tech_pvt = i; - if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { + if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS) || (i->sig == SIG_FXODS)) { /* Only FXO signalled stuff can be picked up */ tmp->callgroup = i->callgroup; tmp->pickupgroup = i->pickupgroup; @@ -5756,6 +5802,7 @@ case SIG_FXOLS: case SIG_FXOGS: case SIG_FXOKS: + case SIG_FXODS: /* Read the first digit */ timeout = firstdigittimeout; /* If starting a threeway call, never timeout on the first digit so someone @@ -6548,6 +6595,7 @@ case SIG_FXOLS: case SIG_FXOGS: case SIG_FXOKS: + case SIG_FXODS: res = zt_set_hook(i->subs[SUB_REAL].zfd, ZT_OFFHOOK); if (res && (errno == EBUSY)) break; @@ -6650,6 +6698,7 @@ switch (i->sig) { case SIG_FXOLS: case SIG_FXOGS: + case SIG_FXODS: case SIG_FEATD: case SIG_FEATDMF: case SIG_FEATDMF_TA: @@ -7136,7 +7185,7 @@ destroy_zt_pvt(&tmp); return NULL; } - if (p.sigtype != (signalling & 0x3ffff)) { + if (p.sigtype != (signalling & 0xbffff)) { ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(signalling), sig2str(p.sigtype)); destroy_zt_pvt(&tmp); return NULL; @@ -7316,11 +7365,22 @@ p.rxflashtime = cur_rxflash; if (cur_debounce >= 0) p.debouncetime = cur_debounce; + if (cur_pulsecountzerofirst >= 0) + p.pulsecountzerofirst = cur_pulsecountzerofirst; + if (cur_pulsebreaktime >= 0) + p.pulsebreaktime = cur_pulsebreaktime; + if (cur_pulsemaketime >= 0) + p.pulsemaketime = cur_pulsemaketime; + if (cur_pulseaftertime >= 0) + p.pulseaftertime = cur_pulseaftertime; } /* dont set parms on a pseudo-channel (or CRV) */ if (tmp->subs[SUB_REAL].zfd >= 0) { + ast_log(LOG_DEBUG, "Setting pulse parameters: zf=%d mk=%d brk=%d after=%d\n", + p.pulsecountzerofirst , p.pulsemaketime, p.pulsebreaktime, p.pulseaftertime); + res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_SET_PARAMS, &p); if (res < 0) { ast_log(LOG_ERROR, "Unable to set parameters\n"); @@ -7351,7 +7411,7 @@ tmp->radio = radio; tmp->ringt_base = ringt_base; tmp->firstradio = 0; - if ((signalling == SIG_FXOKS) || (signalling == SIG_FXOLS) || (signalling == SIG_FXOGS)) + if ((signalling == SIG_FXOKS) || (signalling == SIG_FXOLS) || (signalling == SIG_FXOGS) || (signalling == SIG_FXODS)) tmp->permcallwaiting = callwaiting; else tmp->permcallwaiting = 0; @@ -7533,7 +7593,7 @@ } /* We're at least busy at this point */ if (busy) { - if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) + if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS) || (p->sig == SIG_FXODS)) *busy = 1; } /* If do not disturb, definitely not */ @@ -7592,7 +7652,7 @@ } /* If it's not an FXO, forget about call wait */ - if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) + if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS) && (p->sig != SIG_FXODS)) return 0; if (!p->callwaiting) { @@ -7797,7 +7857,9 @@ #endif if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { +/* if (option_debug) +*/ ast_log(LOG_DEBUG, "Using channel %d\n", p->channel); if (p->inalarm) goto next; @@ -10573,6 +10635,14 @@ hidecalleridname = ast_true(v->value); } else if (!strcasecmp(v->name, "pulsedial")) { pulse = ast_true(v->value); + } else if (!strcasecmp(v->name, "zaptel.pulse.countzerofirst")) { + cur_pulsecountzerofirst = atoi(v->value); + } else if (!strcasecmp(v->name, "zaptel.pulse.break")) { + cur_pulsebreaktime = atoi(v->value); + } else if (!strcasecmp(v->name, "zaptel.pulse.make")) { + cur_pulsemaketime = atoi(v->value); + } else if (!strcasecmp(v->name, "zaptel.pulse.pause")) { + cur_pulseaftertime = atoi(v->value); } else if (!strcasecmp(v->name, "callreturn")) { callreturn = ast_true(v->value); } else if (!strcasecmp(v->name, "callwaiting")) { @@ -10669,6 +10739,9 @@ } else if (!strcasecmp(v->value, "fxo_ks")) { cur_signalling = SIG_FXOKS; cur_radio = 0; + } else if (!strcasecmp(v->value, "fxo_ds")) { + cur_signalling = SIG_FXODS; + cur_radio = 0; } else if (!strcasecmp(v->value, "fxs_rx")) { cur_signalling = SIG_FXSKS; cur_radio = 1; @@ -11028,6 +11101,8 @@ cur_rxflash = atoi(v->value); } else if (!strcasecmp(v->name, "debounce")) { cur_debounce = atoi(v->value); + + } else if (!strcasecmp(v->name, "toneduration")) { int toneduration; int ctlfd; diff -u before-did/sdla_remora.c with-did/sdla_remora.c --- before-did/sdla_remora.c Thu Nov 2 17:39:59 2006 +++ with-did/sdla_remora.c Mon Dec 4 11:34:11 2006 @@ -750,6 +750,7 @@ unsigned short tmp[5]; unsigned char value; volatile int i, x; + int guess_decadicstart = 0; /* By default, don't send on hook */ if (fe->fe_cfg.cfg.remora.reversepolarity){ @@ -1026,15 +1027,31 @@ } wait_just_a_bit(HZ); if (READ_RM_REG(mod_no, 81) < 0x75){ - if (sane){ +/** Ergodata TEST 061021 if (sane){ + **/ DEBUG_EVENT( - "%s: Module %d: TIP/RING is too low on FXS %d!\n", +/** "%s: Module %d: TIP/RING is too low on FXS %d!\n", +**/ + "%s: Module %d: TIP/RING is too low on FXS %d! (reg81=%d sane=%d)\n", fe->name, mod_no, - READ_RM_REG(mod_no, 81) * 375 / 1000); - } + READ_RM_REG(mod_no, 81) * 375 / 1000, + READ_RM_REG(mod_no, 81), sane); +/** Ergodata TEST 061021 } + **/ + /* Ergodata TEST 061023: Decadic/Doro has reg81 = 34 */ + guess_decadicstart = READ_RM_REG(mod_no, 81) < 60; + if (READ_RM_REG(mod_no, 81) < 30){ + DEBUG_EVENT( + "%s: Module %d: TIP/RING is really too low on FXS %d!\n", + fe->name, + mod_no, + READ_RM_REG(mod_no, 81) * 375 / 1000, + READ_RM_REG(mod_no, 81), sane); + return -1; } + } DEBUG_RM("%s: Module %d: Current Battery1 %dV, Battery2 %dV (%d)\n", fe->name, mod_no, @@ -1045,6 +1062,9 @@ /* lowpower */ //WRITE_RM_REG(mod_no, 72, 0x14); //todayWRITE_RM_REG(mod_no, 64, 0x1); + /* Ergodata TEST 061023: DecadicStart should start with battery off */ + if (guess_decadicstart) WRITE_RM_REG(mod_no, 64, 0x0); + return 0; } diff -u before-did/sdla_remora_tdmv.c with-did/sdla_remora_tdmv.c --- before-did/sdla_remora_tdmv.c Thu Nov 2 17:37:08 2006 +++ with-did/sdla_remora_tdmv.c Mon Dec 4 11:46:04 2006 @@ -348,6 +348,10 @@ case ZT_SIG_FXOGS: wr->mod[chan->chanpos-1].fxs.lasttxhook = 3; break; + case ZT_SIG_FXODS: + /* TODO: if reverse polarity */ + wr->mod[chan->chanpos-1].fxs.lasttxhook = 2; + break; } break; case ZT_TXSIG_OFFHOOK: @@ -357,6 +361,10 @@ case ZT_SIG_EM: wr->mod[chan->chanpos-1].fxs.lasttxhook = 5; break; + case ZT_SIG_FXODS: + /* TODO: if reverse polarity */ + wr->mod[chan->chanpos-1].fxs.lasttxhook = 1; + break; default: wr->mod[chan->chanpos-1].fxs.lasttxhook = fe->rm_param.mod[chan->chanpos-1].u.fxs.idletxhookstate; @@ -915,6 +923,7 @@ wr->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | + ZT_SIG_FXODS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR; diff -u before-did/zaptel.c with-did/zaptel.c --- before-did/zaptel.c Thu Feb 8 10:02:38 2007 +++ with-did/zaptel.c Mon Feb 19 18:53:43 2007 @@ -267,7 +267,7 @@ ZT_TXSTATE_FLASH,ZT_TXSTATE_DEBOUNCE,ZT_TXSTATE_AFTERSTART, ZT_TXSTATE_RINGON,ZT_TXSTATE_RINGOFF,ZT_TXSTATE_KEWL, ZT_TXSTATE_AFTERKEWL,ZT_TXSTATE_PULSEBREAK,ZT_TXSTATE_PULSEMAKE, - ZT_TXSTATE_PULSEAFTER + ZT_TXSTATE_PULSEAFTER, ZT_TXSTATE_DECADIC_IDLE } ZT_TXSTATE_t; typedef short sumtype[ZT_MAX_CHUNKSIZE]; @@ -432,7 +432,7 @@ static struct zt_zone *tone_zones[ZT_TONE_ZONE_MAX]; -#define NUM_SIGS 10 +#define NUM_SIGS 11 static inline void rotate_sums(void) @@ -459,6 +459,7 @@ { ZT_SIG_FXSKS,ZT_BBIT | ZT_BBIT | ((ZT_ABIT | ZT_BBIT) << 8)}, { ZT_SIG_FXOLS,0 | (ZT_ABIT << 8)}, { ZT_SIG_FXOGS,ZT_BBIT | ((ZT_ABIT | ZT_BBIT) << 8)}, + { ZT_SIG_FXODS,0 | (ZT_ABIT << 8)}, /* FXO_DS RBS untested */ { ZT_SIG_FXOKS,0 | (ZT_ABIT << 8)}, { ZT_SIG_SF, 0}, { ZT_SIG_EM_E1, ZT_DBIT | ((ZT_ABIT | ZT_DBIT) << 8) }, @@ -497,6 +498,8 @@ return "FXOKS"; case ZT_SIG_FXOGS: return "FXOGS"; + case ZT_SIG_FXODS: + return "FXODS"; case ZT_SIG_EM: return "E&M"; case ZT_SIG_EM_E1: @@ -2011,6 +2014,8 @@ { ZT_SIG_FXOLS, ZT_BBIT | ZT_DBIT, ZT_BBIT | ZT_DBIT, 0, 0 }, /* FXO Loopstart */ { ZT_SIG_FXOGS, ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, ZT_BBIT | ZT_DBIT, 0, 0 }, /* FXO Groundstart */ + { ZT_SIG_FXODS, ZT_BBIT | ZT_DBIT, ZT_BBIT | ZT_DBIT, 0, + ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT }, /* FXO Decadicstart - RBS bits untested */ { ZT_SIG_FXOKS, ZT_BBIT | ZT_DBIT, ZT_BBIT | ZT_DBIT, 0, ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT }, /* FXO Kewlstart */ { ZT_SIG_SF, ZT_BBIT | ZT_CBIT | ZT_DBIT, @@ -2064,6 +2069,9 @@ if (chan->span->hooksig) { if (chan->txhooksig != txsig) { chan->txhooksig = txsig; +#ifdef CONFIG_ZAPATA_DEBUG + printk("Hooksig for channel %s state %d in %d signalling, pdialcount: %d\n", chan->name, txsig, chan->sig, chan->pdialcount); +#endif chan->span->hooksig(chan, txsig); } chan->otimer = timeout * ZT_CHUNKSIZE; /* Otimer is timer in samples */ @@ -2121,12 +2129,26 @@ } else if ((chan->sig == ZT_SIG_FXOKS) && (chan->txstate != ZT_TXSTATE_ONHOOK)) { /* Do RBS signalling on the channel's behalf */ zt_rbs_sethook(chan, ZT_TXSIG_KEWL, ZT_TXSTATE_KEWL, ZT_KEWLTIME); + } else if ((chan->sig == ZT_SIG_FXODS) && (chan->txstate != ZT_TXSTATE_DECADIC_IDLE)) { + /* Decadicstart hangup means go to idle state, battery off */ +#ifdef CONFIG_ZAPATA_DEBUG + printk("Decadic rbs hangup chan: %d %s\n", chan->channo, chan->name); +#endif + zt_rbs_sethook(chan, ZT_TXSIG_KEWL, ZT_TXSTATE_DECADIC_IDLE, 0); } else zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_ONHOOK, 0); } else { /* Let the driver hang up the line if it wants to */ if (chan->span->sethook) { - if (chan->txhooksig != ZT_ONHOOK) { + if (chan->sig == ZT_SIG_FXODS) { + if (chan->txhooksig != ZT_DECIDLE) { +#ifdef CONFIG_ZAPATA_DEBUG + printk("Decadic sethook hangup chan: %d %s\n", chan->channo, chan->name); +#endif + chan->txhooksig = ZT_DECIDLE; + res = chan->span->sethook(chan, ZT_DECIDLE); + } + } else if (chan->txhooksig != ZT_ONHOOK) { chan->txhooksig = ZT_ONHOOK; res = chan->span->sethook(chan, ZT_ONHOOK); } else @@ -2210,6 +2232,7 @@ chan->rxwinktime = ZT_DEFAULT_RXWINKTIME; chan->rxflashtime = ZT_DEFAULT_RXFLASHTIME; chan->debouncetime = ZT_DEFAULT_DEBOUNCETIME; + chan->pulsecountzerofirst = 0; chan->pulsemaketime = ZT_DEFAULT_PULSEMAKETIME; chan->pulsebreaktime = ZT_DEFAULT_PULSEBREAKTIME; chan->pulseaftertime = ZT_DEFAULT_PULSEAFTERTIME; @@ -2728,6 +2751,10 @@ { char c; /* Called with chan->lock held */ +#ifdef CONFIG_ZAPATA_DEBUG + printk("__do_dtmf: chan %s, txdialbuf '%s'\n", chan->name, chan->txdialbuf); + +#endif while (strlen(chan->txdialbuf)) { c = chan->txdialbuf[0]; /* Skooch */ @@ -2751,11 +2778,16 @@ default: if (chan->digitmode == DIGIT_MODE_PULSE) { - if ((c >= '0') && (c <= '9') && (chan->txhooksig == ZT_TXSIG_OFFHOOK)) + if ((c >= '0') && (c <= '9') && ((chan->txhooksig == ZT_TXSIG_OFFHOOK) || ((chan->sig == ZT_SIG_FXODS) && (chan->txhooksig == ZT_TXSIG_ONHOOK)))) { + /* Pulse count may start at zero or one */ chan->pdialcount = c - '0'; + if (chan->pulsecountzerofirst) ++chan->pdialcount; /* a '0' is ten pulses */ - if (!chan->pdialcount) chan->pdialcount = 10; + else if (!chan->pdialcount) chan->pdialcount = 10; +#ifdef CONFIG_ZAPATA_DEBUG + printk("Init pdialcount: %d txdialbuf '%s', channel %s\n", chan->pdialcount, chan->txdialbuf, chan->name); +#endif zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_PULSEBREAK, chan->pulsebreaktime); return; @@ -2773,6 +2805,10 @@ } } } +#ifdef CONFIG_ZAPATA_DEBUG + printk("__do_dtmf: chan %s, end of number, txdialbuf '%s'\n", chan->name, chan->txdialbuf); +#endif + /* Notify userspace process if there is nothing left */ chan->dialing = 0; __qevent(chan, ZT_EVENT_DIALCOMPLETE); @@ -3016,6 +3052,7 @@ if (return_master) stack.param.channo |= chan->master->channo << 16; + stack.param.pulsecountzerofirst = chan->pulsecountzerofirst; stack.param.pulsemaketime = chan->pulsemaketime; stack.param.pulsebreaktime = chan->pulsebreaktime; stack.param.pulseaftertime = chan->pulseaftertime; @@ -3056,6 +3093,7 @@ chan->rxwinktime = stack.param.rxwinktime; chan->rxflashtime = stack.param.rxflashtime; chan->debouncetime = stack.param.debouncetime; + chan->pulsecountzerofirst = stack.param.pulsecountzerofirst; chan->pulsemaketime = stack.param.pulsemaketime; chan->pulsebreaktime = stack.param.pulsebreaktime; chan->pulseaftertime = stack.param.pulseaftertime; @@ -4438,6 +4476,10 @@ return -EINVAL; /* if no span, just do nothing */ if (!chan->span) return(0); +#ifdef CONFIG_ZAPATA_DEBUG + printk("zt_chan_ioctl, ZT_HOOK: chan %s, hookstate %d\n", chan->name, j); +#endif + spin_lock_irqsave(&chan->lock, flags); /* if dialing, stop it */ chan->curtone = NULL; @@ -4463,10 +4505,16 @@ zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_DEBOUNCE, chan->debouncetime); spin_unlock_irqrestore(&chan->lock, flags); break; - case ZT_RING: case ZT_START: + if ((chan->sig == ZT_SIG_FXODS) && (chan->txstate == ZT_TXSTATE_DECADIC_IDLE)) { + /* Decadicstart DID init */ + zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_ONHOOK, 0); + break; + } + /* fall through */ + case ZT_RING: spin_lock_irqsave(&chan->lock, flags); - if (chan->txstate != ZT_TXSTATE_ONHOOK) { + if ((chan->txstate != ZT_TXSTATE_ONHOOK) && !((chan->sig == ZT_SIG_FXODS) && (chan->txstate == ZT_TXSTATE_DECADIC_IDLE))) { spin_unlock_irqrestore(&chan->lock, flags); return -EBUSY; } @@ -4517,6 +4565,11 @@ zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_ONHOOK, 0); spin_unlock_irqrestore(&chan->lock, flags); break; + case ZT_DECIDLE: + spin_lock_irqsave(&chan->lock, flags); + zt_rbs_sethook(chan, ZT_TXSIG_KEWL, ZT_TXSTATE_DECADIC_IDLE, 0); + spin_unlock_irqrestore(&chan->lock, flags); + break; default: return -EINVAL; } @@ -5271,6 +5324,7 @@ { case ZT_SIG_FXOLS: /* if FXO, its definitely on hook */ case ZT_SIG_FXOGS: + case ZT_SIG_FXODS: case ZT_SIG_FXOKS: __qevent(chan,ZT_EVENT_ONHOOK); chan->gotgs = 0; @@ -5401,8 +5455,13 @@ break; case ZT_TXSTATE_PULSEBREAK: + if (chan->sig == ZT_SIG_FXODS) { + zt_rbs_sethook(chan, ZT_TXSIG_KEWL, ZT_TXSTATE_PULSEMAKE, + chan->pulsemaketime); + } else { zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_PULSEMAKE, chan->pulsemaketime); + } wake_up_interruptible(&chan->txstateq); break; @@ -5415,13 +5474,29 @@ ZT_TXSTATE_PULSEBREAK, chan->pulsebreaktime); break; } + if (chan->sig == ZT_SIG_FXODS) { + zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_PULSEAFTER, + chan->pulseaftertime); + } else { chan->txstate = ZT_TXSTATE_PULSEAFTER; chan->otimer = chan->pulseaftertime * ZT_CHUNKSIZE; + } +#ifdef CONFIG_ZAPATA_DEBUG + printk("End of last pulse chan %s, signalling %d\n", chan->name, chan->sig); +#endif + wake_up_interruptible(&chan->txstateq); break; case ZT_TXSTATE_PULSEAFTER: +#ifdef CONFIG_ZAPATA_DEBUG + printk("In pulseAfter chan %s, signalling %d\n", chan->name, chan->sig); +#endif + if (chan->sig == ZT_SIG_FXODS) { + chan->txstate = ZT_TXSTATE_ONHOOK; + } else { chan->txstate = ZT_TXSTATE_OFFHOOK; + } __do_dtmf(chan); wake_up_interruptible(&chan->txstateq); break; @@ -5551,6 +5626,7 @@ /* fall through intentionally */ case ZT_SIG_FXOLS: /* FXO Loopstart */ case ZT_SIG_FXOKS: /* FXO Kewlstart */ + case ZT_SIG_FXODS: /* FXO Decadicstart */ switch(rxsig) { case ZT_RXSIG_OFFHOOK: /* went off hook */ /* if asserti ng ring, stop it */ @@ -5596,6 +5672,9 @@ if (chan->txstate == ZT_TXSTATE_KEWL) chan->kewlonhook = 1; break; +#ifdef CONFIG_ZAPATA_DEBUG + printk("On hook on channel %d, itimer = %d, kewlonhook = %d\n", chan->channo, chan->itimer, chan->kewlonhook); +#endif default: break; } @@ -5632,6 +5711,7 @@ /* Fall through */ case ZT_SIG_EM: /* E and M */ case ZT_SIG_EM_E1: + case ZT_SIG_FXODS: /* FXO Decadicstart */ case ZT_SIG_FXOLS: /* FXO Loopstart */ case ZT_SIG_FXOKS: /* FXO Kewlstart */ if (cursig & ZT_ABIT) /* off hook */ @@ -6081,7 +6161,9 @@ ms->infcs = PPP_INITFCS; ms->readn[ms->inreadbuf] = ms->readidx[ms->inreadbuf]; #ifdef CONFIG_ZAPATA_DEBUG +/*** printk("EOF, len is %d\n", ms->readn[ms->inreadbuf]); +****/ #endif #if defined(CONFIG_ZAPATA_NET) || defined(CONFIG_ZAPATA_PPP) if (ms->flags & (ZT_FLAG_NETDEV | ZT_FLAG_PPP)) { @@ -6174,7 +6256,9 @@ /* Notify a blocked reader that there is data available to be read, unless we're waiting for it to be full */ #ifdef CONFIG_ZAPATA_DEBUG +/*** printk("Notifying reader data in block %d\n", oldbuf); +****/ #endif wake_up_interruptible(&ms->readbufq); wake_up_interruptible(&ms->sel); diff -u before-did/zaptel.h with-did/zaptel.h --- before-did/zaptel.h Thu Feb 8 10:02:37 2007 +++ with-did/zaptel.h Mon May 7 18:46:48 2007 @@ -114,6 +114,7 @@ #define ZT_SIG_FXOLS ((1 << 3) | __ZT_SIG_FXO) /* FXO, Loopstart */ #define ZT_SIG_FXOGS ((1 << 4) | __ZT_SIG_FXO) /* FXO, Groupstart */ #define ZT_SIG_FXOKS ((1 << 5) | __ZT_SIG_FXO) /* FXO, Kewlstart */ +#define ZT_SIG_FXODS ((1 << 19) | __ZT_SIG_FXO) /* FXO, Decadicstart */ #define ZT_SIG_EM (1 << 6) /* Ear & Mouth (E&M) */ @@ -193,6 +194,7 @@ int rxwinktime; int rxflashtime; int debouncetime; +int pulsecountzerofirst; int pulsebreaktime; int pulsemaketime; int pulseaftertime; @@ -866,6 +868,9 @@ /* Value for ZT_HOOK, turn ringer off */ #define ZT_RINGOFF 6 +/* Value for ZT_HOOK, decadic idle */ +#define ZT_DECIDLE 7 + /* Ret. Value for GET/WAIT Event, no event */ #define ZT_EVENT_NONE 0 @@ -926,6 +931,9 @@ /* Echo can disabled event */ #define ZT_EVENT_EC_DISABLED 19 +/* Channel was disconnected. Hint user to close channel */ +#define ZT_EVENT_REMOVED 20 + #define ZT_EVENT_PULSEDIGIT (1 << 16) /* This is OR'd with the digit received */ #define ZT_EVENT_DTMFDOWN (1 << 17) /* Ditto for DTMF key down event */ #define ZT_EVENT_DTMFUP (1 << 18) /* Ditto for DTMF key up event */ @@ -1241,6 +1249,7 @@ int rxwinktime; /* rx wink time (ms) */ int rxflashtime; /* rx flash time (ms) */ int debouncetime; /* FXS GS sig debounce time (ms) */ + int pulsecountzerofirst; /* if pulse count starts at zero */ int pulsebreaktime; /* pulse line open time (ms) */ int pulsemaketime; /* pulse line closed time (ms) */ int pulseaftertime; /* pulse time between digits (ms) */ diff -u before-did/ztcfg.c with-did/ztcfg.c --- before-did/ztcfg.c Wed Nov 29 18:31:17 2006 +++ with-did/ztcfg.c Sat Feb 3 21:30:08 2007 @@ -142,6 +142,8 @@ return "FXO Groundstart"; case ZT_SIG_FXOKS: return "FXO Kewlstart"; + case ZT_SIG_FXODS: + return "FXO Decadicstart"; case ZT_SIG_CAS: return "CAS / User"; case ZT_SIG_DACS: @@ -513,6 +515,9 @@ } else if (!strcasecmp(keyword, "fxoks")) { cc[x].sigtype = ZT_SIG_FXOKS; sig[x] = sigtype_to_str(cc[x].sigtype); + } else if (!strcasecmp(keyword, "fxods")) { + cc[x].sigtype = ZT_SIG_FXODS; + sig[x] = sigtype_to_str(cc[x].sigtype); } else if (!strcasecmp(keyword, "cas") || !strcasecmp(keyword, "user")) { if (parse_idle(&cc[x].idlebits, idle)) return -1; @@ -1193,6 +1198,7 @@ { "fxols", chanconfig }, { "fxogs", chanconfig }, { "fxoks", chanconfig }, + { "fxods", chanconfig }, { "rawhdlc", chanconfig }, { "nethdlc", chanconfig }, { "fcshdlc", chanconfig },