--- channels/chan_zap.c.orig 2007-03-28 21:52:43.000000000 -0400 +++ channels/chan_zap.c 2007-03-28 21:52:12.000000000 -0400 @@ -486,6 +486,7 @@ unsigned int progress:1; unsigned int resetting:1; unsigned int setup_ack:1; + unsigned int changestatus; /* for NFAS MAINTenance SERVice message handling */ #endif unsigned int use_smdi:1; /* Whether to use SMDI on this channel */ struct ast_smdi_interface *smdi_iface; /* The serial port to listen for SMDI data on */ @@ -7540,7 +7541,11 @@ /* If guard time, definitely not */ if (p->guardtime && (time(NULL) < p->guardtime)) return 0; - + + /* If channel is not in service, definitely not */ + if (p->changestatus > 0) + return 0; + /* If no owner definitely available */ if (!p->owner) { #ifdef HAVE_PRI @@ -9286,6 +9291,32 @@ ast_mutex_unlock(&pri->pvts[chanpos]->lock); } break; + case PRI_EVENT_SERVICE: + chanpos = pri_find_principle(pri, e->service.channel); + if (chanpos < 0) { + ast_log(LOG_WARNING, "Received SERVice change status %d on unconfigured channel %d/%d span %d\n", + e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span); + } else { + ast_mutex_lock(&pri->pvts[chanpos]->lock); + pri->pvts[chanpos]->changestatus = e->service.changestatus; + ast_mutex_unlock(&pri->pvts[chanpos]->lock); + ast_log(LOG_WARNING, "Received SERVice change status %d on channel %d/%d span %d\n", + e->service.changestatus, PRI_SPAN(e->service.channel), PRI_CHANNEL(e->service.channel), pri->span); + } + break; + case PRI_EVENT_SERVICE_ACK: + chanpos = pri_find_principle(pri, e->service_ack.channel); + if (chanpos < 0) { + ast_log(LOG_WARNING, "Received SERVice ACKnowledge change status %d on unconfigured channel %d/%d span %d\n", + e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span); + } else { + ast_mutex_lock(&pri->pvts[chanpos]->lock); + pri->pvts[chanpos]->changestatus = e->service_ack.changestatus; + ast_mutex_unlock(&pri->pvts[chanpos]->lock); + ast_log(LOG_WARNING, "Received SERVice ACKnowledge change status %d on channel %d/%d span %d\n", + e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span); + } + break; default: ast_log(LOG_DEBUG, "Event: %d\n", e->e); } @@ -9640,6 +9671,101 @@ return RESULT_SUCCESS; } +static int pri_service_generic(int fd, int argc, char **argv, int changestatus) +{ + int channel; + int interfaceid = 0; + struct zt_pvt *tmp = NULL; + int x; + int y; + ast_mutex_t *lock; + struct zt_pvt *start; + char *c; + int trunkgroup; + struct zt_pri *pri=NULL; + + lock = &iflock; + start = iflist; + + if (argc < 5 || argc > 6) + return RESULT_SHOWUSAGE; + if ((c = strchr(argv[4], ':'))) { + if (sscanf(argv[4], "%d:%d", &trunkgroup, &channel) != 2) + return RESULT_SHOWUSAGE; + if ((trunkgroup < 1) || (channel < 1)) + return RESULT_SHOWUSAGE; + for (x=0;xcrvs; + lock = &pri->lock; + } else { + ast_cli(fd, "No such trunk group %d\n", trunkgroup); + return RESULT_FAILURE; + } + } else + channel = atoi(argv[4]); + + if (argc == 6) + interfaceid = atoi(argv[5]); + + /* either servicing a D-Channel */ + for (x=0;xpri, interfaceid, -1, changestatus); + return RESULT_SUCCESS; + } + } + } + + /* or servicing a B-Channel */ + ast_mutex_lock(lock); + tmp = start; + while (tmp) { + if (tmp->pri && tmp->channel == channel) { + pri_maintenance_service(tmp->pri->pri, PRI_SPAN(PVT_TO_CHANNEL(tmp)), PVT_TO_CHANNEL(tmp), changestatus); + ast_mutex_unlock(lock); + return RESULT_SUCCESS; + } + tmp = tmp->next; + } + ast_mutex_unlock(lock); + + ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel); + return RESULT_FAILURE; +} + +static int pri_service_enable_channel(int fd, int argc, char **argv) +{ + return pri_service_generic(fd, argc, argv, 0); +} + +static int pri_service_loop_channel(int fd, int argc, char **argv) +{ + return pri_service_generic(fd, argc, argv, 1); +} + +static int pri_service_disable_channel(int fd, int argc, char **argv) +{ + return pri_service_generic(fd, argc, argv, 2); +} + +static int pri_service_continuity_channel(int fd, int argc, char **argv) +{ + return pri_service_generic(fd, argc, argv, 3); +} + +static int pri_service_shutdown_channel(int fd, int argc, char **argv) +{ + return pri_service_generic(fd, argc, argv, 4); +} + static const char pri_debug_help[] = "Usage: pri debug span \n" " Enables debugging on a given PRI span\n"; @@ -9660,6 +9786,36 @@ "Usage: pri show spans\n" " Displays PRI Information\n"; +static const char service_enable_channel_usage[] = + "Usage: pri service enable channel []\n" + " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n" + " to restore a channel to service, with optional interface id\n" + " as agreed upon with remote switch operator\n"; + +static const char service_disable_channel_usage[] = + "Usage: pri service disable channel []\n" + " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n" + " to remove a channel from service, with optional interface id\n" + " as agreed upon with remote switch operator\n"; + +static const char service_loop_channel_usage[] = + "Usage: pri service loop channel []\n" + " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n" + " to put a channel into a maintenance loop, with optional interface id\n" + " as agreed upon with remote switch operator\n"; + +static const char service_continuity_channel_usage[] = + "Usage: pri service continuity channel []\n" + " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n" + " to test channel continuity, with optional interface id\n" + " as agreed upon with remote switch operator\n"; + +static const char service_shutdown_channel_usage[] = + "Usage: pri service shutdown channel []\n" + " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n" + " to shutdown a channel, with optional interface id\n" + " as agreed upon with remote switch operator\n"; + static struct ast_cli_entry zap_pri_cli[] = { { { "pri", "debug", "span", NULL }, handle_pri_debug, "Enables PRI debugging on a span", @@ -9689,6 +9845,27 @@ { { "pri", "unset", "debug", "file", NULL }, handle_pri_set_debug_file, "Ends PRI debug output to file" }, + + { {"pri", "service", "enable", "channel", NULL}, + pri_service_enable_channel, "Return a channel to service", + service_enable_channel_usage }, + + { {"pri", "service", "disable", "channel", NULL}, + pri_service_disable_channel, "Remove a channel from service", + service_disable_channel_usage }, + + { {"pri", "service", "loop", "channel", NULL}, + pri_service_loop_channel, "Put a channel into maintenance loop", + service_loop_channel_usage }, + + { {"pri", "service", "continuity", "channel", NULL}, + pri_service_continuity_channel, "Test channel continuity", + service_continuity_channel_usage }, + + { {"pri", "service", "shutdown", "channel", NULL}, + pri_service_shutdown_channel, "Shutdown a channel", + service_shutdown_channel_usage }, + }; #endif /* HAVE_PRI */ @@ -9894,6 +10071,7 @@ } #ifdef HAVE_PRI if (tmp->pri) { + ast_cli(fd, "Change Status: %d\n", tmp->changestatus); ast_cli(fd, "PRI Flags: "); if (tmp->resetting) ast_cli(fd, "Resetting ");