diff --git a/Makefile b/Makefile index 0101ebc49e96c7b17f5db4ad80be6955674f2c75..19f28da5446cda9cb509faa02ed47f2c522e4df3 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 431cd0b9206ff5c82f6ff574ea6428499f54b849..9b7fe3664c34e48b096bce9c407a2eb0992c342f 100755 --- a/channels/chan_zap.c +++ b/channels/chan_zap.c @@ -56,6 +56,9 @@ #include <ctype.h> #ifdef ZAPATA_PRI #include <libpri.h> +#ifndef PRI_GR303_SUPPORT +#error "You need newer libpri" +#endif #endif #ifdef ZAPATA_R2 #include <libmfcr2.h> @@ -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 <span_no>". 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;x<NUM_SPANS;x++) { + if (pris[x].trunkgroup == trunkgroup) { + *span = x; + return 0; + } + } + ast_log(LOG_WARNING, "Channel %d on span %d configured to use non-existant trunk group %d\n", channel, *span, trunkgroup); + *span = -1; + } else { + if (pris[*span].trunkgroup) { + ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup); + *span = -1; + } else if (pris[*span].mastertrunkgroup) { + ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); + *span = -1; + } else { + if (si->totalchans == 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;x<NUM_SPANS;x++) { + if (pris[x].trunkgroup == trunkgroup) { + ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, channel %d\n", trunkgroup, x + 1, pris[x].dchannel); + return -1; + } + } + memset(&si, 0, sizeof(si)); + memset(&p, 0, sizeof(p)); + fd = open("/dev/zap/channel", O_RDWR); + if (fd < 0) { + ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); + return -1; + } + x = channel; + if (ioctl(fd, ZT_SPECIFY, &x)) { + ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channel, strerror(errno)); + close(fd); + return -1; + } + if (ioctl(fd, ZT_GET_PARAMS, &p)) { + ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channel, strerror(errno)); + return -1; + } + if (ioctl(fd, ZT_SPANSTAT, &si)) { + ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d)\n", channel, p.spanno); + close(fd); + return -1; + } + span = p.spanno - 1; + if (pris[span].trunkgroup) { + ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup); + close(fd); + return -1; + } + if (pris[span].pvts[0]) { + ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); + close(fd); + return -1; + } + pris[span].trunkgroup = trunkgroup; + pris[span].offset = channel - p.chanpos; + pris[span].dchannel = p.chanpos; + pris[span].span = span + 1; + close(fd); + return 0; +} + +static int pri_create_spanmap(int span, int trunkgroup, int logicalspan) +{ + if (pris[span].mastertrunkgroup) { + ast_log(LOG_WARNING, "Span %d is already part of trunk group %d, cannot add to trunk group %d\n", span + 1, pris[span].mastertrunkgroup, trunkgroup); + return -1; + } + pris[span].mastertrunkgroup = trunkgroup; + pris[span].logicalspan = logicalspan; +} + +#endif static struct zt_pvt *mkintf(int channel, int signalling, int radio) { @@ -5532,13 +5606,19 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio) signalling = 0; } #ifdef ZAPATA_PRI - if (signalling == SIG_PRI) { + if ((signalling == SIG_PRI) || (signalling == SIG_GR303FXOKS)) { int offset; - int numchans; - int dchannel; + int myswitchtype; offset = 0; - if (ioctl(tmp->subs[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 : "<unspecified>", 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 : "<unspecified>", + 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;x<pri->numchans;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;x<NUM_SPANS;x++) { - for (y=1;y<pris[x].channels;y++) { - if (pris[x].chanmask[y]) { - offset = pris[x].pvt[y]->channel - 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<NUM_SPANS;x++) { - for (y=1;y<23;y++) { - if (pris[x].chanmask[y]) { - pris[x].offset = x * 24; - 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; - } - } - } -#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 8b2dab43f71c6e244f60fa2cc49d0632037db722..c867da9e5de15d4ff1828e9b3dd2a40c00659fc4 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>,<dchannel>[,<backup1>...] +; +; 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>,<trunkgroup>[,<logicalspan>] +; +; 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)