From 27578642b86b8bfa603a1b21a257ccac5729cd88 Mon Sep 17 00:00:00 2001 From: Mark Spencer Date: Sat, 5 Jun 2004 06:54:52 +0000 Subject: [PATCH] Add support for trunk groups in anticipation of NFAS and GR-303, Initial GR-303 work git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3146 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- Makefile | 5 - channels/chan_zap.c | 1066 ++++++++++++++++++++---------------- configs/zapata.conf.sample | 28 + 3 files changed, 609 insertions(+), 490 deletions(-) diff --git a/Makefile b/Makefile index 0101ebc49e..19f28da544 100755 --- a/Makefile +++ b/Makefile @@ -52,11 +52,6 @@ OPTIMIZE=-O6 #Include debug symbols in the executables (-g) and profiling info (-pg) DEBUG=-g #-pg -# New hangup routines for chan_zap.c -# If this flag is uncommented then you need to have new libpri code in your system -# You can still use the old libpri if you do "cvs update -D "08/03/03" in libpri source code -OPTIONS += -DNEW_PRI_HANGUP - # If you are running a radio application, define RADIO_RELAX so that the DTMF # will be received more reliably #OPTIONS += -DRADIO_RELAX diff --git a/channels/chan_zap.c b/channels/chan_zap.c index 431cd0b920..9b7fe3664c 100755 --- a/channels/chan_zap.c +++ b/channels/chan_zap.c @@ -56,6 +56,9 @@ #include #ifdef ZAPATA_PRI #include +#ifndef PRI_GR303_SUPPORT +#error "You need newer libpri" +#endif #endif #ifdef ZAPATA_R2 #include @@ -128,8 +131,10 @@ static char *config = "zapata.conf"; #define SIG_SF_FEATDMF (0x400000 | ZT_SIG_SF) #define SIG_SF_FEATB (0x800000 | ZT_SIG_SF) #define SIG_EM_E1 ZT_SIG_EM_E1 +#define SIG_GR303FXOKS (0x100000 | ZT_SIG_FXOKS) #define NUM_SPANS 32 +#define MAX_CHANNELS 672 /* No more than a DS3 per trunk group */ #define RESET_INTERVAL 3600 /* How often (in seconds) to reset unused channels */ #define CHAN_PSEUDO -2 @@ -289,6 +294,11 @@ static int r2prot = -1; #ifdef ZAPATA_PRI + +#define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->pri->logicalspan << 8)) +#define PRI_CHANNEL(p) ((p) & 0xff) +#define PRI_SPAN(p) (((p) >> 8) & 0xff) + struct zt_pri { pthread_t master; /* Thread of master */ ast_mutex_t lock; /* Mutex */ @@ -301,7 +311,10 @@ struct zt_pri { int switchtype; /* Type of switch to emulate */ int dialplan; /* Dialing plan */ int dchannel; /* What channel the dchannel is on */ - int channels; /* Num of chans in span (31 or 24) */ + int trunkgroup; /* What our trunkgroup is */ + int mastertrunkgroup; /* What trunk group is our master */ + int logicalspan; /* Logical span number within trunk group */ + int numchans; /* Num of channels we represent */ int overlapdial; /* In overlap dialing mode */ struct pri *pri; int debug; @@ -309,12 +322,10 @@ struct zt_pri { int up; int offset; int span; - int chanmask[32]; /* Channel status */ int resetting; - int resetchannel; + int resetpos; time_t lastreset; - struct zt_pvt *pvt[32]; /* Member channel pvt structs */ - struct zt_channel *chan[32]; /* Channels on each line */ + struct zt_pvt *pvts[MAX_CHANNELS]; /* Member channel pvt structs */ }; @@ -502,9 +513,7 @@ static struct zt_pvt { int resetting; int prioffset; int alreadyhungup; -#ifdef PRI_EVENT_PROCEEDING int proceeding; -#endif int setup_ack; /* wheter we received SETUP_ACKNOWLEDGE or not */ #endif #ifdef ZAPATA_R2 @@ -802,15 +811,7 @@ static int zt_digit(struct ast_channel *ast, char digit) index = zt_get_index(ast, p, 0); if (index == SUB_REAL) { #ifdef ZAPATA_PRI -#ifdef PRI_EVENT_SETUP_ACK if (p->sig == SIG_PRI && ast->_state == AST_STATE_DIALING && p->setup_ack && !p->proceeding) { -#else -#ifdef PRI_EVENT_PROCEEDING - if (p->sig == SIG_PRI && ast->_state == AST_STATE_DIALING && !p->proceeding) { -#else - if (p->sig == SIG_PRI && ast->_state == AST_STATE_DIALING) { -#endif -#endif if (!pri_grab(p, p->pri)) { pri_information(p->pri->pri,p->call,digit); pri_rel(p->pri); @@ -944,6 +945,8 @@ static char *sig2str(int sig) return "SF (Tone) Signalling with Feature Group D (MF)"; case SIG_SF_FEATB: return "SF (Tone) Signalling with Feature Group B (MF)"; + case SIG_GR303FXOKS: + return "GR-303 Signalling with FXOKS"; case 0: return "Pseudo Signalling"; default: @@ -1659,7 +1662,7 @@ static int zt_call(struct ast_channel *ast, char *rdest, int timeout) } p->digital = ast_test_flag(ast,AST_FLAG_DIGITAL); if (pri_call(p->pri->pri, p->call, p->digital ? PRI_TRANS_CAP_DIGITAL : PRI_TRANS_CAP_SPEECH, - p->prioffset, p->pri->nodetype == PRI_NETWORK ? 0 : 1, 1, l, p->pri->dialplan - 1, n, + PVT_TO_CHANNEL(p), p->pri->nodetype == PRI_NETWORK ? 0 : 1, 1, l, p->pri->dialplan - 1, n, l ? (ast->restrictcid ? PRES_PROHIB_USER_NUMBER_PASSED_SCREEN : (p->use_callingpres ? ast->callingpres : PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN)) : PRES_NUMBER_NOT_AVAILABLE, c + p->stripmsd, p->pri->dialplan - 1, (p->digital ? -1 : @@ -1890,12 +1893,8 @@ static int zt_hangup(struct ast_channel *ast) p->faxhandled = 0; p->pulsedial = 0; p->onhooktime = time(NULL); -#ifdef PRI_EVENT_PROCEEDING p->proceeding = 0; -#endif -#ifdef PRI_EVENT_SETUP_ACK p->setup_ack = 0; -#endif if (p->dsp) { ast_dsp_free(p->dsp); p->dsp = NULL; @@ -1907,21 +1906,9 @@ static int zt_hangup(struct ast_channel *ast) ast_log(LOG_WARNING, "Unable to set law on channel %d to default\n", p->channel); /* Perform low level hangup if no owner left */ #ifdef ZAPATA_PRI - if (p->sig == SIG_PRI) { + if ((p->sig == SIG_PRI) || (p->sig == SIG_GR303FXOKS)) { if (p->call) { if (!pri_grab(p, p->pri)) { -#ifndef NEW_PRI_HANGUP - if (!p->alreadyhungup) { - res = pri_disconnect(p->pri->pri, p->call, PRI_CAUSE_NORMAL_CLEARING); - } else { - pri_release(p->pri->pri, p->call, -1); - p->call = NULL; - p->alreadyhungup = 0; - } -#else -#ifndef PRI_HANGUP -#error Please update libpri. The new hangup routines were implemented. You can debug then using "pri debug span ". If you dont want to update libpri code simply comment out OPTIONS += -DNEW_PRI_HANGUP in asterisk/Makefile -#endif if (p->alreadyhungup) { pri_hangup(p->pri->pri, p->call, -1); p->call = NULL; @@ -1935,7 +1922,6 @@ static int zt_hangup(struct ast_channel *ast) } pri_hangup(p->pri->pri, p->call, icause); } -#endif if (res < 0) ast_log(LOG_WARNING, "pri_disconnect failed\n"); pri_rel(p->pri); @@ -2083,6 +2069,7 @@ static int zt_answer(struct ast_channel *ast) case SIG_FXOLS: case SIG_FXOGS: case SIG_FXOKS: + case SIG_GR303FXOKS: /* Pick up the line */ ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name); res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK); @@ -2921,7 +2908,6 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast) break; case ZT_EVENT_ALARM: #ifdef ZAPATA_PRI -#ifdef PRI_DESTROYCALL if (p->call) { if (p->pri && p->pri->pri) { pri_hangup(p->pri->pri, p->call, -1); @@ -2932,9 +2918,6 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast) if (p->owner) p->owner->_softhangup |= AST_SOFTHANGUP_DEV; p->call = NULL; -#else -#error Please "cvs update" and recompile libpri -#endif #endif p->inalarm = 1; res = get_alarms(p); @@ -3056,6 +3039,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast) case SIG_FXOLS: case SIG_FXOGS: case SIG_FXOKS: + case SIG_GR303FXOKS: switch(ast->_state) { case AST_STATE_RINGING: zt_enable_ec(p); @@ -3108,6 +3092,13 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast) if (p->owner->bridge) ast_moh_stop(p->owner->bridge); break; + case AST_STATE_RESERVED: + /* Start up dialtone */ + if (has_voicemail(p)) + res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_STUTTER); + else + res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE); + break; default: ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); } @@ -3854,26 +3845,18 @@ static int zt_write(struct ast_channel *ast, struct ast_frame *frame) ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); return -1; } - -#ifdef PRI_EVENT_PROCEEDING + +#ifdef ZAPATA_PRI if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { if (p->pri->pri) { if (!pri_grab(p, p->pri)) { -#ifdef PRI_PROGRESS - pri_progress(p->pri->pri,p->call, p->prioffset, 1); -#else - pri_acknowledge(p->pri->pri,p->call, p->prioffset, 1); -#endif + pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); pri_rel(p->pri); } else ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); } p->proceeding=1; } -#else -#ifdef ZAPATA_PRI -#warning "You need later PRI library" -#endif #endif /* Write a frame of (presumably voice) data */ if (frame->frametype != AST_FRAME_VOICE) { @@ -3947,7 +3930,7 @@ static int zt_indicate(struct ast_channel *chan, int condition) if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { if (p->pri->pri) { if (!pri_grab(p, p->pri)) { - pri_acknowledge(p->pri->pri,p->call, p->prioffset, 1); + pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); pri_rel(p->pri); } else @@ -3968,15 +3951,10 @@ static int zt_indicate(struct ast_channel *chan, int condition) case AST_CONTROL_PROGRESS: ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); #ifdef ZAPATA_PRI -#ifdef PRI_EVENT_PROCEEDING if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { if (p->pri->pri) { if (!pri_grab(p, p->pri)) { -#ifdef PRI_PROGRESS - pri_progress(p->pri->pri,p->call, p->prioffset, 1); -#else - pri_acknowledge(p->pri->pri,p->call, p->prioffset, 1); -#endif + pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); pri_rel(p->pri); } else @@ -3984,9 +3962,6 @@ static int zt_indicate(struct ast_channel *chan, int condition) } p->proceeding=1; } -#else - ast_log(LOG_WARNING, "Please update your libpri package if you want to use overlap sending\n"); -#endif #endif /* don't continue in ast_indicate */ res = 0; @@ -4513,6 +4488,7 @@ static void *ss_thread(void *data) return NULL; } break; + case SIG_GR303FXOKS: case SIG_FXOLS: case SIG_FXOGS: case SIG_FXOKS: @@ -5010,11 +4986,7 @@ static int handle_init_event(struct zt_pvt *i, int event) chan = zt_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0); if (chan) { if (has_voicemail(i)) -#ifdef ZT_TONE_STUTTER res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_STUTTER); -#else - res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_DIALRECALL); -#endif else res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE); if (res < 0) @@ -5174,7 +5146,7 @@ static void *do_monitor(void *data) 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->pri) { 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; @@ -5405,6 +5377,108 @@ static int reset_channel(struct zt_pvt *p) return 0; } +#ifdef ZAPATA_PRI +static int pri_resolve_span(int *span, int channel, int offset, struct zt_spaninfo *si) +{ + int x; + int trunkgroup; + /* Get appropriate trunk group if there is one */ + trunkgroup = pris[*span].mastertrunkgroup; + if (trunkgroup) { + /* Select a specific trunk group */ + for (x=0;xtotalchans == 31) { /* if it's an E1 */ + pris[*span].dchannel = 16; + } else { + pris[*span].dchannel = 24; + } + pris[*span].offset = offset; + pris[*span].span = *span + 1; + } + } + return 0; +} + +static int pri_create_trunkgroup(int trunkgroup, int channel) +{ + struct zt_spaninfo si; + ZT_PARAMS p; + int fd; + int span; + int x; + for (x=0;xsubs[SUB_REAL].zfd, ZT_AUDIOMODE, &offset)) { + pri_resolve_span(&span, channel, (channel - p.chanpos), &si); + if (span < 0) { + ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); + free(tmp); + return NULL; + } + if ((signalling == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &offset)) { ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); + free(tmp); return NULL; } if (span >= NUM_SPANS) { @@ -5552,21 +5632,18 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio) free(tmp); return NULL; } - if (si.totalchans == 31) { /* if it's an E1 */ - dchannel = 16; - numchans = 31; - } else { - dchannel = 24; - numchans = 23; - } + if (signalling == SIG_PRI) + myswitchtype = switchtype; + else + myswitchtype = PRI_SWITCH_GR303_TMC; offset = p.chanpos; - if (offset != dchannel) { + if (offset != pris[span].dchannel) { if (pris[span].nodetype && (pris[span].nodetype != pritype)) { ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); free(tmp); return NULL; } - if (pris[span].switchtype && (pris[span].switchtype != switchtype)) { + if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); free(tmp); return NULL; @@ -5596,13 +5673,16 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio) free(tmp); return NULL; } + if (pris[span].numchans >= MAX_CHANNELS) { + ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, + pris[span].trunkgroup); + free(tmp); + return NULL; + } pris[span].nodetype = pritype; - pris[span].switchtype = switchtype; + pris[span].switchtype = myswitchtype; pris[span].dialplan = dialplan; - pris[span].chanmask[offset] |= MASK_AVAIL; - pris[span].pvt[offset] = tmp; - pris[span].channels = numchans; - pris[span].dchannel = dchannel; + pris[span].pvts[pris[span].numchans++] = tmp; pris[span].minunused = minunused; pris[span].minidle = minidle; pris[span].overlapdial = overlapdial; @@ -6061,57 +6141,75 @@ next: static int pri_find_empty_chan(struct zt_pri *pri) { int x; - for (x=pri->channels;x>0;x--) { - if (pri->pvt[x] && !pri->pvt[x]->owner) + for (x=pri->numchans;x>0;x--) { + if (pri->pvts[x] && !pri->pvts[x]->owner) return x; } return 0; } -static int pri_fixup(struct zt_pri *pri, int channel, q931_call *c) +static int pri_find_principle(struct zt_pri *pri, int channel) +{ + int x; + int span; + int principle = -1; + span = PRI_SPAN(channel); + channel = PRI_CHANNEL(channel); + + for (x=1;x<=pri->numchans;x++) { + if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->logicalspan == span)) { + principle = x; + break; + } + } + + return principle; +} + +static int pri_fixup_principle(struct zt_pri *pri, int principle, q931_call *c) { int x; if (!c) { - if (channel < 1) - return 0; - return channel; - } - if ((channel >= 1) && - (channel <= pri->channels) && - (pri->pvt[channel]) && - (pri->pvt[channel]->call == c)) - return channel; - for (x=1;x<=pri->channels;x++) { - if (!pri->pvt[x]) continue; - if (pri->pvt[x]->call == c) { + if (principle < 0) + return -1; + return principle; + } + if ((principle > -1) && + (principle <= pri->numchans) && + (pri->pvts[principle]) && + (pri->pvts[principle]->call == c)) + return principle; + for (x=1;x<=pri->numchans;x++) { + if (!pri->pvts[x]) continue; + if (pri->pvts[x]->call == c) { /* Found our call */ - if (channel != x) { + if (principle != x) { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n", - x, channel); - if (pri->pvt[channel]->owner) { + pri->pvts[x]->channel, pri->pvts[principle]->channel); + if (pri->pvts[principle]->owner) { ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n", - x, channel, channel); - return 0; + pri->pvts[x]->channel, pri->pvts[principle]->channel, pri->pvts[principle]->channel); + return -1; } /* Fix it all up now */ - pri->pvt[channel]->owner = pri->pvt[x]->owner; - if (pri->pvt[channel]->owner) { - pri->pvt[channel]->owner->pvt->pvt = pri->pvt[channel]; - pri->pvt[channel]->owner->fds[0] = pri->pvt[channel]->subs[SUB_REAL].zfd; - pri->pvt[channel]->subs[SUB_REAL].owner = pri->pvt[x]->subs[SUB_REAL].owner; + pri->pvts[principle]->owner = pri->pvts[x]->owner; + if (pri->pvts[principle]->owner) { + pri->pvts[principle]->owner->pvt->pvt = pri->pvts[principle]; + pri->pvts[principle]->owner->fds[0] = pri->pvts[principle]->subs[SUB_REAL].zfd; + pri->pvts[principle]->subs[SUB_REAL].owner = pri->pvts[x]->subs[SUB_REAL].owner; } else - ast_log(LOG_WARNING, "Whoa, there's no owner, and we're having to fix up channel %d to channel %d\n", x, channel); - pri->pvt[channel]->call = pri->pvt[x]->call; + ast_log(LOG_WARNING, "Whoa, there's no owner, and we're having to fix up channel %d to channel %d\n", pri->pvts[x]->channel, pri->pvts[principle]->channel); + pri->pvts[principle]->call = pri->pvts[x]->call; /* Free up the old channel, now not in use */ - pri->pvt[x]->owner = NULL; - pri->pvt[x]->call = NULL; + pri->pvts[x]->owner = NULL; + pri->pvts[x]->call = NULL; } - return channel; + return principle; } } ast_log(LOG_WARNING, "Call specified, but not found?\n"); - return 0; + return -1; } static void *do_idle_thread(void *vchan) @@ -6183,15 +6281,15 @@ static void zt_pri_error(char *s) static int pri_check_restart(struct zt_pri *pri) { do { - pri->resetchannel++; - } while((pri->resetchannel <= pri->channels) && - (!pri->pvt[pri->resetchannel] || - pri->pvt[pri->resetchannel]->call || - pri->pvt[pri->resetchannel]->resetting)); - if (pri->resetchannel <= pri->channels) { + pri->resetpos++; + } while((pri->resetpos <= pri->numchans) && + (!pri->pvts[pri->resetpos] || + pri->pvts[pri->resetpos]->call || + pri->pvts[pri->resetpos]->resetting)); + if (pri->resetpos <= pri->numchans) { /* Mark the channel as resetting and restart it */ - pri->pvt[pri->resetchannel]->resetting = 1; - pri_reset(pri->pri, pri->resetchannel); + pri->pvts[pri->resetpos]->resetting = 1; + pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); } else { pri->resetting = 0; time(&pri->lastreset); @@ -6205,7 +6303,7 @@ static void *pri_dchannel(void *vpri) pri_event *e; struct pollfd fds[1]; int res; - int chan = 0; + int chanpos = 0; int x; int haveidles; int activeidles; @@ -6249,13 +6347,15 @@ static void *pri_dchannel(void *vpri) fds[0].events = POLLIN | POLLPRI; time(&t); ast_mutex_lock(&pri->lock); - if (pri->resetting && pri->up) { - if (!pri->resetchannel) - pri_check_restart(pri); - } else { - if (!pri->resetting && ((t - pri->lastreset) >= RESET_INTERVAL)) { - pri->resetting = 1; - pri->resetchannel = 0; + if (pri->switchtype != PRI_SWITCH_GR303_TMC) { + if (pri->resetting && pri->up) { + if (pri->resetpos < 0) + pri_check_restart(pri); + } else { + if (!pri->resetting && ((t - pri->lastreset) >= RESET_INTERVAL)) { + pri->resetting = 1; + pri->resetpos = -1; + } } } /* Look for any idle channels if appropriate */ @@ -6263,16 +6363,16 @@ static void *pri_dchannel(void *vpri) nextidle = -1; haveidles = 0; activeidles = 0; - for (x=pri->channels;x>=0;x--) { - if (pri->pvt[x] && !pri->pvt[x]->owner && - !pri->pvt[x]->call) { + for (x=pri->numchans;x>=0;x--) { + if (pri->pvts[x] && !pri->pvts[x]->owner && + !pri->pvts[x]->call) { if (haveidles < pri->minunused) { haveidles++; - } else if (!pri->pvt[x]->resetting) { + } else if (!pri->pvts[x]->resetting) { nextidle = x; break; } - } else if (pri->pvt[x] && pri->pvt[x]->owner && pri->pvt[x]->isidlecall) + } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) activeidles++; } #if 0 @@ -6288,10 +6388,10 @@ static void *pri_dchannel(void *vpri) if (((tv.tv_sec - lastidle.tv_sec) * 1000 + (tv.tv_usec - lastidle.tv_usec) / 1000) > 1000) { /* Don't create a new idle call more than once per second */ - snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvt[nextidle]->channel, pri->idledial); + snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial); idle = zt_request("Zap", AST_FORMAT_ULAW, idlen); if (idle) { - pri->pvt[nextidle]->isidlecall = 1; + pri->pvts[nextidle]->isidlecall = 1; if (pthread_create(&p, NULL, do_idle_thread, idle)) { ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name); zt_hangup(idle); @@ -6304,10 +6404,10 @@ static void *pri_dchannel(void *vpri) (activeidles > pri->minidle)) { /* Mark something for hangup if there is something that can be hungup */ - for (x=pri->channels;x>0;x--) { + for (x=pri->numchans;x>0;x--) { /* find a candidate channel */ - if (pri->pvt[x] && pri->pvt[x]->owner && pri->pvt[x]->isidlecall) { - pri->pvt[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; + if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) { + pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; haveidles++; /* Stop if we have enough idle channels or can't spare any more active idle ones */ @@ -6380,9 +6480,9 @@ static void *pri_dchannel(void *vpri) pri->lastreset += 5; pri->resetting = 0; /* Take the channels from inalarm condition */ - for (i=0; i<=pri->channels; i++) - if (pri->pvt[i]) { - pri->pvt[i]->inalarm = 0; + for (i=0; i<=pri->numchans; i++) + if (pri->pvts[i]) { + pri->pvts[i]->inalarm = 0; } break; case PRI_EVENT_DCHAN_DOWN: @@ -6391,8 +6491,8 @@ static void *pri_dchannel(void *vpri) pri->up = 0; pri->resetting = 0; /* Hangup active channels and put them in alarm mode */ - for (i=0; i<=pri->channels; i++) { - struct zt_pvt *p = pri->pvt[i]; + for (i=0; i<=pri->numchans; i++) { + struct zt_pvt *p = pri->pvts[i]; if (p) { if (p->call) { if (p->pri && p->pri->pri) { @@ -6409,56 +6509,51 @@ static void *pri_dchannel(void *vpri) } break; case PRI_EVENT_RESTART: - chan = e->restart.channel; - if (chan > -1) { - if ((chan < 1) || (chan > pri->channels) ) - ast_log(LOG_WARNING, "Restart requested on odd channel number %d on span %d\n", chan, pri->span); - else if (!pri->pvt[chan]) - ast_log(LOG_WARNING, "Restart requested on unconfigured channel %d on span %d\n", chan, pri->span); + if (e->restart.channel > -1) { + chanpos = pri_find_principle(pri, e->restart.channel); + if (chanpos < 0) + ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", + PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); else { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "B-channel %d restarted on span %d\n", - chan, pri->span); - ast_mutex_lock(&pri->pvt[chan]->lock); - if (pri->pvt[chan]->call) { - pri_destroycall(pri->pri, pri->pvt[chan]->call); - pri->pvt[chan]->call = NULL; + e->restart.channel, pri->span); + ast_mutex_lock(&pri->pvts[chanpos]->lock); + if (pri->pvts[chanpos]->call) { + pri_destroycall(pri->pri, pri->pvts[chanpos]->call); + pri->pvts[chanpos]->call = NULL; } /* Force soft hangup if appropriate */ - if (pri->pvt[chan]->owner) - pri->pvt[chan]->owner->_softhangup |= AST_SOFTHANGUP_DEV; - ast_mutex_unlock(&pri->pvt[chan]->lock); + if (pri->pvts[chanpos]->owner) + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; + ast_mutex_unlock(&pri->pvts[chanpos]->lock); } } else { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span); - for (x=1;x <= pri->channels;x++) - if ((x != pri->dchannel) && pri->pvt[x]) { - ast_mutex_lock(&pri->pvt[x]->lock); - if (pri->pvt[x]->call) { - pri_destroycall(pri->pri, pri->pvt[x]->call); - pri->pvt[x]->call = NULL; + for (x=1;x <= pri->numchans;x++) + if (pri->pvts[x]) { + ast_mutex_lock(&pri->pvts[x]->lock); + if (pri->pvts[x]->call) { + pri_destroycall(pri->pri, pri->pvts[x]->call); + pri->pvts[x]->call = NULL; } - if (pri->pvt[x]->owner) - pri->pvt[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; - ast_mutex_unlock(&pri->pvt[x]->lock); + if (pri->pvts[x]->owner) + pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; + ast_mutex_unlock(&pri->pvts[x]->lock); } } break; case PRI_EVENT_INFO_RECEIVED: - chan = e->ring.channel; - if ((chan < 1) || (chan > pri->channels)) { - ast_log(LOG_WARNING, "INFO received on odd channel number %d span %d\n", chan, pri->span); - chan = 0; - } else if (!pri->pvt[chan]) { - ast_log(LOG_WARNING, "INFO received on unconfigured channel %d span %d\n", chan, pri->span); - chan = 0; - } - if (chan) { - chan = pri_fixup(pri, chan, e->ring.call); - if (chan) { + chanpos = pri_find_principle(pri, e->ring.channel); + if (chanpos < 0) { + ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", + PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); + } else { + chanpos = pri_fixup_principle(pri, chanpos, e->ring.call); + if (chanpos > -1) { /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ - if (pri->overlapdial && pri->pvt[chan]->call==e->ring.call && pri->pvt[chan]->owner) { + if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) { /* how to do that */ int digitlen = strlen(e->ring.callednum); char digit; @@ -6467,7 +6562,7 @@ static void *pri_dchannel(void *vpri) digit = e->ring.callednum[i]; { struct ast_frame f = { AST_FRAME_DTMF, digit, }; - ast_queue_frame(pri->pvt[chan]->owner, &f); + ast_queue_frame(pri->pvts[chanpos]->owner, &f); } } } @@ -6475,269 +6570,249 @@ static void *pri_dchannel(void *vpri) } break; case PRI_EVENT_RING: - chan = e->ring.channel; + if (e->ring.channel == -1) + chanpos = pri_find_empty_chan(pri); + else + chanpos = pri_find_principle(pri, e->ring.channel); /* if no channel specified find one empty */ - if (chan == -1) - chan = pri_find_empty_chan(pri); - if ((chan < 1) || (chan > pri->channels)) { - ast_log(LOG_WARNING, "Ring requested on odd channel number %d span %d\n", chan, pri->span); - chan = 0; - } else if (!pri->pvt[chan]) { - ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d span %d\n", chan, pri->span); - chan = 0; - } else if (pri->pvt[chan]->owner) { - if (pri->pvt[chan]->call == e->ring.call) { - ast_log(LOG_WARNING, "Duplicate setup requested on channel %d already in use on span %d\n", chan, pri->span); + if (chanpos < 0) { + ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", + PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); + } else if (pri->pvts[chanpos]->owner) { + if (pri->pvts[chanpos]->call == e->ring.call) { + ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", + PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); break; } else { - ast_log(LOG_WARNING, "Ring requested on channel %d already in use on span %d. Hanging up owner.\n", chan, pri->span); - pri->pvt[chan]->owner->_softhangup |= AST_SOFTHANGUP_DEV; - chan = 0; + ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d. Hanging up owner.\n", + PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; + chanpos = -1; } } - if (!chan && (e->ring.flexible)) - chan = pri_find_empty_chan(pri); - if (chan) { - pri->pvt[chan]->call = e->ring.call; + if ((chanpos < 0) && (e->ring.flexible)) + chanpos = pri_find_empty_chan(pri); + if (chanpos > -1) { + pri->pvts[chanpos]->call = e->ring.call; /* Get caller ID */ - if (pri->pvt[chan]->use_callerid) { + if (pri->pvts[chanpos]->use_callerid) { if (!ast_strlen_zero(e->ring.callingname)) { - snprintf(pri->pvt[chan]->callerid, sizeof(pri->pvt[chan]->callerid), "\"%s\" <%s>", e->ring.callingname, e->ring.callingnum); + snprintf(pri->pvts[chanpos]->callerid, sizeof(pri->pvts[chanpos]->callerid), "\"%s\" <%s>", e->ring.callingname, e->ring.callingnum); } else - strncpy(pri->pvt[chan]->callerid, e->ring.callingnum, sizeof(pri->pvt[chan]->callerid)-1); + strncpy(pri->pvts[chanpos]->callerid, e->ring.callingnum, sizeof(pri->pvts[chanpos]->callerid)-1); } else - strcpy(pri->pvt[chan]->callerid, ""); - strncpy(pri->pvt[chan]->rdnis, e->ring.redirectingnum, sizeof(pri->pvt[chan]->rdnis)); + strcpy(pri->pvts[chanpos]->callerid, ""); + strncpy(pri->pvts[chanpos]->rdnis, e->ring.redirectingnum, sizeof(pri->pvts[chanpos]->rdnis)); /* If immediate=yes go to s|1 */ - if (pri->pvt[chan]->immediate) { + if (pri->pvts[chanpos]->immediate) { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n"); - strcpy(pri->pvt[chan]->exten, "s"); + strcpy(pri->pvts[chanpos]->exten, "s"); } /* Get called number */ else if (!ast_strlen_zero(e->ring.callednum)) { - strncpy(pri->pvt[chan]->exten, e->ring.callednum, sizeof(pri->pvt[chan]->exten)-1); - strncpy(pri->pvt[chan]->dnid, e->ring.callednum, sizeof(pri->pvt[chan]->dnid)); + strncpy(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten)-1); + strncpy(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); } else - strcpy(pri->pvt[chan]->exten, ""); + strcpy(pri->pvts[chanpos]->exten, ""); /* No number yet, but received "sending complete"? */ if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n"); - strcpy(pri->pvt[chan]->exten, "s"); + strcpy(pri->pvts[chanpos]->exten, "s"); } /* Make sure extension exists (or in overlap dial mode, can exist) */ - if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvt[chan]->context, pri->pvt[chan]->exten, 1, pri->pvt[chan]->callerid)) || - ast_exists_extension(NULL, pri->pvt[chan]->context, pri->pvt[chan]->exten, 1, pri->pvt[chan]->callerid)) { + if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->callerid)) || + ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->callerid)) { /* Setup law */ int law; - /* Set to audio mode at this point */ - law = 1; - if (ioctl(pri->pvt[chan]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1) - ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", pri->pvt[chan]->channel, law); + if (pri->switchtype != PRI_SWITCH_GR303_TMC) { + /* Set to audio mode at this point */ + law = 1; + if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1) + ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", pri->pvts[chanpos]->channel, law); + } if (e->ring.layer1 == PRI_LAYER_1_ALAW) law = ZT_LAW_ALAW; else law = ZT_LAW_MULAW; - res = zt_setlaw(pri->pvt[chan]->subs[SUB_REAL].zfd, law); + res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law); if (res < 0) - ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvt[chan]->channel); - res = set_actual_gain(pri->pvt[chan]->subs[SUB_REAL].zfd, 0, pri->pvt[chan]->rxgain, pri->pvt[chan]->txgain, law); + ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel); + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law); if (res < 0) - ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvt[chan]->channel); + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel); if (e->ring.complete || !pri->overlapdial) { /* Just announce proceeding */ -#ifdef PRI_PROCEEDING_FULL - pri_proceeding(pri->pri, e->ring.call, chan, 0); -#else -#warning "You need a newer libpri!" -#endif + pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); } else { - pri_need_more_info(pri->pri, e->ring.call, chan, 1); + if (pri->switchtype != PRI_SWITCH_GR303_TMC) + pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); + else + pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); } /* Get the use_callingpres state */ - pri->pvt[chan]->callingpres = e->ring.callingpres; + pri->pvts[chanpos]->callingpres = e->ring.callingpres; /* Start PBX */ - if (pri->overlapdial && ast_matchmore_extension(NULL, pri->pvt[chan]->context, pri->pvt[chan]->exten, 1, pri->pvt[chan]->callerid)) { + if (pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->callerid)) { /* Release the PRI lock while we create the channel */ ast_mutex_unlock(&pri->lock); - c = zt_new(pri->pvt[chan], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype); + c = zt_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); ast_mutex_lock(&pri->lock); if (c && !pthread_create(&threadid, &attr, ss_thread, c)) { if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d, span %d\n", - e->ring.callingnum, !ast_strlen_zero(pri->pvt[chan]->exten) ? pri->pvt[chan]->exten : "", chan, pri->span); + ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", + e->ring.callingnum, !ast_strlen_zero(pri->pvts[chanpos]->exten) ? pri->pvts[chanpos]->exten : "", + pri->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); } else { - ast_log(LOG_WARNING, "Unable to start PBX on channel %d, span %d\n", chan, pri->span); + ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", + pri->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); if (c) ast_hangup(c); else { -#if NEW_PRI_HANGUP pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); -#else - pri_release(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); -#endif - pri->pvt[chan]->call = NULL; + pri->pvts[chanpos]->call = NULL; } } } else { ast_mutex_unlock(&pri->lock); /* Release PRI lock while we create the channel */ - c = zt_new(pri->pvt[chan], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype); + c = zt_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype); ast_mutex_lock(&pri->lock); if (c) { if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d, span %d\n", - e->ring.callingnum, pri->pvt[chan]->exten, chan, pri->span); - zt_enable_ec(pri->pvt[chan]); + ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", + e->ring.callingnum, pri->pvts[chanpos]->exten, + pri->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); + zt_enable_ec(pri->pvts[chanpos]); } else { - ast_log(LOG_WARNING, "Unable to start PBX on channel %d, span %d\n", chan, pri->span); -#if NEW_PRI_HANGUP + ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", + pri->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); -#else - pri_release(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); -#endif - pri->pvt[chan]->call = NULL; + pri->pvts[chanpos]->call = NULL; } } } else { if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d, span %d\n",pri->pvt[chan]->exten, pri->pvt[chan]->context, pri->pvt[chan]->callerid, chan, pri->span); -#ifdef NEW_PRI_HANGUP + ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n", + pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->callerid, pri->logicalspan, + pri->pvts[chanpos]->prioffset, pri->span); pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); -#else - pri_release(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); -#endif - pri->pvt[chan]->call = NULL; + pri->pvts[chanpos]->call = NULL; } } else -#ifdef NEW_PRI_HANGUP pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); -#else - pri_release(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); -#endif break; case PRI_EVENT_RINGING: - chan = e->ringing.channel; - if ((chan < 1) || (chan > pri->channels)) { - ast_log(LOG_WARNING, "Ringing requested on odd channel number %d span %d\n", chan, pri->span); - chan = 0; - } else if (!pri->pvt[chan]) { - ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d span %d\n", chan, pri->span); - chan = 0; + chanpos = pri_find_principle(pri, e->ringing.channel); + if (chanpos < 0) { + ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", + PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); + chanpos = -1; } - if (chan) { - chan = pri_fixup(pri, chan, e->ringing.call); - if (!chan) { - ast_log(LOG_WARNING, "Ringing requested on channel %d not in use on span %d\n", e->ringing.channel, pri->span); - chan = 0; - } else if (ast_strlen_zero(pri->pvt[chan]->dop.dialstr)) { - zt_enable_ec(pri->pvt[chan]); - pri->pvt[chan]->subs[SUB_REAL].needringing =1; -#ifdef PRI_EVENT_PROCEEDING - pri->pvt[chan]->proceeding=1; -#endif + if (chanpos > -1) { + chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call); + if (chanpos < 0) { + ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", + PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); + chanpos = -1; + } else if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { + zt_enable_ec(pri->pvts[chanpos]); + pri->pvts[chanpos]->subs[SUB_REAL].needringing =1; + pri->pvts[chanpos]->proceeding=1; } else ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n"); } -#ifndef PRI_EVENT_PROCEEDING - break; -#else /* Fall through */ - if (!chan) break; -#endif -#ifdef PRI_EVENT_PROCEEDING + if (chanpos < 0) break; case PRI_EVENT_PROCEEDING: /* Get chan value if e->e is not PRI_EVNT_RINGING */ if (e->e == PRI_EVENT_PROCEEDING) - chan = e->proceeding.channel; - if ((chan >= 1) && (chan <= pri->channels)) - if (pri->pvt[chan] && pri->overlapdial && !pri->pvt[chan]->proceeding) { - struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; - ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d span %d\n",chan,pri->pvt[chan]->span); - ast_queue_frame(pri->pvt[chan]->owner, &f); - - pri->pvt[chan]->proceeding=1; - } - + chanpos = pri_find_principle(pri, e->proceeding.channel); + if (chanpos > -1) { + if (pri->overlapdial && !pri->pvts[chanpos]->proceeding) { + struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; + ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n", + pri->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); + if (pri->pvts[chanpos]->owner) + ast_queue_frame(pri->pvts[chanpos]->owner, &f); + + pri->pvts[chanpos]->proceeding=1; + } + } break; -#endif case PRI_EVENT_FACNAME: - chan = e->facname.channel; - if ((chan < 1) || (chan > pri->channels)) { - ast_log(LOG_WARNING, "Facilty Name requested on odd channel number %d span %d\n", chan, pri->span); - chan = 0; - } else if (!pri->pvt[chan]) { - ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d span %d\n", chan, pri->span); - chan = 0; + chanpos = pri_find_principle(pri, e->facname.channel); + if (chanpos < 0) { + ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", + PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); + chanpos = -1; } - if (chan) { - chan = pri_fixup(pri, chan, e->facname.call); - if (!chan) { - ast_log(LOG_WARNING, "Facility Name requested on channel %d not in use on span %d\n", e->ringing.channel, pri->span); - chan = 0; + if (chanpos > -1) { + chanpos = pri_fixup_principle(pri, chanpos, e->facname.call); + if (chanpos < 0) { + ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", + PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); + chanpos = -1; } else { /* Re-use *69 field for PRI */ - snprintf(pri->pvt[chan]->lastcallerid, sizeof(pri->pvt[chan]->lastcallerid), "\"%s\" <%s>", e->facname.callingname, e->facname.callingnum); - pri->pvt[chan]->subs[SUB_REAL].needcallerid =1; - zt_enable_ec(pri->pvt[chan]); + snprintf(pri->pvts[chanpos]->lastcallerid, sizeof(pri->pvts[chanpos]->lastcallerid), "\"%s\" <%s>", e->facname.callingname, e->facname.callingnum); + pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1; + zt_enable_ec(pri->pvts[chanpos]); } } break; case PRI_EVENT_ANSWER: - chan = e->answer.channel; - if ((chan < 1) || (chan > pri->channels)) { - ast_log(LOG_WARNING, "Answer on odd channel number %d span %d\n", chan, pri->span); - chan = 0; - } else if (!pri->pvt[chan]) { - ast_log(LOG_WARNING, "Answer on unconfigured channel %d span %d\n", chan, pri->span); - chan = 0; + chanpos = pri_find_principle(pri, e->answer.channel); + if (chanpos < 0) { + ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", + PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); + chanpos = -1; } - if (chan) { - chan = pri_fixup(pri, chan, e->answer.call); - if (!chan) { - ast_log(LOG_WARNING, "Answer requested on channel %d not in use on span %d\n", chan, pri->span); - chan = 0; + if (chanpos > -1) { + chanpos = pri_fixup_principle(pri, chanpos, e->answer.call); + if (chanpos < 0) { + ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", + PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); + chanpos = -1; } else { - if (!ast_strlen_zero(pri->pvt[chan]->dop.dialstr)) { - pri->pvt[chan]->dialing = 1; + if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { + pri->pvts[chanpos]->dialing = 1; /* Send any "w" waited stuff */ - res = ioctl(pri->pvt[chan]->subs[SUB_REAL].zfd, ZT_DIAL, &pri->pvt[chan]->dop); + res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_DIAL, &pri->pvts[chanpos]->dop); if (res < 0) { - ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", pri->pvt[chan]->channel); - pri->pvt[chan]->dop.dialstr[0] = '\0'; + ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", pri->pvts[chanpos]->channel); + pri->pvts[chanpos]->dop.dialstr[0] = '\0'; } else - ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvt[chan]->dop.dialstr); - pri->pvt[chan]->dop.dialstr[0] = '\0'; + ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr); + pri->pvts[chanpos]->dop.dialstr[0] = '\0'; } else - pri->pvt[chan]->subs[SUB_REAL].needanswer =1; + pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1; /* Enable echo cancellation if it's not on already */ - zt_enable_ec(pri->pvt[chan]); + zt_enable_ec(pri->pvts[chanpos]); } } break; case PRI_EVENT_HANGUP: - chan = e->hangup.channel; - if ((chan < 1) || (chan > pri->channels)) { - ast_log(LOG_WARNING, "Hangup requested on odd channel number %d span %d\n", chan, pri->span); - chan = 0; - } else if (!pri->pvt[chan]) { - ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d span %d\n", chan, pri->span); - chan = 0; + chanpos = pri_find_principle(pri, e->hangup.channel); + if (chanpos < 0) { + ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); + chanpos = -1; } - if (chan) { - chan = pri_fixup(pri, chan, e->hangup.call); - if (chan) { - ast_mutex_lock(&pri->pvt[chan]->lock); - if (!pri->pvt[chan]->alreadyhungup) { + if (chanpos > -1) { + chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); + if (chanpos > -1) { + ast_mutex_lock(&pri->pvts[chanpos]->lock); + if (!pri->pvts[chanpos]->alreadyhungup) { /* we're calling here zt_hangup so once we get there we need to clear p->call after calling pri_hangup */ - pri->pvt[chan]->alreadyhungup = 1; + pri->pvts[chanpos]->alreadyhungup = 1; /* Queue a BUSY instead of a hangup if our cause is appropriate */ - if (pri->pvt[chan]->owner) { - pri->pvt[chan]->owner->hangupcause = hangup_pri2cause(e->hangup.cause); + if (pri->pvts[chanpos]->owner) { + pri->pvts[chanpos]->owner->hangupcause = hangup_pri2cause(e->hangup.cause); switch(e->hangup.cause) { case PRI_CAUSE_USER_BUSY: - pri->pvt[chan]->subs[SUB_REAL].needbusy =1; + pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; break; case PRI_CAUSE_CALL_REJECTED: case PRI_CAUSE_NETWORK_OUT_OF_ORDER: @@ -6745,27 +6820,30 @@ static void *pri_dchannel(void *vpri) case PRI_CAUSE_SWITCH_CONGESTION: case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: - pri->pvt[chan]->subs[SUB_REAL].needcongestion =1; + pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; break; default: - pri->pvt[chan]->owner->_softhangup |= AST_SOFTHANGUP_DEV; + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; } } if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Channel %d, span %d got hangup\n", chan, pri->span); + ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup\n", + pri->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); } else { - pri_hangup(pri->pri, pri->pvt[chan]->call, e->hangup.cause); - pri->pvt[chan]->call = NULL; + pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); + pri->pvts[chanpos]->call = NULL; } if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d since channel reported in use\n", chan); - pri_reset(pri->pri, chan); - pri->pvt[chan]->resetting = 1; + ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); + pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); + pri->pvts[chanpos]->resetting = 1; } - ast_mutex_unlock(&pri->pvt[chan]->lock); + ast_mutex_unlock(&pri->pvts[chanpos]->lock); } else { - ast_log(LOG_WARNING, "Hangup on bad channel %d\n", e->hangup.channel); + ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); } } break; @@ -6773,23 +6851,21 @@ static void *pri_dchannel(void *vpri) #error please update libpri #endif case PRI_EVENT_HANGUP_REQ: - chan = e->hangup.channel; - if ((chan < 1) || (chan > pri->channels)) { - ast_log(LOG_WARNING, "Hangup REQ requested on odd channel number %d span %d\n", chan, pri->span); - chan = 0; - } else if (!pri->pvt[chan]) { - ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d span %d\n", chan, pri->span); - chan = 0; + chanpos = pri_find_principle(pri, e->hangup.channel); + if (chanpos < 0) { + ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); + chanpos = -1; } - if (chan) { - chan = pri_fixup(pri, chan, e->hangup.call); - if (chan) { - ast_mutex_lock(&pri->pvt[chan]->lock); - if (pri->pvt[chan]->owner) { - pri->pvt[chan]->owner->hangupcause = hangup_pri2cause(e->hangup.cause); + if (chanpos > -1) { + chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); + if (chanpos > -1) { + ast_mutex_lock(&pri->pvts[chanpos]->lock); + if (pri->pvts[chanpos]->owner) { + pri->pvts[chanpos]->owner->hangupcause = hangup_pri2cause(e->hangup.cause); switch(e->hangup.cause) { case PRI_CAUSE_USER_BUSY: - pri->pvt[chan]->subs[SUB_REAL].needbusy =1; + pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; break; case PRI_CAUSE_CALL_REJECTED: case PRI_CAUSE_NETWORK_OUT_OF_ORDER: @@ -6797,49 +6873,48 @@ static void *pri_dchannel(void *vpri) case PRI_CAUSE_SWITCH_CONGESTION: case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: - pri->pvt[chan]->subs[SUB_REAL].needcongestion =1; + pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; break; default: - pri->pvt[chan]->owner->_softhangup |= AST_SOFTHANGUP_DEV; + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; } if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Channel %d, span %d got hangup\n", chan, pri->span); + ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); } else { - pri_hangup(pri->pri, pri->pvt[chan]->call, e->hangup.cause); - pri->pvt[chan]->call = NULL; + pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); + pri->pvts[chanpos]->call = NULL; } if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d since channel reported in use\n", chan); - pri_reset(pri->pri, chan); - pri->pvt[chan]->resetting = 1; + ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); + pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); + pri->pvts[chanpos]->resetting = 1; } - ast_mutex_unlock(&pri->pvt[chan]->lock); + ast_mutex_unlock(&pri->pvts[chanpos]->lock); } else { - ast_log(LOG_WARNING, "Hangup REQ on bad channel %d\n", e->hangup.channel); + ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); } } break; case PRI_EVENT_HANGUP_ACK: - chan = e->hangup.channel; - if ((chan < 1) || (chan > pri->channels)) { - ast_log(LOG_WARNING, "Hangup ACK requested on odd channel number %d span %d\n", chan, pri->span); - chan = 0; - } else if (!pri->pvt[chan]) { - ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel %d span %d\n", chan, pri->span); - chan = 0; + chanpos = pri_find_principle(pri, e->hangup.channel); + if (chanpos < 0) { + ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); + chanpos = -1; } - if (chan) { - chan = pri_fixup(pri, chan, e->hangup.call); - if (chan) { - ast_mutex_lock(&pri->pvt[chan]->lock); - pri->pvt[chan]->call = NULL; - pri->pvt[chan]->resetting = 0; - if (pri->pvt[chan]->owner) { + if (chanpos > -1) { + chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); + if (chanpos > -1) { + ast_mutex_lock(&pri->pvts[chanpos]->lock); + pri->pvts[chanpos]->call = NULL; + pri->pvts[chanpos]->resetting = 0; + if (pri->pvts[chanpos]->owner) { if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Channel %d, span %d got hangup ACK\n", chan, pri->span); + ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); } - ast_mutex_unlock(&pri->pvt[chan]->lock); + ast_mutex_unlock(&pri->pvts[chanpos]->lock); } } break; @@ -6847,65 +6922,65 @@ static void *pri_dchannel(void *vpri) ast_log(LOG_WARNING, "PRI Error: %s\n", e->err.err); break; case PRI_EVENT_RESTART_ACK: - chan = e->restartack.channel; - if ((chan < 1) || (chan > pri->channels)) { + chanpos = pri_find_principle(pri, e->restartack.channel); + if (chanpos < 0) { /* Sometime switches (e.g. I421 / British Telecom) don't give us the channel number, so we have to figure it out... This must be why everybody resets exactly a channel at a time. */ - for (x=1;x<=pri->channels;x++) { - if (pri->pvt[x] && pri->pvt[x]->resetting) { - chan = x; - ast_mutex_lock(&pri->pvt[chan]->lock); - ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d span %d\n", chan, pri->span); - if (pri->pvt[chan]->owner) { - ast_log(LOG_WARNING, "Got restart ack on channel %d with owner\n", chan); - pri->pvt[chan]->owner->_softhangup |= AST_SOFTHANGUP_DEV; + for (x=1;xnumchans;x++) { + if (pri->pvts[x] && pri->pvts[x]->resetting) { + chanpos = x; + ast_mutex_lock(&pri->pvts[chanpos]->lock); + ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->logicalspan, + pri->pvts[chanpos]->prioffset, pri->span); + if (pri->pvts[chanpos]->owner) { + ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->logicalspan, + pri->pvts[chanpos]->prioffset, pri->span); + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; } - pri->pvt[chan]->resetting = 0; + pri->pvts[chanpos]->resetting = 0; if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "B-channel %d successfully restarted on span %d\n", chan, pri->span); - ast_mutex_unlock(&pri->pvt[chan]->lock); + ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->logicalspan, + pri->pvts[chanpos]->prioffset, pri->span); + ast_mutex_unlock(&pri->pvts[chanpos]->lock); if (pri->resetting) pri_check_restart(pri); break; } } - if ((chan < 1) || (chan > pri->channels)) { - ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d span %d\n", chan, pri->span); + if (chanpos < 0) { + ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", + PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); } - chan = 0; - } else if (!pri->pvt[chan]) { - ast_log(LOG_WARNING, "Restart ACK requested on unconfigured channel %d span %d\n", chan, pri->span); - chan = 0; + chanpos = -1; } - if ((chan >= 1) && (chan <= pri->channels)) { - if (pri->pvt[chan]) { - ast_mutex_lock(&pri->pvt[chan]->lock); - if (pri->pvt[chan]->owner) { - ast_log(LOG_WARNING, "Got restart ack on channel %d with owner\n", chan); - pri->pvt[chan]->owner->_softhangup |= AST_SOFTHANGUP_DEV; + if (chanpos > -1) { + if (pri->pvts[chanpos]) { + ast_mutex_lock(&pri->pvts[chanpos]->lock); + if (pri->pvts[chanpos]->owner) { + ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n", + PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; } - pri->pvt[chan]->resetting = 0; + pri->pvts[chanpos]->resetting = 0; if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "B-channel %d successfully restarted on span %d\n", chan, pri->span); - ast_mutex_unlock(&pri->pvt[chan]->lock); + ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->logicalspan, + pri->pvts[chanpos]->prioffset, pri->span); + ast_mutex_unlock(&pri->pvts[chanpos]->lock); if (pri->resetting) pri_check_restart(pri); } } break; -#ifdef PRI_EVENT_SETUP_ACK case PRI_EVENT_SETUP_ACK: - chan = e->setup_ack.channel; - if ((chan < 1) || (chan > pri->channels)) { - ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on strange channel %d span %d\n", chan, pri->span); - } else if (!pri->pvt[chan]) { - ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d span %d\n", chan, pri->span); + chanpos = pri_find_principle(pri, e->setup_ack.channel); + if (chanpos < 0) { + ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", + PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span); } else { - pri->pvt[chan]->setup_ack = 1; + pri->pvts[chanpos]->setup_ack = 1; } break; -#endif default: ast_log(LOG_DEBUG, "Event: %d\n", e->e); } @@ -6933,7 +7008,7 @@ static int start_pri(struct zt_pri *pri) pri->fd = open("/dev/zap/channel", O_RDWR, 0600); x = pri->offset + pri->dchannel; if ((pri->fd < 0) || (ioctl(pri->fd,ZT_SPECIFY,&x) == -1)) { - ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); + ast_log(LOG_ERROR, "Unable to open D-channel %d (%d + %d) (%s)\n", x, pri->offset, pri->dchannel, strerror(errno)); return -1; } @@ -6947,7 +7022,7 @@ static int start_pri(struct zt_pri *pri) if (p.sigtype != ZT_SIG_HDLCFCS) { close(pri->fd); pri->fd = -1; - ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/zaptel.conf\n", x); + ast_log(LOG_ERROR, "D-channel %d (%d + %d) is not in HDLC/FCS mode. See /etc/zaptel.conf\n", x, pri->offset, pri->dchannel); return -1; } bi.txbufpolicy = ZT_POLICY_IMMEDIATE; @@ -6967,9 +7042,11 @@ static int start_pri(struct zt_pri *pri) ast_log(LOG_ERROR, "Unable to create PRI structure\n"); return -1; } -#ifdef PRI_SET_OVERLAPDIAL + pri->resetpos = -1; + /* Force overlap dial if we're doing GR-303! */ + if (pri->switchtype == PRI_SWITCH_GR303_TMC) + pri->overlapdial = 1; pri_set_overlapdial(pri->pri,pri->overlapdial); -#endif pri_set_debug(pri->pri, DEFAULT_PRI_DEBUG); if (pthread_create(&pri->master, NULL, pri_dchannel, pri)) { close(pri->fd); @@ -7070,12 +7147,7 @@ static int handle_pri_show_span(int fd, int argc, char *argv[]) ast_cli(fd, "No PRI running on span %d\n", span); return RESULT_SUCCESS; } -#ifdef PRI_DUMP_INFO pri_dump_info(pris[span-1].pri); -#else -#warning Please update libpri. pri_dump_info not found - ast_log(LOG_WARNING, "Please update libpri. pri_dump_info not available\n"); -#endif return RESULT_SUCCESS; } @@ -7291,6 +7363,11 @@ static int zap_show_channel(int fd, int argc, char **argv) ast_cli(fd, "Call "); ast_cli(fd, "\n"); } + if (tmp->pri->logicalspan) + ast_cli(fd, "PRI Span: %d\n", tmp->pri->logicalspan); + else + ast_cli(fd, "PRI Span: Implicit\n"); + #endif #ifdef ZAPATA_R2 if (tmp->r2) { @@ -7303,15 +7380,11 @@ static int zap_show_channel(int fd, int argc, char **argv) } #endif memset(&ci, 0, sizeof(ci)); - if (ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONF, &ci)) { - ast_log(LOG_WARNING, "Failed to get conference info on channel %d\n", tmp->channel); - } else { + if (!ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONF, &ci)) { ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); } #ifdef ZT_GETCONFMUTE - if (ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONFMUTE, &x)) { - ast_log(LOG_WARNING, "Failed to get confmute info on channel %d\n", tmp->channel); - } else { + if (!ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONFMUTE, &x)) { ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); } #endif @@ -7605,7 +7678,10 @@ static int setup_zap(void) int found_pseudo = 0; int cur_radio = 0; #ifdef ZAPATA_PRI - int offset; + int spanno; + int logicalspan; + int trunkgroup; + int dchannel; #endif cfg = ast_load(config); @@ -7622,6 +7698,55 @@ static int setup_zap(void) ast_log(LOG_ERROR, "Unable to lock interface list???\n"); return -1; } +#ifdef ZAPATA_PRI + /* Process trunkgroups first */ + v = ast_variable_browse(cfg, "trunkgroups"); + while(v) { + if (!strcasecmp(v->name, "trunkgroup")) { + trunkgroup = atoi(v->value); + if (trunkgroup > 0) { + if ((c = strchr(v->value, ','))) { + dchannel = atoi(c + 1); + if (dchannel > 0) { + if (pri_create_trunkgroup(trunkgroup, dchannel)) { + ast_log(LOG_WARNING, "Unable to create trunk group %d with D-channel %d at line %d of zapata.conf\n", trunkgroup, dchannel, v->lineno); + } else if (option_verbose > 1) + ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with D-channel %d\n", trunkgroup, dchannel); + } else + ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of zapata.conf\n", trunkgroup, v->lineno); + } else + ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of zapata.conf\n", trunkgroup, v->lineno); + } else + ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of zapata.conf\n", v->lineno); + } else if (!strcasecmp(v->name, "spanmap")) { + spanno = atoi(v->value); + if (spanno > 0) { + if ((c = strchr(v->value, ','))) { + trunkgroup = atoi(c + 1); + if (trunkgroup > 0) { + if ((c = strchr(c + 1, ','))) + logicalspan = atoi(c + 1); + else + logicalspan = 0; + if (logicalspan >= 0) { + if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { + ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); + } else if (option_verbose > 1) + ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); + } else + ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of zapata.conf\n", v->lineno); + } else + ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of zapata.conf\n", v->lineno); + } else + ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of zapata.conf\n", v->lineno); + } else + ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of zapata.conf\n", v->lineno); + } else { + ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); + } + v = v->next; + } +#endif v = ast_variable_browse(cfg, "channels"); while(v) { /* Create the interface list */ @@ -7630,7 +7755,6 @@ static int setup_zap(void) ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); ast_destroy(cfg); ast_mutex_unlock(&iflock); - __unload_module(); return -1; } c = v->value; @@ -7648,7 +7772,6 @@ static int setup_zap(void) ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", v->value, chan); ast_destroy(cfg); ast_mutex_unlock(&iflock); - __unload_module(); return -1; } if (finish < start) { @@ -7667,7 +7790,6 @@ static int setup_zap(void) ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value); ast_destroy(cfg); ast_mutex_unlock(&iflock); - /*__unload_module();*/ return -1; } } @@ -7890,6 +8012,10 @@ static int setup_zap(void) cur_signalling = SIG_PRI; cur_radio = 0; pritype = PRI_CPE; + } else if (!strcasecmp(v->value, "gr303fxoks_net")) { + cur_signalling = SIG_GR303FXOKS; + cur_radio = 0; + pritype = PRI_NETWORK; #endif #ifdef ZAPATA_R2 } else if (!strcasecmp(v->value, "r2")) { @@ -7924,10 +8050,8 @@ static int setup_zap(void) } else if (!strcasecmp(v->name, "switchtype")) { if (!strcasecmp(v->value, "national")) switchtype = PRI_SWITCH_NI2; -#ifdef PRI_SWITCH_NI1 else if (!strcasecmp(v->value, "ni1")) switchtype = PRI_SWITCH_NI1; -#endif else if (!strcasecmp(v->value, "dms100")) switchtype = PRI_SWITCH_DMS100; else if (!strcasecmp(v->value, "4ess")) @@ -7940,7 +8064,6 @@ static int setup_zap(void) ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value); ast_destroy(cfg); ast_mutex_unlock(&iflock); - __unload_module(); return -1; } } else if (!strcasecmp(v->name, "minunused")) { @@ -8066,21 +8189,12 @@ static int setup_zap(void) ast_destroy(cfg); #ifdef ZAPATA_PRI for (x=0;xchannel - y; - if ((pris[x].offset > -1) && (pris[x].offset != offset)) { - ast_log(LOG_WARNING, "Huh?? Offset mismatch...\n"); - } - pris[x].offset = offset; - pris[x].span = x + 1; - if (start_pri(pris + x)) { - ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); - return -1; - } else if (option_verbose > 1) - ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1); - break; - } + if (pris[x].pvts[0]) { + if (start_pri(pris + x)) { + ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); + return -1; + } else if (option_verbose > 1) + ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1); } } #endif @@ -8436,24 +8550,6 @@ static int reload_zt(void) ast_mutex_unlock(&iflock); ast_destroy(cfg); -#if 0 -#ifdef ZAPATA_PRI - for (x=0;x 1) - ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1); - break; - } - } - } -#endif -#endif /* And start the monitor for the first time */ restart_monitor(); diff --git a/configs/zapata.conf.sample b/configs/zapata.conf.sample index 8b2dab43f7..c867da9e5d 100755 --- a/configs/zapata.conf.sample +++ b/configs/zapata.conf.sample @@ -3,6 +3,33 @@ ; ; Configuration file +[trunkgroups] +; +; Trunk groups are used for NFAS or GR-303 connections. +; +; Group: Defines a trunk group. +; group => ,[,...] +; +; trunkgroup is the numerical trunk group to create +; dchannel is the zap channel which will have the +; d-channel for the trunk. +; backup1 is an optional list of backup d-channels. +; +;trunkgroup => 1,24,48 +; +; Spanmap: Associates a span with a trunk group +; spanmap => ,[,] +; +; zapspan is the zap span number to associate +; trunkgroup is the trunkgroup (specified above) for the mapping +; logicalspan is the logical span number within the trunk group to use. +; if unspecified, no logical span number is used. +; +;spanmap => 1,1,1 +;spanmap => 2,1,2 +;spanmap => 3,1,3 +;spanmap => 4,1,4 + [channels] ; ; Default language @@ -52,6 +79,7 @@ switchtype=national ; fxo_ks: FXO (Kewl Start) ; pri_cpe: PRI signalling, CPE side ; pri_net: PRI signalling, Network side +; gr303fxoks_net: GR-303 Signalling, FXO Loopstart, Network side ; sf: SF (Inband Tone) Signalling ; sf_w: SF Wink ; sf_featd: SF Feature Group D (The fake, Adtran style, DTMF)